From f04207d2dd624aeb88f099e82069683095d0c32e Mon Sep 17 00:00:00 2001 From: Relly Date: Sun, 4 Aug 2024 14:15:35 +0800 Subject: [PATCH 1/3] blend-finance --- projects/blend-finance/index.js | 14 ++ projects/helper/abis/blend.json | 17 ++ projects/helper/blend.js | 299 ++++++++++++++++++++++++++++++++ projects/helper/coreAssets.json | 6 +- 4 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 projects/blend-finance/index.js create mode 100644 projects/helper/abis/blend.json create mode 100644 projects/helper/blend.js diff --git a/projects/blend-finance/index.js b/projects/blend-finance/index.js new file mode 100644 index 000000000000..c42f002325a4 --- /dev/null +++ b/projects/blend-finance/index.js @@ -0,0 +1,14 @@ + +const { aaveExports } = require('../helper/blend') +const methodologies = require('../helper/methodologies') +const { mergeExports } = require('../helper/utils') + +const mainMarket = { + bevm: aaveExports('bevm', '0x26fb0b1eef8822f8F71a385d2839b6a654cA186a', undefined, ['0x3Eb2Dd6c395B8E6E3ab843858480aC60e9D0f3Bc'], {v3: true}), +} + +const innovativeMarket = { +} + +module.exports = mergeExports(mainMarket, innovativeMarket) +module.exports.methodology = methodologies.lendingMarket diff --git a/projects/helper/abis/blend.json b/projects/helper/abis/blend.json new file mode 100644 index 000000000000..6eec23164f6c --- /dev/null +++ b/projects/helper/abis/blend.json @@ -0,0 +1,17 @@ +{ + "getTotalDebt": "function getTotalDebt(address asset) view returns (uint256)", + "getReservesList": "address[]:getReservesList", + "getAMMReserveData": "function getReserveData(address asset) view returns (tuple(tuple(uint256 data) configuration, uint128 liquidityIndex, uint128 variableBorrowIndex, uint128 currentLiquidityRate, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint8 id))", + "getCurrentTokens": "address[]:getCurrentTokens", + "getReserveData": "function getReserveData(address _reserve) view returns (uint256 totalLiquidity, uint256 availableLiquidity, uint256 totalBorrowsStable, uint256 totalBorrowsVariable, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 utilizationRate, uint256 liquidityIndex, uint256 variableBorrowIndex, address aTokenAddress, uint40 lastUpdateTimestamp)", + "getReserveConfigurationData": "function getReserveConfigurationData(address _reserve) view returns (uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, address interestRateStrategyAddress, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, bool isActive)", + "getReserves": "address[]:getReserves", + "getAddressesProvidersList": "address[]:getAddressesProvidersList", + "getAddress": "function getAddress(bytes32 id) view returns (address)", + "getAllBTokens": "function getAllBTokens() view returns (tuple(string symbol, address tokenAddress)[])", + "getUnderlying": "address:UNDERLYING_ASSET_ADDRESS", + "getReserveDataV2": "function getReserveData(address asset) view returns (uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp)", + "getBPool": "address:bPool", + "getHelperReserveData": "function getReserveData(address asset) view returns (uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp)", + "getReserveTotalBorrows": "function getReserveTotalBorrows(address _reserve) view returns (uint256)" +} \ No newline at end of file diff --git a/projects/helper/blend.js b/projects/helper/blend.js new file mode 100644 index 000000000000..0e78ebfb75fc --- /dev/null +++ b/projects/helper/blend.js @@ -0,0 +1,299 @@ +const { getLogs } = require('./cache/getLogs') +const ADDRESSES = require('./coreAssets.json') +const sdk = require('@defillama/sdk'); +const { default: BigNumber } = require('bignumber.js'); +const abi = require('./abis/blend.json'); +const { getChainTransform, getFixBalancesSync, } = require('../helper/portedTokens') +const { sumTokens2 } = require('../helper/unwrapLPs'); +const methodologies = require('./methodologies'); + +async function getV2Reserves(block, addressesProviderRegistry, chain, dataHelperAddress, abis = {}) { + let validProtocolDataHelpers + if (dataHelperAddress === undefined) { + const addressesProviders = ( + await sdk.api.abi.call({ + target: addressesProviderRegistry, + abi: abi["getAddressesProvidersList"], + block, + chain + }) + ).output; + + const protocolDataHelpers = ( + await sdk.api.abi.multiCall({ + calls: addressesProviders.map((provider) => ({ + target: provider, + params: "0x0100000000000000000000000000000000000000000000000000000000000000", + })), + abi: abi["getAddress"], + block, + chain + }) + ).output; + + validProtocolDataHelpers = protocolDataHelpers.filter( + (helper) => + helper.output !== ADDRESSES.null + ).map(p => p.output); + } else { + validProtocolDataHelpers = dataHelperAddress + } + + console.log({validProtocolDataHelpers}); + console.log({sdk}); + console.log({block}); + console.log({chain}); + + + const aTokenMarketData = ( + await sdk.api.abi.multiCall({ + calls: validProtocolDataHelpers.map((dataHelper) => ({ + target: dataHelper, + })), + abi: abis.getAllBTokens || abi["getAllBTokens"], + block, + chain + }) + ).output; + + let aTokenAddresses = []; + aTokenMarketData.map((aTokensData) => { + aTokenAddresses = [ + ...aTokenAddresses, + ...aTokensData.output.map((aToken) => aToken[1]), + ]; + }); + + const underlyingAddressesData = ( + await sdk.api.abi.multiCall({ + calls: aTokenAddresses.map((aToken) => ({ + target: aToken, + })), + abi: abi["getUnderlying"], + block, + chain + }) + ).output; + + const reserveAddresses = underlyingAddressesData.map((reserveData) => reserveData.output); + + return [aTokenAddresses, reserveAddresses, validProtocolDataHelpers[0]] +} + +async function getTvl(balances, block, chain, v2Atokens, v2ReserveTokens, transformAddress) { + const balanceOfUnderlying = await sdk.api.abi.multiCall({ + calls: v2Atokens.map((aToken, index) => ({ + target: v2ReserveTokens[index], + params: aToken, + })), + abi: "erc20:balanceOf", + block, + chain + }); + sdk.util.sumMultiBalanceOf(balances, balanceOfUnderlying, true, transformAddress) +} + +async function getBorrowed(balances, block, chain, v2ReserveTokens, dataHelper, transformAddress, v3 = false) { + const reserveData = await sdk.api.abi.multiCall({ + calls: v2ReserveTokens.map((token) => ({ + target: dataHelper, + params: [token], + })), + abi: v3 ? abi.getTotalDebt : abi.getHelperReserveData, + block, + chain + }); + + reserveData.output.forEach((data, idx) => { + const quantity = v3 ? data.output : BigNumber(data.output.totalVariableDebt).plus(data.output.totalStableDebt).toFixed(0) + sdk.util.sumSingleBalance(balances, transformAddress(data.input.params[0]), quantity) + }) +} + +function aaveChainTvl(_chain, addressesProviderRegistry, transformAddressRaw, dataHelperAddresses, borrowed, v3 = false, { abis = {}, oracle, blacklistedTokens = [], hasV2LPs = false, } = {}) { + return async (api) => { +console.log("api.chain",api.chain); + + + const chain = api.chain + const block = api.block + const balances = {} + console.log({oracle, chain, block, addressesProviderRegistry, dataHelperAddresses, transformAddressRaw, abis,}); + + const { transformAddress, fixBalances, v2Atokens, v2ReserveTokens, dataHelper, updateBalances } = await getData({ oracle, chain, block, addressesProviderRegistry, dataHelperAddresses, transformAddressRaw, abis, }) +console.log({balances, block, chain, v2Atokens, v2ReserveTokens, transformAddress}); + + if (borrowed) { + await getBorrowed(balances, block, chain, v2ReserveTokens, dataHelper, transformAddress, v3); + } else { + await getTvl(balances, block, chain, v2Atokens, v2ReserveTokens, transformAddress); + } + if (updateBalances) updateBalances(balances) + fixBalances(balances) + Object.keys(balances).forEach((key) => { + if (!blacklistedTokens.length) return; + if (blacklistedTokens.some(i => new RegExp(i, 'gi').test(key))) { + delete balances[key] + } + }) + if (hasV2LPs) await sumTokens2({ block, resolveLP: true, balances, chain, }) + return balances + } +} +function aaveExports(_chain, addressesProviderRegistry, transform = undefined, dataHelpers = undefined, { oracle, abis, v3 = false, blacklistedTokens = [], hasV2LPs = false, } = {}) { + return { + tvl: aaveChainTvl(_chain, addressesProviderRegistry, transform, dataHelpers, false, v3, { oracle, abis, blacklistedTokens, hasV2LPs, }), + borrowed: aaveChainTvl(_chain, addressesProviderRegistry, transform, dataHelpers, true, v3, { oracle, abis, hasV2LPs, blacklistedTokens, }) + } +} + +module.exports = { + methodology: methodologies.lendingMarket, + aaveChainTvl, + getV2Reserves, + getTvl, + aaveExports, + getBorrowed, + aaveV2Export, +} + +const cachedData = {} + +async function getData({ oracle, chain, block, addressesProviderRegistry, dataHelperAddresses, transformAddressRaw, abis, }) { + let dataHelperAddressesStr + if (dataHelperAddresses && dataHelperAddresses.length) dataHelperAddressesStr = dataHelperAddresses.join(',') + const key = `${chain}-${block}-${addressesProviderRegistry}-${dataHelperAddresses}-${oracle}` + console.log({key}); + + if (!cachedData[key]) cachedData[key] = _getData() + + return cachedData[key] + + async function _getData() { + sdk.log('get aava metadata:', key) + + const transformAddress = transformAddressRaw || await getChainTransform(chain) + const fixBalances = await getFixBalancesSync(chain) + const [v2Atokens, v2ReserveTokens, dataHelper] = await getV2Reserves(block, addressesProviderRegistry, chain, dataHelperAddresses, abis) + let updateBalances + + if (oracle) { + const params = { chain, block, target: oracle, } + const [ + baseCurrency, baseCurrencyUnit, prices, + ] = await Promise.all([ + sdk.api2.abi.call({ ...params, abi: oracleAbis.BASE_CURRENCY, }), + sdk.api2.abi.call({ ...params, abi: oracleAbis.BASE_CURRENCY_UNIT, }), + sdk.api2.abi.call({ ...params, abi: oracleAbis.getAssetsPrices, params: [v2ReserveTokens], }), + ]) + + const baseToken = transformAddress(baseCurrency) + updateBalances = balances => { + v2ReserveTokens.map(i => `${chain}:${i.toLowerCase()}`).forEach((token, i) => { + if (!balances[token]) return; + const balance = balances[token] * prices[i] / baseCurrencyUnit + delete balances[token] + sdk.util.sumSingleBalance(balances, baseToken, balance) + }) + return balances + } + } + + return { transformAddress, fixBalances, v2Atokens, v2ReserveTokens, dataHelper, updateBalances, } + } +} + +const oracleAbis = { + BASE_CURRENCY: "address:BASE_CURRENCY", + BASE_CURRENCY_UNIT: "uint256:BASE_CURRENCY_UNIT", + getAssetsPrices: "function getAssetsPrices(address[] assets) view returns (uint256[])", +} + +function aaveV2Export(registry, { useOracle = false, baseCurrency, baseCurrencyUnit, abis = {}, fromBlock, blacklistedTokens = [] } = {}) { + + async function tvl(api) { + const data = await getReservesData(api) + const tokensAndOwners = data.map(i => ([i.underlying, i.aTokenAddress])) + if (!useOracle) + return sumTokens2({ tokensAndOwners, api, blacklistedTokens }) + const balances = {} + const res = await api.multiCall({ abi: 'erc20:balanceOf', calls: tokensAndOwners.map(i => ({ target: i[0], params: i[1] })) }) + res.forEach((v, i) => { + sdk.util.sumSingleBalance(balances, data[i].currency, v * data[i].price, api.chain) + }) + return balances + } + + async function borrowed(api) { + const balances = {} + const data = await getReservesData(api) + const supplyVariable = await api.multiCall({ + abi: 'erc20:totalSupply', + calls: data.map(i => i.variableDebtTokenAddress), + }) + const supplyStable = await api.multiCall({ + abi: 'erc20:totalSupply', + calls: data.map(i => i.stableDebtTokenAddress), + }) + data.forEach((i, idx) => { + let value = +supplyVariable[idx] + +supplyStable[idx] + if (useOracle) { + sdk.util.sumSingleBalance(balances, i.currency, value * i.price, api.chain) + } else { + sdk.util.sumSingleBalance(balances, i.underlying, value, api.chain) + } + }) + return balances + } + + async function getReservesData(api) { + if (fromBlock) return getReservesDataFromBlock(api) + const tokens = await api.call({ abi: abiv2.getReservesList, target: registry }) + const data = await api.multiCall({ abi: abis.getReserveData ?? abiv2.getReserveData, calls: tokens, target: registry, }) + data.forEach((v, i) => v.underlying = tokens[i]) + if (useOracle) { + let currency = baseCurrency + let unit = baseCurrencyUnit + + const addressProvider = await api.call({ abi: abiv2.getAddressesProvider, target: registry }) + const oracle = await api.call({ abi: abiv2.getPriceOracle, target: addressProvider }) + + if (!currency) currency = await api.call({ abi: abiv2.BASE_CURRENCY, target: oracle }) + if (!unit) unit = await api.call({ abi: abiv2.BASE_CURRENCY_UNIT, target: oracle }) + + const decimals = await api.multiCall({ abi: 'erc20:decimals', calls: tokens }) + // const currencyDecimal = await api.call({ abi: 'erc20:decimals', target: currency }) + const currencyDecimal = 18 + const prices = await api.call({ abi: abiv2.getAssetsPrices, target: oracle, params: [tokens] }) + prices.forEach((v, i) => { + data[i].price = (v / unit )/ (10 ** (decimals[i] - currencyDecimal)) + data[i].currency = currency + }) + } + return data + } + + async function getReservesDataFromBlock(api) { + const logs = await getLogs({ + api, + target: registry, + topics: ['0x3a0ca721fc364424566385a1aa271ed508cc2c0949c2272575fb3013a163a45f'], + fromBlock, + eventAbi: 'event ReserveInitialized (address indexed underlying, address indexed aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress)', + onlyArgs: true, + }) + return logs + } + + const abiv2 = { + getReservesList: "address[]:getReservesList", + getAddressesProvider: "address:getAddressesProvider", + BASE_CURRENCY: "address:BASE_CURRENCY", + BASE_CURRENCY_UNIT: "uint256:BASE_CURRENCY_UNIT", + getPriceOracle: "address:getPriceOracle", + getAssetsPrices: "function getAssetsPrices(address[]) view returns (uint256[])", + getReserveData: "function getReserveData(address asset) view returns (tuple(tuple(uint256 data) configuration, uint128 liquidityIndex, uint128 variableBorrowIndex, uint128 currentLiquidityRate, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint8 id))", + } + + return { tvl, borrowed, } +} \ No newline at end of file diff --git a/projects/helper/coreAssets.json b/projects/helper/coreAssets.json index 9fd47702a747..5ddb33fd161c 100644 --- a/projects/helper/coreAssets.json +++ b/projects/helper/coreAssets.json @@ -1730,7 +1730,11 @@ "WETH": "0x7526B5318Cbe690FBd3eC8DD7ad122f4F1b1d76F" }, "bevm": { - "WBTC": "0xB5136FEba197f5fF4B765E5b50c74db717796dcD" + "WBTC": "0xB5136FEba197f5fF4B765E5b50c74db717796dcD", + "SAT": "0xF2692468666E459D87052f68aE474E36C1a34fbB", + "USDT": "0xa67ed736649f2958a35fd249a584151056b4b745", + "USDC": "0x915247bf09471922e2c6da6f69fc9114708e8a26", + "ETH": "0x948def74953a18ebd854a5b015f63b0910be58cc" }, "degen": { "WDEGEN": "0xeb54dacb4c2ccb64f8074eceea33b5ebb38e5387" From 47741d4966e106c3f6272367bf519ccd84922cc0 Mon Sep 17 00:00:00 2001 From: g1nt0ki <99907941+g1nt0ki@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:47:11 +0200 Subject: [PATCH 2/3] minor fix --- projects/predx/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 projects/predx/index.js diff --git a/projects/predx/index.js b/projects/predx/index.js new file mode 100644 index 000000000000..4c6a0bd0d173 --- /dev/null +++ b/projects/predx/index.js @@ -0,0 +1,10 @@ +const { sumTokensExport } = require('../helper/unwrapLPs') + +module.exports = { + zklink: { + tvl: sumTokensExport({ + owners: ["0x986Ca3A4F05AA7EA5733d81Da6649043f43cB9A8"], + tokens: ["0x2F8A25ac62179B31D62D7F80884AE57464699059"] + }), + }, +} \ No newline at end of file From 4719bd6a0a9d6c9bd45b0863df2919ef21ee5ab4 Mon Sep 17 00:00:00 2001 From: relly Date: Wed, 7 Aug 2024 23:37:56 +0800 Subject: [PATCH 3/3] moveflow --- projects/moveflow/index.js | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 projects/moveflow/index.js diff --git a/projects/moveflow/index.js b/projects/moveflow/index.js new file mode 100644 index 000000000000..135aff5de25d --- /dev/null +++ b/projects/moveflow/index.js @@ -0,0 +1,46 @@ +const ADDRESSES = require('../helper/coreAssets.json') +const sdk = require("@defillama/sdk"); +const { staking } = require("../helper/staking"); +const { sumTokensAndLPsSharedOwners } = require("../helper/unwrapLPs"); +const { request, gql } = require("graphql-request"); +const { getBlock } = require('../helper/http') +const { transformBalances } = require("../helper/portedTokens"); + +const graphUrl = 'https://main-api.flow.movefuns.xyz/' +const graphQuery = gql` +query ExampleQuery { + tvl { + coin_type + lock_amount + } +}` +async function getTokenAmount() { + const data = await request( + graphUrl, + graphQuery, + {}, + { + "x-auth-info":"123" + } + ); + console.log("data.tvl",data.tvl); + return data.tvl +} + +async function aptosTvl(api) { + const coinContainers = await getTokenAmount(); + + coinContainers.map((item)=>{ + api.add(item.coin_type, parseInt(item.lock_amount)); + }) +} + + + + +module.exports = { + aptos: { + tvl: aptosTvl, + }, + +};