From 9971cd2b703df45b9cd085bf54b6250f067f2b21 Mon Sep 17 00:00:00 2001 From: jovonni Date: Mon, 10 Jun 2024 13:54:01 -0400 Subject: [PATCH 1/8] =?UTF-8?q?prototype=20for=20defillama=20IST=20tvl=20c?= =?UTF-8?q?alculation=20v0.0.1=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- projects/helper/chains.json | 1 + projects/inter-protocol/README.md | 127 ++++++++++++++++++++++++++++++ projects/inter-protocol/index.js | 116 +++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 projects/inter-protocol/README.md create mode 100644 projects/inter-protocol/index.js diff --git a/projects/helper/chains.json b/projects/helper/chains.json index 5fe8d95cb3..a9bfabf8c9 100644 --- a/projects/helper/chains.json +++ b/projects/helper/chains.json @@ -2,6 +2,7 @@ "acala", "ace", "aelf", + "agoric", "airdao", "alephium", "algorand", diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md new file mode 100644 index 0000000000..85b954495f --- /dev/null +++ b/projects/inter-protocol/README.md @@ -0,0 +1,127 @@ +# Inter Protocol Adapter + +I'm exploring two ways to calculate the Total Value Locked (TVL) for Inter-Protocol (IST) on Agoric. One method uses the total supply of IST, and the other converts it to USD using CoinGecko prices. + +## Configuration and Helper Function: + +```javascript +const sdk = require("@defillama/sdk"); +const axios = require("axios"); + +// note: added agoric to projects/helper/chains.json +const agoric = { + chainId: "agoric-3", + denom: "uist", + coinGeckoId: "agoric", +}; + +/* +@name getCoinDecimals +@description returns the number of decimals for the given denomination +@param denom - the denomintion to get decimals for +*/ +function getCoinDecimals(denom) { + return 1e6; // IST uses 1e6 +} +``` + +## Approach 1: Total Supply Based Calculation +This method calculates TVL based on the total supply of IST. + +```javascript +/* +@name fetchISTData +@description fetches the total supply of IST and returns it in a format compatible with defillama +*/ +async function fetchISTData() { + // from https://github.com/DefiLlama/peggedassets-server/pull/292 + const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; + const response = await axios.get(url); + const assetBalance = response.data.amount.amount; + const coinDecimals = getCoinDecimals(agoric.denom); + const amount = assetBalance / coinDecimals; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, amount); + + return balances; +} +``` + +### Example Output for fetchISTData: + +``` +node test.js projects/inter-protocol/index.js +--- agoric --- +BLD 136.79 k +Total: 136.79 k + +--- tvl --- +BLD 136.79 k +Total: 136.79 k + +------ TVL ------ +agoric 136.79 k + +total 136.79 k +``` + +## Approach 2: USD Value Based Calculation + +This method calculates TVL by converting the total supply of IST to its USD value using the price from CoinGeko. + +```javascript +/* +@name fetchISTDataWithUSD +@description fetches the total supply of IST, converts it to USD value and returns it in a format compatible with defillama +@note wantd to explore another calculation, although this is dependent on external cg call +*/ +async function fetchISTDataWithUSD() { + // fetch total supply of ist + const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; + const response = await axios.get(url); + const assetBalance = response.data.amount.amount; + const coinDecimals = getCoinDecimals(agoric.denom); + const amount = assetBalance / coinDecimals; + + // fetch ist price in usd from coingecko + const priceUrl = "https://api.coingecko.com/api/v3/simple/price?ids=agoric&vs_currencies=usd"; + const priceResponse = await axios.get(priceUrl); + const price = priceResponse.data.agoric.usd; + + // calculate tvl in usd + const tvl = amount * price; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, tvl); + + return balances; +} +``` + +### Example Output for fetchISTDataWithUSD: + +``` +node test.js projects/inter-protocol/index.js +--- agoric --- +BLD 13.93 k +Total: 13.93 k + +--- tvl --- +BLD 13.93 k +Total: 13.93 k + +------ TVL ------ +agoric 13.93 k + +total 13.93 k +``` + +# fetchISTData by default +By default, the module exports the fetchISTDta method. To use the USD value calculation, uncomment the respective line. + +# Things to discuss with team +- Accuracy: The total supply approach doesn’t consider the market value, while the USD approach gives a real-time value. +- Dependency: The USD approach relies on external data from CoinGecko. +- Implementtion: Decide if the extra accuracy is worth the reliance on an external service. + diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js new file mode 100644 index 0000000000..54bf599410 --- /dev/null +++ b/projects/inter-protocol/index.js @@ -0,0 +1,116 @@ +const sdk = require("@defillama/sdk"); +const axios = require("axios"); + +// note: added agoric to projects/helper/chains.json +const agoric = { + chainId: "agoric-3", + denom: "uist", + coinGeckoId: "agoric", +}; + +/* +@name getCoinDecimals +@description returns the number of decimals for the given denomination +@param denom - the denomination to get decimals for +*/ +function getCoinDecimals(denom) { + return 1e6; // IST uses 1e6 +} + +/* +@name fetchISTData +@description fetches the total supply of IST and returns it in a format compatble with defillama +*/ +async function fetchISTData() { + // from https://github.com/DefiLlama/peggedassets-server/pull/292 + const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; + const response = await axios.get(url); + const assetBalance = response.data.amount.amount; + const coinDecimals = getCoinDecimals(agoric.denom); + const amount = assetBalance / coinDecimals; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, amount); + + return balances; +} + +/* +@name fetchISTDataWithUSD - NOT USED BY DEFAULT +@description fetches the total supply of IST, converts it to USD value and returns it in a format compatible with defillama +@note wanted to explore another calculation, although this is dependent on external cg call +*/ +async function fetchISTDataWithUSD() { + // fetch total supply of ist + const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; + const response = await axios.get(url); + const assetBalance = response.data.amount.amount; + const coinDecimals = getCoinDecimals(agoric.denom); + const amount = assetBalance / coinDecimals; + + // fetch ist price in usd from coingecko + const priceUrl = "https://api.coingecko.com/api/v3/simple/price?ids=agoric&vs_currencies=usd"; + const priceResponse = await axios.get(priceUrl); + const price = priceResponse.data.agoric.usd; + + // calculate tvl in usd + const tvl = amount * price; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, tvl); + + return balances; +} + +module.exports = { + timetravel: false, + methodology: "Sum of all the tokens in the IST supply on Agoric.", + agoric: { + tvl: fetchISTData, // use fetchISTData for now + // tvl: fetchISTDataWithUSD, // uncomment to use usd calculation + }, +}; + +// TODO: discuss which approach to take, and verify calculation results + +/* + +CALCULATION RESULTS + + + +1) Result for fetchISTData: + +node test.js projects/inter-protocol/index.js +--- agoric --- +BLD 136.79 k +Total: 136.79 k + +--- tvl --- +BLD 136.79 k +Total: 136.79 k + +------ TVL ------ +agoric 136.79 k + +total 136.79 k + + + + +2) Result for fetchISTDataWithUSD: + +node test.js projects/inter-protocol/index.js +--- agoric --- +BLD 13.93 k +Total: 13.93 k + +--- tvl --- +BLD 13.93 k +Total: 13.93 k + +------ TVL ------ +agoric 13.93 k + +total 13.93 k +*/ \ No newline at end of file From 716822ffc1353fe004adf187bda3b70ccedb18c2 Mon Sep 17 00:00:00 2001 From: jovonni Date: Wed, 12 Jun 2024 01:59:03 -0400 Subject: [PATCH 2/8] debugging new calc using vaulta/reserves/psm, checkpoint for sanity check --- projects/helper/chains.json | 2 +- projects/inter-protocol/README.md | 315 ++++++++++++++++++++++++++++++ projects/inter-protocol/index.js | 190 ++++++++++++++---- 3 files changed, 470 insertions(+), 37 deletions(-) diff --git a/projects/helper/chains.json b/projects/helper/chains.json index a9bfabf8c9..3e8a425875 100644 --- a/projects/helper/chains.json +++ b/projects/helper/chains.json @@ -2,7 +2,6 @@ "acala", "ace", "aelf", - "agoric", "airdao", "alephium", "algorand", @@ -142,6 +141,7 @@ "icon", "icp", "imx", + "ist", "inevm", "injective", "interlay", diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md index 85b954495f..55335669be 100644 --- a/projects/inter-protocol/README.md +++ b/projects/inter-protocol/README.md @@ -1,5 +1,10 @@ # Inter Protocol Adapter +Run with this command, from the root directory: +``` +node test.js projects/inter-protocol/index.js +``` + I'm exploring two ways to calculate the Total Value Locked (TVL) for Inter-Protocol (IST) on Agoric. One method uses the total supply of IST, and the other converts it to USD using CoinGecko prices. ## Configuration and Helper Function: @@ -125,3 +130,313 @@ By default, the module exports the fetchISTDta method. To use the USD value calc - Dependency: The USD approach relies on external data from CoinGecko. - Implementtion: Decide if the extra accuracy is worth the reliance on an external service. + +---------------------------- + +### vault/PSD/reserve debug +Most updated run for sharing +``` +node test.js projects/inter-protocol/index.js +reserveData +{ + value: '{"blockHeight":"3650","values":["{\\"body\\":\\"#{\\\\\\"allocations\\\\\\":{\\\\\\"Fee\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+155159308\\\\\\"}},\\\\\\"shortfallBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalFeeBurned\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalFeeMinted\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board0257\\"]}"]}' +} +firstParsedReserveData +{ + blockHeight: '3650', + values: [ + '{"body":"#{\\"allocations\\":{\\"Fee\\":{\\"brand\\":\\"$0.Alleged: IST brand\\",\\"value\\":\\"+155159308\\"}},\\"shortfallBalance\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalFeeBurned\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalFeeMinted\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"}}","slots":["board0257"]}' + ] +} +secondParsedReserveData +{ + body: '#{"allocations":{"Fee":{"brand":"$0.Alleged: IST brand","value":"+155159308"}},"shortfallBalance":{"brand":"$0","value":"+0"},"totalFeeBurned":{"brand":"$0","value":"+0"},"totalFeeMinted":{"brand":"$0","value":"+0"}}', + slots: [ 'board0257' ] +} +4 +{ + allocations: { Fee: { brand: '$0.Alleged: IST brand', value: '+155159308' } }, + shortfallBalance: { brand: '$0', value: '+0' }, + totalFeeBurned: { brand: '$0', value: '+0' }, + totalFeeMinted: { brand: '$0', value: '+0' } +} +{ Fee: { brand: '$0.Alleged: IST brand', value: '+155159308' } } +RESERVE +155159308 +assetType DAI_axl +fetchPSMData iteration +{ + value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: DAI_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board05736\\",\\"board0257\\"]}"]}' +} +firstParsedPsmData +{ + blockHeight: '226', + values: [ + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: DAI_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board05736","board0257"]}' + ] +} +secondParsedPsmData +{ + body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: DAI_axl brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', + slots: [ 'board05736', 'board0257' ] +} +thirdParsedPsmData +{ + anchorPoolBalance: { brand: '$0.Alleged: DAI_axl brand', value: '+0' }, + feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, + mintedPoolBalance: { brand: '$1', value: '+0' }, + totalAnchorProvided: { brand: '$0', value: '+0' }, + totalMintedProvided: { brand: '$1', value: '+0' } +} +PSM +0 +assetType DAI_grv +fetchPSMData iteration +{ + value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: DAI_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03138\\",\\"board0257\\"]}"]}' +} +firstParsedPsmData +{ + blockHeight: '226', + values: [ + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: DAI_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03138","board0257"]}' + ] +} +secondParsedPsmData +{ + body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: DAI_grv brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', + slots: [ 'board03138', 'board0257' ] +} +thirdParsedPsmData +{ + anchorPoolBalance: { brand: '$0.Alleged: DAI_grv brand', value: '+0' }, + feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, + mintedPoolBalance: { brand: '$1', value: '+0' }, + totalAnchorProvided: { brand: '$0', value: '+0' }, + totalMintedProvided: { brand: '$1', value: '+0' } +} +PSM +0 +assetType USDC_axl +fetchPSMData iteration +{ + value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03040\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+30010011\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+30010011\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+30010011\\\\\\"}}\\",\\"slots\\":[\\"board03040\\",\\"board0257\\"]}"]}' +} +firstParsedPsmData +{ + blockHeight: '226', + values: [ + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03040","board0257"]}', + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_axl brand\\",\\"value\\":\\"+30010011\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+30010011\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+30010011\\"}}","slots":["board03040","board0257"]}' + ] +} +secondParsedPsmData +{ + body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDC_axl brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', + slots: [ 'board03040', 'board0257' ] +} +thirdParsedPsmData +{ + anchorPoolBalance: { brand: '$0.Alleged: USDC_axl brand', value: '+0' }, + feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, + mintedPoolBalance: { brand: '$1', value: '+0' }, + totalAnchorProvided: { brand: '$0', value: '+0' }, + totalMintedProvided: { brand: '$1', value: '+0' } +} +PSM +0 +assetType USDC_grv +fetchPSMData iteration +{ + value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board04542\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board04542\\",\\"board0257\\"]}"]}' +} +firstParsedPsmData +{ + blockHeight: '226', + values: [ + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board04542","board0257"]}', + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board04542","board0257"]}' + ] +} +secondParsedPsmData +{ + body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDC_grv brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', + slots: [ 'board04542', 'board0257' ] +} +thirdParsedPsmData +{ + anchorPoolBalance: { brand: '$0.Alleged: USDC_grv brand', value: '+0' }, + feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, + mintedPoolBalance: { brand: '$1', value: '+0' }, + totalAnchorProvided: { brand: '$0', value: '+0' }, + totalMintedProvided: { brand: '$1', value: '+0' } +} +PSM +0 +assetType USDT_axl +fetchPSMData iteration +{ + value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board01744\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board01744\\",\\"board0257\\"]}"]}' +} +firstParsedPsmData +{ + blockHeight: '226', + values: [ + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board01744","board0257"]}', + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board01744","board0257"]}' + ] +} +secondParsedPsmData +{ + body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDT_axl brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', + slots: [ 'board01744', 'board0257' ] +} +thirdParsedPsmData +{ + anchorPoolBalance: { brand: '$0.Alleged: USDT_axl brand', value: '+0' }, + feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, + mintedPoolBalance: { brand: '$1', value: '+0' }, + totalAnchorProvided: { brand: '$0', value: '+0' }, + totalMintedProvided: { brand: '$1', value: '+0' } +} +PSM +0 +assetType USDT_grv +fetchPSMData iteration +{ + value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03446\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03446\\",\\"board0257\\"]}"]}' +} +firstParsedPsmData +{ + blockHeight: '226', + values: [ + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03446","board0257"]}', + '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03446","board0257"]}' + ] +} +secondParsedPsmData +{ + body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDT_grv brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', + slots: [ 'board03446', 'board0257' ] +} +thirdParsedPsmData +{ + anchorPoolBalance: { brand: '$0.Alleged: USDT_grv brand', value: '+0' }, + feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, + mintedPoolBalance: { brand: '$1', value: '+0' }, + totalAnchorProvided: { brand: '$0', value: '+0' }, + totalMintedProvided: { brand: '$1', value: '+0' } +} +PSM +0 +Fetching vaults for ManagerID: 0 +fetch vault: 0 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+6030000' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+8000000' }, + vaultState: 'active' +} +fetch vault: 1 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+0' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+0' }, + vaultState: 'closed' +} +fetch vault: 2 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+0' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+0' }, + vaultState: 'closed' +} +fetch vault: 3 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+0' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+0' }, + vaultState: 'closed' +} +fetch vault: 4 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+3506445000' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+583000000' }, + vaultState: 'active' +} +fetch vault: 5 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+10203765000' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+1693000000' }, + vaultState: 'active' +} +fetch vault: 6 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+4745610000' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+788000000' }, + vaultState: 'active' +} +fetch vault: 7 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+5637045000' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+936000000' }, + vaultState: 'active' +} +fetch vault: 8 with manager id: 0 +{ + debtSnapshot: { + debt: { brand: '$0.Alleged: IST brand', value: '+100500000' }, + interest: { denominator: [Object], numerator: [Object] } + }, + locked: { brand: '$1.Alleged: ATOM brand', value: '+100000000' }, + vaultState: 'active' +} +No more vaults found for manager 0, vaultId 9 +Fetching vaults for ManagerID: 1 +No more vaults found for manager 1, vaultId 0 +IST Data: { agoric: 1334429.86126 } +Reserve Data: 155159308 +PSM Data: 0 +Vault Data: 4108000000 +------------------- +Warning: +Token coingecko:agoric has more than 100M in value (404.947796373004 M) , price data: { + price: 0.094958, + symbol: 'BLD', + timestamp: 1718171444, + confidence: 0.99 +} +------------------- +--- ist --- +BLD 404.95 M +Total: 404.95 M + +--- tvl --- +BLD 404.95 M +Total: 404.95 M + +------ TVL ------ +ist 404.95 M + +total 404.95 M +``` \ No newline at end of file diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js index 54bf599410..5ff4bd89aa 100644 --- a/projects/inter-protocol/index.js +++ b/projects/inter-protocol/index.js @@ -62,55 +62,173 @@ async function fetchISTDataWithUSD() { return balances; } -module.exports = { - timetravel: false, - methodology: "Sum of all the tokens in the IST supply on Agoric.", - agoric: { - tvl: fetchISTData, // use fetchISTData for now - // tvl: fetchISTDataWithUSD, // uncomment to use usd calculation - }, -}; - -// TODO: discuss which approach to take, and verify calculation results /* - -CALCULATION RESULTS - +@name fetchVstorageData +@description fetches data from vstorage using RPC +@param path - the vstorage path to query +*/ +async function fetchVstorageData(path) { + const url = "http://localhost:26657/"; + const payload = { + jsonrpc: "2.0", + id: 1, + method: "abci_query", + params: { + path: path, + }, + }; + + try { + const response = await axios.post(url, payload, { + headers: { + "Content-Type": "application/json", + }, + }); + + if (response.data.result.response.value) { + const decodedValue = Buffer.from(response.data.result.response.value, 'base64').toString('utf8'); + return JSON.parse(decodedValue); + } else { + throw new Error('No value found in response'); + } + } catch (error) { + // console.error("Error fetching vstorage data:", error); + throw error; + } +} -1) Result for fetchISTData: +/* +@name fetchReserveData +@description fetches reserve data from agoric storage using RPC utils +*/ +async function fetchReserveData() { + const reserveData = await fetchVstorageData('/custom/vstorage/data/published.reserve.metrics'); + console.log("reserveData"); + console.log(reserveData); + const firstParsedReserveData = JSON.parse(reserveData.value); + console.log("firstParsedReserveData"); + console.log(firstParsedReserveData); + const secondParsedReserveData = JSON.parse(firstParsedReserveData.values[0]); + console.log("secondParsedReserveData"); + console.log(secondParsedReserveData); + const thirdParsedReserveData = JSON.parse(secondParsedReserveData.body.substring(1)); + console.log(4); + console.log(thirdParsedReserveData); + console.log(thirdParsedReserveData.allocations); + const reserve = parseFloat(thirdParsedReserveData.allocations.Fee.value.replace('+', '')); + console.log("RESERVE") + console.log(reserve) + return reserve; +} -node test.js projects/inter-protocol/index.js ---- agoric --- -BLD 136.79 k -Total: 136.79 k +/* +@name fetchPSMData +@description fetches PSM data from agoric storage using RPC utils for all asset types +*/ +async function fetchPSMData() { + const assetTypes = ['DAI_axl', 'DAI_grv', 'USDC_axl', 'USDC_grv', 'USDT_axl', 'USDT_grv']; + let totalPsm = 0; + + for (const assetType of assetTypes) { + console.log("assetType", assetType) + const psmData = await fetchVstorageData(`/custom/vstorage/data/published.psm.IST.${assetType}.metrics`); + console.log("fetchPSMData iteration"); + console.log(psmData); + const firstParsedPsmData = JSON.parse(psmData.value); + console.log("firstParsedPsmData"); + console.log(firstParsedPsmData); + const secondParsedPsmData = JSON.parse(firstParsedPsmData.values[0]); + console.log("secondParsedPsmData"); + console.log(secondParsedPsmData); + const cleanedBody = secondParsedPsmData.body.substring(1); + const thirdParsedPsmData = JSON.parse(cleanedBody); + console.log("thirdParsedPsmData"); + console.log(thirdParsedPsmData); + const psm = parseFloat(thirdParsedPsmData.anchorPoolBalance.value.replace('+', '')); + console.log("PSM") + console.log(psm) + totalPsm += psm; + } + + return totalPsm; +} ---- tvl --- -BLD 136.79 k -Total: 136.79 k ------- TVL ------ -agoric 136.79 k +/* +@name fetchVaultData +@description fetches vault data from vstorage using RPC utils +*/ +async function fetchVaultData() { + const managerIds = [0, 1]; // list of manager IDs to check, ideally we can fetch these ahead of time too so we can iterate deteministically without hardcoding.... + let totalLocked = 0; + + for (const managerId of managerIds) { + console.log("Fetching vaults for ManagerID: ", managerId) + let vaultId = 0; + while (true) { // TODO: this is naive approach for testing, ideally we should fetch the amount of vaults concretely, and iterate... + try { + const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.manager${managerId}.vaults.vault${vaultId}`); + const firstParsed = JSON.parse(vaultData.value); + const secondParsed = JSON.parse(firstParsed.values[0]); + const cleanedBody = secondParsed.body.substring(1); // remove the first character "#" + const thirdParsed = JSON.parse(cleanedBody); + console.log("fetch vault: ", vaultId, " with manager id: ", managerId) + console.log(thirdParsed) + const locked = parseFloat(thirdParsed.locked.value.replace('+', '')); + totalLocked += locked; + vaultId += 1; + } catch (error) { + if (error.message.includes('No value found in response')) { + console.log(`No more vaults found for manager ${managerId}, vaultId ${vaultId}`); + break; + } else { + console.error("Error fetching vault data:", error); + break; + } + } + } + } + + return totalLocked; +} -total 136.79 k +/* +@name fetchTotalTVL +@description calculates total TVL including reserves, PSM, vaultsl, (and IST supply?) +*/ +async function fetchTotalTVL() { + const istData = await fetchISTData(); + const reserveData = await fetchReserveData(); + const psmData = await fetchPSMData(); + const vaultData = await fetchVaultData(); + console.log("IST Data:", istData); + console.log("Reserve Data:", reserveData); + console.log("PSM Data:", psmData); + console.log("Vault Data:", vaultData); -2) Result for fetchISTDataWithUSD: + const totalIST = parseFloat(Object.values(istData)[0]); + // const totalTVL = totalIST + reserveData + psmData; + // const totalTVL = reserveData + psmData; // remove total supply from calc? + const totalTVL = totalIST + reserveData + psmData + vaultData; //try vaut data -node test.js projects/inter-protocol/index.js ---- agoric --- -BLD 13.93 k -Total: 13.93 k + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, totalTVL); ---- tvl --- -BLD 13.93 k -Total: 13.93 k + return balances; +} ------- TVL ------ -agoric 13.93 k -total 13.93 k -*/ \ No newline at end of file +module.exports = { + timetravel: false, + methodology: "Sum of IST TVL on Agoric", + ist: { + // tvl: fetchISTData, // use fetchISTData for now + // tvl: fetchISTDataWithUSD, // uncomment to use usd calculation + tvl: fetchTotalTVL, //debug: total tvl + }, +}; From 32f8247a41f946eab795be0a2f40a422a1d620d4 Mon Sep 17 00:00:00 2001 From: jovonni Date: Wed, 12 Jun 2024 20:09:22 -0400 Subject: [PATCH 3/8] updated calculations, and iteratively getting vault values, to calc value in vaults w.r.t the asset locked... --- projects/inter-protocol/README.md | 339 ++---------------------------- projects/inter-protocol/index.js | 183 +++++++++------- 2 files changed, 124 insertions(+), 398 deletions(-) diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md index 55335669be..55914ba813 100644 --- a/projects/inter-protocol/README.md +++ b/projects/inter-protocol/README.md @@ -104,339 +104,24 @@ async function fetchISTDataWithUSD() { } ``` -### Example Output for fetchISTDataWithUSD: +### Updated Example Output +Taking into account reserve, vaults, and psm ``` -node test.js projects/inter-protocol/index.js ---- agoric --- -BLD 13.93 k -Total: 13.93 k - ---- tvl --- -BLD 13.93 k -Total: 13.93 k - ------- TVL ------ -agoric 13.93 k - -total 13.93 k -``` - -# fetchISTData by default -By default, the module exports the fetchISTDta method. To use the USD value calculation, uncomment the respective line. - -# Things to discuss with team -- Accuracy: The total supply approach doesn’t consider the market value, while the USD approach gives a real-time value. -- Dependency: The USD approach relies on external data from CoinGecko. -- Implementtion: Decide if the extra accuracy is worth the reliance on an external service. - - ----------------------------- - -### vault/PSD/reserve debug -Most updated run for sharing -``` -node test.js projects/inter-protocol/index.js -reserveData -{ - value: '{"blockHeight":"3650","values":["{\\"body\\":\\"#{\\\\\\"allocations\\\\\\":{\\\\\\"Fee\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+155159308\\\\\\"}},\\\\\\"shortfallBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalFeeBurned\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalFeeMinted\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board0257\\"]}"]}' -} -firstParsedReserveData -{ - blockHeight: '3650', - values: [ - '{"body":"#{\\"allocations\\":{\\"Fee\\":{\\"brand\\":\\"$0.Alleged: IST brand\\",\\"value\\":\\"+155159308\\"}},\\"shortfallBalance\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalFeeBurned\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalFeeMinted\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"}}","slots":["board0257"]}' - ] -} -secondParsedReserveData -{ - body: '#{"allocations":{"Fee":{"brand":"$0.Alleged: IST brand","value":"+155159308"}},"shortfallBalance":{"brand":"$0","value":"+0"},"totalFeeBurned":{"brand":"$0","value":"+0"},"totalFeeMinted":{"brand":"$0","value":"+0"}}', - slots: [ 'board0257' ] -} -4 -{ - allocations: { Fee: { brand: '$0.Alleged: IST brand', value: '+155159308' } }, - shortfallBalance: { brand: '$0', value: '+0' }, - totalFeeBurned: { brand: '$0', value: '+0' }, - totalFeeMinted: { brand: '$0', value: '+0' } -} -{ Fee: { brand: '$0.Alleged: IST brand', value: '+155159308' } } -RESERVE -155159308 -assetType DAI_axl -fetchPSMData iteration -{ - value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: DAI_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board05736\\",\\"board0257\\"]}"]}' -} -firstParsedPsmData -{ - blockHeight: '226', - values: [ - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: DAI_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board05736","board0257"]}' - ] -} -secondParsedPsmData -{ - body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: DAI_axl brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', - slots: [ 'board05736', 'board0257' ] -} -thirdParsedPsmData -{ - anchorPoolBalance: { brand: '$0.Alleged: DAI_axl brand', value: '+0' }, - feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, - mintedPoolBalance: { brand: '$1', value: '+0' }, - totalAnchorProvided: { brand: '$0', value: '+0' }, - totalMintedProvided: { brand: '$1', value: '+0' } -} -PSM -0 -assetType DAI_grv -fetchPSMData iteration -{ - value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: DAI_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03138\\",\\"board0257\\"]}"]}' -} -firstParsedPsmData -{ - blockHeight: '226', - values: [ - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: DAI_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03138","board0257"]}' - ] -} -secondParsedPsmData -{ - body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: DAI_grv brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', - slots: [ 'board03138', 'board0257' ] -} -thirdParsedPsmData -{ - anchorPoolBalance: { brand: '$0.Alleged: DAI_grv brand', value: '+0' }, - feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, - mintedPoolBalance: { brand: '$1', value: '+0' }, - totalAnchorProvided: { brand: '$0', value: '+0' }, - totalMintedProvided: { brand: '$1', value: '+0' } -} -PSM -0 -assetType USDC_axl -fetchPSMData iteration -{ - value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03040\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+30010011\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+30010011\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+30010011\\\\\\"}}\\",\\"slots\\":[\\"board03040\\",\\"board0257\\"]}"]}' -} -firstParsedPsmData -{ - blockHeight: '226', - values: [ - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03040","board0257"]}', - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_axl brand\\",\\"value\\":\\"+30010011\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+30010011\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+30010011\\"}}","slots":["board03040","board0257"]}' - ] -} -secondParsedPsmData -{ - body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDC_axl brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', - slots: [ 'board03040', 'board0257' ] -} -thirdParsedPsmData -{ - anchorPoolBalance: { brand: '$0.Alleged: USDC_axl brand', value: '+0' }, - feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, - mintedPoolBalance: { brand: '$1', value: '+0' }, - totalAnchorProvided: { brand: '$0', value: '+0' }, - totalMintedProvided: { brand: '$1', value: '+0' } -} -PSM -0 -assetType USDC_grv -fetchPSMData iteration -{ - value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board04542\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board04542\\",\\"board0257\\"]}"]}' -} -firstParsedPsmData -{ - blockHeight: '226', - values: [ - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board04542","board0257"]}', - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDC_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board04542","board0257"]}' - ] -} -secondParsedPsmData -{ - body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDC_grv brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', - slots: [ 'board04542', 'board0257' ] -} -thirdParsedPsmData -{ - anchorPoolBalance: { brand: '$0.Alleged: USDC_grv brand', value: '+0' }, - feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, - mintedPoolBalance: { brand: '$1', value: '+0' }, - totalAnchorProvided: { brand: '$0', value: '+0' }, - totalMintedProvided: { brand: '$1', value: '+0' } -} -PSM -0 -assetType USDT_axl -fetchPSMData iteration -{ - value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board01744\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_axl brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board01744\\",\\"board0257\\"]}"]}' -} -firstParsedPsmData -{ - blockHeight: '226', - values: [ - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board01744","board0257"]}', - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_axl brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board01744","board0257"]}' - ] -} -secondParsedPsmData -{ - body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDT_axl brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', - slots: [ 'board01744', 'board0257' ] -} -thirdParsedPsmData -{ - anchorPoolBalance: { brand: '$0.Alleged: USDT_axl brand', value: '+0' }, - feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, - mintedPoolBalance: { brand: '$1', value: '+0' }, - totalAnchorProvided: { brand: '$0', value: '+0' }, - totalMintedProvided: { brand: '$1', value: '+0' } -} -PSM -0 -assetType USDT_grv -fetchPSMData iteration -{ - value: '{"blockHeight":"226","values":["{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03446\\",\\"board0257\\"]}","{\\"body\\":\\"#{\\\\\\"anchorPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDT_grv brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"feePoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"mintedPoolBalance\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalAnchorProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"totalMintedProvided\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"}}\\",\\"slots\\":[\\"board03446\\",\\"board0257\\"]}"]}' -} -firstParsedPsmData -{ - blockHeight: '226', - values: [ - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03446","board0257"]}', - '{"body":"#{\\"anchorPoolBalance\\":{\\"brand\\":\\"$0.Alleged: USDT_grv brand\\",\\"value\\":\\"+0\\"},\\"feePoolBalance\\":{\\"brand\\":\\"$1.Alleged: IST brand\\",\\"value\\":\\"+0\\"},\\"mintedPoolBalance\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"},\\"totalAnchorProvided\\":{\\"brand\\":\\"$0\\",\\"value\\":\\"+0\\"},\\"totalMintedProvided\\":{\\"brand\\":\\"$1\\",\\"value\\":\\"+0\\"}}","slots":["board03446","board0257"]}' - ] -} -secondParsedPsmData -{ - body: '#{"anchorPoolBalance":{"brand":"$0.Alleged: USDT_grv brand","value":"+0"},"feePoolBalance":{"brand":"$1.Alleged: IST brand","value":"+0"},"mintedPoolBalance":{"brand":"$1","value":"+0"},"totalAnchorProvided":{"brand":"$0","value":"+0"},"totalMintedProvided":{"brand":"$1","value":"+0"}}', - slots: [ 'board03446', 'board0257' ] -} -thirdParsedPsmData -{ - anchorPoolBalance: { brand: '$0.Alleged: USDT_grv brand', value: '+0' }, - feePoolBalance: { brand: '$1.Alleged: IST brand', value: '+0' }, - mintedPoolBalance: { brand: '$1', value: '+0' }, - totalAnchorProvided: { brand: '$0', value: '+0' }, - totalMintedProvided: { brand: '$1', value: '+0' } -} -PSM -0 -Fetching vaults for ManagerID: 0 -fetch vault: 0 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+6030000' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+8000000' }, - vaultState: 'active' -} -fetch vault: 1 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+0' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+0' }, - vaultState: 'closed' -} -fetch vault: 2 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+0' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+0' }, - vaultState: 'closed' -} -fetch vault: 3 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+0' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+0' }, - vaultState: 'closed' -} -fetch vault: 4 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+3506445000' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+583000000' }, - vaultState: 'active' -} -fetch vault: 5 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+10203765000' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+1693000000' }, - vaultState: 'active' -} -fetch vault: 6 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+4745610000' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+788000000' }, - vaultState: 'active' -} -fetch vault: 7 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+5637045000' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+936000000' }, - vaultState: 'active' -} -fetch vault: 8 with manager id: 0 -{ - debtSnapshot: { - debt: { brand: '$0.Alleged: IST brand', value: '+100500000' }, - interest: { denominator: [Object], numerator: [Object] } - }, - locked: { brand: '$1.Alleged: ATOM brand', value: '+100000000' }, - vaultState: 'active' -} -No more vaults found for manager 0, vaultId 9 -Fetching vaults for ManagerID: 1 -No more vaults found for manager 1, vaultId 0 -IST Data: { agoric: 1334429.86126 } -Reserve Data: 155159308 -PSM Data: 0 -Vault Data: 4108000000 -------------------- -Warning: -Token coingecko:agoric has more than 100M in value (404.947796373004 M) , price data: { - price: 0.094958, - symbol: 'BLD', - timestamp: 1718171444, - confidence: 0.99 -} -------------------- +IST Data: { agoric: 1334769.86126 } +Reserve Data: 155816555 +PSM Data: 30010011 +Vault Data: 31960.240000000005 --- ist --- -BLD 404.95 M -Total: 404.95 M +BLD 18.09 M +Total: 18.09 M --- tvl --- -BLD 404.95 M -Total: 404.95 M +BLD 18.09 M +Total: 18.09 M ------ TVL ------ -ist 404.95 M +ist 18.09 M -total 404.95 M +total 18.09 M ``` \ No newline at end of file diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js index 5ff4bd89aa..6f1612ea5b 100644 --- a/projects/inter-protocol/index.js +++ b/projects/inter-protocol/index.js @@ -49,7 +49,7 @@ async function fetchISTDataWithUSD() { const amount = assetBalance / coinDecimals; // fetch ist price in usd from coingecko - const priceUrl = "https://api.coingecko.com/api/v3/simple/price?ids=agoric&vs_currencies=usd"; + const priceUrl = "https://api.coingecko.com/api/v3/simple/price?ids=inter-stable-token&vs_currencies=usd"; const priceResponse = await axios.get(priceUrl); const price = priceResponse.data.agoric.usd; @@ -65,7 +65,7 @@ async function fetchISTDataWithUSD() { /* @name fetchVstorageData -@description fetches data from vstorage using RPC +@description fetches data from vstorage @param path - the vstorage path to query */ async function fetchVstorageData(path) { @@ -101,99 +101,142 @@ async function fetchVstorageData(path) { /* @name fetchReserveData -@description fetches reserve data from agoric storage using RPC utils +@description fetches reserve data from vstorage */ async function fetchReserveData() { - const reserveData = await fetchVstorageData('/custom/vstorage/data/published.reserve.metrics'); - console.log("reserveData"); - console.log(reserveData); - const firstParsedReserveData = JSON.parse(reserveData.value); - console.log("firstParsedReserveData"); - console.log(firstParsedReserveData); - const secondParsedReserveData = JSON.parse(firstParsedReserveData.values[0]); - console.log("secondParsedReserveData"); - console.log(secondParsedReserveData); - const thirdParsedReserveData = JSON.parse(secondParsedReserveData.body.substring(1)); - console.log(4); - console.log(thirdParsedReserveData); - console.log(thirdParsedReserveData.allocations); - const reserve = parseFloat(thirdParsedReserveData.allocations.Fee.value.replace('+', '')); - console.log("RESERVE") - console.log(reserve) + const reserveData = await fetchVstorageData('/custom/vstorage/data/published.reserve.metrics'); // "+"" means is marshalled bigint + const parsedValue = JSON.parse(reserveData.value); + const parsedMetrics = JSON.parse(parsedValue.values[0]); + const cleanedMetricsBody = JSON.parse(parsedMetrics.body.substring(1)); + // TODO: look at marshaler, fromCapData UPDATE: cannot add dep to repo + const reserve = parseFloat(cleanedMetricsBody.allocations.Fee.value.replace('+', '')); + console.log("RESERVE"); + console.log(reserve); return reserve; } /* @name fetchPSMData -@description fetches PSM data from agoric storage using RPC utils for all asset types +@description fetches PSM data from vstorage for all asset types */ -async function fetchPSMData() { - const assetTypes = ['DAI_axl', 'DAI_grv', 'USDC_axl', 'USDC_grv', 'USDT_axl', 'USDT_grv']; +const fetchPSMData = async () => { + const psmTypes = await fetchVstorageData('/custom/vstorage/children/published.psm.IST'); let totalPsm = 0; - for (const assetType of assetTypes) { - console.log("assetType", assetType) + await Promise.all(psmTypes.children.map(async (assetType) => { + console.log("assetType", assetType); const psmData = await fetchVstorageData(`/custom/vstorage/data/published.psm.IST.${assetType}.metrics`); console.log("fetchPSMData iteration"); console.log(psmData); - const firstParsedPsmData = JSON.parse(psmData.value); - console.log("firstParsedPsmData"); - console.log(firstParsedPsmData); - const secondParsedPsmData = JSON.parse(firstParsedPsmData.values[0]); - console.log("secondParsedPsmData"); - console.log(secondParsedPsmData); - const cleanedBody = secondParsedPsmData.body.substring(1); - const thirdParsedPsmData = JSON.parse(cleanedBody); - console.log("thirdParsedPsmData"); - console.log(thirdParsedPsmData); - const psm = parseFloat(thirdParsedPsmData.anchorPoolBalance.value.replace('+', '')); - console.log("PSM") - console.log(psm) - totalPsm += psm; - } + const parsedPsmValue = JSON.parse(psmData.value); + console.log("parsedPsmValue"); + console.log(parsedPsmValue); + + parsedPsmValue.values.forEach((value) => { + const parsedMetrics = JSON.parse(value); + console.log("parsedMetrics"); + console.log(parsedMetrics); + const cleanedMetricsBody = parsedMetrics.body.substring(1); + const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); + console.log("cleanedParsedMetrics"); + console.log(cleanedParsedMetrics); + const psm = parseFloat(cleanedParsedMetrics.anchorPoolBalance.value.replace('+', '')); + console.log("PSM") + console.log(psm) + totalPsm += psm; + }); + })); return totalPsm; -} +}; + /* @name fetchVaultData -@description fetches vault data from vstorage using RPC utils +@description fetches vault data from vstorage and calculates the total locked value in USD */ async function fetchVaultData() { - const managerIds = [0, 1]; // list of manager IDs to check, ideally we can fetch these ahead of time too so we can iterate deteministically without hardcoding.... - let totalLocked = 0; - - for (const managerId of managerIds) { - console.log("Fetching vaults for ManagerID: ", managerId) - let vaultId = 0; - while (true) { // TODO: this is naive approach for testing, ideally we should fetch the amount of vaults concretely, and iterate... + const managerData = await fetchVstorageData('/custom/vstorage/children/published.vaultFactory.managers'); + let totalLockedUSD = 0; + const collateralSet = new Set(); // no dups + + // collect unique collateral types... + await Promise.all(managerData.children.map(async (managerId) => { + const vaultDataList = await fetchVstorageData(`/custom/vstorage/children/published.vaultFactory.managers.${managerId}.vaults`); + await Promise.all(vaultDataList.children.map(async (vaultId) => { try { - const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.manager${managerId}.vaults.vault${vaultId}`); - const firstParsed = JSON.parse(vaultData.value); - const secondParsed = JSON.parse(firstParsed.values[0]); - const cleanedBody = secondParsed.body.substring(1); // remove the first character "#" - const thirdParsed = JSON.parse(cleanedBody); - console.log("fetch vault: ", vaultId, " with manager id: ", managerId) - console.log(thirdParsed) - const locked = parseFloat(thirdParsed.locked.value.replace('+', '')); - totalLocked += locked; - vaultId += 1; + const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.${managerId}.vaults.${vaultId}`); + const parsedVaultData = JSON.parse(vaultData.value); + parsedVaultData.values.forEach((value) => { + const vaultMetrics = JSON.parse(value); + const cleanedMetricsBody = vaultMetrics.body.substring(1); + const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); + const lockedBrand = cleanedParsedMetrics.locked.brand.split(" ")[1].toLowerCase(); + collateralSet.add(lockedBrand); + }); } catch (error) { - if (error.message.includes('No value found in response')) { - console.log(`No more vaults found for manager ${managerId}, vaultId ${vaultId}`); - break; - } else { - console.error("Error fetching vault data:", error); - break; - } + console.error("Error fetching vault data:", error); } + })); + })); + + // fetch prices for unique collateral types... + const collateralPrices = {}; + await Promise.all([...collateralSet].map(async (collateral) => { + console.log("coll: ", collateral); + const collateralToFetch = (collateral === "atom") ? "cosmos" : collateral; + const priceUrl = `https://api.coingecko.com/api/v3/simple/price?ids=${collateralToFetch}&vs_currencies=usd`; + console.log("priceUrl:", priceUrl); + try { + const priceResponse = await axios.get(priceUrl); + if (priceResponse.data[collateralToFetch]) { + console.log("Got Price: ", priceResponse); + collateralPrices[collateral] = priceResponse.data[collateralToFetch].usd; + } else { + console.error(`Price data not found for: ${collateral}`); + } + } catch (error) { + console.error(`Error fetching price for ${collateral}:`, error); } - } + })); + + // calculate total locked value in USD... + await Promise.all(managerData.children.map(async (managerId) => { + const vaultDataList = await fetchVstorageData(`/custom/vstorage/children/published.vaultFactory.managers.${managerId}.vaults`); + console.log("vaultDataList"); + console.log(vaultDataList); + await Promise.all(vaultDataList.children.map(async (vaultId) => { + try { + const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.${managerId}.vaults.${vaultId}`); + const parsedVaultData = JSON.parse(vaultData.value); + parsedVaultData.values.forEach((value) => { + const vaultMetrics = JSON.parse(value); + const cleanedMetricsBody = vaultMetrics.body.substring(1); + const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); + const locked = parseFloat(cleanedParsedMetrics.locked.value.replace('+', '')); + const lockedBrand = cleanedParsedMetrics.locked.brand.split(" ")[1].toLowerCase(); + console.log("lockedBrand: ", lockedBrand); + console.log(collateralPrices); + const price = collateralPrices[lockedBrand]; + console.log("coll price: ", price); + if (price) { + const lockedUSD = locked * price / getCoinDecimals(lockedBrand); + totalLockedUSD += lockedUSD; + } else { + console.error(`Price not available for collateral: ${lockedBrand}`); + } + }); + } catch (error) { + console.error("Error fetching vault data:", error); + } + })); + })); - return totalLocked; + return totalLockedUSD; } + /* @name fetchTotalTVL @description calculates total TVL including reserves, PSM, vaultsl, (and IST supply?) @@ -205,7 +248,7 @@ async function fetchTotalTVL() { const vaultData = await fetchVaultData(); - console.log("IST Data:", istData); + console.log("IST Data:", istData); // do we need the supply? would it be redundant? console.log("Reserve Data:", reserveData); console.log("PSM Data:", psmData); console.log("Vault Data:", vaultData); @@ -214,7 +257,7 @@ async function fetchTotalTVL() { const totalIST = parseFloat(Object.values(istData)[0]); // const totalTVL = totalIST + reserveData + psmData; // const totalTVL = reserveData + psmData; // remove total supply from calc? - const totalTVL = totalIST + reserveData + psmData + vaultData; //try vaut data + const totalTVL = totalIST + reserveData + psmData + vaultData; //TODO: try vaut data const balances = {}; sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, totalTVL); @@ -227,8 +270,6 @@ module.exports = { timetravel: false, methodology: "Sum of IST TVL on Agoric", ist: { - // tvl: fetchISTData, // use fetchISTData for now - // tvl: fetchISTDataWithUSD, // uncomment to use usd calculation tvl: fetchTotalTVL, //debug: total tvl }, }; From 46069a481163df3698429d6184e967d7d8e045fc Mon Sep 17 00:00:00 2001 From: jovonni Date: Wed, 12 Jun 2024 20:17:42 -0400 Subject: [PATCH 4/8] updated readme --- projects/inter-protocol/README.md | 112 ++++-------------------------- 1 file changed, 12 insertions(+), 100 deletions(-) diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md index 55914ba813..1c38ba9823 100644 --- a/projects/inter-protocol/README.md +++ b/projects/inter-protocol/README.md @@ -5,106 +5,18 @@ Run with this command, from the root directory: node test.js projects/inter-protocol/index.js ``` -I'm exploring two ways to calculate the Total Value Locked (TVL) for Inter-Protocol (IST) on Agoric. One method uses the total supply of IST, and the other converts it to USD using CoinGecko prices. - -## Configuration and Helper Function: - -```javascript -const sdk = require("@defillama/sdk"); -const axios = require("axios"); - -// note: added agoric to projects/helper/chains.json -const agoric = { - chainId: "agoric-3", - denom: "uist", - coinGeckoId: "agoric", -}; - -/* -@name getCoinDecimals -@description returns the number of decimals for the given denomination -@param denom - the denomintion to get decimals for -*/ -function getCoinDecimals(denom) { - return 1e6; // IST uses 1e6 -} -``` - -## Approach 1: Total Supply Based Calculation -This method calculates TVL based on the total supply of IST. - -```javascript -/* -@name fetchISTData -@description fetches the total supply of IST and returns it in a format compatible with defillama -*/ -async function fetchISTData() { - // from https://github.com/DefiLlama/peggedassets-server/pull/292 - const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; - const response = await axios.get(url); - const assetBalance = response.data.amount.amount; - const coinDecimals = getCoinDecimals(agoric.denom); - const amount = assetBalance / coinDecimals; - - const balances = {}; - sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, amount); - - return balances; -} -``` - -### Example Output for fetchISTData: - -``` -node test.js projects/inter-protocol/index.js ---- agoric --- -BLD 136.79 k -Total: 136.79 k - ---- tvl --- -BLD 136.79 k -Total: 136.79 k - ------- TVL ------ -agoric 136.79 k - -total 136.79 k -``` - -## Approach 2: USD Value Based Calculation - -This method calculates TVL by converting the total supply of IST to its USD value using the price from CoinGeko. - -```javascript -/* -@name fetchISTDataWithUSD -@description fetches the total supply of IST, converts it to USD value and returns it in a format compatible with defillama -@note wantd to explore another calculation, although this is dependent on external cg call -*/ -async function fetchISTDataWithUSD() { - // fetch total supply of ist - const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; - const response = await axios.get(url); - const assetBalance = response.data.amount.amount; - const coinDecimals = getCoinDecimals(agoric.denom); - const amount = assetBalance / coinDecimals; - - // fetch ist price in usd from coingecko - const priceUrl = "https://api.coingecko.com/api/v3/simple/price?ids=agoric&vs_currencies=usd"; - const priceResponse = await axios.get(priceUrl); - const price = priceResponse.data.agoric.usd; - - // calculate tvl in usd - const tvl = amount * price; - - const balances = {}; - sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, tvl); - - return balances; -} -``` - -### Updated Example Output +## functions overview +- getCoinDecimals: returns the numbr of decimals for a givn denomination. IST uses 1e6 decimals. +- fetchISTData: fetches the total supply of IST and returns it in a format compatble with defillama. uses the cosmos directory api to get the supply data and processes it. +- fetchISTDataWithUSD: fetches the total suply of IST, converts it to usd value using coingecko api, and returns it in a format compatible with defillama. note: this function is not used by default. +- fetchVstorageData: fetches data from vstorage using rpc. sends a request to the local vstorage endpoint and processes the response. +- fetchReserveData: fetches reserve data from vstorage. parses the reserve metrics from the response to get the reserve allocation fee value. +- fetchPSMData: fetches psm data from vstorage for all asset types. iterates over each asset type, fetches their metrics, and sums up the psm values. +- fetchVaultData: fetches vault data from vstorage and calculates the total locked value in usd. collects unique collateral types, fetches their prices from coingecko, and calculates the total usd value of the locked collateral. +- fetchTotalTVL: calculates total tvl (total value locked) including reserves, psm, vaults, and IST supply. sums up the values fetched by the other functions to get the total tvl. + + +## Updated Example Output Taking into account reserve, vaults, and psm ``` From 35eff55f3d88cbcfd65f27ffb3f3e35c622f09d4 Mon Sep 17 00:00:00 2001 From: jovonni Date: Wed, 12 Jun 2024 20:29:06 -0400 Subject: [PATCH 5/8] tldr logic added to readme --- projects/inter-protocol/README.md | 9 +++++++++ projects/inter-protocol/index.js | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md index 1c38ba9823..bccb4d08e2 100644 --- a/projects/inter-protocol/README.md +++ b/projects/inter-protocol/README.md @@ -15,6 +15,15 @@ node test.js projects/inter-protocol/index.js - fetchVaultData: fetches vault data from vstorage and calculates the total locked value in usd. collects unique collateral types, fetches their prices from coingecko, and calculates the total usd value of the locked collateral. - fetchTotalTVL: calculates total tvl (total value locked) including reserves, psm, vaults, and IST supply. sums up the values fetched by the other functions to get the total tvl. +### logic + +for ```fetchISTData```, we are pulling the total IST supply from the cosmos directory. the endpoint we’re hitting is https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist. we process this to get the amount of IST in circulation. (May not need this as it might be redundant..?) + +for ```fetchReserveData```, this one’s for grabbing reserve metrics. we hit the path /custom/vstorage/data/published.reserve.metrics. the data we get back includes some marshaled bigints. we parse this to get the fee allocation value. + +for ```fetchPSMData```, we first get the different asset types from /custom/vstorage/children/published.psm.IST. then, for each asset type, we fetch its metrics from /custom/vstorage/data/published.psm.IST.${assetType}.metrics. we parse these to sum up the anchor pool balances. + +for ```fetchVaultData```, we start by fetching the vault managers from /custom/vstorage/children/published.vaultFactory.managers. then, for each manager, we get the vault data from ## Updated Example Output Taking into account reserve, vaults, and psm diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js index 6f1612ea5b..b74e1e8a2e 100644 --- a/projects/inter-protocol/index.js +++ b/projects/inter-protocol/index.js @@ -257,7 +257,8 @@ async function fetchTotalTVL() { const totalIST = parseFloat(Object.values(istData)[0]); // const totalTVL = totalIST + reserveData + psmData; // const totalTVL = reserveData + psmData; // remove total supply from calc? - const totalTVL = totalIST + reserveData + psmData + vaultData; //TODO: try vaut data + // const totalTVL = totalIST + reserveData + psmData + vaultData; //TODO: try vaut data + const totalTVL = reserveData + psmData + vaultData; const balances = {}; sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, totalTVL); From 29d58deeff4ac9f85d12d1d7b3dab7411ad55434 Mon Sep 17 00:00:00 2001 From: jovonni Date: Wed, 12 Jun 2024 20:45:15 -0400 Subject: [PATCH 6/8] fixed cg token id, and readme --- projects/inter-protocol/README.md | 16 ++++++++-------- projects/inter-protocol/index.js | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md index bccb4d08e2..ff3170a97d 100644 --- a/projects/inter-protocol/README.md +++ b/projects/inter-protocol/README.md @@ -29,20 +29,20 @@ for ```fetchVaultData```, we start by fetching the vault managers from /custom/v Taking into account reserve, vaults, and psm ``` -IST Data: { agoric: 1334769.86126 } +IST Data: { 'inter-stable-token': 1334769.86126 } Reserve Data: 155816555 PSM Data: 30010011 -Vault Data: 31960.240000000005 +Vault Data: 31960.239999999998 --- ist --- -BLD 18.09 M -Total: 18.09 M +IST 185.86 M +Total: 185.86 M --- tvl --- -BLD 18.09 M -Total: 18.09 M +IST 185.86 M +Total: 185.86 M ------ TVL ------ -ist 18.09 M +ist 185.86 M -total 18.09 M +total 185.86 M ``` \ No newline at end of file diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js index b74e1e8a2e..e562bcc8bb 100644 --- a/projects/inter-protocol/index.js +++ b/projects/inter-protocol/index.js @@ -5,7 +5,7 @@ const axios = require("axios"); const agoric = { chainId: "agoric-3", denom: "uist", - coinGeckoId: "agoric", + coinGeckoId: "inter-stable-token", }; /* From c4780223339c640c84de25938724815d0844e0d5 Mon Sep 17 00:00:00 2001 From: jovonni Date: Thu, 13 Jun 2024 23:56:05 -0400 Subject: [PATCH 7/8] working graphQL approach using subquery indexer :) TODO: verify numbers and finalize calculation --- projects/inter-protocol/README.md | 40 ++- projects/inter-protocol/index.js | 330 ++++++++++---------- projects/inter-protocol/index_old.js | 435 +++++++++++++++++++++++++++ 3 files changed, 636 insertions(+), 169 deletions(-) create mode 100644 projects/inter-protocol/index_old.js diff --git a/projects/inter-protocol/README.md b/projects/inter-protocol/README.md index ff3170a97d..c2f12ec9ba 100644 --- a/projects/inter-protocol/README.md +++ b/projects/inter-protocol/README.md @@ -5,7 +5,7 @@ Run with this command, from the root directory: node test.js projects/inter-protocol/index.js ``` -## functions overview +# Approach 1: functions overview (deprecated) - getCoinDecimals: returns the numbr of decimals for a givn denomination. IST uses 1e6 decimals. - fetchISTData: fetches the total supply of IST and returns it in a format compatble with defillama. uses the cosmos directory api to get the supply data and processes it. - fetchISTDataWithUSD: fetches the total suply of IST, converts it to usd value using coingecko api, and returns it in a format compatible with defillama. note: this function is not used by default. @@ -15,7 +15,7 @@ node test.js projects/inter-protocol/index.js - fetchVaultData: fetches vault data from vstorage and calculates the total locked value in usd. collects unique collateral types, fetches their prices from coingecko, and calculates the total usd value of the locked collateral. - fetchTotalTVL: calculates total tvl (total value locked) including reserves, psm, vaults, and IST supply. sums up the values fetched by the other functions to get the total tvl. -### logic +## logic for ```fetchISTData```, we are pulling the total IST supply from the cosmos directory. the endpoint we’re hitting is https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist. we process this to get the amount of IST in circulation. (May not need this as it might be redundant..?) @@ -45,4 +45,40 @@ Total: 185.86 M ist 185.86 M total 185.86 M +``` + +# Approach 2: Subquery approach + +This approach simply makes graphql queries to our aubquery indexer + +## logic + +for ```fetchReserveData```, we fetch reserve metrics data from the subquery endpoint. we get the reserve allocations and calculate the total reserve value. + +for ```fetchPSMData```, we fetch PSM metrics data from the subquery endpoint. we get the minted pool balances for all asset types and calculate the total PSM value. + +for ```fetchVaultData```, we fetch vault manager metrics data from the subquery endpoint. we get the total collateral locked in the vaults and calculate its value. + +for ```fetchTotalCollateral```, we fetch the total collateral and oracle prices from the subquery endpoint. for each collateral brand, we get its total collateral value and usd price from the oracle prices. we also get the decimal places for each collateral brand from board aux data. we calculate the usd value by multiplying the collateral amount by its price and dividing by its decimal places. finally, we sum up the usd values for all collateral types (need to sanity check this) + +## example output + +``` +IST Data: { 'inter-stable-token': 1324886.823845 } +Reserve Data: 88840.683426 +PSM Data: 5475.886243 +Vault Data: 1981257.5781 +Total Collat: 57157332.45712694 +--- ist --- +IST 56.99 M +Total: 56.99 M + +--- tvl --- +IST 56.99 M +Total: 56.99 M + +------ TVL ------ +ist 56.99 M + +total 56.99 M ``` \ No newline at end of file diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js index e562bcc8bb..ddd47bddf2 100644 --- a/projects/inter-protocol/index.js +++ b/projects/inter-protocol/index.js @@ -8,20 +8,48 @@ const agoric = { coinGeckoId: "inter-stable-token", }; +/* +@name delay +@description throttle rpc calls +@param ms - milliseconds to delay +*/ +const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + /* @name getCoinDecimals @description returns the number of decimals for the given denomination @param denom - the denomination to get decimals for */ -function getCoinDecimals(denom) { - return 1e6; // IST uses 1e6 +const getCoinDecimals = (denom) => 1e6; // IST uses 1e6 + +/* +@name fetchSubqueryData +@description fetches data from the Agoric Subquery Indexer +@param query - the GraphQL query to execute +*/ +const fetchSubqueryData = async (query) => { + const url = 'https://api.subquery.network/sq/agoric-labs/agoric-mainnet-v2'; + try { + const response = await axios.post(url, { query }, { + headers: { "Content-Type": "application/json" } + }); + + if (response.data.errors) { + throw new Error(response.data.errors.map(e => e.message).join(", ")); + } + + return response.data.data; + } catch (error) { + console.error('Error fetching data from Subquery:', error); + throw error; + } } /* @name fetchISTData @description fetches the total supply of IST and returns it in a format compatble with defillama */ -async function fetchISTData() { +const fetchISTData = async () => { // from https://github.com/DefiLlama/peggedassets-server/pull/292 const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; const response = await axios.get(url); @@ -40,7 +68,7 @@ async function fetchISTData() { @description fetches the total supply of IST, converts it to USD value and returns it in a format compatible with defillama @note wanted to explore another calculation, although this is dependent on external cg call */ -async function fetchISTDataWithUSD() { +const fetchISTDataWithUSD = async () => { // fetch total supply of ist const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; const response = await axios.get(url); @@ -62,215 +90,183 @@ async function fetchISTDataWithUSD() { return balances; } - -/* -@name fetchVstorageData -@description fetches data from vstorage -@param path - the vstorage path to query -*/ -async function fetchVstorageData(path) { - const url = "http://localhost:26657/"; - const payload = { - jsonrpc: "2.0", - id: 1, - method: "abci_query", - params: { - path: path, - }, - }; - - try { - const response = await axios.post(url, payload, { - headers: { - "Content-Type": "application/json", - }, - }); - - if (response.data.result.response.value) { - const decodedValue = Buffer.from(response.data.result.response.value, 'base64').toString('utf8'); - return JSON.parse(decodedValue); - } else { - throw new Error('No value found in response'); - } - } catch (error) { - // console.error("Error fetching vstorage data:", error); - throw error; - } -} - - /* @name fetchReserveData -@description fetches reserve data from vstorage +@description fetches reserve data from subquery */ -async function fetchReserveData() { - const reserveData = await fetchVstorageData('/custom/vstorage/data/published.reserve.metrics'); // "+"" means is marshalled bigint - const parsedValue = JSON.parse(reserveData.value); - const parsedMetrics = JSON.parse(parsedValue.values[0]); - const cleanedMetricsBody = JSON.parse(parsedMetrics.body.substring(1)); - // TODO: look at marshaler, fromCapData UPDATE: cannot add dep to repo - const reserve = parseFloat(cleanedMetricsBody.allocations.Fee.value.replace('+', '')); - console.log("RESERVE"); - console.log(reserve); +const fetchReserveData = async () => { + const query = ` + query { + reserveMetrics { + nodes { + shortfallBalance + allocations { + nodes { + id + denom + value + } + } + } + } + }`; + const data = await fetchSubqueryData(query); + const allocations = data.reserveMetrics.nodes[0].allocations.nodes; + let totalReserve = 0; + allocations.forEach(allocation => { + totalReserve += parseFloat(allocation.value); + }); + const reserve = totalReserve / getCoinDecimals('uist'); return reserve; } /* @name fetchPSMData -@description fetches PSM data from vstorage for all asset types +@description fetches PSM data from subquery for all asset types */ const fetchPSMData = async () => { - const psmTypes = await fetchVstorageData('/custom/vstorage/children/published.psm.IST'); + const query = ` + query { + psmMetrics { + nodes { + mintedPoolBalance + } + } + }`; + const data = await fetchSubqueryData(query); let totalPsm = 0; - - await Promise.all(psmTypes.children.map(async (assetType) => { - console.log("assetType", assetType); - const psmData = await fetchVstorageData(`/custom/vstorage/data/published.psm.IST.${assetType}.metrics`); - console.log("fetchPSMData iteration"); - console.log(psmData); - const parsedPsmValue = JSON.parse(psmData.value); - console.log("parsedPsmValue"); - console.log(parsedPsmValue); - - parsedPsmValue.values.forEach((value) => { - const parsedMetrics = JSON.parse(value); - console.log("parsedMetrics"); - console.log(parsedMetrics); - const cleanedMetricsBody = parsedMetrics.body.substring(1); - const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); - console.log("cleanedParsedMetrics"); - console.log(cleanedParsedMetrics); - const psm = parseFloat(cleanedParsedMetrics.anchorPoolBalance.value.replace('+', '')); - console.log("PSM") - console.log(psm) - totalPsm += psm; - }); - })); - - return totalPsm; -}; - - + data.psmMetrics.nodes.forEach(psm => { + totalPsm += parseFloat(psm.mintedPoolBalance); + }); + return totalPsm / getCoinDecimals('uist'); +} /* @name fetchVaultData -@description fetches vault data from vstorage and calculates the total locked value in USD +@description fetches vault data from subquery and calculates the total locked value in IST */ -async function fetchVaultData() { - const managerData = await fetchVstorageData('/custom/vstorage/children/published.vaultFactory.managers'); - let totalLockedUSD = 0; - const collateralSet = new Set(); // no dups - - // collect unique collateral types... - await Promise.all(managerData.children.map(async (managerId) => { - const vaultDataList = await fetchVstorageData(`/custom/vstorage/children/published.vaultFactory.managers.${managerId}.vaults`); - await Promise.all(vaultDataList.children.map(async (vaultId) => { - try { - const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.${managerId}.vaults.${vaultId}`); - const parsedVaultData = JSON.parse(vaultData.value); - parsedVaultData.values.forEach((value) => { - const vaultMetrics = JSON.parse(value); - const cleanedMetricsBody = vaultMetrics.body.substring(1); - const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); - const lockedBrand = cleanedParsedMetrics.locked.brand.split(" ")[1].toLowerCase(); - collateralSet.add(lockedBrand); - }); - } catch (error) { - console.error("Error fetching vault data:", error); +const fetchVaultData = async () => { + const query = ` + query { + vaultManagerMetrics { + nodes { + totalCollateral } - })); - })); + } + }`; + const data = await fetchSubqueryData(query); + let totalCollateral = 0; + data.vaultManagerMetrics.nodes.forEach(vault => { + totalCollateral += parseFloat(vault.totalCollateral); + }); + return totalCollateral / getCoinDecimals('uist'); +} - // fetch prices for unique collateral types... - const collateralPrices = {}; - await Promise.all([...collateralSet].map(async (collateral) => { - console.log("coll: ", collateral); - const collateralToFetch = (collateral === "atom") ? "cosmos" : collateral; - const priceUrl = `https://api.coingecko.com/api/v3/simple/price?ids=${collateralToFetch}&vs_currencies=usd`; - console.log("priceUrl:", priceUrl); - try { - const priceResponse = await axios.get(priceUrl); - if (priceResponse.data[collateralToFetch]) { - console.log("Got Price: ", priceResponse); - collateralPrices[collateral] = priceResponse.data[collateralToFetch].usd; - } else { - console.error(`Price data not found for: ${collateral}`); +/* +@name fetchTotalCollateral +@description fetches total collateral and calculates its USD value +*/ +const fetchTotalCollateral = async () => { + const query = ` + query { + vaultManagerMetrics { + nodes { + totalCollateral + liquidatingCollateralBrand } - } catch (error) { - console.error(`Error fetching price for ${collateral}:`, error); } - })); - - // calculate total locked value in USD... - await Promise.all(managerData.children.map(async (managerId) => { - const vaultDataList = await fetchVstorageData(`/custom/vstorage/children/published.vaultFactory.managers.${managerId}.vaults`); - console.log("vaultDataList"); - console.log(vaultDataList); - await Promise.all(vaultDataList.children.map(async (vaultId) => { - try { - const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.${managerId}.vaults.${vaultId}`); - const parsedVaultData = JSON.parse(vaultData.value); - parsedVaultData.values.forEach((value) => { - const vaultMetrics = JSON.parse(value); - const cleanedMetricsBody = vaultMetrics.body.substring(1); - const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); - const locked = parseFloat(cleanedParsedMetrics.locked.value.replace('+', '')); - const lockedBrand = cleanedParsedMetrics.locked.brand.split(" ")[1].toLowerCase(); - console.log("lockedBrand: ", lockedBrand); - console.log(collateralPrices); - const price = collateralPrices[lockedBrand]; - console.log("coll price: ", price); - if (price) { - const lockedUSD = locked * price / getCoinDecimals(lockedBrand); - totalLockedUSD += lockedUSD; - } else { - console.error(`Price not available for collateral: ${lockedBrand}`); - } - }); - } catch (error) { - console.error("Error fetching vault data:", error); + oraclePrices { + nodes { + priceFeedName + typeOutAmount + typeInAmount + } + } + boardAuxes { + nodes { + allegedName + decimalPlaces } - })); - })); + } + }`; - return totalLockedUSD; -} + const data = await fetchSubqueryData(query); + console.log(data); + let totalCollateral = 0; + const collateralPrices = {}; + const collateralDecimals = {}; + const collateralSet = new Set(); + + data.vaultManagerMetrics.nodes.forEach(vault => { + console.log("vault"); + console.log(vault); + totalCollateral += parseFloat(vault.totalCollateral); + collateralSet.add(vault.liquidatingCollateralBrand); + }); + + data.oraclePrices.nodes.forEach(price => { + console.log("price"); + console.log(price); + collateralPrices[price.priceFeedName] = parseFloat(price.typeOutAmount) / parseFloat(price.typeInAmount); + }); + + data.boardAuxes.nodes.forEach(aux => { + console.log("aux") + console.log(aux) + collateralDecimals[aux.allegedName.toLowerCase()] = Math.pow(10, aux.decimalPlaces); + }); + + let totalCollateralUSD = 0; + collateralSet.forEach(collateral => { + const collatKey = `${collateral}-USD`; + const price = collateralPrices[collatKey]; + const decimals = collateralDecimals[collateral.toLowerCase()] || 1; + console.log("decimals: ", decimals) + if (price) { + console.log(`[${collatKey}]collat price: `, price); + console.log(`[${collatKey}]collat amount: `, totalCollateral / decimals); + console.log(`[${collatKey}]collat price USD: `, (totalCollateral / decimals) * price); + totalCollateralUSD += (totalCollateral / decimals) * price; + } else { + console.error(`Price not found for collateral: ${collateral}`); + } + }); + return totalCollateralUSD / getCoinDecimals('uist'); +}; /* @name fetchTotalTVL @description calculates total TVL including reserves, PSM, vaultsl, (and IST supply?) */ -async function fetchTotalTVL() { +const fetchTotalTVL = async () => { const istData = await fetchISTData(); const reserveData = await fetchReserveData(); const psmData = await fetchPSMData(); const vaultData = await fetchVaultData(); - + const totalCollateral = await fetchTotalCollateral(); console.log("IST Data:", istData); // do we need the supply? would it be redundant? console.log("Reserve Data:", reserveData); console.log("PSM Data:", psmData); console.log("Vault Data:", vaultData); - + console.log("Total Collat: ", totalCollateral) const totalIST = parseFloat(Object.values(istData)[0]); - // const totalTVL = totalIST + reserveData + psmData; - // const totalTVL = reserveData + psmData; // remove total supply from calc? - // const totalTVL = totalIST + reserveData + psmData + vaultData; //TODO: try vaut data - const totalTVL = reserveData + psmData + vaultData; + // TODO: decide on which one.... + // const totalTVL = totalIST + reserveData + psmData + vaultData; + const totalTVL = totalCollateral const balances = {}; sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, totalTVL); return balances; } - module.exports = { timetravel: false, - methodology: "Sum of IST TVL on Agoric", + methodology: "sum of ist tvl on agoric", ist: { - tvl: fetchTotalTVL, //debug: total tvl + tvl: fetchTotalTVL, }, -}; +}; \ No newline at end of file diff --git a/projects/inter-protocol/index_old.js b/projects/inter-protocol/index_old.js new file mode 100644 index 0000000000..8bbb455a30 --- /dev/null +++ b/projects/inter-protocol/index_old.js @@ -0,0 +1,435 @@ +const sdk = require("@defillama/sdk"); +const axios = require("axios"); + +// note: added agoric to projects/helper/chains.json +const agoric = { + chainId: "agoric-3", + denom: "uist", + coinGeckoId: "inter-stable-token", +}; + +/* +@name delay +@description throttle rpc calls +@param ms - milliseconds to delay +*/ +const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +/* +@name getCoinDecimals +@description returns the number of decimals for the given denomination +@param denom - the denomination to get decimals for +*/ +const getCoinDecimals = (denom) => 1e6; // IST uses 1e6 + + +/* +@name fetchISTData +@description fetches the total supply of IST and returns it in a format compatble with defillama +*/ +const fetchISTData = async () => { + // from https://github.com/DefiLlama/peggedassets-server/pull/292 + const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; + const response = await axios.get(url); + const assetBalance = response.data.amount.amount; + const coinDecimals = getCoinDecimals(agoric.denom); + const amount = assetBalance / coinDecimals; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, amount); + + return balances; +} + +/* +@name fetchISTDataWithUSD - NOT USED BY DEFAULT +@description fetches the total supply of IST, converts it to USD value and returns it in a format compatible with defillama +@note wanted to explore another calculation, although this is dependent on external cg call +*/ +const fetchISTDataWithUSD = async () => { + // fetch total supply of ist + const url = "https://rest.cosmos.directory/agoric/cosmos/bank/v1beta1/supply/by_denom?denom=uist"; + const response = await axios.get(url); + const assetBalance = response.data.amount.amount; + const coinDecimals = getCoinDecimals(agoric.denom); + const amount = assetBalance / coinDecimals; + + // fetch ist price in usd from coingecko + const priceUrl = "https://api.coingecko.com/api/v3/simple/price?ids=inter-stable-token&vs_currencies=usd"; + const priceResponse = await axios.get(priceUrl); + const price = priceResponse.data.agoric.usd; + + // calculate tvl in usd + const tvl = amount * price; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, tvl); + + return balances; +} + + +/* +@name fetchVstorageData +@description fetches data from vstorage +@param path - the vstorage path to query +*/ +let CALL_COUNTER = 0 +const fetchVstorageData = (() => { + const cache = new Map(); + + return async (path) => { + if (cache.has(path)) { + return cache.get(path); + } + + CALL_COUNTER += 1; + // const url = "http://localhost:26657/"; + // const url = "https://main.rpc.agoric.net:443"; + const url = "https://agoric-rpc.polkachu.com/" + // const url = "https://agoric-testnet-rpc.polkachu.com/" + const payload = { + jsonrpc: "2.0", + id: 1, + method: "abci_query", + params: { path }, + }; + + try { + await delay(5000); // 3-second delay + const response = await axios.post(url, payload, { + headers: { "Content-Type": "application/json" }, + }); + + if (response.data.result.response.value) { + const decodedValue = Buffer.from(response.data.result.response.value, 'base64').toString('utf8'); + const result = JSON.parse(decodedValue); + console.log("vstorage result:") + console.log(result) + cache.set(path, result); + return result; + } else { + throw new Error('No value found in response'); + } + } catch (error) { + throw error; + } + }; +})(); + + +/* +@name fetchReserveData +@description fetches reserve data from vstorage +*/ +const fetchReserveData = async () => { + const reserveData = await fetchVstorageData('/custom/vstorage/data/published.reserve.metrics'); // "+"" means is marshalled bigint + const parsedValue = JSON.parse(reserveData.value); + const parsedMetrics = JSON.parse(parsedValue.values[0]); + const cleanedMetricsBody = JSON.parse(parsedMetrics.body.substring(1)); + // TODO: look at marshaler, fromCapData UPDATE: cannot add dep to repo + const reserve = parseFloat(cleanedMetricsBody.allocations.Fee.value.replace('+', '')); + console.log("RESERVE"); + console.log(reserve); + return reserve; +} + +/* +@name fetchPSMData +@description fetches PSM data from vstorage for all asset types +*/ +const fetchPSMData = async () => { + const psmTypes = await fetchVstorageData('/custom/vstorage/children/published.psm.IST'); + let totalPsm = 0; + + await Promise.all(psmTypes.children.map(async (assetType) => { + console.log("assetType", assetType); + const psmData = await fetchVstorageData(`/custom/vstorage/data/published.psm.IST.${assetType}.metrics`); + console.log("fetchPSMData iteration"); + console.log(psmData); + const parsedPsmValue = JSON.parse(psmData.value); + console.log("parsedPsmValue"); + console.log(parsedPsmValue); + + parsedPsmValue.values.forEach((value) => { + const parsedMetrics = JSON.parse(value); + console.log("parsedMetrics"); + console.log(parsedMetrics); + const cleanedMetricsBody = parsedMetrics.body.substring(1); + const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); + console.log("cleanedParsedMetrics"); + console.log(cleanedParsedMetrics); + // const psm = parseFloat(cleanedParsedMetrics.anchorPoolBalance.value.replace('+', '')); + const psm = parseFloat(cleanedParsedMetrics.mintedPoolBalance.value.replace('+', '')); // anchor pool would be the coll, but we want the IST yes? + console.log("PSM") + console.log(psm) + totalPsm += psm; + }); + })); + + return totalPsm; +}; + + + +/* +@name fetchVaultData +@description fetches vault data from vstorage and calculates the total locked value in USD +CALL_COUNTER: 578 - first attempt +CALL_COUNTER: 573 - second attempt - with vault cache +CALL_COUNTER: 293 - third attempt - with price cache +*/ +// only calculating based on IST price +let VAULT_COUNT = 0 + +const fetchVaultData = async () => { + const managerData = await fetchVstorageData('/custom/vstorage/children/published.vaultFactory.managers'); + let totalLockedUSD = 0; + const collateralSet = new Set(); // no dups + const vaultDataCache = new Map(); // cache for vault data + const priceCache = new Map(); // cache for prices + + // collect unique collateral types... + await Promise.all(managerData.children.map(async (managerId) => { + if (!vaultDataCache.has(managerId)) { + const vaultDataList = await fetchVstorageData(`/custom/vstorage/children/published.vaultFactory.managers.${managerId}.vaults`); + vaultDataCache.set(managerId, vaultDataList); // cache the vault data list + } + const vaultDataList = vaultDataCache.get(managerId); + await Promise.all(vaultDataList.children.map(async (vaultId) => { + try { + if (!vaultDataCache.has(vaultId)) { + const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.${managerId}.vaults.${vaultId}`); + vaultDataCache.set(vaultId, vaultData); + } + const vaultData = vaultDataCache.get(vaultId); + const parsedVaultData = JSON.parse(vaultData.value); + parsedVaultData.values.forEach((value) => { + const vaultMetrics = JSON.parse(value); + const cleanedMetricsBody = vaultMetrics.body.substring(1); + const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); + const lockedBrand = cleanedParsedMetrics.locked.brand.split(" ")[1].toLowerCase(); + collateralSet.add(lockedBrand); + }); + } catch (error) { + console.error("Error fetching vault data:", error); + } + })); + })); + + // fetch prices for unique collateral types... + const fetchPrice = async (collateral) => { + console.log("coll: ", collateral); + let collateralToFetch; + switch (collateral) { + case "atom": + collateralToFetch = "cosmos"; + break; + case "statom": + collateralToFetch = "stride-staked-atom"; + break; + case "stosmo": + collateralToFetch = "stride-staked-osmo"; + break; + case "sttia": + collateralToFetch = "stride-staked-tia"; + break; + // case "stkatom": + // collateralToFetch = "pstake-staked-atom-2"; + break; + default: + collateralToFetch = collateral; + } + + const priceUrl = `https://api.coingecko.com/api/v3/simple/price?ids=${collateralToFetch}&vs_currencies=usd`; + console.log("priceUrl:", priceUrl); + try { + await delay(3000); // 3-second delay + const priceResponse = await axios.get(priceUrl); + console.log("priceResponse.data") + // console.log(priceResponse.data) + if (priceResponse.data[collateralToFetch]) { + // console.log("Got Price: ", priceResponse); + return priceResponse.data[collateralToFetch].usd; + } else { + console.error(`Price data not found for: ${collateral}`); + return null; + } + } catch (error) { + console.error(`Error fetching price for ${collateral}:`, error); + return null; + } + }; + + const pricePromises = {}; + await Promise.all([...collateralSet].map(async (collateral) => { + // console.log("priceCache") + // console.log(priceCache) + if (!priceCache.has(collateral)) { + if (!pricePromises[collateral]) { + pricePromises[collateral] = fetchPrice(collateral); + } + const price = await pricePromises[collateral]; + if (price !== null) { + priceCache.set(collateral, price); + } + } + })); + + // calculate total locked value in USD... + await Promise.all(managerData.children.map(async (managerId) => { + const vaultDataList = vaultDataCache.get(managerId); // retrieve from cache + console.log("vaultDataList"); + // console.log(vaultDataList); + await Promise.all(vaultDataList.children.map(async (vaultId) => { + try { + const vaultData = vaultDataCache.get(vaultId); // retrieve from cache + const parsedVaultData = JSON.parse(vaultData.value); + parsedVaultData.values.forEach((value) => { + const vaultMetrics = JSON.parse(value); + const cleanedMetricsBody = vaultMetrics.body.substring(1); + const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); + const locked = parseFloat(cleanedParsedMetrics.locked.value.replace('+', '')); + const lockedBrand = cleanedParsedMetrics.locked.brand.split(" ")[1].toLowerCase(); + console.log("lockedBrand: ", lockedBrand); + // console.log(priceCache); + const price = priceCache.get(lockedBrand); + // console.log("coll price: ", price); + if (price) { + const lockedUSD = locked * price / getCoinDecimals(lockedBrand); + totalLockedUSD += lockedUSD; + } else { + console.error(`Price not available for collateral: ${lockedBrand}`); + } + }); + } catch (error) { + console.error("Error fetching vault data:", error); + } + })); + })); + + return totalLockedUSD; +}; + + + +// first attempt - VAULT_COUNT: 512 should not be as high: +// second attempt - VAULT_COUNT: 225 +/* +test: +Reserve Data: 69625972760 +PSM Data: 5475886243 +Vault Data: 1532786.3758959998 + + +example: +vstorage result: +{ + value: '{"blockHeight":"13092169","values":["{\\"body\\":\\"#{\\\\\\"debtSnapshot\\\\\\":{\\\\\\"debt\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: IST brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"interest\\\\\\":{\\\\\\"denominator\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+100000000000000000000\\\\\\"},\\\\\\"numerator\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+100452870470097742390\\\\\\"}}},\\\\\\"locked\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$1.Alleged: stATOM brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+0\\\\\\"},\\\\\\"vaultState\\\\\\":\\\\\\"closed\\\\\\"}\\",\\"slots\\":[\\"board0257\\",\\"board037112\\"]}"]}' +} +IST brand amount: 100000000000000000000 ? this isn't 6 decimals... does it need to be... +statom brand amount: 100452870470097742390 + +from inter ui (seems wrong): + +Total Reserve Assets +$106.51K + +Total Locked Collateral Value +$4.14M + + +*/ +// const fetchVaultData = async () => { +// const managerData = await fetchVstorageData('/custom/vstorage/children/published.vaultFactory.managers'); +// let totalLockedIST = 0; +// const vaultDataCache = new Map(); // cache for vault data + +// // helper function to process vault data +// const processVaultData = async (managerId, vaultId) => { +// if (!vaultDataCache.has(vaultId)) { +// try { +// const vaultData = await fetchVstorageData(`/custom/vstorage/data/published.vaultFactory.managers.${managerId}.vaults.${vaultId}`); +// vaultDataCache.set(vaultId, vaultData); +// VAULT_COUNT += 1; // increment only when a new vault data is fetched +// } catch (error) { +// console.error("Error fetching vault data:", error); +// return; +// } +// } + +// const vaultData = vaultDataCache.get(vaultId); +// const parsedVaultData = JSON.parse(vaultData.value); +// parsedVaultData.values.forEach((value) => { +// const vaultMetrics = JSON.parse(value); +// const cleanedMetricsBody = vaultMetrics.body.substring(1); +// const cleanedParsedMetrics = JSON.parse(cleanedMetricsBody); +// const lockedIST = parseFloat(cleanedParsedMetrics.locked.value.replace('+', '')); +// totalLockedIST += lockedIST / getCoinDecimals('uist'); +// }); +// }; + +// // collect IST values from vaults... +// const vaultIdsToProcess = []; +// for (const managerId of managerData.children) { +// if (!vaultDataCache.has(managerId)) { +// try { +// const vaultDataList = await fetchVstorageData(`/custom/vstorage/children/published.vaultFactory.managers.${managerId}.vaults`); +// vaultDataCache.set(managerId, vaultDataList); // Cache the vault data list +// vaultIdsToProcess.push(...vaultDataList.children.map(vaultId => ({ managerId, vaultId }))); +// } catch (error) { +// console.error("Error fetching vault list:", error); +// continue; +// } +// } +// } + +// // process all collected vault IDs +// await Promise.all(vaultIdsToProcess.map(({ managerId, vaultId }) => processVaultData(managerId, vaultId))); + +// console.log("VAULT_COUNT: ", VAULT_COUNT); +// return totalLockedIST; +// }; + + + + +/* +@name fetchTotalTVL +@description calculates total TVL including reserves, PSM, vaultsl, (and IST supply?) +*/ +const fetchTotalTVL = async () => { + const istData = await fetchISTData(); + const reserveData = await fetchReserveData(); + const psmData = await fetchPSMData(); + const vaultData = await fetchVaultData(); + + + console.log("IST Data:", istData); // do we need the supply? would it be redundant? + console.log("Reserve Data:", reserveData); + console.log("PSM Data:", psmData); + console.log("Vault Data:", vaultData); + + + const totalIST = parseFloat(Object.values(istData)[0]); + // const totalTVL = totalIST + reserveData + psmData; + // const totalTVL = reserveData + psmData; // remove total supply from calc? + // const totalTVL = totalIST + reserveData + psmData + vaultData; //TODO: try vaut data + const totalTVL = reserveData + psmData + vaultData; + + const balances = {}; + sdk.util.sumSingleBalance(balances, agoric.coinGeckoId, totalTVL); + + console.log("CALL_COUNTER: ", CALL_COUNTER) + console.log("VAULT_COUNT: ", VAULT_COUNT) + return balances; +} + + +module.exports = { + timetravel: false, + methodology: "Sum of IST TVL on Agoric", + ist: { + tvl: fetchTotalTVL, //debug: total tvl + }, +}; From 235f720153e44be5c91b6f81b6c23bf4587ac09f Mon Sep 17 00:00:00 2001 From: jovonni Date: Fri, 14 Jun 2024 00:28:26 -0400 Subject: [PATCH 8/8] fix on total coll --- projects/inter-protocol/index.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/projects/inter-protocol/index.js b/projects/inter-protocol/index.js index ddd47bddf2..631cd535ab 100644 --- a/projects/inter-protocol/index.js +++ b/projects/inter-protocol/index.js @@ -192,16 +192,19 @@ const fetchTotalCollateral = async () => { const data = await fetchSubqueryData(query); console.log(data); - let totalCollateral = 0; const collateralPrices = {}; const collateralDecimals = {}; - const collateralSet = new Set(); + const collateralMap = {}; data.vaultManagerMetrics.nodes.forEach(vault => { console.log("vault"); console.log(vault); - totalCollateral += parseFloat(vault.totalCollateral); - collateralSet.add(vault.liquidatingCollateralBrand); + const collateralType = vault.liquidatingCollateralBrand; + const collateralValue = parseFloat(vault.totalCollateral); + if (!collateralMap[collateralType]) { + collateralMap[collateralType] = 0; + } + collateralMap[collateralType] += collateralValue; }); data.oraclePrices.nodes.forEach(price => { @@ -217,16 +220,17 @@ const fetchTotalCollateral = async () => { }); let totalCollateralUSD = 0; - collateralSet.forEach(collateral => { + Object.keys(collateralMap).forEach(collateral => { const collatKey = `${collateral}-USD`; const price = collateralPrices[collatKey]; const decimals = collateralDecimals[collateral.toLowerCase()] || 1; - console.log("decimals: ", decimals) + const collateralAmount = collateralMap[collateral] / decimals; + console.log("decimals: ", decimals); if (price) { console.log(`[${collatKey}]collat price: `, price); - console.log(`[${collatKey}]collat amount: `, totalCollateral / decimals); - console.log(`[${collatKey}]collat price USD: `, (totalCollateral / decimals) * price); - totalCollateralUSD += (totalCollateral / decimals) * price; + console.log(`[${collatKey}]collat amount: `, collateralAmount); + console.log(`[${collatKey}]collat price USD: `, collateralAmount * price); + totalCollateralUSD += collateralAmount * price; } else { console.error(`Price not found for collateral: ${collateral}`); }