DeFi Aggregator

Happy to announce our 100% on-chain DeFi Aggregator is now working alpha and stable after one month of extensive testing and debugging.
It serves all the information needed for a site like <icpcoins.com> including all charts (Notice: icpcoins is using the old web2.0 version currently). It also allows for a bit more than that. Treasury/time charts; Unlocking/time maps; Marketdepth/time maps; Supply/Time; Real circulating supply (without locked tokens) & Industry standard circulating supply.

Potential usage: Stats sites / Dashboards. DeFi contracts. Wallets - Currently all wallets are not displaying the USD value of your tokens (but have placeholders for it).

This aggregator is the only canister (that we are aware of) that currently has a liquidity-weighted average price collected from DEXes and all the other important information related to tokens.

All data is stored in ticks and easily queriable

The canister currently makes 2,815,200 inter-canister calls/ per month to collect everything from hundreds of canisters and you can get what you need with one call, potentially saving your apps tens of thousands of $ in development and IC fees. Additionally, without the DeFi Aggregator for many of the valuable attributes, while you can query the latest data, you cannot retrieve and chart the data from a month ago.

Example visualization coming from a single call get_latest

Example chart:

BTC/USD, ETH/USD, ICP/USD, ICP/XDR get refreshed every minute and come from the Exchange Rate Canister (XRC).

One way to go is to make it self-sustainable with fees (paid by other projects). If you have a wallet or a dapp that wants to use this data DM us. This way we can figure out what the demand is and calculate the fees these apps will have to pay to keep this running.
There are many other options, including SNS. Please let us know how you think it should be set.

23 Likes

API playground
https://jglts-daaaa-aaaai-qnpma-cai.ic0.app/120.635594b676b05184946afc8b2718c3bea243edfd038ebf112ca93fe6

Fees: To be decided

Notes:

Oracle external ICP/USD ETH/USD BTC/USD, market caps, and volume are pushed from outside. These values stay in their tracks and are not used unless XRC fetching the same stops working for more than 4 hours. They are refreshed every 5 seconds and someone can use them if they want faster updates. XRC prices are updated once per minute.

Sonic volume not included - no on-chain API for it. Sonic also doesn’t seem to record its pool prices and provide API for it, on or off-chain. There is only the current price available.

ICDex reports volume in tokens and not USD, which changes price. Then it becomes hard to tell what is the actual volume. When keeping track of volume by adding the transaction value not in tokens but in a stable currency like USD - it is more accurate. Example: Trades happen all day at a price of 2.3 (for a total of 30k USD) and at the end of the day the price goes to 4.6 (10k USD). If you convert volume 24 with the current token price, you will get a total volume (70k USD) - almost double what it really is. It will also be halved if the price goes down. Our API can record the total volume and use that to fix the issue, but it’s still good to have volume in USD.

ICPSwap We are currently ****using TVL to determine liquidity (depth -50%). The other way of doing it is complicated and may not even be possible without implementing a good portion of their dex algorithm. Some tokens aren’t tagged to count towards TVL, probably to discourage users from trying to cheat the reward system by filling it with custom coins without value. However, XTC and Ghost don’t count towards it too at the time of writing. Making the stat we are providing not very accurate. We have contacted them and asked for a multi_quote function, which could be used to amend that.

Conclusion: We will need to create a standard for fetching information from DEXes that will work for both order book and AMM DEXes and also for both single and multiple tokens inside one canister. This will ensure the stability of systems relying on such information. The functions we currently use are most likely made to serve the developer’s web apps. We will also need another standard for getting locked & unlocking(optional) tokens from non-SNS contracts.

5 Likes

This looks really cool and going forward is something we could probably make use of in our project.

I’m wondering, what potential use cases do you foresee for this, outside of maybe charts and stats?

Is one of the primary advantages of this, its ability to aggregate Internet Computer tokens? Since data for both ICP and Bitcoin is widely accessible via various Web2 APIs, would this mostly be beneficial for projects that aim to display statistics for native ICP coins?

1 Like

Wallets, DeFi contracts (once it becomes bulletproof).

Yes, the primary advantage is that you have the data on-chain usable by other canisters and that you have coins from IC ledgers.
There is a benefit even for off-chain scripts. You can’t trust a single web2.0 API, so you would have to fetch a lot of them to make sure your data is correct. If you don’t want to write all that and maintain it (inside or outside a browser) - Your prices coming from IC are signed and come from multiple sources, so all you have to do is one call (after verifying contracts work as intended)

BTW. On second thought the circulating supply currently excludes locked tokens circulating = total - total_locked - treasury, but they aren’t really locked (a canister can own SNS neurons and sell them locked). Having that number is valuable, but we should probably use circulating = total - treasury to calculate the market cap, which is how icpcoins works right now.

3 Likes

Thanks for your replies.

Do you have plans to open-source the code (I can’t find it).

1 Like

Thanks for this. I have already started using it in my project, and I have an inquiry. when using the get_pairs function to get the price history for the tokens, the base of most of the sns tokens is ICP but I would want the base to be USD, is there a way I can twist the data to achieve this? I need some guidance.

