# WINkLink Price Feed Service

# Overview

To ensure that smart contracts reflect token prices in real-world time, it is necessary to frequently update them. In particular, the prices of assets in DeFi must closely match those of the real world. Otherwise, arbitrage or contract attacks may cause losses for users and developers.

WINkLink's price service focuses on digital currency pairs, providing decentralized applications (DApps) with accurate and stable price information on real-world digital currencies. The solution offered by WINkLink aggregates price data from multiple oracle nodes, resulting in a stable price service known as the Price Feed Contract.

# Supported Price Pairs List & Configurations

# Mainnet

Pair Contract Address (Proxy)
BTC-TRX TX4rin6u2SaF3TqANqRgzfSCGi95azQNVY
BTC-USD TQoijQ1iZKRgJsAAWNPMu6amgtCJ3WMUV7
BTT-TRX TS26cn4GmmipyGTcgvRRwqL6AyEU6vK4rw
BTT-USD TBAAW545oJ6iTxqzezGvagrSUzCpz1S8eR
BTTOLD-TRX TUjTmKMxGmH78t5DmY7YsfJFoGw6XyX9VZ
BTTOLD-USD TEEnwU47Fgx4Ehii7Xs9bLWK3XKo4fs6sV
ETH-TRX TXZ9AUk6nC2454NSDGUWvPB72JxSNJrezX
ETH-USD TR2yWYWovJaSM7TfZq7L7sT7ZRugdJJQmL
JST-TRX TC19QPF2mjP1ZhXxD8JNKJs4ksxMZkCuNP
JST-USD TE5rKoDzKmpVAQp1sn7x6V8biivR3d5r47
LIVE-USD TNdLmxVhdj1H1yGjhhSp33cMaAJKjyTAM4
LTC-TRX TVJPFXKMysYsRWEXJ3JkSnAUPucinUFUB6
LTC-USD TGxGL85kN3W5sGdBiobgWabWFcMEtoqRJJ
NFT-TRX TKtc1V6QAY1Gpy511QjzXkLUphG8Dre8CY
STRX-TRX TW9bNueyJZA9iZnNXGYkJuPJJ7KFN3o5qw
NFT-USD TEC8b2oL6sAQFMiea73tTgjtTLwyV1GuZU
SUN-TRX TLLyqXr5cbYEMjzeThe1esss1SVBbxxubu
SUN-USD TRMgzSPsuWEcVpd5hv19XtLeCk8Z799sZa
SUNOLD-TRX TWAob1YsNzh7bfgkjfAD9MAdarcoSWScWw
SUNOLD-USD TEEuSdqyv2NFREtNoUXMTDSmJVK3KCuLac
TRX-USD TR5HtpPK4gX4RFC4DCBUHfFgsGkGFEzSAb
TUSD-TRX TLXMULb1SRpv841Q54C4DhWkmmGfRA2rUH
TUSD-USD TBc3yBP8xcyQ1E3hDTUhRxToMrgekLH2kh
USDC-TRX TNTm5ezUGHxYc9Mvst58yYTAjxDmqWWGZc
USDC-USD TNu3zS55MP4KnBBP6Maw1nHSzRpc3CXAxm
USDD-TRX TWW4P2pck8rFcxx3H8NfnH4qhNPu1V35Pb
USDD-USD TJ7jEgoYVaeymVfYZ3bS57dYArwVDS1mhW
USDJ-TRX TCBKyYMP4YQFHxYznuUaResHDTaEWLuJNW
USDJ-USD TB1MyT7pDCNg8w7cSW1QvYKs4WPzErzP5k
USDT-TRX TUfV7S4RYtdmBvtHzedfFPVsK9nvndtETp
USDT-USD TKePc46n5CiUCR8LL788TFeKA4kjvNnuem
WIN-TRX TQvCG1U2jGTVwXLqvFWR27LDtEJZVgRbEg
WIN-USD TSCef3LT3jpLwwXCWhZe3hZoMsYk1ZLif2
WSTUSDT-TRX TKcTU5vCPqBBfuULEGXg9kkLx6Tzs2Zo3x

