diff --git a/adapters/3ADAO/src/index.ts b/adapters/3ADAO/src/index.ts index a5644ea6..f1cf385b 100644 --- a/adapters/3ADAO/src/index.ts +++ b/adapters/3ADAO/src/index.ts @@ -40,10 +40,7 @@ export const getUserTVLByBlock = async ( logOutput?: boolean ) => { const allCsvRows: OutputDataSchemaRow[] = []; // Array to accumulate CSV rows for all blocks - const batchSize = 10; // Size of batch to trigger writing to the file - // let i = 0; - console.log("length:", blocks.length); for (let i = 0; i < blocks.length; i++) { const { blockNumber, blockTimestamp } = blocks[i]; try { @@ -58,22 +55,7 @@ export const getUserTVLByBlock = async ( allCsvRows.push(...csvRowsTvl); i++; - console.log(`Processed block ${i}`); - - // Write to file when batch size is reached or at the end of loop - // if (i % batchSize === 0 || i === blocks.length) { - // const ws = fs.createWriteStream(`test/outputData.csv`, { - // flags: i === batchSize ? "w" : "a", - // }); - // write(allCsvRows, { headers: i === batchSize ? true : false }) - // .pipe(ws) - // .on("finish", () => { - // console.log(`CSV file has been written.`); - // }); - - // // Clear the accumulated CSV rows - // // allCsvRows.length = 0; - // } + // console.log(`Processed block ${i}`); } catch (error) { console.error(`An error occurred for block ${blockNumber}:`, error); } @@ -109,7 +91,7 @@ const readBlocksFromCSV = async (filePath: string): Promise => { return blocks; }; -readBlocksFromCSV("test/test_hourly_blocks.csv") +readBlocksFromCSV("hourly_blocks.csv") .then(async (blocks: any[]) => { const allCsvRows: any[] = []; for (const block of blocks) { @@ -122,7 +104,7 @@ readBlocksFromCSV("test/test_hourly_blocks.csv") } } await new Promise((resolve, reject) => { - const ws = fs.createWriteStream(`test/test_outputData.csv`, { + const ws = fs.createWriteStream(`outputData.csv`, { flags: "w", }); write(allCsvRows, { headers: true }) diff --git a/adapters/3ADAO/src/sdk/config.ts b/adapters/3ADAO/src/sdk/config.ts index d4bbcf78..9a8ed9f5 100644 --- a/adapters/3ADAO/src/sdk/config.ts +++ b/adapters/3ADAO/src/sdk/config.ts @@ -1,5 +1,7 @@ -export const LINEA_RPC = "https://rpc.linea.build"; -// export const LINEA_RPC = "https://linea.decubate.com"; +export const LINEA_RPC1 = "https://linea.decubate.com"; +export const LINEA_RPC2 = "https://1rpc.io/linea"; +export const LINEA_RPC3 = "https://rpc.linea.build"; +export const LINEA_RPC4 = "https://linea.blockpi.network/v1/rpc/public"; export const addresses = { vaultFactory: "0x65c6FD9B3a2A892096881e28f07c732ed128893E", diff --git a/adapters/3ADAO/src/sdk/helpers.ts b/adapters/3ADAO/src/sdk/helpers.ts index 18c862e1..0f523a93 100644 --- a/adapters/3ADAO/src/sdk/helpers.ts +++ b/adapters/3ADAO/src/sdk/helpers.ts @@ -1,7 +1,14 @@ import { BlockData } from "./interfaces"; import { ethers } from "ethers"; import { vaultFactoryHelperABI } from "./ABIs/vaultFactoryHelper"; -import { addresses, LINEA_RPC, whitelistedCollaterals } from "./config"; +import { + addresses, + LINEA_RPC1, + LINEA_RPC2, + LINEA_RPC3, + LINEA_RPC4, // Added fourth RPC + whitelistedCollaterals, +} from "./config"; import { balanceGetterABI } from "./ABIs/balanceGetter"; import { vaultABI } from "./ABIs/vault"; @@ -26,7 +33,14 @@ interface BalanceGetter { getBalances(vaultAddress: string, collaterals: string[]): Promise; } -const provider = new ethers.JsonRpcProvider(LINEA_RPC); +const provider1 = new ethers.JsonRpcProvider(LINEA_RPC1); +const provider2 = new ethers.JsonRpcProvider(LINEA_RPC2); +const provider3 = new ethers.JsonRpcProvider(LINEA_RPC3); +const provider4 = new ethers.JsonRpcProvider(LINEA_RPC4); + +const providers = [provider1, provider2, provider3, provider4]; +let providerIndex = 0; +let provider = providers[providerIndex]; const getVaultFactoryHelper = (): VaultFactoryHelper => { return new ethers.Contract( @@ -55,6 +69,11 @@ interface TVLResult { balancesByVault: number[][]; } +const switchProvider = () => { + providerIndex = (providerIndex + 1) % providers.length; + provider = providers[providerIndex]; +}; + export const getTvlByVaultAtBlock = async ( blockNumber: number ): Promise => { @@ -66,84 +85,92 @@ export const getTvlByVaultAtBlock = async ( ); } - const helper = getVaultFactoryHelper(); - const balanceGetter = getBalanceGetter(); + try { + const helper = getVaultFactoryHelper(); + const balanceGetter = getBalanceGetter(); - // Fetch all vault addresses in parallel - const vaults = await helper.getAllVaults(addresses.vaultFactory, { - blockNumber: blockNumber, - }); + // Fetch all vault addresses in parallel + const vaults = await helper.getAllVaults(addresses.vaultFactory, { + blockNumber: blockNumber, + }); - const owners: string[] = []; - const vaultsTvl: number[][] = []; - const balancesByVault: number[][] = []; - const collateralsByVaults: string[][] = []; + const owners: string[] = []; + const vaultsTvl: number[][] = []; + const balancesByVault: number[][] = []; + const collateralsByVaults: string[][] = []; - // Process each vault concurrently - const vaultPromises = vaults.map(async (vaultAddress: string) => { - const vault = getVault(vaultAddress); + // Process each vault concurrently + const vaultPromises = vaults.map(async (vaultAddress: string) => { + const vault = getVault(vaultAddress); - const vaultOwnerPromise = vault.vaultOwner({ blockNumber }); - const whitelistedCollateralsFiltered = Object.fromEntries( - Object.entries(whitelistedCollaterals).filter( - ([key]) => Number(key) <= blockNumber - ) - ); + const vaultOwnerPromise = vault.vaultOwner({ blockNumber }); + const whitelistedCollateralsFiltered = Object.fromEntries( + Object.entries(whitelistedCollaterals).filter( + ([key]) => Number(key) <= blockNumber + ) + ); - const tvlByCollateralPromises = Object.values( - whitelistedCollateralsFiltered - ) - .flat() - .map(async (collateral: string) => { - const collateralTvl = await helper.getVaultTvlByCollateral( - vaultAddress, - collateral, - { - blockNumber, - } - ); - return { - collateral, - tvl: - Number(collateralTvl) > 0 - ? Number(ethers.formatEther(collateralTvl)) - : 0, - }; + const tvlByCollateralPromises = Object.values( + whitelistedCollateralsFiltered + ) + .flat() + .map(async (collateral: string) => { + const collateralTvl = await helper.getVaultTvlByCollateral( + vaultAddress, + collateral, + { + blockNumber, + } + ); + return { + collateral, + tvl: + Number(collateralTvl) > 0 + ? Number(ethers.formatEther(collateralTvl)) + : 0, + }; + }); + + const [vaultOwner, tvlByCollateralResults] = await Promise.all([ + vaultOwnerPromise, + Promise.all(tvlByCollateralPromises), + ]); + + const tvlByCollateral: number[] = []; + const usedCollaterals: string[] = []; + tvlByCollateralResults.forEach(({ collateral, tvl }) => { + if (tvl > 0) { + tvlByCollateral.push(tvl); + usedCollaterals.push(collateral); + } }); - const [vaultOwner, tvlByCollateralResults] = await Promise.all([ - vaultOwnerPromise, - Promise.all(tvlByCollateralPromises), - ]); - - const tvlByCollateral: number[] = []; - const usedCollaterals: string[] = []; - tvlByCollateralResults.forEach(({ collateral, tvl }) => { - if (tvl > 0) { - tvlByCollateral.push(tvl); - usedCollaterals.push(collateral); - } + const balances = + usedCollaterals.length > 0 + ? await balanceGetter.getBalances(vaultAddress, usedCollaterals) + : []; + + owners.push(vaultOwner); + vaultsTvl.push(tvlByCollateral); + collateralsByVaults.push(usedCollaterals); + balancesByVault.push(balances); }); - const balances = - usedCollaterals.length > 0 - ? await balanceGetter.getBalances(vaultAddress, usedCollaterals) - : []; - - owners.push(vaultOwner); - vaultsTvl.push(tvlByCollateral); - collateralsByVaults.push(usedCollaterals); - balancesByVault.push(balances); - }); - - await Promise.all(vaultPromises); - - return { - vaultsTvl, - owners, - collateralsByVaults, - balancesByVault, - }; + await Promise.all(vaultPromises); + + return { + vaultsTvl, + owners, + collateralsByVaults, + balancesByVault, + }; + } catch (error) { + console.error( + `Provider ${providerIndex + 1} failed, switching to the next provider.` + ); + switchProvider(); + return getTvlByVaultAtBlock(blockNumber); + } }; // // Usage example