DefiLlama

Introduction to DefiLlama

DefiLlma provides inclusive, non-biased, and community-driven statistics for the decentralized finance industry. They treat all projects equally with regards to what is and isn't included in TVL, how long it takes to list or update a project's TVL, and everything else.
Astar/ Shiden is now live on DefiLlama. DefiLlama maintains homepages for the top Astar Defi and Shiden Defi.

How to list a DeFi project on Astar/Shiden

If you'd like to list a DeFi project on DefiLlama:
  1. 1.
    Fork the Adapters repo (button towards the top right of the repo page).
  2. 2.
    Add a new folder with the same name as the project to projects/.
  3. 3.
    Write an SDK adapter (or a fetch adapter if you cant use the SDK for this project) in the new folder.
  4. 4.
    Make a Pull Request with the changes on your fork, to the main DefiLlama Adapters repo, with a brief explanation of what you changed.
  5. 5.
    Wait for someone to either comment on or merge your Pull Request. There is no need to ask for someone to check your PR as there a monitored regularly.
  6. 6.
    Once your PR has been merged, please give 24 hours for the front-end team to load your listing onto the UI.

How to build an adapter

An adapter is just some code that:
  1. 1.
    Collects data on a protocol by calling some endpoints or making some blockchain calls
  2. 2.
    Computes the TVL of a protocol and returns it

Types of adapters

Right now there are two types of adapters co-existing within the repository:
  • Fetch adapters: These calculate the TVL directly and just export a fetch method
  • SDK adapters: These use the SDK and return all the assets locked along with their balances

Which adapter type should I develop?

Right now DefiLlama SDK only supports EVM chains, so if your project is in any of these chains you should develop an SDK-based adapter, while if your project is on another chain a fetch adapter is likely the way to go. If your project is not on an EVM chain but you are able to give us historical data, we can help support this if you message us in Discord.

How to write an SDK adapter

Basic adapter

Below, you can see the one AstridDAO used on Astar Network (ASTR). Let's walk through it to get a better understanding of how it works.
projects/astriddao/index.js
1
const { sumTokens } = require('../helper/unwrapLPs')
2
const { getFixBalances } = require('../helper/portedTokens')
3
4
const WASTAR = "0x19574c3c8fafc875051b665ec131b7e60773d2c9"
5
const chain = 'astar'
6
7
const CONTRACT_ADDRESSES = {
8
// Pools holding ASTR.
9
ACTIVE_POOL: "0x70724b57618548eE97623146F76206033E67086e",
10
DEFAULT_POOL: "0x2fE3FDf91786f75C92e8AB3B861588D3D051D83F",
11
};
12
13
async function tvl(ts, _block, chainBlocks ) {
14
const block = chainBlocks[chain]
15
const balances = {}
16
const tokensAndOwners = Object.values(CONTRACT_ADDRESSES).map(owner => [WASTAR, owner])
17
await sumTokens(balances, tokensAndOwners, block, chain);
18
(await getFixBalances(chain))(balances)
19
return balances
20
}
21
22
module.exports = {
23
timetravel: true,
24
start: 915830,
25
methodology: "Total locked ASTR (in wrapped ERC-20 form) in ActivePool and DefaultPool",
26
astar: {
27
tvl,
28
},
29
};
Copied!
The adapter consists of 3 main sections. First, any dependencies we want to use. Next, an async function containing the code for calculating TVL (where the bulk of the code usually is). Finally, the module exports.

Line 13 - Input Parameters:

  1. 1.
    The first param taken by the function (line 13) will be a timestamp. In your testing, this will be the current timestamp, but when we backfill chart data for your protocol, past timestamps will also be input.
  2. 2.
    Next is the mainnet block height corresponding to the timestamp in the first param.

Line 15 - Initialising The Balances Object:

SDK adapters always export balance objects, which is a dictionary where all the keys are either token addresses or Coingecko token IDs. On this line, we just initialize the balance object to be empty.
If a token balance has an address key, the DefiLlama SDK will manage any raw to real amount conversion for you (so you don't need to worry about erc20 decimals). If a token balance has a Coingecko ID key, you will need to process the decimals and use a real token amount in the balances object.
If you export token addresses in your balances object that isn't on CoinGecko, DefiLlama won't be able to fetch prices for the tokens. You can check which addresses are supported by going to the token on CoinGecko and checking the 'Contract' field on the right (pictured above).

Line 17 - Adding Data To The Balances Object

In the SDK we have utilities to add data to the balances dictionary. sdk.util.sumSingleBalance() takes 3 parameters:
  1. 1.
    The object you want to add token balances to.
  2. 2.
    The token key you want to add to. We will transform the token address.
  3. 3.
    The balance we want to add. (NB: If we were using a CoinGecko ID in position 2, we'd need to divide collateralBalance by 10 ** <token decimals> to convert the raw balance to a real balance).

Line 22 - Module Exports

The module exports must be constructed correctly, and use the correct keys, so that the DefiLlama UI can show your data. Nest chain TVL (and separate types of TVL like staking, pool2 etc) inside the chain key (eg 'astar', 'shiden').
Please also let us know:
  • timetravel (bool) - if we can backfill data with your adapter. Most SDK adapters will allow this, but not all. For example, if you fetch a list of live contracts from an API before querying data on-chain, timetravel should be 'false'.
  • misrepresentedTokens (bool) - if you have used token substitutions at any point in the adapter this should be 'true'.
  • methodology (string) - this is a small description that will explain to DefiLlama users how the adapter works out your protocol's TVL.
  • start (number) - the earliest block height the adapter will work at.

Testing

Once you are done writing it you can verify that it returns the correct value by running the following code:
1
$ npm install
2
# Replace with your adapter's name
3
$ node test.js projects/astriddao/index.js
Copied!
If the adapter runs successfully, the console will show you a breakdown of your project's TVL in USD. If it all looks accurate, you're ready to submit.

Submit

Just submit a PR to the adapter repository on Github!

How to write a fetch adapter

Fetch adapters export a function, called fetch, which returns a project's total TVL (in USD) as a number. The following basic adapter would just always return a TVL of 100$:
1
async function fetch() {
2
return 100;
3
}
4
5
module.exports = {
6
fetch
7
}
Copied!
Fetch adapters only allow us to get the TVL at the current time, so it's impossible to fill old values on a protocol's TVL chart or recompute them, thus leading to charts that look jumpy. To solve this we introduced SDK adapters, which allow us to retrieve a protocol's TVL at any point in time.
Fetch adapters can only be used for projects on non-EVM chains. Where possible, SDK adapters are preferred to fetch adapters because on-chain calls are more transparent.
Third-party APIs should be used where possible to reduce bias. If third-party APIs are not available for the data you need, proprietary APIs can be used if they're open source.

Examples

projects/balancer.js
1
const retry = require('async-retry')
2
const { GraphQLClient, gql } = require('graphql-request')
3
4
async function fetch() {
5
var endpoint ='https://api.thegraph.com/subgraphs/name/balancer-labs/balancer';
6
var graphQLClient = new GraphQLClient(endpoint)
7
8
var query = gql`
9
{
10
balancers(first: 5) {
11
totalLiquidity,
12
totalSwapVolume
13
}
14
}
15
`;
16
const results = await retry(async bail => await graphQLClient.request(query))
17
return parseFloat(results.balancers[0].totalLiquidity);
18
}
19
20
module.exports = {
21
fetch
22
}
Copied!
projects/ren.js
1
const retry = require('async-retry')
2
const axios = require("axios");
3
const BigNumber = require("bignumber.js");
4
5
async function fetch() {
6
let price_feed = await retry(async bail => await axios.get('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true'))
7
let response = await retry(async bail => await axios.get('https://api.etherscan.io/api?module=stats&action=tokensupply&contractaddress=0xeb4c2781e4eba804ce9a9803c67d0893436bb27d&apikey=H6NGIGG7N74TUH8K2X31J1KB65HFBH2E82'))
8
let tvl = new BigNumber(response.data.result).div(10 ** 8).toFixed(2);
9
return (tvl * price_feed.data.bitcoin.usd);
10
}
11
12
module.exports = {
13
fetch
14
}
Copied!
projects/thorchain.js
1
const retry = require('async-retry')
2
const axios = require("axios");
3
const BigNumber = require("bignumber.js");
4
5
async function fetch() {
6
var price_feed = await retry(async bail => await axios.get('https://api.coingecko.com/api/v3/simple/price?ids=thorchain&vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true'))
7
8
var res = await retry(async bail => await axios.get('https://chaosnet-midgard.bepswap.com/v1/network'))
9
var tvl = await new BigNumber((parseFloat(res.data.totalStaked) * 2) + parseFloat(res.data.bondMetrics.totalActiveBond) + parseFloat(res.data.bondMetrics.totalStandbyBond)).div(10 ** 8).toFixed(2);
10
tvl = tvl * price_feed.data.thorchain.usd;
11
return tvl;
12
}
13
14
module.exports = {
15
fetch
16
}
Copied!

How to update a project

If you'd like to update the code used to calculate the TVL of a DeFi project already listed on DefiLlama:
  1. 1.
    Fork the Adapters repo (button towards the top right of the repo page).
  2. 2.
    Make your changes to the fork (generally easiest by cloning your new fork into a desktop IDE).
  3. 3.
    Make a Pull Request from your fork, to the main DefiLlama Adapters repo, with a brief explanation of what you changed.
  4. 4.
    Wait for someone to either comment on or merge your Pull Request. There is no need to ask for someone to check your PR as there a monitored regularly.
If you'd like to update the metadata (name, logo, description etc) of a project already listed on DefiLlama:
  1. 1.
    Join the DefiLlama Discord server.
  2. 2.
    Message the 'listings' channel about the changes you'd like to make.
  3. 3.
    Wait for a response from the team.
If you don't have a Discord account, you can always reach the DefiLlama team through Github or Twitter. Responses are generally quicker on Discord.
If you'd like to list or update the listing for an NFT project, also get in contact with the DefiLlama team over Discord.