# Nile Testnet

  • WIN Token Contract Address: TNDSHKGBmgRx9mDYA9CnxPx55nu672yQw2
  • WinkMid Contract Address: TLDU7C8K3Gd3pXrAj9gtpVVNRHZHuHHZ8P

List of price service contract addresses:

Pair Nile (Proxy)
BTC-TRX TFETSL1Yc8dCJM7z6uBkHhAsPbqP5UaCDE
BTC-USD TAX8Pm3FgN74za72TFZrn5gPBxJTKgnnpE
BTT-TRX TKbeHN2hdrgSShG6iF3mDsJTu9fFzNrHjo
BTT-USD TJdzg4wqBt4JkP1ehbYQufg1cLjbomT2j7
BTTOLD-TRX TETkTRbnyB4ptWiK9qXgiyFxQQ9d8ZacT6
BTTOLD-USD TRpRfFzubR7oheDCwHRbwJRfeFa85L6tWE
ETH-TRX TSVJwLrhWBF7K6BkEG6hStjMxQJXAzBABQ
ETH-USD TQGyY3mWTTzKKBLBg3wQTSbAGqBnGqYSzX
JST-TRX TSf6ZwFrDg5Jvyci1PnRHrrZvPpCCKNTjj
JST-USD TJ7SizJiCAjMPAri1CFAxzg4xCRLycumMj
LIVE-USD TPxNjLNrn3WAwoyGQgqJyw3dLo9E79mUdH
LTC-TRX TWProfbHdGBCf7HVNys5KAbVT4vhUwpu22
LTC-USD TRSFTb2seuQxQqUsyeJ8Wg8XhX1e2g3T19
NFT-TRX TWP99RnyMVKFjzuu9XT5J21qBZu8DwhCum
NFT-USD TX5KVe4sp24w5HJ4nfk2ZstRhV8RTFm67W
STRX-TRX TEbUQ4gohuK5wdtKmpnGd2kvyzhhznJDCx
SUN-TRX TTxxeWGpSDV3zPDxnYXzG1ue7RpTYTvDpY
SUN-USD TJjENuVH7TD8RJdGtj22ac6Bt1ktpBGURR
SUNOLD-TRX TNfn4qt4QJ7LAndM2aWbxrGGH8CRGvzxui
SUNOLD-USD TMKzWKMA1gSwjYSL6VpfCUXLuwPKdjEsQ2
TRX-USD TCeXRh9vcb78j2Eb2oJk4YwwnoHQDT64T1
TUSD-TRX TM1bvBzHkRrQqvvHGi1CC1Heb8ESWreiNW
TUSD-USD TUuxMFxv6qPn1ymZoYY45SSK1hhEVAvyKz
USDC-TRX TWio8JqYx2aey49ua2ohLoyBPbVVWos8RB
USDC-USD TF5a2qhfxtWzUQnAocPoxgKXLe1vEE8oER
USDD-TRX TFr7TWdb5RWPNCfecr3HNfnCmNNL8qvgmJ
USDD-USD TX264fxRmdhNfUgkruk9orzAVvtCehyowq
USDJ-TRX TDJtnT7JRNqmNaqY1mK9i1xWN4GnX1UfGd
USDJ-USD TKZUQTYAhH1LTG67QmhX4HxTWZdvLfH9d1
USDT-TRX TJL5M1QqL7oF2ceazAFJ2ump9jf87jUqnK
USDT-USD TT2ETLY1Mmx2DKYT9S6fMvKGPqbWH3LDEJ
WIN-TRX TP7aHYuXUkKPKsojs9BNJDVyAJeQ2KtfCj
WIN-USD TYYMqsRNZTwsiFkRtn2NewvXT9GnnsPBH9
WSTUSDT-TRX TZGEUihByCHG79Hbpider6pGZfY9S8ct6P

# Apply for New Trading Pairs

To request for new trading pair to be added to WINkLink officially, please fill in and submit this form. (opens new window)

