# WINkLink Price Feed Service
# Overview
# WINkLink Price Feed Service Introduction
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)
# How to use existing WINkLink Price Feed
# 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:
- TronScan: Mainnet (opens new window), Nile Testnet (opens new window)
- Official wallet-cli (opens new window)
- Tron IDE (opens new window)
- TronBox (opens new window)
- tronweb (opens new window)
# 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