2 Likes

The pairs are just rates between two tokens.
You can take the rate ICP/USD from one of the pairs and ICP/SNS1 from another. Then you can use these two to get SNS1/USD or SNS1/BTC for every tick.

One of the backend functions does this for the last tick, but not for get_pairs. That will be computationally expensive. I am doing these calculations inside the client/ frontend.

1 Like

Thanks for the confirmation. I had thought of doing it that way but I wanted to see if it was already implemented so as I don’t repeat the same thing.

1 Like

Latest DeFi aggregator playground script:
https://jglts-daaaa-aaaai-qnpma-cai.ic0.app/598.bdfed151fd302377e032f8fc5a17acd1b356760781d18815478af582

Other projects integrating it will get the latest info for all listed tokens with one query call
u45jl-liaaa-aaaam-abppa-cai . get_latest_extended

1 Like

I regret not discovering ICPCoin until now.
The dapp looks like it fits my needs perfectly, but as a developer I’m finding it a bit difficult to discover where the api documentation is.
Can ICPCoin provide me with an api for the historical prices of tokens other than ICP?
It doesn’t need to be very precise, just specific to each day, and preferably free to call.

2 Likes

It is pretty simple and that is why the link above was sufficient for now. It is something like interactive documentation and everything you need is there.

https://jglts-daaaa-aaaai-qnpma-cai.ic0.app/598.bdfed151fd302377e032f8fc5a17acd1b356760781d18815478af582

let config = await can.get_config()
let data = await can.get_pairs({ t1d: null }, [2,3,4], (Date.now()/1000 - 60*60*24*365) * 1000000000, (Date.now()/1000) * 1000000000);

To get daily pair data for 365 days. If you want to get the price of token QWE in USD. You need to calculate it using QWE/ICP pair and ICP/USD pair.

1 Like

Blast is truly a wonderful site and I’ve grown to feel the benefits of it.
But I don’t quite understand what the parameters and return values of the get_pairs method represent.
I’ve only figured out that the first parameter represents the enum, I don’t quite understand the second parameter, and I probably understand that the third and fourth parameters represent intervals of time.
And the return value is totally confusing

It’s made like this to be compact when transferred & stored. Also doesn’t have any transformations happening in the backend - costs less instructions and very fast.

// Periods available: t5m - 5min, t1h - 1 hour, t1d. - 1 day 

// Result format:
// first array index = tick
// timestamp = first + tick * 5 min
// second array index = pair id
// (High, Low, LastBid, LastAsk, Volume24, DepthBid, DepthAsk)
// Depth array - 1% 2% 4% 8% 15% 25% 50% 100%

// Volume24 is in USD. DepthBid values are in token0. DepthAsk values are in token1
// Price = (LastBid + LastAsk) / 2   // You should use that or just LastBid


207 is the tick. We have asked it to return t1d - daily ticks. 207th day after the start timestamp
4 is the pair id. Look for config.pairs[4]. There you have config.pairs[4].tokens and you can find out the pair symbols by taking it from config.tokens[ x ].symbol
0 - highest bid
1 - lowest ask
2 - last bid
3 - last ask
4 - volume24
5,6 are bid depth and ask depth, but they aren’t present in t1d only in t1h.

Both icpcoins and the defi aggregator are open-source and you can check how things work there too.

1 Like

I have a general understanding of the return value, but after multiple attempts with Blast, I have discovered some issues:
In theory, the second parameter refers to the index number corresponding to the token in “get_config()”.
But why is it that when the second parameter is [], the first index value in the return value is 2400, the second is 13.5, and the third is 45000.
From my understanding, these three are eth, icp, and btc, but in the token list, they should be USD, btc, eth, and icp in the correct order.
Is this due to the inconsistent order of synchronization and asynchrony?

Can you make a screenshot of the data you are referring to




In my opinion, when the parameter is set to [2,3,4], the return value should correspond to BTC, ETH, ICP. Is this understanding correct?
But in fact, it seems to be different from what I understand

According to the test, the above error is due to my previous understanding deviation. It should be based on the number in pairs[x].tokens in the “get_config()” method, which corresponds to the tokens of this method, to convert the corresponding token pairs.
It has to be said that this is really a quite brain wracking construction. Is there any convenient JS method that can be converted?
And I also want to know, what parameters should I input if I want to obtain the daily price change of a certain token pair from start to end?

Anyway, the data collected by ICPCoin is indeed very helpful

Yes. These are pairs not tokens. They correspond to config.pairs[ idx ]
We have extracted the js redux state management from the dapp and our plan is to put it inside an npm library.

When you think about it, there isn’t a simpler way to store and transmit the data. A token doesn’t only have USD prices, it has many pairs against many other tokens. We could put some easy to use functions inside the backend (like get_latest_extended), but the service queries are free now, so they better be fast and not cost a lot of instructions.

It could be done in many ways. Perhaps get the t1d ticks. Use last price = (last bid + last ask)/2 for each tick and calculate the change for each day

Perhaps my expression was incorrect.

I mean the daily prices for all times since the token was launched.