From 047c63d4d8c7723fd5d3af9175f03930ccd9086f Mon Sep 17 00:00:00 2001 From: Apeguru Date: Thu, 14 Nov 2024 13:25:05 +0700 Subject: [PATCH] refactor: Reduce amount of RPC calls --- adapters/lynex/package.json | 2 + adapters/lynex/src/index.ts | 86 ++---- adapters/lynex/src/sdk/lensDetails.ts | 116 ++++++++ adapters/lynex/src/sdk/subgraphDetails.ts | 84 +++++- adapters/lynex/yarn.lock | 332 +++++++++++----------- 5 files changed, 402 insertions(+), 218 deletions(-) diff --git a/adapters/lynex/package.json b/adapters/lynex/package.json index 6f39d663..99e407b4 100644 --- a/adapters/lynex/package.json +++ b/adapters/lynex/package.json @@ -21,11 +21,13 @@ "decimal.js-light": "^2.5.1", "fast-csv": "^5.0.1", "jsbi": "^4.3.0", + "lodash": "^4.17.21", "tiny-invariant": "^1.3.1", "toformat": "^2.0.0", "viem": "^2.8.13" }, "devDependencies": { + "@types/lodash": "^4.17.13", "@types/node": "^20.11.17", "typescript": "^5.3.3" } diff --git a/adapters/lynex/src/index.ts b/adapters/lynex/src/index.ts index 2f3fd61b..f9c0cfae 100644 --- a/adapters/lynex/src/index.ts +++ b/adapters/lynex/src/index.ts @@ -1,12 +1,12 @@ import fs from "fs"; import { write } from "fast-csv"; import csv from "csv-parser"; -import { getTimestampAtBlock, getUserAddresses } from "./sdk/subgraphDetails"; import { - LYNX_ADDRESS, - fetchUserPools, - fetchUserVotes, -} from "./sdk/lensDetails"; + getGauges, + getTimestampAtBlock, + getUserAddresses, +} from "./sdk/subgraphDetails"; +import { LYNX_ADDRESS, fetchPools, fetchVeLynx } from "./sdk/lensDetails"; import BigNumber from "bignumber.js"; import { BlockData, OutputSchemaRow } from "./sdk/types"; import { @@ -80,64 +80,38 @@ export const getUserStakedTVLByBlock = async ({ blockTimestamp, }: BlockData): Promise => { const result: OutputSchemaRow[] = []; - const [userAddresses] = await Promise.all([getUserAddresses(blockNumber)]); + const [userAddresses, allGauges] = await Promise.all([ + getUserAddresses(blockNumber), + getGauges(blockNumber), + ]); console.log(`Block: ${blockNumber}`); console.log("UserAddresses: ", userAddresses.length); + console.log("Gauges: ", allGauges.length); + + const pools = await fetchPools(BigInt(blockNumber), allGauges); const tokenBalanceMap = {} as { [userAddress: string]: { [tokenAddress: string]: BigNumber }; }; - let userPoolFetch = []; - let userVotesFetch = []; - - const batchSize = 100; - let position = 0; - let userFetchResult: any = []; - let userVotesResult: any = []; + let userVotesResult = await fetchVeLynx(BigInt(blockNumber)); for (const user of userAddresses) { - userPoolFetch.push( - fetchUserPools(BigInt(blockNumber), user.id, user.pools) - ); - userVotesFetch.push(fetchUserVotes(BigInt(blockNumber), user.id)); - if (position % batchSize === 0) { - userFetchResult = [ - ...userFetchResult, - ...(await Promise.all(userPoolFetch)), - ]; - userPoolFetch = []; - userVotesResult = [ - ...userVotesResult, - ...(await Promise.all(userVotesFetch)), - ]; - userVotesFetch = []; - console.timeEnd("Batch"); - const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) - await delay(60000) - } - position++; - } - - userVotesResult = [ - ...userVotesResult, - ...(await Promise.all(userVotesFetch)), - ]; - - userFetchResult = [...userFetchResult, ...(await Promise.all(userPoolFetch))]; - - for (const userFetchedPools of userFetchResult) { - for (const userPool of userFetchedPools) { - const user_address = userPool.result.userAddress.toLowerCase(); - const totalLPBalance = userPool.result.account_gauge_balance; + for (const userPool of user.liquidityPositions) { + const currentPool = pools[userPool.gauge.pool.toLowerCase()] + ? pools[userPool.gauge.pool.toLowerCase()][0] + : undefined; + if (currentPool) { + const user_address = user.id.toLowerCase(); + const totalLPBalance = BigInt(userPool.amount); const total0 = - (totalLPBalance * userPool.result.reserve0) / - userPool.result.total_supply; + (totalLPBalance * BigInt(currentPool.reserve0)) / + BigInt(currentPool.total_supply); const total1 = - (totalLPBalance * userPool.result.reserve1) / - userPool.result.total_supply; - const token0Address = userPool.result.token0.toLowerCase(); - const token1Address = userPool.result.token1.toLowerCase(); + (totalLPBalance * BigInt(currentPool.reserve1)) / + BigInt(currentPool.total_supply); + const token0Address = currentPool.token0.toLowerCase(); + const token1Address = currentPool.token1.toLowerCase(); // Aggregate tokens tokenBalanceMap[user_address] = tokenBalanceMap[user_address] ?? {}; @@ -148,18 +122,18 @@ export const getUserStakedTVLByBlock = async ({ tokenBalanceMap[user_address][token1Address] = BigNumber( tokenBalanceMap[user_address][token1Address] ?? 0 ).plus(total1.toString()); + } } } - for (const userFecthedVotes of userVotesResult) { - for (const userVote of userFecthedVotes) { + for (const userVote of userVotesResult) { + if (!userVote.result?.userAddress) continue; const user_address = userVote.result.userAddress.toLowerCase(); const token0Address = LYNX_ADDRESS.toLowerCase(); tokenBalanceMap[user_address] = tokenBalanceMap[user_address] ?? {}; tokenBalanceMap[user_address][token0Address] = BigNumber( tokenBalanceMap[user_address][token0Address] ?? 0 - ).plus(userVote.result.amount?.toString() ?? '0'); - } + ).plus(userVote.result.amount?.toString() ?? "0"); } Object.entries(tokenBalanceMap).forEach(([user_address, balances]) => { diff --git a/adapters/lynex/src/sdk/lensDetails.ts b/adapters/lynex/src/sdk/lensDetails.ts index d0aab9af..54d63789 100644 --- a/adapters/lynex/src/sdk/lensDetails.ts +++ b/adapters/lynex/src/sdk/lensDetails.ts @@ -10,6 +10,8 @@ import { import { client, PROBLEM_POOLS } from "./config"; import lensABI from "./abis/PairAPIABI.json"; import veLYNXAbi from "./abis/veLYNX.json"; +import { Gauge } from "./subgraphDetails"; +import { chunk, flatten, groupBy } from 'lodash'; export const LENS_ADDRESS = "0x6c84329CC8c37376eb32db50a17F3bFc917c3665"; // PairAPI export const VE_LYNX_ADDRESS = "0x8d95f56b0bac46e8ac1d3a3f12fb1e5bc39b4c0c"; // veLYNX @@ -53,6 +55,10 @@ export interface LensResponseWithBlock { result: LensResponse; } +export interface PoolsLensResponseWithBlock { + [key: string]: LensResponse[]; +} + export interface VoteRequest { userAddress: string; amount: bigint; @@ -94,6 +100,41 @@ export const fetchUserPools = async ( }) as LensResponseWithBlock[]; }; +export const fetchPools = async ( + blockNumber: bigint, + allGauges: Gauge[], +): Promise => { + const publicClient = client; + const validPools = allGauges.filter( + (gauge) => + PROBLEM_POOLS[gauge.pool] === undefined || + PROBLEM_POOLS[gauge.pool] > blockNumber, + ); + + const calls = validPools.map((gauge: Gauge) => { + return { + address: LENS_ADDRESS, + name: 'getPair', + params: [gauge.pool, '0x0000000000000000000000000000000000000000'], + }; + }); + + const res = await multicall( + publicClient, + lensABI as Abi, + calls, + blockNumber, + ); + + const mapped = res.map((r: any) => { + return { ...r.result, pair_address: r.result.pair_address.toLowerCase() }; + }); + + const grouped = groupBy(mapped, 'pair_address'); + + return grouped; +}; + export const fetchUserVotes = async ( blockNumber: bigint, userAddress: string @@ -152,6 +193,81 @@ export const fetchUserVotes = async ( }) as VoteResponse[]; }; +export const fetchVeLynx = async ( + blockNumber: bigint, +): Promise => { + const publicClient = client; + + const totalNftIdsCall = await multicall( + publicClient, + veLYNXAbi as Abi, + [ + { + address: VE_LYNX_ADDRESS, + name: "totalNftsMinted", + }, + ], + blockNumber + ); + + const totalNftIds = parseInt(totalNftIdsCall[0].result as string) + + const calls = []; + for (let i = 2; i <= totalNftIds; i++) { + calls.push({ + address: VE_LYNX_ADDRESS, + name: "ownerOf", + params: [i], + }); + } + + const addressCalls = await multicallChunk( + publicClient, + veLYNXAbi as Abi, + calls, + blockNumber, + 3000 + ); + + const detailsCall = addressCalls.map((call, i) => { + return { + address: VE_LYNX_ADDRESS, + name: "lockDetails", + params: [i + 2], + }; + }); + + const res = (await multicallChunk( + publicClient, + veLYNXAbi as Abi, + detailsCall, + blockNumber, + 3000 + )) as any; + const result = res.map((r: any, i: number) => { + return { result: { ...r.result, userAddress: addressCalls[i].result } }; + }) as VoteResponse[]; + return result +}; + +async function multicallChunk( + publicClient: PublicClient, + abi: Abi, + calls: any[], + blockNumber: bigint, + size = 100 +) { + const chunked = chunk(calls, size); + const callsPromises = []; + for (let i = 0; i < chunked.length; i++) { + callsPromises.push( + multicall(publicClient, abi, chunked[i], blockNumber), + ); + } + const res = await Promise.all(callsPromises); + return flatten(res); +} + function multicall( publicClient: PublicClient, abi: Abi, diff --git a/adapters/lynex/src/sdk/subgraphDetails.ts b/adapters/lynex/src/sdk/subgraphDetails.ts index 38bbfc8b..98e73573 100644 --- a/adapters/lynex/src/sdk/subgraphDetails.ts +++ b/adapters/lynex/src/sdk/subgraphDetails.ts @@ -2,9 +2,44 @@ import { createPublicClient, extractChain, http } from "viem"; import { linea } from "viem/chains"; import { GAUGE_SUBGRAPH_URL, client } from "./config"; -interface UserStake { +export interface UserStake { id: string; pools: any[]; + liquidityPositions: LiquidityPosition[]; +} +export interface Gauge { + id: string; + pool: string; + token0: { + id: string; + symbol: string; + }; + token1: { + id: string; + symbol: string; + }; +} + +export interface Token { + symbol: string; + id: string; +} + +export interface GaugePosition { + id: string; + token0: Token; + token1: Token; + pool: string; +} + +export interface LiquidityPosition { + id: string; + gauge: GaugePosition; + amount: string; + userToken0: string; + userToken1: string; + userToken0Decimals: string; + userToken1Decimals: string; } export const getUserAddresses = async ( @@ -56,6 +91,7 @@ export const getUserAddresses = async ( let transformedUserStake: UserStake = { id: userStake.id, pools: userStake.liquidityPositions.map((lp: any) => lp.gauge.pool), + liquidityPositions: userStake.liquidityPositions, }; result.push(transformedUserStake); } @@ -68,6 +104,52 @@ export const getUserAddresses = async ( return result; }; +export async function getGauges(blockNumber: number): Promise { + + let subgraphUrl = GAUGE_SUBGRAPH_URL; + const blockQuery = + blockNumber !== 0 ? ` block: {number: ${blockNumber}}` : ``; + + let skip = 0; + let fetchNext = true; + const result: Gauge[] = []; + while (fetchNext) { + const query = ` + query GaugesQuery { + gauges(${blockQuery} first:1000,skip:${skip}) { + id + pool + token0 { + id + symbol + } + token1 { + id + symbol + } + } + }`; + + const response = await fetch(subgraphUrl, { + method: 'POST', + body: JSON.stringify({ query }), + headers: { 'Content-Type': 'application/json' }, + }); + const data = await response.json(); + const gauges = data.data.gauges; + for (let i = 0; i < gauges.length; i++) { + const gauge = gauges[i]; + result.push(gauge); + } + if (gauges.length < 1000) { + fetchNext = false; + } else { + skip += 1000; + } + } + return result; +} + export const getTimestampAtBlock = async (blockNumber: number) => { const publicClient = client; diff --git a/adapters/lynex/yarn.lock b/adapters/lynex/yarn.lock index 7d4fae57..da8ab156 100644 --- a/adapters/lynex/yarn.lock +++ b/adapters/lynex/yarn.lock @@ -3,204 +3,214 @@ "@adraffy/ens-normalize@1.10.0": - "integrity" "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" - "resolved" "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz" - "version" "1.10.0" + version "1.10.0" + resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== "@fast-csv/format@5.0.0": - "integrity" "sha512-IyMpHwYIOGa2f0BJi6Wk55UF0oBA5urdIydoEDYxPo88LFbeb3Yr4rgpu98OAO1glUWheSnNtUgS80LE+/dqmw==" - "resolved" "https://registry.npmjs.org/@fast-csv/format/-/format-5.0.0.tgz" - "version" "5.0.0" + version "5.0.0" + resolved "https://registry.npmjs.org/@fast-csv/format/-/format-5.0.0.tgz" + integrity sha512-IyMpHwYIOGa2f0BJi6Wk55UF0oBA5urdIydoEDYxPo88LFbeb3Yr4rgpu98OAO1glUWheSnNtUgS80LE+/dqmw== dependencies: - "lodash.escaperegexp" "^4.1.2" - "lodash.isboolean" "^3.0.3" - "lodash.isequal" "^4.5.0" - "lodash.isfunction" "^3.0.9" - "lodash.isnil" "^4.0.0" + lodash.escaperegexp "^4.1.2" + lodash.isboolean "^3.0.3" + lodash.isequal "^4.5.0" + lodash.isfunction "^3.0.9" + lodash.isnil "^4.0.0" "@fast-csv/parse@5.0.0": - "integrity" "sha512-ecF8tCm3jVxeRjEB6VPzmA+1wGaJ5JgaUX2uesOXdXD6qQp0B3EdshOIed4yT1Xlj/F2f8v4zHSo0Oi31L697g==" - "resolved" "https://registry.npmjs.org/@fast-csv/parse/-/parse-5.0.0.tgz" - "version" "5.0.0" + version "5.0.0" + resolved "https://registry.npmjs.org/@fast-csv/parse/-/parse-5.0.0.tgz" + integrity sha512-ecF8tCm3jVxeRjEB6VPzmA+1wGaJ5JgaUX2uesOXdXD6qQp0B3EdshOIed4yT1Xlj/F2f8v4zHSo0Oi31L697g== dependencies: - "lodash.escaperegexp" "^4.1.2" - "lodash.groupby" "^4.6.0" - "lodash.isfunction" "^3.0.9" - "lodash.isnil" "^4.0.0" - "lodash.isundefined" "^3.0.1" - "lodash.uniq" "^4.5.0" - -"@noble/curves@~1.2.0", "@noble/curves@1.2.0": - "integrity" "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==" - "resolved" "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz" - "version" "1.2.0" + lodash.escaperegexp "^4.1.2" + lodash.groupby "^4.6.0" + lodash.isfunction "^3.0.9" + lodash.isnil "^4.0.0" + lodash.isundefined "^3.0.1" + lodash.uniq "^4.5.0" + +"@noble/curves@1.2.0", "@noble/curves@~1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== dependencies: "@noble/hashes" "1.3.2" -"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2", "@noble/hashes@1.3.2": - "integrity" "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" - "resolved" "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz" - "version" "1.3.2" +"@noble/hashes@1.3.2", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": + version "1.3.2" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== "@scure/base@~1.1.0", "@scure/base@~1.1.2": - "integrity" "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==" - "resolved" "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz" - "version" "1.1.6" + version "1.1.6" + resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz" + integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g== "@scure/bip32@1.3.2": - "integrity" "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==" - "resolved" "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz" - "version" "1.3.2" + version "1.3.2" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz" + integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== dependencies: "@noble/curves" "~1.2.0" "@noble/hashes" "~1.3.2" "@scure/base" "~1.1.2" "@scure/bip39@1.2.1": - "integrity" "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==" - "resolved" "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz" - "version" "1.2.1" + version "1.2.1" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== dependencies: "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" "@types/big.js@^6.2.2": - "integrity" "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==" - "resolved" "https://registry.npmjs.org/@types/big.js/-/big.js-6.2.2.tgz" - "version" "6.2.2" + version "6.2.2" + resolved "https://registry.npmjs.org/@types/big.js/-/big.js-6.2.2.tgz" + integrity sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA== + +"@types/lodash@^4.17.13": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.13.tgz#786e2d67cfd95e32862143abe7463a7f90c300eb" + integrity sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg== "@types/node@^20.11.17": - "integrity" "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==" - "resolved" "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz" - "version" "20.11.30" + version "20.11.30" + resolved "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz" + integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw== dependencies: - "undici-types" "~5.26.4" - -"abitype@1.0.0": - "integrity" "sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==" - "resolved" "https://registry.npmjs.org/abitype/-/abitype-1.0.0.tgz" - "version" "1.0.0" - -"big.js@^6.2.1": - "integrity" "sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ==" - "resolved" "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz" - "version" "6.2.1" - -"bignumber.js@^9.1.2": - "integrity" "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==" - "resolved" "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz" - "version" "9.1.2" - -"csv-parser@^3.0.0": - "integrity" "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==" - "resolved" "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz" - "version" "3.0.0" + undici-types "~5.26.4" + +abitype@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/abitype/-/abitype-1.0.0.tgz" + integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== + +big.js@^6.2.1: + version "6.2.1" + resolved "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz" + integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== + +bignumber.js@^9.1.2: + version "9.1.2" + resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + +csv-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz" + integrity sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ== dependencies: - "minimist" "^1.2.0" + minimist "^1.2.0" -"decimal.js-light@^2.5.1": - "integrity" "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" - "resolved" "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz" - "version" "2.5.1" +decimal.js-light@^2.5.1: + version "2.5.1" + resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== -"fast-csv@^5.0.1": - "integrity" "sha512-Q43zC4NdQD5MAWOVQOF8KA+D6ddvTJjX2ib8zqysm74jZhtk6+dc8C75/OqRV6Y9CLc4kgvbC3PLG8YL4YZfgw==" - "resolved" "https://registry.npmjs.org/fast-csv/-/fast-csv-5.0.1.tgz" - "version" "5.0.1" +fast-csv@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/fast-csv/-/fast-csv-5.0.1.tgz" + integrity sha512-Q43zC4NdQD5MAWOVQOF8KA+D6ddvTJjX2ib8zqysm74jZhtk6+dc8C75/OqRV6Y9CLc4kgvbC3PLG8YL4YZfgw== dependencies: "@fast-csv/format" "5.0.0" "@fast-csv/parse" "5.0.0" -"isows@1.0.3": - "integrity" "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==" - "resolved" "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz" - "version" "1.0.3" - -"jsbi@^4.3.0": - "integrity" "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==" - "resolved" "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz" - "version" "4.3.0" - -"lodash.escaperegexp@^4.1.2": - "integrity" "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==" - "resolved" "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz" - "version" "4.1.2" - -"lodash.groupby@^4.6.0": - "integrity" "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==" - "resolved" "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz" - "version" "4.6.0" - -"lodash.isboolean@^3.0.3": - "integrity" "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - "resolved" "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" - "version" "3.0.3" - -"lodash.isequal@^4.5.0": - "integrity" "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - "resolved" "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" - "version" "4.5.0" - -"lodash.isfunction@^3.0.9": - "integrity" "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - "resolved" "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz" - "version" "3.0.9" - -"lodash.isnil@^4.0.0": - "integrity" "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==" - "resolved" "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz" - "version" "4.0.0" - -"lodash.isundefined@^3.0.1": - "integrity" "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==" - "resolved" "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz" - "version" "3.0.1" - -"lodash.uniq@^4.5.0": - "integrity" "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - "resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" - "version" "4.5.0" - -"minimist@^1.2.0": - "integrity" "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" - "version" "1.2.8" - -"tiny-invariant@^1.3.1": - "integrity" "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - "resolved" "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz" - "version" "1.3.3" - -"toformat@^2.0.0": - "integrity" "sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ==" - "resolved" "https://registry.npmjs.org/toformat/-/toformat-2.0.0.tgz" - "version" "2.0.0" - -"typescript@^5.3.3", "typescript@>=5.0.4": - "integrity" "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==" - "resolved" "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz" - "version" "5.4.3" - -"undici-types@~5.26.4": - "integrity" "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - "resolved" "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" - "version" "5.26.5" - -"viem@^2.8.13": - "integrity" "sha512-J8tu1aP7TfI2HT/IEmyJ+n+WInrA/cuMuJtfgvYhYgHBobxhYGc2SojHm5lZBWcWgErN1Ld7VcKUwTmPh4ToQA==" - "resolved" "https://registry.npmjs.org/viem/-/viem-2.8.16.tgz" - "version" "2.8.16" +isows@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + +jsbi@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz" + integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== + +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz" + integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw== + +lodash.groupby@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz" + integrity sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.isfunction@^3.0.9: + version "3.0.9" + resolved "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz" + integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== + +lodash.isnil@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz" + integrity sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng== + +lodash.isundefined@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz" + integrity sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA== + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +tiny-invariant@^1.3.1: + version "1.3.3" + resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + +toformat@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/toformat/-/toformat-2.0.0.tgz" + integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== + +typescript@^5.3.3: + version "5.4.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +viem@^2.8.13: + version "2.8.16" + resolved "https://registry.npmjs.org/viem/-/viem-2.8.16.tgz" + integrity sha512-J8tu1aP7TfI2HT/IEmyJ+n+WInrA/cuMuJtfgvYhYgHBobxhYGc2SojHm5lZBWcWgErN1Ld7VcKUwTmPh4ToQA== dependencies: "@adraffy/ens-normalize" "1.10.0" "@noble/curves" "1.2.0" "@noble/hashes" "1.3.2" "@scure/bip32" "1.3.2" "@scure/bip39" "1.2.1" - "abitype" "1.0.0" - "isows" "1.0.3" - "ws" "8.13.0" - -"ws@*", "ws@8.13.0": - "integrity" "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==" - "resolved" "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz" - "version" "8.13.0" + abitype "1.0.0" + isows "1.0.3" + ws "8.13.0" + +ws@8.13.0: + version "8.13.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==