Skip to content

Commit 2bfa156

Browse files
authored
Merge pull request #2138 from Singularity-DAO/master
singularity-finance: use new vault registry and batch calls
2 parents 6fefa0c + f705911 commit 2bfa156

File tree

1 file changed

+124
-16
lines changed
  • src/adaptors/singularity-finance

1 file changed

+124
-16
lines changed

src/adaptors/singularity-finance/index.js

Lines changed: 124 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,141 @@
1+
const axios = require('axios');
12
const sdk = require('@defillama/sdk');
23
const utils = require('../utils');
34

4-
const baseChainId = 8453;
5-
const baseVaultRegistry = "0x414F0e07cd833cE73c9d59280699f910b48E1ECb";
5+
const baseVaultRegistry = "0xe260c97949bB01E49c0af64a3525458197851657";
6+
const USDC = { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6, symbol: "USDC" };
67

78
async function getApy() {
8-
const dynaVaults = (await sdk.api.abi.call({
9-
abi: 'function allVaults() view returns (tuple(address vault, uint8 VaultType, bool active)[] memory)',
9+
const numberOfVaults = (await sdk.api.abi.call({
10+
abi: 'function nrOfVaults() view returns (uint256)',
1011
target: baseVaultRegistry,
1112
chain: "base"
1213
})).output;
1314

15+
const batchSize = 100;
1416

15-
return await Promise.all(dynaVaults.map(async (vault) => {
16-
const vaultInfo = await utils.getERC4626Info(vault.vault, "base");
17-
const { tvl, apyBase, ...rest } = vaultInfo;
17+
let results = [];
1818

19-
return {
20-
pool: vault.vault,
19+
for (let i = 0; i < numberOfVaults; i += batchSize) {
20+
const dynaVaults = (await sdk.api.abi.call({
21+
abi: 'function getVaults(uint256 offset, uint256 size) view returns (tuple(address vault, uint8 vaultType, bool active)[] memory)',
22+
target: baseVaultRegistry,
2123
chain: "base",
22-
project: 'singularity-finance',
23-
symbol: utils.formatSymbol("USDC"),
24-
tvlUsd: tvl / 1e6,
25-
apyBase,
26-
url: `https://singularityfinance.ai/vaults/${vault.vault}`,
27-
};
28-
}));
24+
params: [
25+
BigInt(i),
26+
BigInt(batchSize),
27+
],
28+
})).output;
29+
30+
// vault type: 3 = beta, 4 = production
31+
const activeVaultsInProdOrBeta = dynaVaults.filter(vault => vault.active && (vault.vaultType == 3 || vault.vaultType == 4));
32+
const vaultInfos = await multiGetERC4626Infos(activeVaultsInProdOrBeta.map(vault => vault.vault), "base");
33+
34+
const subResults = await Promise.all(activeVaultsInProdOrBeta.map(async (vault, index) => {
35+
const referenceAssetAddress = (await sdk.api.abi.call({
36+
abi: 'function referenceAsset() view returns (address)',
37+
target: vault.vault,
38+
chain: "base",
39+
})).output;
40+
41+
const referenceAssetSymbol = (await sdk.api.abi.call({
42+
abi: 'function symbol() view returns (string)',
43+
target: referenceAssetAddress,
44+
chain: "base",
45+
})).output;
46+
47+
const { tvl, apyBase, ...rest } = vaultInfos[index];
48+
49+
const tvlUsd = referenceAssetAddress == USDC.address ? tvl : (await sdk.api.abi.call({
50+
abi: 'function tokenValueInQuoteAsset(address base, uint256 amount, address quote) view returns (uint256 value)',
51+
target: vault.vault,
52+
chain: "base",
53+
params: [
54+
referenceAssetAddress,
55+
tvl,
56+
USDC.address,
57+
],
58+
})).output;
59+
60+
return {
61+
pool: vault.vault,
62+
chain: "base",
63+
project: 'singularity-finance',
64+
symbol: utils.formatSymbol(referenceAssetSymbol),
65+
tvlUsd: tvlUsd / 10 ** USDC.decimals,
66+
apyBase,
67+
url: `https://singularityfinance.ai/vaults/${vault.vault}:8453`,
68+
};
69+
}));
70+
71+
if (subResults != []) results.push(...subResults);
72+
}
73+
74+
return results;
2975
}
3076

77+
// multicall version of getERC4625Info found in utils
78+
async function multiGetERC4626Infos(
79+
addresses,
80+
chain,
81+
timestamp = Math.floor(Date.now() / 1e3),
82+
{
83+
assetUnit = '100000000000000000',
84+
totalAssetsAbi = 'uint:totalAssets',
85+
convertToAssetsAbi = 'function convertToAssets(uint256 shares) external view returns (uint256)',
86+
} = {}
87+
) {
88+
const DAY = 24 * 3600;
89+
90+
const [blockNow, blockYesterday] = await Promise.all(
91+
[timestamp, timestamp - DAY].map((time) =>
92+
axios
93+
.get(`https://coins.llama.fi/block/${chain}/${time}`)
94+
.then((r) => r.data.height)
95+
)
96+
);
97+
98+
const allTotalAssets = (await sdk.api.abi.multiCall({
99+
calls: addresses.map(a => ({
100+
target: a,
101+
})),
102+
block: blockNow,
103+
abi: totalAssetsAbi,
104+
chain
105+
})).output.map(result => result.output);
106+
107+
const allPriceNow = (await sdk.api.abi.multiCall({
108+
calls: addresses.map(a => ({
109+
target: a,
110+
params: [assetUnit],
111+
})),
112+
block: blockNow,
113+
abi: convertToAssetsAbi,
114+
chain
115+
})).output.map(result => result.output);
116+
117+
const allPriceYesterday = (await sdk.api.abi.multiCall({
118+
calls: addresses.map(a => ({
119+
target: a,
120+
params: [assetUnit],
121+
})),
122+
block: blockYesterday,
123+
abi: convertToAssetsAbi,
124+
chain
125+
})).output.map(result => result.output);
126+
127+
const apy = (priceNow, priceYesterday) => (priceNow / priceYesterday) ** 365 * 100 - 100;
128+
129+
return await Promise.all(
130+
addresses.map((address, index) => ({
131+
pool: address,
132+
chain,
133+
tvl: allTotalAssets[index],
134+
apyBase: apy(allPriceNow[index], allPriceYesterday[index]),
135+
}))
136+
);
137+
};
138+
31139
module.exports = {
32140
timetravel: false,
33141
apy: getApy,

0 commit comments

Comments
 (0)