DeFi Llama
Search…
How to write an SDK adapter
You should start by forking the DefiLlama/DefiLlama-Adapters repository on github. Afterwards, just create a new folder on `/projects` and write your adapter there.

Adapters 101

At it's core, an adapter is just some code that takes in a UNIX timestamp and an Ethereum block height and returns the balances of assets locked in a protocol, including all the decimals (that is, the way it's stored on chain).
For example, the following adapter would return a TVL that increases by 1 WBTC and 3 BAT every block:
1
const BigNumber = require("bignumber.js")
2
3
const wbtcContract = "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
4
const batContract = "0x0d8775f648430679a709e98d2b0cb6250d2887ef"
5
6
async function tvl(timestamp, block) {
7
// WBTC has a 8 decimals
8
const wbtcBalance = BigNumber(block).times(1e8)
9
// BAT has 18 decimals
10
const batBalance = BigNumber(block).times(3).times(1e18)
11
12
// toFixed(0) just converts the numbers into strings
13
return {
14
[wbtcContract]: wbtcBalance.toFixed(0),
15
[batContract]: batBalance.toFixed(0)
16
};
17
}
18
19
module.exports = {
20
ethereum:{
21
tvl,
22
},
23
tvl,
24
};
Copied!
If we were to evaluate it to get the TVL at block height 12 we would then get the following output:
1
{
2
'0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599': '1200000000',
3
'0x0d8775f648430679a709e98d2b0cb6250d2887ef': '36000000000000000000'
4
}
Copied!
Which our SDK would then convert into their USD equivalent and sum to obtain total TVL.
So, all in all, adapters just do that, take in a time and return a list of assets locked at that moment, specified by the address of their token, and their respective balances as strings and with all the decimals.

Basic adapter

Now let's move on to a real adapter, here's the one we use for PoolTogether:
projects/pooltogether/index.js
1
const sdk = require("@defillama/sdk");
2
const { request, gql } = require("graphql-request");
3
const abi = require('./abi.json')
4
5
const graphUrl =
6
'https://api.thegraph.com/subgraphs/name/pooltogether/pooltogether-v3_1_0';
7
const graphQuery = gql`
8
query GET_POOLS($block: Int) {
9
prizePools(
10
block: { number: $block }
11
) {
12
id
13
underlyingCollateralSymbol
14
underlyingCollateralToken
15
compoundPrizePool{
16
cToken
17
}
18
}
19
}
20
`;
21
22
async function tvl(timestamp, block) {
23
let balances = {};
24
25
const { prizePools } = await request(
26
graphUrl,
27
graphQuery,
28
{
29
block,
30
}
31
);
32
const lockedTokens = await sdk.api.abi.multiCall({
33
abi: abi['accountedBalance'],
34
calls: prizePools.map(pool => ({
35
target: pool.id
36
})),
37
block
38
});
39
lockedTokens.output.forEach((call, index) => {
40
const underlyingToken = prizePools[index].underlyingCollateralToken;
41
const underlyingTokenBalance = call.output;
42
sdk.util.sumSingleBalance(balances, underlyingToken, underlyingTokenBalance);
43
})
44
return balances
45
}
46
47
48
module.exports = {
49
ethereum:{
50
tvl,
51
},
52
tvl
53
}
Copied!
What we are doing here is getting all their pools from their subgraph, then making an Ethereum call to each of them to get how many tokens are locked in each and then just returning each of these tokens along with the balances we got.
On top of all this, it's also important to notice that all calls are done through an SDK, this allows our adapters to be compatible with DeFi Pulse's and makes it so you only have to write them once and can submit them to multiple pages.

SDK Reference

Check it out here.

Examples

Check the following page for several examples of adapters along with input/outputs:

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/pooltogether/index.js
Copied!

Submit 🎉

Just submit a PR to the adapter repository on Github!
Last modified 2mo ago