Skip to content

Latest commit

 

History

History
142 lines (106 loc) · 6.34 KB

README.md

File metadata and controls

142 lines (106 loc) · 6.34 KB

DeFi Pulse Token Adapter Writing Doc

Documentation Links

Follow These Instructions First
SDK Reference

Writing a Token Adapter

Let's take a look at the existing WBTC token adapter to see a minimal example of a token adapter. Each token adapter gets it's own sub-directory under /tokens/${category}, with an index.js and abi.json file containing the main code and settings.

tokens
└───btc
  └───wbtc
    └───index.js
    └───abi.json

Feel free to add additional files and folders within your project adapter directly as needed to help organize your code, but most token adapters shouldn't be too large. Please keep all code within your token adapter directory - PR's with modifications or additions outside the scope of your own project usually won't be allowed, and in cases where they are needed will need to be discussed with the DeFi Pulse team in advance.

The balance Function

The main balance function of a token adapter is where token balance is fetched. On DeFi Pulse, this function is run every hour, with a unix timestamp and block number passed to the function. Please note that token adapters need to be able to run successfully for any point back to a token project starting time, not just for recent points. This is necessary both to allow collection of historical data that may exist prior to the release of a newly added token project, and for repairing or catching up a token projects data history in the event of any errors.

async function balance (timestamp, block) {
  const totalSupply = (await sdk.api.abi.call({
    block,
    target: wbtcContract,
    abi: abi['totalSupply'],
  })).output;

  return { [wbtcContract]: totalSupply };
}

For consistency, we treat balance associated with token address as raw/wei value (before decimal conversion) and balance associated with token symbol as decimal converted value. Due to the methods most commonly available in core contracts for most projects already on Defi Pulse (and a lack of broad standardization), we've found the most effective solution is for token adapters to work internally with token address; symbol conversions are done automatically after the adapter runs;

The important thing is that the adapter is expected to output an object with token address and raw non-decimal converted balance.

Metadata

Each token adapter needs to export the main balance function, in addition to some important metadata - This data is outlined in the wbtc token adapter with accompanying descriptions:

module.exports = {
  name: 'Wrapped Bitcoin',  // token project name
  symbol: 'WBTC',           // token symbol
  type: 'custodial',        // allowed values can be 'custodial', 'synthetic', 'decentralized'
  start: 1514764800,        // unix timestamp (utc 0) specifying when the token project began, or where live data begins
  balance,                  // balance adapter
}

Testing

While writing your token adapter, you'll need to run the code to check for errors, check for output etc. Some testing commands are provided for this purpose.

npm run test-token -- --token=wbtc
npm run validate-token -- --token=wbtc

The test-token command will run a token adapter once for the latest hourly point, perform some basic checks on it's output, and log the result.

wbtc token adapter running & output format
    runs for specified time: latest hour
      ✓ returns valid balance data at hour 0 (5608ms)


  1 passing (6s)

Output of tests are stored in json files under tokens/output/**project_name**/balance and are named based on the time they were run to fetch data for.

In the above example, the output is saved to tokens/output/wbtc/balance/2020-11-19T18:00:00Z.json since the project is wbtc, and the adapter function provided is for balance. It's output is shown below:

{
  "ethCallCount": 1,
  "timestamp": 1605808800,
  "block": 11289973,
  "output": {
    "BTC": {
      "balance": "124260.330682",
      "coingeckoId": "wrapped-bitcoin"
    }
  }
}

The test will output how many Ethereum network calls were used for the run, confirm the timestamp and block the test was run on, and provide the output generated by the adapter.

You can also provide an optional timestamp or block parameters to the test in order to reproduce and troubleshoot previous results:

npm run test-token -- --token=wbtc --block=11289973
npm run test-token -- --token=wbtc --timestamp=1605808800

When you think your token adapter is ready, the validate-token command can be used to do a final more thorough check. This command runs the adapter through a series of points spread over it's lifespan, and also checks that valid metadata is exported by the adapter as well.

npm run validate-token -- --token=wbtc
wbtc token adapter export format
    ✓ has a valid name
    ✓ has a valid symbol
    ✓ has a valid start time
    ✓ has a valid balance method
    ✓ type matches one of the defined types

  wbtc token adapter running & output format
    runs for a variety of points at different times
      ✓ returns valid balance data at hour 0 (4614ms)
      ✓ returns valid balance data at hour -6 (4278ms)
      ✓ returns valid balance data at hour -12 (4390ms)
      ✓ returns valid balance data at hour -36 (4327ms)
      ✓ returns valid balance data at hour -72 (4340ms)
      ✓ returns valid balance data at 2020-11-09T00:00:00Z (4336ms)
      ✓ returns valid balance data at 2020-08-29T00:00:00Z (6386ms)
      ✓ returns valid balance data at 2020-06-18T00:00:00Z (4271ms)
      ✓ returns valid balance data at 2020-04-08T00:00:00Z (4339ms)
      ✓ returns valid balance data at 2020-01-27T00:00:00Z (4349ms)
      ✓ returns valid balance data at 2019-11-17T00:00:00Z (4643ms)
      ✓ returns valid balance data at 2019-09-06T00:00:00Z (5341ms)
      ✓ returns valid balance data at 2019-06-26T00:00:00Z (4338ms)
      ✓ returns valid balance data at 2019-04-16T00:00:00Z (4718ms)
      ✓ returns valid balance data at 2019-02-03T00:00:00Z (4329ms)


  20 passing (1m)

This test suite will only log verbose results and adapter output in the event of a problem