# Acquire latest price

Acquiring the latest price data in the consumer contract requires AggregatorInterface.

This interface defines the functions provided by the Price Feed Contract to the public. The code below demonstrates an example of using the AggregatorInterface to acquire the latest price:


pragma solidity ^0.5.0;

interface AggregatorInterface {
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
function latestRound() external view returns (uint256);
function getAnswer(uint256 roundId) external view returns (int256);
function getTimestamp(uint256 roundId) external view returns (uint256);
}

contract PriceConsumer {
AggregatorInterface internal priceFeed;

    /**
     * Price Aggregator Address: TYZxQSHAhxGgUWzxYEZAohvWc9cQWXtNBt
     */
    constructor() public {
        priceFeed = AggregatorInterface(0xF7e52418572834722ED87E9425d673FEdBD55a0e);
    }

    /**
     * Returns the latest price
     */
    function getLatestPrice() public view returns (int) {
        // If the round is not complete yet, timestamp is 0
        require(priceFeed.latestTimestamp() > 0, "Round not complete");
        return priceFeed.latestAnswer();
    }
}

# Acquire Price History

The AggregatorInterface interface provides the getAnswer(uint256 roundId) function to obtain the price history. The corresponding timestamp can be acquired via getTimestamp(uint256 roundId).

# How to setup Price Feed contracts

# Contract Deployment

Employing a decentralized structure, WINkLink features open-source smart contracts and allows any organization or individual to deploy their WINkLink oracle contracts and release these services to the public.

Users may pick their sets from all the open services available on WINkLink to create their own aggregated data contracts and benefit from decentralization.

Contracts for the project is hosted at: https://github.com/tron-oracle/winklink-libocr/tree/main/tvm-contracts (opens new window) - Connect your Github account

You may use any of the following tools or libraries for contract deployment and call testing:

# Aggregator Contract

Aggregator contract is deployed on the TRON public chain with the following features:

  • Accepts transmission from WINKLink node's off-chain aggregation
  • Calculate the WIN fee on data requests and allow Oracle nodes to claim rewards
  • Implements the Owned interface. This provides access control on different methods of exposed by the aggregator contract.

Contract code is available at AccessControlledOCRAggregator.sol.

# How to launch a Price Feed Service Node

# Node Deployment

WINkLink node can be deployed after the contract is deployed.

WINkLink node (project directory node) code is available at: https://github.com/tron-oracle/winklink-2.0/tree/main (opens new window) - Connect your Github account .

WARNING

Current node implementation includes the adapter for accessing token price via exchange APIs. Please run the node in a stable network environment outside Mainland China.

# Prepare Node Account

Each WINkLink node must be linked to a TRON account for calling Aggregator contract to transmit data.

After generating the account address and the private key, the developer can test TRX token on the Testnet Faucet page.The token is used for paying the handling fees on calling the smart contracts.

Account will be generated on the initial run of the node and the private key will be stored in the keychain. Node will use this account for price feed transmissions.

WARNING

Account generated is not activated, please transfer any amount of TRX into the account for activation

# Required Environment

WINkLink node relies on a running PostgreSQL database. Developers can find more information in the official documentation PostgreSQL .

TIP

Here we assume that the username and the password for the PostgreSQL instance deployed locally are root:root respectively. Please use a strong password or other verification methods in the production environment.

WINkLink node is written in Go programming language and requires Golang environment.

# Node Configuration

WINkLink node is configured using TOML files. Main config is tools/config/config.toml. With secrets.toml you can specify a db instance to be used. Below is a sample template for reference.

# secrets.toml
[Database]
URL = 'postgresql://root:root@localhost:5432/winklink?sslmode=disable' # Require
AllowSimplePasswords = true

[Password]
Keystore = 'keystorePassword' # Required

[Tron]
TronApiKey = 'apiKey'

After the node configuration file is confirmed, it is required to create password and apicredentials files and write the userid and password to access the node’s api:

