Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: Error handling for retrying with different providers in case of error #177

Merged
merged 3 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 3 additions & 21 deletions adapters/3ADAO/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
}
Expand Down Expand Up @@ -109,7 +91,7 @@ const readBlocksFromCSV = async (filePath: string): Promise<BlockData[]> => {
return blocks;
};

readBlocksFromCSV("test/test_hourly_blocks.csv")
readBlocksFromCSV("hourly_blocks.csv")
.then(async (blocks: any[]) => {
const allCsvRows: any[] = [];
for (const block of blocks) {
Expand All @@ -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 })
Expand Down
6 changes: 4 additions & 2 deletions adapters/3ADAO/src/sdk/config.ts
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
169 changes: 98 additions & 71 deletions adapters/3ADAO/src/sdk/helpers.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -26,7 +33,14 @@ interface BalanceGetter {
getBalances(vaultAddress: string, collaterals: string[]): Promise<number[]>;
}

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(
Expand Down Expand Up @@ -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<TVLResult> => {
Expand All @@ -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
Expand Down
Loading