From 9bcdd7e1cb7f77b03c2a70727891c5c72b4deb82 Mon Sep 17 00:00:00 2001 From: 0xweb3loop Date: Mon, 19 Aug 2024 22:05:44 +0900 Subject: [PATCH 1/3] feat: Adapter, double2win.xyz --- projects/double2win/config.js | 29 +++++++++ projects/double2win/index.js | 119 ++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 projects/double2win/config.js create mode 100644 projects/double2win/index.js diff --git a/projects/double2win/config.js b/projects/double2win/config.js new file mode 100644 index 000000000000..b4acfe13e1ea --- /dev/null +++ b/projects/double2win/config.js @@ -0,0 +1,29 @@ +module.exports = { + arbitrum: { + uniswapV2Vault: { + doubleContract: '0xBf212dEE0aea6531dEb0B02be6E70b527dDF8246', + fromBlock: 217487403, + type: 'v2-vault' + }, + uniswapV2Migration: { + doubleContract: '0x1c6E7CE03ae7a9A252BcE0C9F871654dBB0C7ca5', + fromBlock: 217487754, + type: 'v2-lp' + }, + uniswapV3Vault: { + doubleContract: '0x07116C5ED5cBb49464f64926Ba152B8985fe3AFf', + fromBlock: 217488144, + type: 'v3-vault' + }, + uniswapV3Migration: { + doubleContract: '0x99F980fa0b1939A0A1033092EF2a668df8D8b70D', + fromBlock: 217488619, + type: 'v3-lp' + }, + assetVault: { + doubleContract: '0x7C09A9c30736F17043Fe6D0C0A3D03a7Cf6e78FD', + fromBlock: 217484114, + type: 'asset-vault' + }, + } +}; diff --git a/projects/double2win/index.js b/projects/double2win/index.js new file mode 100644 index 000000000000..4d9806bfb4bf --- /dev/null +++ b/projects/double2win/index.js @@ -0,0 +1,119 @@ +const config = require("./config"); +const { sumTokens2 } = require('../helper/unwrapLPs') +const { cachedGraphQuery } = require('../helper/cache'); +const { getTokenPrices } = require('../helper/unknownTokens'); +const { stripTokenHeader } = require('../helper/utils'); +const sdk = require('@defillama/sdk'); +const { getChainTransform, getFixBalances } = require("../helper/portedTokens"); +const { default: BigNumber } = require("bignumber.js"); + +const subgraphs = { + "arbitrum": "https://api.studio.thegraph.com/query/16975/double-arbitrum/version/latest", +} + +async function getTokens(chain) { + const graphQuery = ` + { + assetTokens(where: {amount_gt: "0"}) { + tokenAddress + } + migrations(where: {pair_starts_with: "0x", lpAmount_gt: "0"}) { + pair + ammType + } + liquidities(where: {pair_starts_with: "0x", lpAmount_gt: "0"}) { + pair + ammType + } + } + `; + + const { assetTokens, migrations, liquidities } = await cachedGraphQuery(`double2win/${chain}`, subgraphs[chain], graphQuery); + + return { assetTokens, migrations, liquidities }; +} + +module.exports = {} + +Object.keys(config).forEach((network) => { + const networkConfig = config[network]; + + module.exports[network] = { + tvl: async (api) => { + // Initialize an empty map to store TVL per token + const block = api.block; + const tokenBalances = {}; + const tokenData = await getTokens(network); + const pairAddresses = []; + tokenData.migrations.forEach(migration => { + pairAddresses.push(migration.pair.toLowerCase()); + }); + tokenData.liquidities.forEach(liquidity => { + pairAddresses.push(liquidity.pair.toLowerCase()); + }); + const assetAddresses = []; + tokenData.assetTokens.forEach(assetToken => { + assetAddresses.push(assetToken.tokenAddress.toLowerCase()); + }); + // Iterate over each contract type within the network + await Promise.all( + Object.keys(networkConfig).map(async (contractType) => { + const tokensAndOwners = []; + const { doubleContract, fromBlock, type } = networkConfig[contractType]; + if (type.startsWith("v3")) { + await sumTokens2({ api, balances: tokenBalances, owner: doubleContract, resolveUniV3: true, chain: network, sumChunkSize: 50 }) + } else { + if (type.startsWith("v2")) { + pairAddresses.forEach(pairAddress => { + tokensAndOwners.push([pairAddress, doubleContract]); + }); + await sumTokens2({ api, balances: tokenBalances, tokensAndOwners: tokensAndOwners, chain: network, resolveLP: true, sumChunkSize: 50}) + } else { + assetAddresses.forEach(asset => { + tokensAndOwners.push([asset, doubleContract]); + }); + await sumTokens2({ api, balances: tokenBalances, tokensAndOwners: tokensAndOwners, chain: network, sumChunkSize: 50}) + } + } + }) + ); + const balances = Object.fromEntries( + Object.entries(tokenBalances).filter(([_, value]) => !Number.isNaN(value)) + ); + const lpAddresses = []; + const finalBalances = balances; + transformAddress = await getChainTransform(network); + const { pairBalances, prices} = await getTokenPrices({ chain: network, block, lps: ["0x27D336a834775988b1305df42569E27128932bDD"], useDefaultCoreAssets: true}) + Object.entries(balances).forEach(([address, amount = 0]) => { + const token = stripTokenHeader(address) + const price = prices[token]; + if (pairBalances[token]) { + lpAddresses.push(token) + return; + } + if (!price) return; + let tokenAmount = price[1] * +amount + const coreAsset = price[2] + sdk.util.sumSingleBalance(balances, transformAddress(coreAsset), BigNumber(tokenAmount).toFixed(0)) + delete balances[address] + }) + + if (lpAddresses.length) { + const totalBalances = (await sdk.api.abi.multiCall({ + abi: 'erc20:totalSupply', calls: lpAddresses.map(i => ({ target: i })), block, chain + })).output + + totalBalances.forEach((item) => { + const token = item.input.target + const address = transformAddress(token) + const ratio = +item.output > 0 ? (+(balances[address]) || 0) / +item.output : 0 + addBalances(pairBalances[token], finalBalances, { ratio, pairAddress: token, }) + delete balances[address] + }) + } + const fixBalances = await getFixBalances(network) + fixBalances(finalBalances) + return finalBalances + }, + }; +}); From 083abf09ea7cc5f8809485b1a125206922947cdb Mon Sep 17 00:00:00 2001 From: 0xweb3loop Date: Mon, 19 Aug 2024 22:26:12 +0900 Subject: [PATCH 2/3] fix: eslint issue --- projects/double2win/index.js | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/projects/double2win/index.js b/projects/double2win/index.js index 4d9806bfb4bf..52f932ed4b91 100644 --- a/projects/double2win/index.js +++ b/projects/double2win/index.js @@ -80,37 +80,18 @@ Object.keys(config).forEach((network) => { const balances = Object.fromEntries( Object.entries(tokenBalances).filter(([_, value]) => !Number.isNaN(value)) ); - const lpAddresses = []; const finalBalances = balances; - transformAddress = await getChainTransform(network); - const { pairBalances, prices} = await getTokenPrices({ chain: network, block, lps: ["0x27D336a834775988b1305df42569E27128932bDD"], useDefaultCoreAssets: true}) + const transformAddress = await getChainTransform(network); + const { prices} = await getTokenPrices({ chain: network, block, lps: ["0x27D336a834775988b1305df42569E27128932bDD"], useDefaultCoreAssets: true}) Object.entries(balances).forEach(([address, amount = 0]) => { const token = stripTokenHeader(address) const price = prices[token]; - if (pairBalances[token]) { - lpAddresses.push(token) - return; - } if (!price) return; let tokenAmount = price[1] * +amount const coreAsset = price[2] sdk.util.sumSingleBalance(balances, transformAddress(coreAsset), BigNumber(tokenAmount).toFixed(0)) delete balances[address] }) - - if (lpAddresses.length) { - const totalBalances = (await sdk.api.abi.multiCall({ - abi: 'erc20:totalSupply', calls: lpAddresses.map(i => ({ target: i })), block, chain - })).output - - totalBalances.forEach((item) => { - const token = item.input.target - const address = transformAddress(token) - const ratio = +item.output > 0 ? (+(balances[address]) || 0) / +item.output : 0 - addBalances(pairBalances[token], finalBalances, { ratio, pairAddress: token, }) - delete balances[address] - }) - } const fixBalances = await getFixBalances(network) fixBalances(finalBalances) return finalBalances From 1a6598df41af6979d45476dc26509b550af9ecac Mon Sep 17 00:00:00 2001 From: g1nt0ki <99907941+g1nt0ki@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:38:15 +0200 Subject: [PATCH 3/3] code refactor --- projects/double2win/config.js | 9 +-- projects/double2win/index.js | 105 +++++++++++----------------------- 2 files changed, 36 insertions(+), 78 deletions(-) diff --git a/projects/double2win/config.js b/projects/double2win/config.js index b4acfe13e1ea..262c97895652 100644 --- a/projects/double2win/config.js +++ b/projects/double2win/config.js @@ -2,27 +2,22 @@ module.exports = { arbitrum: { uniswapV2Vault: { doubleContract: '0xBf212dEE0aea6531dEb0B02be6E70b527dDF8246', - fromBlock: 217487403, type: 'v2-vault' }, uniswapV2Migration: { doubleContract: '0x1c6E7CE03ae7a9A252BcE0C9F871654dBB0C7ca5', - fromBlock: 217487754, - type: 'v2-lp' + type: 'v2-vault' }, uniswapV3Vault: { doubleContract: '0x07116C5ED5cBb49464f64926Ba152B8985fe3AFf', - fromBlock: 217488144, type: 'v3-vault' }, uniswapV3Migration: { doubleContract: '0x99F980fa0b1939A0A1033092EF2a668df8D8b70D', - fromBlock: 217488619, - type: 'v3-lp' + type: 'v3-vault' }, assetVault: { doubleContract: '0x7C09A9c30736F17043Fe6D0C0A3D03a7Cf6e78FD', - fromBlock: 217484114, type: 'asset-vault' }, } diff --git a/projects/double2win/index.js b/projects/double2win/index.js index 52f932ed4b91..ebb95389caa0 100644 --- a/projects/double2win/index.js +++ b/projects/double2win/index.js @@ -1,11 +1,6 @@ -const config = require("./config"); +const config = require("./config") const { sumTokens2 } = require('../helper/unwrapLPs') -const { cachedGraphQuery } = require('../helper/cache'); -const { getTokenPrices } = require('../helper/unknownTokens'); -const { stripTokenHeader } = require('../helper/utils'); -const sdk = require('@defillama/sdk'); -const { getChainTransform, getFixBalances } = require("../helper/portedTokens"); -const { default: BigNumber } = require("bignumber.js"); +const { cachedGraphQuery } = require('../helper/cache') const subgraphs = { "arbitrum": "https://api.studio.thegraph.com/query/16975/double-arbitrum/version/latest", @@ -26,75 +21,43 @@ async function getTokens(chain) { ammType } } - `; + ` - const { assetTokens, migrations, liquidities } = await cachedGraphQuery(`double2win/${chain}`, subgraphs[chain], graphQuery); + const { assetTokens, migrations, liquidities } = await cachedGraphQuery(`double2win/${chain}`, subgraphs[chain], graphQuery) - return { assetTokens, migrations, liquidities }; + return { assets: assetTokens.map(i => i.tokenAddress), v2Tokens: migrations.concat(liquidities).filter(i => i.ammType === 'UniswapV2').map(i => i.pair) } } -module.exports = {} +module.exports = { + doublecounted: true, +} -Object.keys(config).forEach((network) => { - const networkConfig = config[network]; +Object.keys(config).forEach((chain) => { + const configs = Object.values(config[chain]) - module.exports[network] = { + module.exports[chain] = { tvl: async (api) => { - // Initialize an empty map to store TVL per token - const block = api.block; - const tokenBalances = {}; - const tokenData = await getTokens(network); - const pairAddresses = []; - tokenData.migrations.forEach(migration => { - pairAddresses.push(migration.pair.toLowerCase()); - }); - tokenData.liquidities.forEach(liquidity => { - pairAddresses.push(liquidity.pair.toLowerCase()); - }); - const assetAddresses = []; - tokenData.assetTokens.forEach(assetToken => { - assetAddresses.push(assetToken.tokenAddress.toLowerCase()); - }); - // Iterate over each contract type within the network - await Promise.all( - Object.keys(networkConfig).map(async (contractType) => { - const tokensAndOwners = []; - const { doubleContract, fromBlock, type } = networkConfig[contractType]; - if (type.startsWith("v3")) { - await sumTokens2({ api, balances: tokenBalances, owner: doubleContract, resolveUniV3: true, chain: network, sumChunkSize: 50 }) - } else { - if (type.startsWith("v2")) { - pairAddresses.forEach(pairAddress => { - tokensAndOwners.push([pairAddress, doubleContract]); - }); - await sumTokens2({ api, balances: tokenBalances, tokensAndOwners: tokensAndOwners, chain: network, resolveLP: true, sumChunkSize: 50}) - } else { - assetAddresses.forEach(asset => { - tokensAndOwners.push([asset, doubleContract]); - }); - await sumTokens2({ api, balances: tokenBalances, tokensAndOwners: tokensAndOwners, chain: network, sumChunkSize: 50}) - } - } - }) - ); - const balances = Object.fromEntries( - Object.entries(tokenBalances).filter(([_, value]) => !Number.isNaN(value)) - ); - const finalBalances = balances; - const transformAddress = await getChainTransform(network); - const { prices} = await getTokenPrices({ chain: network, block, lps: ["0x27D336a834775988b1305df42569E27128932bDD"], useDefaultCoreAssets: true}) - Object.entries(balances).forEach(([address, amount = 0]) => { - const token = stripTokenHeader(address) - const price = prices[token]; - if (!price) return; - let tokenAmount = price[1] * +amount - const coreAsset = price[2] - sdk.util.sumSingleBalance(balances, transformAddress(coreAsset), BigNumber(tokenAmount).toFixed(0)) - delete balances[address] + const v2Vaults = [] + const v3Vaults = [] + const assetVaults = [] + configs.forEach((config) => { + switch (config.type) { + case 'v2-vault': + v2Vaults.push(config.doubleContract) + break + case 'v3-vault': + v3Vaults.push(config.doubleContract) + break + case 'asset-vault': + assetVaults.push(config.doubleContract) + break + } }) - const fixBalances = await getFixBalances(network) - fixBalances(finalBalances) - return finalBalances - }, - }; -}); + const { assets, v2Tokens } = await getTokens(chain) + await sumTokens2({ resolveUniV3: true, api, owners: v3Vaults }) + await sumTokens2({ owners: assetVaults, tokens: assets, api }) + return sumTokens2({ owners: v2Vaults, tokens: v2Tokens, resolveLP: true, api }) + } + } + +})