# apicredentials
example.user@fake.email
totallyNotFakePassword (16 characters long)
# password
totallyNotFakePassword (16 characters long)

TIP

It is important that you keep private information safe.

# Building a docker image for the node

Use the following command to build a standard linux docker image:

#build a docker image
docker buildx build --platform linux/amd64 -t winklink-2.0 -f core/winklink.Dockerfile .

After building, we can tag and push it to the desired repository for deployment.

# Start a Node from source code

Install go1.20 (opens new window)

Go into the base directory of the source code winklink-2.0

Build the command line interface with

make install

Start your WINkLink node using the following command with the respective configuration items:

winklink -c /tools/config/config.toml -s /tools/config/secrets.toml node start -p /tools/secrets/vrfpassword -a /tools/secrets/apicredentials

WARNING

Your node account must have enough TRX tokens for contract calls. You can apply testnet tokens at Testnet Faucet.

# Add a Job to Your Node

The job of your node represents the data service that your node supports, and each job has a unique 32-byte ID. For end users, (Oracle address, job ID) uniquely identifies the data service provided by a WINkLink node. Each WINkLink node can provide multiple data services.

When your WINkLink node is running properly, you can add a job to your node via Operator UI:

Example: (change the parameters below to the Oracle contract address deployed in the steps above)

TIP

For bootstrap node, set the DefaultBootstrapPeers in the config file as well.

Example: DefaultBootstrapPeers = ['/ip4/127.0.0.1/tcp/6788/p2p/12D3KooWMrKGdnH6nBrf7hDz25NXFSFNk7vgsTxj9bHskWEct4xh']

# Bootstrap node

type               = "offchainreporting"
schemaVersion      = 1
tvmChainID         = 1
name               = "TUSD-TRX"
contractAddress    = "ACCESS-CONTROLLED-OCR-AGGREGATOR-ADDRESS"
p2pBootstrapPeers  = [
  "/ip4/127.0.0.1/tcp/6788/p2p/P2P-PEER-ID",
]
isBootstrapPeer = true
keyBundleID = "NODE-KEY-BUNDLE"
forwardingAllowed = false
maxTaskDuration = "0s"

TIP

Ensure that the bootstrap node and the oracle node are configured as individual entities, each linking to its unique database instance. When operating locally, modify the config.toml file to designate different port numbers for each instance, facilitating access to the distinct Operator UIs for each.

[WebServer]
HTTPPort = 3000
SecureCookies = false # Default

# Oracle node

type               = "offchainreporting"
schemaVersion      = 1
tvmChainID         = 2
name               = "OCR: TUSD-TRX"
contractAddress    = "ACCESS-CONTROLLED-OCR-AGGREGATOR-ADDRESS"
p2pBootstrapPeers  = [
"/ip4/127.0.0.1/tcp/6788/p2p/P2P-PEER-ID",
]
isBootstrapPeer    = false
keyBundleID        = "NODE-KEY-BUNDLE"
transmitterAddress = "THE-CURRENT-NODE-EIP55-ADDRESS"
observationTimeout = "10s"
blockchainTimeout  = "20s"
contractConfigTrackerSubscribeInterval = "2m"
contractConfigTrackerPollInterval = "1m"
contractConfigConfirmations = 3
observationSource   = """
ds_http           [type="http" method=GET url="https://www.okx.com/api/v5/market/index-tickers?instId=TUSD-USD"]
    ds_parse          [type="jsonparse" path="data,0,idxPx"]
ds_converttrx     [type="converttrx" url="https://www.okx.com/api/v5/market/index-tickers?instId=TRX-USD" path="data.0.idxPx"]
ds_multiply       [type="multiply" times=1000000]

    ds_http -> ds_parse -> ds_converttrx -> ds_multiply
"""

# Query Jobs

Jobs can be retrieved under the jobs tab in Operator UI.

The sub-tabs are as follows:

  • Overview: list of recent job runs and task flow
  • Definition: job specification
  • Errors: cumulative count of different errors encountered since job creation
  • Runs: list of all job runs

job-page-ui.png