From 6e300d6bd0a618a86050569b35920f102bf3a3d6 Mon Sep 17 00:00:00 2001 From: SdCrypt0 Date: Mon, 20 May 2024 16:33:23 +0300 Subject: [PATCH 1/3] Metavault adapter updated --- adapters/metavault/package.json | 9 +- adapters/metavault/src/index.ts | 203 ++++----- adapters/metavault/src/sdk/blockApi.ts | 35 -- adapters/metavault/src/sdk/config.ts | 31 +- .../metavault/src/sdk/entities/positions.ts | 24 -- adapters/metavault/src/sdk/lib.ts | 290 +++++++++++++ adapters/metavault/src/sdk/mathUtils.ts | 37 -- adapters/metavault/src/sdk/poolDetails.ts | 0 adapters/metavault/src/sdk/positionDetails.ts | 51 --- adapters/metavault/src/sdk/subgraphDetails.ts | 386 ------------------ adapters/metavault/src/sdk/types.ts | 32 ++ adapters/metavault/src/sdk/utils/constant.ts | 38 -- .../src/sdk/utils/fractions/fraction.ts | 159 -------- .../src/sdk/utils/fractions/percent.ts | 43 -- adapters/metavault/src/sdk/utils/fullMath.ts | 16 - .../src/sdk/utils/internalConstants.ts | 16 - .../src/sdk/utils/mostSignificantBit.ts | 20 - .../metavault/src/sdk/utils/positionMath.ts | 50 --- .../src/sdk/utils/squarePriceMath.ts | 131 ------ .../metavault/src/sdk/utils/tickLibrary.ts | 59 --- adapters/metavault/src/sdk/utils/tickMath.ts | 115 ------ adapters/metavault/tsconfig.json | 26 +- 22 files changed, 419 insertions(+), 1352 deletions(-) delete mode 100644 adapters/metavault/src/sdk/blockApi.ts delete mode 100644 adapters/metavault/src/sdk/entities/positions.ts create mode 100644 adapters/metavault/src/sdk/lib.ts delete mode 100644 adapters/metavault/src/sdk/mathUtils.ts delete mode 100644 adapters/metavault/src/sdk/poolDetails.ts delete mode 100644 adapters/metavault/src/sdk/positionDetails.ts delete mode 100644 adapters/metavault/src/sdk/subgraphDetails.ts create mode 100644 adapters/metavault/src/sdk/types.ts delete mode 100644 adapters/metavault/src/sdk/utils/constant.ts delete mode 100644 adapters/metavault/src/sdk/utils/fractions/fraction.ts delete mode 100644 adapters/metavault/src/sdk/utils/fractions/percent.ts delete mode 100644 adapters/metavault/src/sdk/utils/fullMath.ts delete mode 100644 adapters/metavault/src/sdk/utils/internalConstants.ts delete mode 100644 adapters/metavault/src/sdk/utils/mostSignificantBit.ts delete mode 100644 adapters/metavault/src/sdk/utils/positionMath.ts delete mode 100644 adapters/metavault/src/sdk/utils/squarePriceMath.ts delete mode 100644 adapters/metavault/src/sdk/utils/tickLibrary.ts delete mode 100644 adapters/metavault/src/sdk/utils/tickMath.ts diff --git a/adapters/metavault/package.json b/adapters/metavault/package.json index eccdbff5..db241ce0 100644 --- a/adapters/metavault/package.json +++ b/adapters/metavault/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "description": "", "main": "index.js", + "type": "commonjs", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node dist/index.js", @@ -12,17 +13,11 @@ }, "keywords": [], "author": "", - "license": "ISC", + "license": "UNLICENSED", "dependencies": { - "@types/big.js": "^6.2.2", - "big.js": "^6.2.1", "bignumber.js": "^9.1.2", "csv-parser": "^3.0.0", - "decimal.js-light": "^2.5.1", "fast-csv": "^5.0.1", - "jsbi": "^4.3.0", - "tiny-invariant": "^1.3.1", - "toformat": "^2.0.0", "viem": "^2.8.13" }, "devDependencies": { diff --git a/adapters/metavault/src/index.ts b/adapters/metavault/src/index.ts index 0e32019d..ed3666a3 100644 --- a/adapters/metavault/src/index.ts +++ b/adapters/metavault/src/index.ts @@ -1,145 +1,96 @@ -import { CHAINS, PROTOCOLS, AMM_TYPES } from "./sdk/config"; -import { getPositionDetailsFromPosition, getPositionsForAddressByPoolAtBlock, getTimestampAtBlock, getTradeLiquidityForAddressByPoolAtBlock } from "./sdk/subgraphDetails"; -(BigInt.prototype as any).toJSON = function () { - return this.toString(); -}; -import { write } from 'fast-csv'; +import { promisify } from 'util'; +import stream from 'stream'; import csv from 'csv-parser'; import fs from 'fs'; +import { write } from 'fast-csv'; + +import { BlockData, OutputSchemaRow } from './sdk/types'; +import { getTimestampAtBlock, getTradeLiquidityForAddressByPoolAtBlock, getV2UserPositionsAtBlock, getV3UserPositionsAtBlock } from './sdk/lib'; -interface BlockData { - blockNumber: number; - blockTimestamp: number; -} +const pipeline = promisify(stream.pipeline); -type OutputDataSchemaRow = { - block_number: number; - timestamp: number; - user_address: string; - token_address: string; - token_balance: number; - token_symbol?: string; - usd_price: number; +const readBlocksFromCSV = async (filePath: string): Promise => { + const blocks: number[] = []; + await pipeline( + fs.createReadStream(filePath), + csv(), + async function* (source) { + for await (const chunk of source) { + // Assuming each row in the CSV has a column 'block' with the block number + if (chunk.block) blocks.push(parseInt(chunk.block, 10)); + } + } + ); + return blocks; }; +const getData = async () => { + const blocks = [ + 4314766 + ]; //await readBlocksFromCSV('src/sdk/mode_chain_daily_blocks.csv'); -export const getUserTVLByBlock = async ({ - blockNumber, - blockTimestamp, -}: BlockData): Promise => { - return await getPoolData({ blockNumber, blockTimestamp }); -} + const csvRows: OutputSchemaRow[] = []; -export const getPoolData = async ({ - blockNumber, - blockTimestamp, -}: BlockData): Promise => { - const allCsvRows: OutputDataSchemaRow[] = []; // Array to accumulate CSV rows for all blocks - try { - // const blockTimestamp = new Date(await getTimestampAtBlock(blockNumber)).toISOString(); - const positions = await getPositionsForAddressByPoolAtBlock( - blockNumber, "", "", CHAINS.L2_CHAIN_ID, PROTOCOLS.METAVAULT, AMM_TYPES.UNISWAPV3 - ); + for (const block of blocks) { + const timestamp = await getTimestampAtBlock(block) - console.log(`Block: ${blockNumber}`); - console.log("Positions: ", positions.length); + csvRows.push(...await getUserTVLByBlock({ blockNumber: block, blockTimestamp: timestamp })) + } + // Write the CSV output to a file + const ws = fs.createWriteStream('outputData.csv'); + write(csvRows, { headers: true }).pipe(ws).on('finish', () => { + console.log("CSV file has been written."); + }); +}; - // Assuming this part of the logic remains the same - let positionsWithUSDValue = positions.map(getPositionDetailsFromPosition); - // let lpValueByUsers = getLPValueByUserAndPoolFromPositions(positionsWithUSDValue); +export const getUserTVLByBlock = async ({ blockNumber, blockTimestamp }: BlockData): Promise => { + const result: OutputSchemaRow[] = [] - positionsWithUSDValue.forEach((value, key) => { - // Accumulate CSV row data - if (value.token0DecimalValue > 0) { - allCsvRows.push({ - block_number: blockNumber, - timestamp: blockTimestamp, - user_address: value.owner, - token_address: value.token0.id, - token_balance: value.token0DecimalValue, - usd_price: 0, - }); - } - if (value.token1DecimalValue > 0) { - allCsvRows.push({ - block_number: blockNumber, - timestamp: blockTimestamp, - user_address: value.owner, - token_address: value.token1.id, - token_balance: value.token1DecimalValue, - usd_price: 0, - }); - } - }); - const liquidities = await getTradeLiquidityForAddressByPoolAtBlock( - blockNumber, "", "", CHAINS.L2_CHAIN_ID, PROTOCOLS.METAVAULT, AMM_TYPES.TRADE - ); - liquidities.forEach((value, key) => { - if (value.amount > 0) { - allCsvRows.push({ - block_number: blockNumber, - timestamp: blockTimestamp, - user_address: value.user, - token_address: value.asset, - token_balance: value.amount, - usd_price: 0, - }); - } - }); + const [v2Positions, v3Positions, tradeLiquidities] = await Promise.all([ + getV2UserPositionsAtBlock(blockNumber), + getV3UserPositionsAtBlock(blockNumber), + getTradeLiquidityForAddressByPoolAtBlock(blockNumber) + ]) + + // combine v2 & v3 + const combinedPositions = [...v2Positions, ...v3Positions] + const balances: Record> = {} + for (const position of combinedPositions) { + balances[position.user] = balances[position.user] || {} - } catch (error) { - console.error(`An error occurred for block ${blockNumber}:`, error); - } - return allCsvRows -} + if (position.token0.balance > 0n) + balances[position.user][position.token0.address] = + (balances?.[position.user]?.[position.token0.address] ?? 0n) + + position.token0.balance -const readBlocksFromCSV = async (filePath: string): Promise => { - const blocks: BlockData[] = []; + if (position.token1.balance > 0n) + balances[position.user][position.token1.address] = + (balances?.[position.user]?.[position.token1.address] ?? 0n) + + position.token1.balance + } + for (const position of tradeLiquidities) { + balances[position.user] = balances[position.user] || {} - await new Promise((resolve, reject) => { - fs.createReadStream(filePath) - .pipe(csv()) // Specify the separator as '\t' for TSV files - .on('data', (row) => { - const blockNumber = parseInt(row.number, 10); - const blockTimestamp = parseInt(row.timestamp, 10); - if (!isNaN(blockNumber) && blockTimestamp) { - blocks.push({ blockNumber: blockNumber, blockTimestamp }); + if (position.amount > 0n) + balances[position.user][position.asset] = + (balances?.[position.user]?.[position.asset] ?? 0n) + + position.amount + } + for (const [user, tokenBalances] of Object.entries(balances)) { + for (const [token, balance] of Object.entries(tokenBalances)) { + result.push({ + block_number: blockNumber, + timestamp: blockTimestamp, + user_address: user, + token_address: token, + token_balance: balance, + }) } - }) - .on('end', () => { - resolve(); - }) - .on('error', (err) => { - reject(err); - }); - }); + } - return blocks; + return result }; -readBlocksFromCSV('hourly_blocks.csv').then(async (blocks: BlockData[]) => { - console.log(blocks); - const allCsvRows: any[] = []; // Array to accumulate CSV rows for all blocks - - for (const block of blocks) { - try { - const result = await getUserTVLByBlock(block); - for(let i = 0; i < result.length; i++){ - allCsvRows.push(result[i]) - } - } catch (error) { - console.error(`An error occurred for block ${block}:`, error); - } - } - await new Promise((resolve, reject) => { - const ws = fs.createWriteStream(`outputData.csv`, { flags: 'w' }); - write(allCsvRows, { headers: true }) - .pipe(ws) - .on("finish", () => { - console.log(`CSV file has been written.`); - resolve; - }); - }); -}).catch((err) => { - console.error('Error reading CSV file:', err); +getData().then(() => { + console.log("Done"); }); \ No newline at end of file diff --git a/adapters/metavault/src/sdk/blockApi.ts b/adapters/metavault/src/sdk/blockApi.ts deleted file mode 100644 index 5ac856bc..00000000 --- a/adapters/metavault/src/sdk/blockApi.ts +++ /dev/null @@ -1,35 +0,0 @@ -export const readBlocksFromApi = async (startTime: number, endTime: number): Promise => { - const results = [] - for (let i = startTime; i <= endTime; i += 3600) { - let response = await fetch(`https://api.lineascan.build/api?module=block&action=getblocknobytime×tamp=${i}&closest=after&apikey=ADD_API_KEY`, { - headers: { "Content-Type": "application/json" }, - }); - - const json = await response.json() - // sleep - await new Promise(r => setTimeout(r, 1000)); - results.push(Number(json.result)) - } - console.log(results); - - return results - - // daily blocks - return [ - 1459540, 1473940, 1488339, 1502715, 1517109, 1531509, - 1545909, 1560309, 1574707, 1589104, 1603499, 1617898, - 1632296, 1646696, 1661096, 1675487, 1689885, 1704285, - 1718685, 1733085, 1747485, 1761885, 1779844, 1800972, - 1822511, 1844067, 1865652, 1887247, 1908844, 1930429, - 1951984, 1973539, 1994976, 2016544, 2038130, 2059720, - 2081313, 2102851, 2124303, 2145723, 2166829, 2188347, - 2209908, 2231357, 2252825, 2274361, 2295942, 2317539, - 2339139, 2360738, 2382328, 2403928, 2425521, 2447121, - 2468721, 2490321, 2511921, 2533521, 2555120, 2576720, - 2598320, 2619920, 2641520, 2663120, 2684720, 2706320, - 2727920, 2749520, 2771120, 2792720, 2814320, 2835920, - 2857520, 2879120, 2900720, 2922320, 2943907, 2965507, - 2987107, 3008707, 3030307, 3051907, 3073507, 3095107, - 3116707 - ] -} \ No newline at end of file diff --git a/adapters/metavault/src/sdk/config.ts b/adapters/metavault/src/sdk/config.ts index 9fdbfc9f..dbc5b84a 100644 --- a/adapters/metavault/src/sdk/config.ts +++ b/adapters/metavault/src/sdk/config.ts @@ -1,24 +1,11 @@ -export const enum CHAINS{ - L2_CHAIN_ID = 59144, -} -export const enum PROTOCOLS{ - METAVAULT = 0, -} +import { createPublicClient, http } from "viem"; +import { linea } from "viem/chains" -export const enum AMM_TYPES{ - UNISWAPV3 = 0, - TRADE = 1 -} +export const V2_SUBGRAPH_URL = "https://api.studio.thegraph.com/query/55804/linea-v2/version/latest" +export const V3_SUBGRAPH_URL = "https://api.studio.thegraph.com/query/55804/linea-v3/version/latest" +export const TRADE_SUBGRAPH_URL = "https://api.studio.thegraph.com/query/55804/linea-trade/version/latest" -export const SUBGRAPH_URLS = { - [CHAINS.L2_CHAIN_ID]: { - [PROTOCOLS.METAVAULT]: { - [AMM_TYPES.UNISWAPV3]: "https://api.studio.thegraph.com/query/55804/linea-v3/version/latest", - [AMM_TYPES.TRADE]: "https://api.studio.thegraph.com/query/55804/linea-trade/version/latest" - } - }, - -} -export const RPC_URLS = { - [CHAINS.L2_CHAIN_ID]: "https://rpc.linea.build" -} \ No newline at end of file +export const client = createPublicClient({ + chain: linea, + transport: http("https://rpc.linea.build") +}) \ No newline at end of file diff --git a/adapters/metavault/src/sdk/entities/positions.ts b/adapters/metavault/src/sdk/entities/positions.ts deleted file mode 100644 index bb410185..00000000 --- a/adapters/metavault/src/sdk/entities/positions.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Q128 } from '../utils/internalConstants' -import { subIn256 } from '../utils/tickLibrary' - -export abstract class PositionLibrary { - /** - * Cannot be constructed. - */ - private constructor() {} - - // replicates the portions of Position#update required to compute unaccounted fees - public static getTokensOwed( - feeGrowthInside0LastX128: bigint, - feeGrowthInside1LastX128: bigint, - liquidity: bigint, - feeGrowthInside0X128: bigint, - feeGrowthInside1X128: bigint - ) { - const tokensOwed0 = (subIn256(feeGrowthInside0X128, feeGrowthInside0LastX128) * liquidity) / Q128 - - const tokensOwed1 = (subIn256(feeGrowthInside1X128, feeGrowthInside1LastX128) * liquidity) / Q128 - - return [tokensOwed0, tokensOwed1] - } -} diff --git a/adapters/metavault/src/sdk/lib.ts b/adapters/metavault/src/sdk/lib.ts new file mode 100644 index 00000000..d133109f --- /dev/null +++ b/adapters/metavault/src/sdk/lib.ts @@ -0,0 +1,290 @@ +import { TRADE_SUBGRAPH_URL, V2_SUBGRAPH_URL, V3_SUBGRAPH_URL, client } from "./config" +import { UserLiquidity, UserPosition } from "./types" + +type V2Position = { + balance: string, + user: { + id: string, + }, + pair: { + liquidity: string, + reserve0: string, + reserve1: string, + token0: { + id: string, + symbol: string, + }, + token1: { + id: string, + symbol: string, + } + token0Price: string, + token1Price: string + } +} + +const getV2PositionReserves = (position: V2Position) => { + return { + reserve0: BigInt(position.pair.reserve0) * BigInt(position.balance) / BigInt(position.pair.liquidity), + reserve1: BigInt(position.pair.reserve1) * BigInt(position.balance) / BigInt(position.pair.liquidity) + } +} + +export const getV2UserPositionsAtBlock = async (blockNumber: number): Promise => { + const result: UserPosition[] = [] + + let skip = 0 + let fetchNext = true + while (fetchNext) { + const query = `query { + liquidityPositions( + first: 1000, + skip: ${skip}, + where: { balance_gt: 0 }, + block: { number: ${blockNumber} } + ) { + balance + user { + id + } + pair { + liquidity + reserve0 + reserve1 + token0 { + id + symbol + } + token1 { + id + symbol + } + token0Price + token1Price + } + } + }` + + const response = await fetch(V2_SUBGRAPH_URL, { + method: "POST", + body: JSON.stringify({ query }), + headers: { "Content-Type": "application/json" }, + }) + const { data: { liquidityPositions } } = await response.json(); + + result.push(...liquidityPositions.map((position: V2Position) => { + const { reserve0, reserve1 } = getV2PositionReserves(position) + return { + user: position.user.id, + token0: { + address: position.pair.token0.id, + balance: reserve0, + symbol: position.pair.token0.symbol, + usdPrice: +position.pair.token0Price + }, + token1: { + address: position.pair.token1.id, + balance: reserve1, + symbol: position.pair.token1.symbol, + usdPrice: +position.pair.token1Price + } + } + })) + + if (liquidityPositions.length < 1000) { + fetchNext = false; + } else { + skip += 1000; + } + } + + return result +} + +export const getTradeLiquidityForAddressByPoolAtBlock = async (blockNumber: number): Promise => { + let blockQuery = blockNumber !== 0 ? ` block: {number: ${blockNumber}}` : ``; + + let skip = 0; + let fetchNext = true; + let result: any[] = []; + let _stores: any[] = []; + while (fetchNext) { + let query = `{ + liquidities(where: {period: "user" lpBalance_gt: 1 } ${blockQuery} orderBy: createTimestamp, first:1000,skip:${skip}) { + user + asset + lpBalance + }, + stores(${blockQuery}){ + asset:id + lpSupply + poolBalance + } + }`; + + // console.log(query) + + let response = await fetch(TRADE_SUBGRAPH_URL, { + method: "POST", + body: JSON.stringify({ query }), + headers: { "Content-Type": "application/json" }, + }); + const { data: { liquidities, stores } } = await response.json(); + _stores = stores + result = result.concat(liquidities) + + if (liquidities.length < 1000) { + fetchNext = false; + } else { + skip += 1000; + } + } + return result.map(r => { + let store = _stores.find(s => s.asset === r.asset); + return { + user: r.user, + asset: r.asset, + // user pool share is equal to user pool balance divided by the total balance. + amount: BigInt(r.lpBalance) * BigInt(store.poolBalance) / BigInt(store.lpSupply), + } + }); +} + +type V3Position = { + liquidity: string, + owner: string, + pool: { + sqrtPrice: string, + tick: string, + token0: { + id: string, + symbol: string, + }, + token1: { + id: string, + symbol: string + } + token0Price: string, + token1Price: string + } + tickLower: { + tickIdx: string + }, + tickUpper: { + tickIdx: string + }, +} + +const getV3PositionReserves = (position: V3Position) => { + const liquidity = +position.liquidity + const _sqrtPrice = +position.pool.sqrtPrice + const currentTick = +position.pool.tick + const tickLower = +position.tickLower.tickIdx + const tickUpper = +position.tickUpper.tickIdx + + let reserve0 = 0n + let reserve1 = 0n + + if (liquidity === 0) { + return { + reserve0, + reserve1, + } + } + + const sqrtRatioA = Math.sqrt(1.0001 ** tickLower) + const sqrtRatioB = Math.sqrt(1.0001 ** tickUpper) + const sqrtPrice = _sqrtPrice / (2 ** 96) + + if (currentTick >= tickLower && currentTick < tickUpper) { + reserve0 = BigInt(Math.floor(liquidity * ((sqrtRatioB - sqrtPrice) / (sqrtPrice * sqrtRatioB)))) + reserve1 = BigInt(Math.floor(liquidity * (sqrtPrice - sqrtRatioA))) + } + + return { + reserve0, + reserve1 + } +} + +export const getV3UserPositionsAtBlock = async (blockNumber: number): Promise => { + const result: UserPosition[] = [] + + let skip = 0 + let fetchNext = true + while (fetchNext) { + const query = `query { + positions( + first: 1000, + skip: ${skip}, + where: { liquidity_gt: 0 }, + block: { number: ${blockNumber} } + ) { + liquidity + owner + pool { + sqrtPrice + tick + token0 { + id + symbol + } + token1 { + id + symbol + } + token0Price + token1Price + } + tickLower { + tickIdx + } + tickUpper { + tickIdx + } + } + }` + + const response = await fetch(V3_SUBGRAPH_URL, { + method: "POST", + body: JSON.stringify({ query }), + headers: { "Content-Type": "application/json" }, + }) + + const { data: { positions } } = await response.json(); + + result.push(...positions.map((position: V3Position) => { + const { reserve0, reserve1 } = getV3PositionReserves(position) + return { + user: position.owner, + token0: { + address: position.pool.token0.id, + balance: reserve0, + symbol: position.pool.token0.symbol, + usdPrice: +position.pool.token0Price + }, + token1: { + address: position.pool.token1.id, + balance: reserve1, + symbol: position.pool.token1.symbol, + usdPrice: +position.pool.token1Price + } + } + })) + + if (positions.length < 1000) { + fetchNext = false; + } else { + skip += 1000; + } + } + + return result +} + +export const getTimestampAtBlock = async (blockNumber: number) => { + const block = await client.getBlock({ + blockNumber: BigInt(blockNumber), + }); + return Number(block.timestamp * 1000n); +}; \ No newline at end of file diff --git a/adapters/metavault/src/sdk/mathUtils.ts b/adapters/metavault/src/sdk/mathUtils.ts deleted file mode 100644 index d245b2df..00000000 --- a/adapters/metavault/src/sdk/mathUtils.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { BigNumber } from 'bignumber.js'; - -export const getPrice = (sqrtPriceX96: BigNumber, Decimal0: number, Decimal1: number)=> { - console.log("sqrtPriceX96 : " + sqrtPriceX96.toString()); - console.log("Decimal0 : " + Decimal0); - console.log("Decimal1 : " + Decimal1); - - const twoPower96 = new BigNumber(2).pow(96); - const tenPowerDecimal0 = new BigNumber(10).pow(Decimal0); - const tenPowerDecimal1 = new BigNumber(10).pow(Decimal1); - - // Perform calculations using BigNumber for high precision arithmetic - const priceSquared = (sqrtPriceX96.dividedBy(twoPower96)).pow(2); - - console.log("priceSquared : " + priceSquared.toString()); - const ratio = priceSquared.multipliedBy(tenPowerDecimal0).dividedBy(tenPowerDecimal1); - console.log("ratio : " + ratio.toString()); - // Convert to string with fixed decimal places for display - const buyOneOfToken0 = ratio.toFixed(Decimal1); - const buyOneOfToken1 = new BigNumber(1).div(ratio).toFixed(Decimal0); - - console.log(`price of token0 in value of token1 : ${buyOneOfToken0}`); - console.log(`price of token1 in value of token0 : ${buyOneOfToken1}`); - console.log(""); - - // Convert to lowest decimal representation for display - const buyOneOfToken0Wei = ratio.multipliedBy(tenPowerDecimal1).toFixed(0); - const buyOneOfToken1Wei = new BigNumber(1).div(ratio).multipliedBy(tenPowerDecimal0).toFixed(0); - - console.log(`price of token0 in value of token1 in lowest decimal : ${buyOneOfToken0Wei}`); - console.log(`price of token1 in value of token1 in lowest decimal : ${buyOneOfToken1Wei}`); - console.log(""); -} - -// // Example usage with BigNumber inputs: -// // Convert string inputs to BigNumber. Ensure the input values are strings to prevent precision loss. -// getPrice(new BigNumber('3956146591263498000000000'), 18, 6); diff --git a/adapters/metavault/src/sdk/poolDetails.ts b/adapters/metavault/src/sdk/poolDetails.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/adapters/metavault/src/sdk/positionDetails.ts b/adapters/metavault/src/sdk/positionDetails.ts deleted file mode 100644 index a51d248a..00000000 --- a/adapters/metavault/src/sdk/positionDetails.ts +++ /dev/null @@ -1,51 +0,0 @@ -function getTickAtSqrtPrice(sqrtPriceX96: bigint): number { - const Q96: bigint = 2n ** 96n; - return Math.floor(Math.log(Number(sqrtPriceX96 / Q96) ** 2) / Math.log(1.0001)); -} - -export const getTokenAmounts = async( - liquidity: bigint, - sqrtPriceX96: bigint, - tickLow: number, - tickHigh: number, - Decimal0: number, - Decimal1: number -)=> { - const Q96: bigint = 2n ** 96n; - const sqrtRatioA: number = Math.sqrt(1.0001 ** tickLow); - const sqrtRatioB: number = Math.sqrt(1.0001 ** tickHigh); - const currentTick: number = getTickAtSqrtPrice(sqrtPriceX96); - const sqrtPrice: number = Number(sqrtPriceX96 / Q96); - let amount0: bigint = 0n; - let amount1: bigint = 0n; - - // print all the values - console.log("liquidity : " + liquidity.toString()); - console.log("sqrtPriceX96 : " + sqrtPriceX96.toString()); - console.log("tickLow : " + tickLow); - console.log("tickHigh : " + tickHigh); - console.log("Decimal0 : " + Decimal0); - console.log("Decimal1 : " + Decimal1); - console.log("sqrtRatioA : " + sqrtRatioA); - console.log("sqrtRatioB : " + sqrtRatioB); - console.log("currentTick : " + currentTick); - console.log("sqrtPrice : " + sqrtPrice); - - - if (currentTick < tickLow) { - amount0 = BigInt(Math.floor(Number(liquidity) * ((sqrtRatioB - sqrtRatioA) / (sqrtRatioA * sqrtRatioB)))); - } else if (currentTick >= tickHigh) { - amount1 = BigInt(Math.floor(Number(liquidity) * (sqrtRatioB - sqrtRatioA))); - } else if (currentTick >= tickLow && currentTick < tickHigh) { - amount0 = BigInt(Math.floor(Number(liquidity) * ((sqrtRatioB - sqrtPrice) / (sqrtPrice * sqrtRatioB)))); - amount1 = BigInt(Math.floor(Number(liquidity) * (sqrtPrice - sqrtRatioA))); - } - let amount0Human: string = (Number(amount0) / 10 ** Decimal0).toFixed(Decimal0); - let amount1Human: string = (Number(amount1) / 10 ** Decimal1).toFixed(Decimal1); - - console.log("Amount Token0 in lowest decimal: " + amount0.toString()); - console.log("Amount Token1 in lowest decimal: " + amount1.toString()); - console.log("Amount Token0 : " + amount0Human); - console.log("Amount Token1 : " + amount1Human); - return [amount0, amount1]; -} diff --git a/adapters/metavault/src/sdk/subgraphDetails.ts b/adapters/metavault/src/sdk/subgraphDetails.ts deleted file mode 100644 index 9bf18158..00000000 --- a/adapters/metavault/src/sdk/subgraphDetails.ts +++ /dev/null @@ -1,386 +0,0 @@ -import BigNumber from "bignumber.js"; -import { AMM_TYPES, CHAINS, PROTOCOLS, RPC_URLS, SUBGRAPH_URLS } from "./config"; -import { PositionMath } from "./utils/positionMath"; -import { createPublicClient, extractChain, http } from "viem"; -import { linea } from "viem/chains"; - - - -export interface Position { - id: string; - liquidity: bigint; - owner: string; - pool: { - sqrtPrice: bigint; - tick: number; - id: string; - }; - tickLower: { - tickIdx: number; - }; - tickUpper: { - tickIdx: number; - }; - - token0: { - id: string; - decimals: number; - derivedUSD: number; - name: string; - symbol: string; - }; - token1: { - id: string; - decimals: number; - derivedUSD: number; - name: string; - symbol: string; - } -}; - - -export interface PositionWithUSDValue extends Position { - token0USDValue: string; - token1USDValue: string; - token0AmountsInWei: bigint; - token1AmountsInWei: bigint; - token0DecimalValue: number; - token1DecimalValue: number; -} - -export const getPositionsForAddressByPoolAtBlock = async ( - blockNumber: number, - address: string, - poolId: string, - chainId: CHAINS, - protocol: PROTOCOLS, - ammType: AMM_TYPES -): Promise => { - let subgraphUrl = SUBGRAPH_URLS[chainId][protocol][ammType]; - let blockQuery = blockNumber !== 0 ? ` block: {number: ${blockNumber}}` : ``; - let poolQuery = poolId !== "" ? ` pool_:{id: "${poolId.toLowerCase()}"}` : ``; - let ownerQuery = address !== "" ? `owner: "${address.toLowerCase()}"` : ``; - - let whereQuery = ownerQuery !== "" && poolQuery !== "" ? `where: {${ownerQuery} , ${poolQuery}}` : ownerQuery !== "" ? `where: {${ownerQuery}}` : poolQuery !== "" ? `where: {${poolQuery}}` : ``; - let skip = 0; - let fetchNext = true; - let result: Position[] = []; - while (fetchNext) { - let query = `{ - bundle( id: 1 ${blockQuery}){ - ethPriceUSD - } - positions(${whereQuery} ${blockQuery} orderBy: transaction__timestamp, first:1000,skip:${skip}) { - id - - liquidity - owner - pool { - sqrtPrice - tick - id - } - tickLower{ - tickIdx - } - tickUpper{ - tickIdx - } - token0 { - id - decimals - derivedETH - name - symbol - } - token1 { - id - decimals - derivedETH - name - symbol - } - }, - _meta{ - block{ - number - } - } - }`; - - // console.log(query) - - let response = await fetch(subgraphUrl, { - method: "POST", - body: JSON.stringify({ query }), - headers: { "Content-Type": "application/json" }, - }); - let data = await response.json(); - let positions = data.data.positions; - let ethPriceUSD = data.data.bundle.ethPriceUSD - - for (let i = 0; i < positions.length; i++) { - let position = positions[i]; - let transformedPosition: Position = { - id: position.id, - liquidity: BigInt(position.liquidity), - owner: position.owner, - pool: { - sqrtPrice: BigInt(position.pool.sqrtPrice), - tick: Number(position.pool.tick), - id: position.pool.id, - }, - tickLower: { - tickIdx: Number(position.tickLower.tickIdx), - }, - tickUpper: { - tickIdx: Number(position.tickUpper.tickIdx), - }, - token0: { - id: position.token0.id, - decimals: position.token0.decimals, - derivedUSD: Number(position.token0.derivedETH) * Number(ethPriceUSD), - name: position.token0.name, - symbol: position.token0.symbol, - }, - token1: { - id: position.token1.id, - decimals: position.token1.decimals, - derivedUSD: Number(position.token1.derivedETH) * Number(ethPriceUSD), - name: position.token1.name, - symbol: position.token1.symbol, - }, - }; - result.push(transformedPosition); - - } - if (positions.length < 1000) { - fetchNext = false; - } else { - skip += 1000; - } - } - return result; -} -export const getTradeLiquidityForAddressByPoolAtBlock = async ( - blockNumber: number, - address: string, - poolId: string, - chainId: CHAINS, - protocol: PROTOCOLS, - ammType: AMM_TYPES -): Promise => { - let subgraphUrl = SUBGRAPH_URLS[chainId][protocol][ammType]; - let blockQuery = blockNumber !== 0 ? ` block: {number: ${blockNumber}}` : ``; - let whereQuery = address !== "" ? `where: {user: "${address.toLowerCase()}"}` : `where: {period: "user"}`; - - ; - let skip = 0; - let fetchNext = true; - let result: any[] = []; - while (fetchNext) { - let query = `{ - liquidities(${whereQuery} ${blockQuery} orderBy: createTimestamp, first:1000,skip:${skip}) { - user - asset - amountUsd - amount - }, - _meta{ - block{ - number - } - } - }`; - - // console.log(query) - - let response = await fetch(subgraphUrl, { - method: "POST", - body: JSON.stringify({ query }), - headers: { "Content-Type": "application/json" }, - }); - let data = await response.json(); - let liquidities = data.data.liquidities; - - result = result.concat(liquidities) - if (liquidities.length < 1000) { - fetchNext = false; - } else { - skip += 1000; - } - } - return result; -} - -export const getPositionAtBlock = async ( - blockNumber: number, - positionId: number, - chainId: CHAINS, - protocol: PROTOCOLS, - ammType: AMM_TYPES -): Promise => { - let subgraphUrl = SUBGRAPH_URLS[chainId][protocol][ammType]; - let blockQuery = blockNumber !== 0 ? `, block: {number: ${blockNumber}}` : ``; - let query = `{ - bundle( id: 1 ${blockQuery}){ - ethPriceUSD - } - position(id: "${positionId}" ${blockQuery}) { - id - pool { - sqrtPrice - tick - } - tickLower{ - tickIdx - } - tickUpper{ - tickIdx - } - liquidity - token0 { - id - decimals - derivedETH - name - symbol - } - token1 { - id - decimals - derivedETH - name - symbol - } - }, - _meta{ - block{ - number - } - } - }`; - let response = await fetch(subgraphUrl, { - method: "POST", - body: JSON.stringify({ query }), - headers: { "Content-Type": "application/json" }, - }); - let data = await response.json(); - let position = data.data.position; - const ethPriceUSD = data.data.bundle.ethPriceUSD - - return { - id: position.id, - liquidity: BigInt(position.liquidity), - owner: position.owner, - pool: { - sqrtPrice: BigInt(position.pool.sqrtPrice), - tick: Number(position.pool.tick), - id: position.pool.id, - }, - tickLower: { - tickIdx: Number(position.tickLower.tickIdx), - }, - tickUpper: { - tickIdx: Number(position.tickUpper.tickIdx), - }, - token0: { - id: position.token0.id, - decimals: position.token0.decimals, - derivedUSD: Number(position.token0.derivedETH) * Number(ethPriceUSD), - name: position.token0.name, - symbol: position.token0.symbol, - }, - token1: { - id: position.token1.id, - decimals: position.token1.decimals, - derivedUSD: Number(position.token1.derivedETH) * Number(ethPriceUSD), - name: position.token1.name, - symbol: position.token1.symbol, - }, - }; - - // let tickLow = Number(position.tickLower.tickIdx); - // let tickHigh = Number(position.tickUpper.tickIdx); - // let liquidity = BigInt(position.liquidity); - // let sqrtPriceX96 = BigInt(position.pool.sqrtPrice); - // let tick = Number(position.pool.tick); - // let decimal0 = position.token0.decimals; - // let decimal1 = position.token1.decimals; - // let token0DerivedUSD = position.token0.derivedUSD; - // let token1DerivedUSD = position.token1.derivedUSD; - // let token0AmountsInWei = PositionMath.getToken0Amount(tick, tickLow, tickHigh, sqrtPriceX96, liquidity); - // let token1AmountsInWei = PositionMath.getToken1Amount(tick, tickLow, tickHigh, sqrtPriceX96, liquidity); - - - // let token0DecimalValue = Number(token0AmountsInWei) / 10 ** decimal0; - // let token1DecimalValue = Number(token1AmountsInWei) / 10 ** decimal1; - - // let token0UsdValue = BigNumber(token0AmountsInWei.toString()).multipliedBy(token0DerivedUSD).div(10 ** decimal0).toFixed(4); - // let token1UsdValue = BigNumber(token1AmountsInWei.toString()).multipliedBy(token1DerivedUSD).div(10 ** decimal1).toFixed(4); - - - // return [position.token0, position.token1,token0AmountsInWei, token1AmountsInWei, token0DecimalValue, token1DecimalValue,token0UsdValue, token1UsdValue,data.data._meta]; -} - -export const getPositionDetailsFromPosition = ( - position: Position -): PositionWithUSDValue => { - let tickLow = position.tickLower.tickIdx; - let tickHigh = position.tickUpper.tickIdx; - let liquidity = position.liquidity; - let sqrtPriceX96 = position.pool.sqrtPrice; - let tick = Number(position.pool.tick); - let decimal0 = position.token0.decimals; - let decimal1 = position.token1.decimals; - let token0DerivedUSD = position.token0.derivedUSD; - let token1DerivedUSD = position.token1.derivedUSD; - let token0AmountsInWei = PositionMath.getToken0Amount(tick, tickLow, tickHigh, sqrtPriceX96, liquidity); - let token1AmountsInWei = PositionMath.getToken1Amount(tick, tickLow, tickHigh, sqrtPriceX96, liquidity); - - let token0DecimalValue = Number(token0AmountsInWei) / 10 ** decimal0; - let token1DecimalValue = Number(token1AmountsInWei) / 10 ** decimal1; - - let token0UsdValue = BigNumber(token0AmountsInWei.toString()).multipliedBy(token0DerivedUSD).div(10 ** decimal0).toFixed(4); - let token1UsdValue = BigNumber(token1AmountsInWei.toString()).multipliedBy(token1DerivedUSD).div(10 ** decimal1).toFixed(4); - - - return { ...position, token0USDValue: token0UsdValue, token1USDValue: token1UsdValue, token0AmountsInWei, token1AmountsInWei, token0DecimalValue, token1DecimalValue }; - -} - -export const getLPValueByUserAndPoolFromPositions = ( - positions: Position[] -): Map> => { - let result = new Map>(); - for (let i = 0; i < positions.length; i++) { - let position = positions[i]; - let poolId = position.pool.id; - let owner = position.owner; - let userPositions = result.get(owner); - if (userPositions === undefined) { - userPositions = new Map(); - result.set(owner, userPositions); - } - let poolPositions = userPositions.get(poolId); - if (poolPositions === undefined) { - poolPositions = BigNumber(0); - } - let positionWithUSDValue = getPositionDetailsFromPosition(position); - poolPositions = poolPositions.plus(BigNumber(positionWithUSDValue.token0USDValue).plus(positionWithUSDValue.token1USDValue)); - userPositions.set(poolId, poolPositions); - } - return result; -} - -export const getTimestampAtBlock = async (blockNumber: number) => { - const publicClient = createPublicClient({ - chain: extractChain({ chains: [linea], id: CHAINS.L2_CHAIN_ID }), - transport: http(RPC_URLS[CHAINS.L2_CHAIN_ID]), - }); - - const block = await publicClient.getBlock({ - blockNumber: BigInt(blockNumber), - }); - return Number(block.timestamp * 1000n); -}; diff --git a/adapters/metavault/src/sdk/types.ts b/adapters/metavault/src/sdk/types.ts new file mode 100644 index 00000000..122cd67c --- /dev/null +++ b/adapters/metavault/src/sdk/types.ts @@ -0,0 +1,32 @@ +export interface BlockData { + blockNumber: number; + blockTimestamp: number; +} + +export type OutputSchemaRow = { + block_number: number; + timestamp: number; + user_address: string; + token_address: string; + token_balance: bigint; + token_symbol?: string; + usd_price?: number; +}; + +export type UserPosition = { + user: string; + token0: { + address: string, + balance: bigint, + } + token1: { + address: string, + balance: bigint, + } +} + +export type UserLiquidity = { + user: string; + asset: string; + amount: bigint; +} \ No newline at end of file diff --git a/adapters/metavault/src/sdk/utils/constant.ts b/adapters/metavault/src/sdk/utils/constant.ts deleted file mode 100644 index 375569d6..00000000 --- a/adapters/metavault/src/sdk/utils/constant.ts +++ /dev/null @@ -1,38 +0,0 @@ -// exports for external consumption -export type BigintIsh = bigint | number | string - -export enum TradeType { - EXACT_INPUT, - EXACT_OUTPUT, -} - -export enum Rounding { - ROUND_DOWN, - ROUND_HALF_UP, - ROUND_UP, -} - -export const MINIMUM_LIQUIDITY = 1000n - -// exports for internal consumption -export const ZERO = 0n -export const ONE = 1n -export const TWO = 2n -export const THREE = 3n -export const FIVE = 5n -export const TEN = 10n -export const _100 = 100n -export const _9975 = 9975n -export const _10000 = 10000n - -export const MaxUint256 = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') - -export enum VMType { - uint8 = 'uint8', - uint256 = 'uint256', -} - -export const VM_TYPE_MAXIMA = { - [VMType.uint8]: BigInt('0xff'), - [VMType.uint256]: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'), -} diff --git a/adapters/metavault/src/sdk/utils/fractions/fraction.ts b/adapters/metavault/src/sdk/utils/fractions/fraction.ts deleted file mode 100644 index 3970dd43..00000000 --- a/adapters/metavault/src/sdk/utils/fractions/fraction.ts +++ /dev/null @@ -1,159 +0,0 @@ -import invariant from 'tiny-invariant' -import _Decimal from 'decimal.js-light' -import _Big from 'big.js' -// @ts-ignore -import toFormat from 'toformat' - -import { BigintIsh, Rounding } from '../constant' - -const Decimal = toFormat(_Decimal) -const Big = toFormat(_Big) - -const toSignificantRounding = { - [Rounding.ROUND_DOWN]: Decimal.ROUND_DOWN, - [Rounding.ROUND_HALF_UP]: Decimal.ROUND_HALF_UP, - [Rounding.ROUND_UP]: Decimal.ROUND_UP, -} - -const enum RoundingL2_CHAIN_ID { - /** - * Rounds towards zero. - * I.e. truncate, no rounding. - */ - RoundDown = 0, - /** - * Rounds towards nearest neighbour. - * If equidistant, rounds away from zero. - */ - RoundHalfUp = 1, - /** - * Rounds towards nearest neighbour. - * If equidistant, rounds towards even neighbour. - */ - RoundHalfEven = 2, - /** - * Rounds away from zero. - */ - RoundUp = 3, -} - -const toFixedRounding = { - [Rounding.ROUND_DOWN]: RoundingL2_CHAIN_ID.RoundDown, - [Rounding.ROUND_HALF_UP]: RoundingL2_CHAIN_ID.RoundHalfUp, - [Rounding.ROUND_UP]: RoundingL2_CHAIN_ID.RoundUp, -} - -export class Fraction { - public readonly numerator: bigint - - public readonly denominator: bigint - - public constructor(numerator: BigintIsh, denominator: BigintIsh = 1n) { - this.numerator = BigInt(numerator) - this.denominator = BigInt(denominator) - } - - private static tryParseFraction(fractionish: BigintIsh | Fraction): Fraction { - if (typeof fractionish === 'bigint' || typeof fractionish === 'number' || typeof fractionish === 'string') - return new Fraction(fractionish) - - if ('numerator' in fractionish && 'denominator' in fractionish) return fractionish - throw new Error('Could not parse fraction') - } - - // performs floor division - public get quotient(): bigint { - return this.numerator / this.denominator - } - - // remainder after floor division - public get remainder(): Fraction { - return new Fraction(this.numerator % this.denominator, this.denominator) - } - - public invert(): Fraction { - return new Fraction(this.denominator, this.numerator) - } - - public add(other: Fraction | BigintIsh): Fraction { - const otherParsed = Fraction.tryParseFraction(other) - if (this.denominator === otherParsed.denominator) { - return new Fraction(this.numerator + otherParsed.numerator, this.denominator) - } - return new Fraction( - this.numerator * otherParsed.denominator + otherParsed.numerator * this.denominator, - this.denominator * otherParsed.denominator - ) - } - - public subtract(other: Fraction | BigintIsh): Fraction { - const otherParsed = Fraction.tryParseFraction(other) - if (this.denominator === otherParsed.denominator) { - return new Fraction(this.numerator - otherParsed.numerator, this.denominator) - } - return new Fraction( - this.numerator * otherParsed.denominator - otherParsed.numerator * this.denominator, - this.denominator * otherParsed.denominator - ) - } - - public lessThan(other: Fraction | BigintIsh): boolean { - const otherParsed = Fraction.tryParseFraction(other) - return this.numerator * otherParsed.denominator < otherParsed.numerator * this.denominator - } - - public equalTo(other: Fraction | BigintIsh): boolean { - const otherParsed = Fraction.tryParseFraction(other) - return this.numerator * otherParsed.denominator === otherParsed.numerator * this.denominator - } - - public greaterThan(other: Fraction | BigintIsh): boolean { - const otherParsed = Fraction.tryParseFraction(other) - return this.numerator * otherParsed.denominator > otherParsed.numerator * this.denominator - } - - public multiply(other: Fraction | BigintIsh): Fraction { - const otherParsed = Fraction.tryParseFraction(other) - return new Fraction(this.numerator * otherParsed.numerator, this.denominator * otherParsed.denominator) - } - - public divide(other: Fraction | BigintIsh): Fraction { - const otherParsed = Fraction.tryParseFraction(other) - return new Fraction(this.numerator * otherParsed.denominator, this.denominator * otherParsed.numerator) - } - - public toSignificant( - significantDigits: number, - format: object = { groupSeparator: '' }, - rounding: Rounding = Rounding.ROUND_HALF_UP - ): string { - invariant(Number.isInteger(significantDigits), `${significantDigits} is not an integer.`) - invariant(significantDigits > 0, `${significantDigits} is not positive.`) - - Decimal.set({ precision: significantDigits + 1, rounding: toSignificantRounding[rounding] }) - const quotient = new Decimal(this.numerator.toString()) - .div(this.denominator.toString()) - .toSignificantDigits(significantDigits) - return quotient.toFormat(quotient.decimalPlaces(), format) - } - - public toFixed( - decimalPlaces: number, - format: object = { groupSeparator: '' }, - rounding: Rounding = Rounding.ROUND_HALF_UP - ): string { - invariant(Number.isInteger(decimalPlaces), `${decimalPlaces} is not an integer.`) - invariant(decimalPlaces >= 0, `${decimalPlaces} is negative.`) - - Big.DP = decimalPlaces - Big.RM = toFixedRounding[rounding] - return new Big(this.numerator.toString()).div(this.denominator.toString()).toFormat(decimalPlaces, format) - } - - /** - * Helper method for converting any super class back to a fraction - */ - public get asFraction(): Fraction { - return new Fraction(this.numerator, this.denominator) - } -} diff --git a/adapters/metavault/src/sdk/utils/fractions/percent.ts b/adapters/metavault/src/sdk/utils/fractions/percent.ts deleted file mode 100644 index 5fcb5d72..00000000 --- a/adapters/metavault/src/sdk/utils/fractions/percent.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { BigintIsh, Rounding } from '../constant' -import { Fraction } from './fraction' - -const ONE_HUNDRED = new Fraction(100n) - -/** - * Converts a fraction to a percent - * @param fraction the fraction to convert - */ -function toPercent(fraction: Fraction): Percent { - return new Percent(fraction.numerator, fraction.denominator) -} - -export class Percent extends Fraction { - /** - * This boolean prevents a fraction from being interpreted as a Percent - */ - public readonly isPercent = true as const - - add(other: Fraction | BigintIsh): Percent { - return toPercent(super.add(other)) - } - - subtract(other: Fraction | BigintIsh): Percent { - return toPercent(super.subtract(other)) - } - - multiply(other: Fraction | BigintIsh): Percent { - return toPercent(super.multiply(other)) - } - - divide(other: Fraction | BigintIsh): Percent { - return toPercent(super.divide(other)) - } - - public toSignificant(significantDigits = 5, format?: object, rounding?: Rounding): string { - return super.multiply(ONE_HUNDRED).toSignificant(significantDigits, format, rounding) - } - - public toFixed(decimalPlaces = 2, format?: object, rounding?: Rounding): string { - return super.multiply(ONE_HUNDRED).toFixed(decimalPlaces, format, rounding) - } -} diff --git a/adapters/metavault/src/sdk/utils/fullMath.ts b/adapters/metavault/src/sdk/utils/fullMath.ts deleted file mode 100644 index fe84c76b..00000000 --- a/adapters/metavault/src/sdk/utils/fullMath.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { ONE, ZERO } from "./internalConstants" - -export abstract class FullMath { - /** - * Cannot be constructed. - */ - private constructor() {} - - public static mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint): bigint { - const product = a * b - let result = product / denominator - // eslint-disable-next-line operator-assignment - if (product % denominator !== ZERO) result = result + ONE - return result - } -} diff --git a/adapters/metavault/src/sdk/utils/internalConstants.ts b/adapters/metavault/src/sdk/utils/internalConstants.ts deleted file mode 100644 index a9fc9a73..00000000 --- a/adapters/metavault/src/sdk/utils/internalConstants.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Percent } from "./fractions/percent" - -// constants used internally but not expected to be used externally -export const NEGATIVE_ONE = BigInt(-1) -export const ZERO = 0n -export const ONE = 1n - -// used in liquidity amount math -export const Q96 = 2n ** 96n -export const Q192 = Q96 ** 2n - -// used in fee calculation -export const MAX_FEE = 10n ** 6n -export const ONE_HUNDRED_PERCENT = new Percent('1') -export const ZERO_PERCENT = new Percent('0') -export const Q128 = 2n ** 128n diff --git a/adapters/metavault/src/sdk/utils/mostSignificantBit.ts b/adapters/metavault/src/sdk/utils/mostSignificantBit.ts deleted file mode 100644 index c1cb4c31..00000000 --- a/adapters/metavault/src/sdk/utils/mostSignificantBit.ts +++ /dev/null @@ -1,20 +0,0 @@ -import invariant from 'tiny-invariant' -import { MaxUint256, ZERO } from './constant' - -const TWO = 2n -const POWERS_OF_2 = [128, 64, 32, 16, 8, 4, 2, 1].map((pow: number): [number, bigint] => [pow, TWO ** BigInt(pow)]) - -export function mostSignificantBit(x: bigint): number { - invariant(x > ZERO, 'ZERO') - invariant(x <= MaxUint256, 'MAX') - - let msb = 0 - for (const [power, min] of POWERS_OF_2) { - if (x >= min) { - // eslint-disable-next-line operator-assignment - x = x >> BigInt(power) - msb += power - } - } - return msb -} diff --git a/adapters/metavault/src/sdk/utils/positionMath.ts b/adapters/metavault/src/sdk/utils/positionMath.ts deleted file mode 100644 index d20f2b90..00000000 --- a/adapters/metavault/src/sdk/utils/positionMath.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { ZERO } from "./constant" -import { SqrtPriceMath } from "./squarePriceMath" -import { TickMath } from "./tickMath" - -function getToken0Amount( - tickCurrent: number, - tickLower: number, - tickUpper: number, - sqrtRatioX96: bigint, - liquidity: bigint -): bigint { - if (tickCurrent < tickLower) { - return SqrtPriceMath.getAmount0Delta( - TickMath.getSqrtRatioAtTick(tickLower), - TickMath.getSqrtRatioAtTick(tickUpper), - liquidity, - false - ) - } - if (tickCurrent < tickUpper) { - return SqrtPriceMath.getAmount0Delta(sqrtRatioX96, TickMath.getSqrtRatioAtTick(tickUpper), liquidity, false) - } - return ZERO -} - -function getToken1Amount( - tickCurrent: number, - tickLower: number, - tickUpper: number, - sqrtRatioX96: bigint, - liquidity: bigint -): bigint { - if (tickCurrent < tickLower) { - return ZERO - } - if (tickCurrent < tickUpper) { - return SqrtPriceMath.getAmount1Delta(TickMath.getSqrtRatioAtTick(tickLower), sqrtRatioX96, liquidity, false) - } - return SqrtPriceMath.getAmount1Delta( - TickMath.getSqrtRatioAtTick(tickLower), - TickMath.getSqrtRatioAtTick(tickUpper), - liquidity, - false - ) -} - -export const PositionMath = { - getToken0Amount, - getToken1Amount, -} diff --git a/adapters/metavault/src/sdk/utils/squarePriceMath.ts b/adapters/metavault/src/sdk/utils/squarePriceMath.ts deleted file mode 100644 index 02639c62..00000000 --- a/adapters/metavault/src/sdk/utils/squarePriceMath.ts +++ /dev/null @@ -1,131 +0,0 @@ -import invariant from "tiny-invariant" -import { MaxUint256, ONE, ZERO } from "./constant" -import { FullMath } from "./fullMath" -import { Q96 } from "./internalConstants" - -const MaxUint160 = 2n ** 160n - ONE - -function multiplyIn256(x: bigint, y: bigint): bigint { - const product = x * y - return product & MaxUint256 -} - -function addIn256(x: bigint, y: bigint): bigint { - const sum = x + y - return sum & MaxUint256 -} - -export abstract class SqrtPriceMath { - /** - * Cannot be constructed. - */ - private constructor() {} - - public static getAmount0Delta( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - roundUp: boolean - ): bigint { - if (sqrtRatioAX96 > sqrtRatioBX96) { - sqrtRatioAX96 = sqrtRatioBX96 - sqrtRatioBX96 = sqrtRatioAX96 - } - - const numerator1 = liquidity << 96n - const numerator2 = sqrtRatioBX96 - sqrtRatioAX96 - - return roundUp - ? FullMath.mulDivRoundingUp(FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), ONE, sqrtRatioAX96) - : (numerator1 * numerator2) / sqrtRatioBX96 / sqrtRatioAX96 - } - - public static getAmount1Delta( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - roundUp: boolean - ): bigint { - if (sqrtRatioAX96 > sqrtRatioBX96) { - sqrtRatioAX96 = sqrtRatioBX96 - sqrtRatioBX96 = sqrtRatioAX96 - } - - return roundUp - ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, Q96) - : (liquidity * (sqrtRatioBX96 - sqrtRatioAX96)) / Q96 - } - - public static getNextSqrtPriceFromInput( - sqrtPX96: bigint, - liquidity: bigint, - amountIn: bigint, - zeroForOne: boolean - ): bigint { - invariant(sqrtPX96 > ZERO) - invariant(liquidity > ZERO) - - return zeroForOne - ? this.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true) - : this.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true) - } - - public static getNextSqrtPriceFromOutput( - sqrtPX96: bigint, - liquidity: bigint, - amountOut: bigint, - zeroForOne: boolean - ): bigint { - invariant(sqrtPX96 > ZERO) - invariant(liquidity > ZERO) - - return zeroForOne - ? this.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false) - : this.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false) - } - - private static getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96: bigint, - liquidity: bigint, - amount: bigint, - add: boolean - ): bigint { - if (amount === ZERO) return sqrtPX96 - const numerator1 = liquidity << 96n - - if (add) { - const product = multiplyIn256(amount, sqrtPX96) - if (product / amount === sqrtPX96) { - const denominator = addIn256(numerator1, product) - if (denominator >= numerator1) { - return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator) - } - } - - return FullMath.mulDivRoundingUp(numerator1, ONE, numerator1 / sqrtPX96 + amount) - } - const product = multiplyIn256(amount, sqrtPX96) - - invariant(product / amount === sqrtPX96) - invariant(numerator1 > product) - const denominator = numerator1 - product - return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator) - } - - private static getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96: bigint, - liquidity: bigint, - amount: bigint, - add: boolean - ): bigint { - if (add) { - const quotient = amount <= MaxUint160 ? (amount << 96n) / liquidity : (amount * Q96) / liquidity - - return sqrtPX96 + quotient - } - const quotient = FullMath.mulDivRoundingUp(amount, Q96, liquidity) - - invariant(sqrtPX96 > quotient) - return sqrtPX96 - quotient - } -} diff --git a/adapters/metavault/src/sdk/utils/tickLibrary.ts b/adapters/metavault/src/sdk/utils/tickLibrary.ts deleted file mode 100644 index 7d59c95e..00000000 --- a/adapters/metavault/src/sdk/utils/tickLibrary.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ZERO } from "./internalConstants" - -interface FeeGrowthOutside { - feeGrowthOutside0X128: bigint - feeGrowthOutside1X128: bigint -} - -const Q256 = 2n ** 256n - -export function subIn256(x: bigint, y: bigint): bigint { - const difference = x - y - - if (difference < ZERO) { - return Q256 + difference - } - return difference -} - -export abstract class TickLibrary { - /** - * Cannot be constructed. - */ - private constructor() {} - - public static getFeeGrowthInside( - feeGrowthOutsideLower: FeeGrowthOutside, - feeGrowthOutsideUpper: FeeGrowthOutside, - tickLower: number, - tickUpper: number, - tickCurrent: number, - feeGrowthGlobal0X128: bigint, - feeGrowthGlobal1X128: bigint - ) { - let feeGrowthBelow0X128: bigint - let feeGrowthBelow1X128: bigint - if (tickCurrent >= tickLower) { - feeGrowthBelow0X128 = feeGrowthOutsideLower.feeGrowthOutside0X128 - feeGrowthBelow1X128 = feeGrowthOutsideLower.feeGrowthOutside1X128 - } else { - feeGrowthBelow0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideLower.feeGrowthOutside0X128) - feeGrowthBelow1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideLower.feeGrowthOutside1X128) - } - - let feeGrowthAbove0X128: bigint - let feeGrowthAbove1X128: bigint - if (tickCurrent < tickUpper) { - feeGrowthAbove0X128 = feeGrowthOutsideUpper.feeGrowthOutside0X128 - feeGrowthAbove1X128 = feeGrowthOutsideUpper.feeGrowthOutside1X128 - } else { - feeGrowthAbove0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideUpper.feeGrowthOutside0X128) - feeGrowthAbove1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideUpper.feeGrowthOutside1X128) - } - - return [ - subIn256(subIn256(feeGrowthGlobal0X128, feeGrowthBelow0X128), feeGrowthAbove0X128), - subIn256(subIn256(feeGrowthGlobal1X128, feeGrowthBelow1X128), feeGrowthAbove1X128), - ] - } -} diff --git a/adapters/metavault/src/sdk/utils/tickMath.ts b/adapters/metavault/src/sdk/utils/tickMath.ts deleted file mode 100644 index 18a01d96..00000000 --- a/adapters/metavault/src/sdk/utils/tickMath.ts +++ /dev/null @@ -1,115 +0,0 @@ -import invariant from "tiny-invariant" -import { MaxUint256, ONE, ZERO } from "./constant" -import { mostSignificantBit } from "./mostSignificantBit" - - -function mulShift(val: bigint, mulBy: string): bigint { - return (val * BigInt(mulBy)) >> 128n -} - -const Q32 = 2n ** 32n - -export abstract class TickMath { - /** - * Cannot be constructed. - */ - private constructor() {} - - /** - * The minimum tick that can be used on any pool. - */ - // eslint-disable-next-line @typescript-eslint/no-inferrable-types - public static MIN_TICK: number = -887272 - - /** - * The maximum tick that can be used on any pool. - */ - public static MAX_TICK: number = -TickMath.MIN_TICK - - /** - * The sqrt ratio corresponding to the minimum tick that could be used on any pool. - */ - public static MIN_SQRT_RATIO = 4295128739n - - /** - * The sqrt ratio corresponding to the maximum tick that could be used on any pool. - */ - public static MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342n - - /** - * Returns the sqrt ratio as a Q64.96 for the given tick. The sqrt ratio is computed as sqrt(1.0001)^tick - * @param tick the tick for which to compute the sqrt ratio - */ - public static getSqrtRatioAtTick(tick: number): bigint { - - invariant(tick >= TickMath.MIN_TICK && tick <= TickMath.MAX_TICK && Number.isInteger(tick), 'TICK') - const absTick: number = tick < 0 ? tick * -1 : tick - - let ratio: bigint = - (absTick & 0x1) != 0 - ? BigInt('0xfffcb933bd6fad37aa2d162d1a594001') - : BigInt('0x100000000000000000000000000000000') - if ((absTick & 0x2) != 0) ratio = mulShift(ratio, '0xfff97272373d413259a46990580e213a') - if ((absTick & 0x4) != 0) ratio = mulShift(ratio, '0xfff2e50f5f656932ef12357cf3c7fdcc') - if ((absTick & 0x8) != 0) ratio = mulShift(ratio, '0xffe5caca7e10e4e61c3624eaa0941cd0') - if ((absTick & 0x10) != 0) ratio = mulShift(ratio, '0xffcb9843d60f6159c9db58835c926644') - if ((absTick & 0x20) != 0) ratio = mulShift(ratio, '0xff973b41fa98c081472e6896dfb254c0') - if ((absTick & 0x40) != 0) ratio = mulShift(ratio, '0xff2ea16466c96a3843ec78b326b52861') - if ((absTick & 0x80) != 0) ratio = mulShift(ratio, '0xfe5dee046a99a2a811c461f1969c3053') - if ((absTick & 0x100) != 0) ratio = mulShift(ratio, '0xfcbe86c7900a88aedcffc83b479aa3a4') - if ((absTick & 0x200) != 0) ratio = mulShift(ratio, '0xf987a7253ac413176f2b074cf7815e54') - if ((absTick & 0x400) != 0) ratio = mulShift(ratio, '0xf3392b0822b70005940c7a398e4b70f3') - if ((absTick & 0x800) != 0) ratio = mulShift(ratio, '0xe7159475a2c29b7443b29c7fa6e889d9') - if ((absTick & 0x1000) != 0) ratio = mulShift(ratio, '0xd097f3bdfd2022b8845ad8f792aa5825') - if ((absTick & 0x2000) != 0) ratio = mulShift(ratio, '0xa9f746462d870fdf8a65dc1f90e061e5') - if ((absTick & 0x4000) != 0) ratio = mulShift(ratio, '0x70d869a156d2a1b890bb3df62baf32f7') - if ((absTick & 0x8000) != 0) ratio = mulShift(ratio, '0x31be135f97d08fd981231505542fcfa6') - if ((absTick & 0x10000) != 0) ratio = mulShift(ratio, '0x9aa508b5b7a84e1c677de54f3e99bc9') - if ((absTick & 0x20000) != 0) ratio = mulShift(ratio, '0x5d6af8dedb81196699c329225ee604') - if ((absTick & 0x40000) != 0) ratio = mulShift(ratio, '0x2216e584f5fa1ea926041bedfe98') - if ((absTick & 0x80000) != 0) ratio = mulShift(ratio, '0x48a170391f7dc42444e8fa2') - - if (tick > 0) ratio = MaxUint256 / ratio - - // back to Q96 - return ratio % Q32 > ZERO ? ratio / Q32 + ONE : ratio / Q32 - } - - /** - * Returns the tick corresponding to a given sqrt ratio, s.t. #getSqrtRatioAtTick(tick) <= sqrtRatioX96 - * and #getSqrtRatioAtTick(tick + 1) > sqrtRatioX96 - * @param sqrtRatioX96 the sqrt ratio as a Q64.96 for which to compute the tick - */ - public static getTickAtSqrtRatio(sqrtRatioX96: bigint): number { - invariant(sqrtRatioX96 >= TickMath.MIN_SQRT_RATIO && sqrtRatioX96 < TickMath.MAX_SQRT_RATIO, 'SQRT_RATIO') - - const sqrtRatioX128 = sqrtRatioX96 << 32n - - const msb = mostSignificantBit(sqrtRatioX128) - - let r: bigint - if (BigInt(msb) >= 128n) { - r = sqrtRatioX128 >> BigInt(msb - 127) - } else { - r = sqrtRatioX128 << BigInt(127 - msb) - } - - let log_2: bigint = (BigInt(msb) - 128n) << 64n - - for (let i = 0; i < 14; i++) { - r = (r * r) >> 127n - const f = r >> 128n - // eslint-disable-next-line operator-assignment - log_2 = log_2 | (f << BigInt(63 - i)) - // eslint-disable-next-line operator-assignment - r = r >> f - } - - const log_sqrt10001 = log_2 * 255738958999603826347141n - - const tickLow = Number((log_sqrt10001 - 3402992956809132418596140100660247210n) >> 128n) - const tickHigh = Number((log_sqrt10001 + 291339464771989622907027621153398088495n) >> 128n) - - return tickLow === tickHigh ? tickLow : TickMath.getSqrtRatioAtTick(tickHigh) <= sqrtRatioX96 ? tickHigh : tickLow - } -} diff --git a/adapters/metavault/tsconfig.json b/adapters/metavault/tsconfig.json index 9852ff27..8df9e19a 100644 --- a/adapters/metavault/tsconfig.json +++ b/adapters/metavault/tsconfig.json @@ -1,7 +1,6 @@ { "compilerOptions": { /* Visit https://aka.ms/tsconfig to read more about this file */ - /* Projects */ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ @@ -9,9 +8,8 @@ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "es2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ @@ -23,10 +21,9 @@ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, - "rootDir": "src/" /* Specify the root folder within your source files. */, + "module": "commonjs", /* Specify what module code is generated. */ + "rootDir": "src/", /* Specify the root folder within your source files. */ // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ @@ -39,15 +36,13 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - "resolveJsonModule": true /* Enable importing .json files. */, + // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ @@ -55,7 +50,7 @@ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "dist/" /* Specify an output folder for all emitted files. */, + "outDir": "dist/", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ @@ -72,17 +67,15 @@ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, + "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ @@ -101,9 +94,8 @@ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ } -} +} \ No newline at end of file From 00043fb3fcf086549745b72568082e640dfe0ac8 Mon Sep 17 00:00:00 2001 From: SdCrypt0 Date: Mon, 20 May 2024 16:47:05 +0300 Subject: [PATCH 2/3] Metavault adapter updated --- adapters/metavault/src/index.ts | 82 ++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/adapters/metavault/src/index.ts b/adapters/metavault/src/index.ts index ed3666a3..98aa68b5 100644 --- a/adapters/metavault/src/index.ts +++ b/adapters/metavault/src/index.ts @@ -1,48 +1,60 @@ -import { promisify } from 'util'; -import stream from 'stream'; import csv from 'csv-parser'; import fs from 'fs'; import { write } from 'fast-csv'; import { BlockData, OutputSchemaRow } from './sdk/types'; -import { getTimestampAtBlock, getTradeLiquidityForAddressByPoolAtBlock, getV2UserPositionsAtBlock, getV3UserPositionsAtBlock } from './sdk/lib'; +import { getTradeLiquidityForAddressByPoolAtBlock, getV2UserPositionsAtBlock, getV3UserPositionsAtBlock } from './sdk/lib'; -const pipeline = promisify(stream.pipeline); -const readBlocksFromCSV = async (filePath: string): Promise => { - const blocks: number[] = []; - await pipeline( - fs.createReadStream(filePath), - csv(), - async function* (source) { - for await (const chunk of source) { - // Assuming each row in the CSV has a column 'block' with the block number - if (chunk.block) blocks.push(parseInt(chunk.block, 10)); - } - } - ); - return blocks; -}; +const readBlocksFromCSV = async (filePath: string): Promise => { + const blocks: BlockData[] = []; -const getData = async () => { - const blocks = [ - 4314766 - ]; //await readBlocksFromCSV('src/sdk/mode_chain_daily_blocks.csv'); + await new Promise((resolve, reject) => { + fs.createReadStream(filePath) + .pipe(csv()) // Specify the separator as '\t' for TSV files + .on('data', (row) => { + const blockNumber = parseInt(row.number, 10); + const blockTimestamp = parseInt(row.timestamp, 10); + if (!isNaN(blockNumber) && blockTimestamp) { + blocks.push({ blockNumber: blockNumber, blockTimestamp }); + } + }) + .on('end', () => { + resolve(); + }) + .on('error', (err) => { + reject(err); + }); + }); - const csvRows: OutputSchemaRow[] = []; + return blocks; +}; +readBlocksFromCSV('hourly_blocks.csv').then(async (blocks: BlockData[]) => { + console.log(blocks); + const allCsvRows: any[] = []; // Array to accumulate CSV rows for all blocks + const batchSize = 1000; // Size of batch to trigger writing to the file + let i = 0; for (const block of blocks) { - const timestamp = await getTimestampAtBlock(block) - - csvRows.push(...await getUserTVLByBlock({ blockNumber: block, blockTimestamp: timestamp })) + try { + const result = await getUserTVLByBlock(block); + allCsvRows.push(...result); + } catch (error) { + console.error(`An error occurred for block ${block}:`, error); + } } - // Write the CSV output to a file - const ws = fs.createWriteStream('outputData.csv'); - write(csvRows, { headers: true }).pipe(ws).on('finish', () => { - console.log("CSV file has been written."); + await new Promise((resolve, reject) => { + const ws = fs.createWriteStream(`outputData.csv`, {flags: 'w'}); + write(allCsvRows, {headers: true}) + .pipe(ws) + .on("finish", () => { + console.log(`CSV file has been written.`); + resolve; + }); }); -}; - +}).catch((err) => { + console.error('Error reading CSV file:', err); +}); export const getUserTVLByBlock = async ({ blockNumber, blockTimestamp }: BlockData): Promise => { const result: OutputSchemaRow[] = [] @@ -89,8 +101,4 @@ export const getUserTVLByBlock = async ({ blockNumber, blockTimestamp }: BlockDa } return result -}; - -getData().then(() => { - console.log("Done"); -}); \ No newline at end of file +}; \ No newline at end of file From 2ef66ad58ed9f3dccd8be5fa63b2df3a183b6716 Mon Sep 17 00:00:00 2001 From: SdCrypt0 Date: Mon, 20 May 2024 17:10:48 +0300 Subject: [PATCH 3/3] Metavault adapter updated --- adapters/metavault/src/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/adapters/metavault/src/index.ts b/adapters/metavault/src/index.ts index 98aa68b5..c4d43be8 100644 --- a/adapters/metavault/src/index.ts +++ b/adapters/metavault/src/index.ts @@ -44,8 +44,8 @@ readBlocksFromCSV('hourly_blocks.csv').then(async (blocks: BlockData[]) => { } } await new Promise((resolve, reject) => { - const ws = fs.createWriteStream(`outputData.csv`, {flags: 'w'}); - write(allCsvRows, {headers: true}) + const ws = fs.createWriteStream(`outputData.csv`, { flags: 'w' }); + write(allCsvRows, { headers: true }) .pipe(ws) .on("finish", () => { console.log(`CSV file has been written.`); @@ -96,6 +96,8 @@ export const getUserTVLByBlock = async ({ blockNumber, blockTimestamp }: BlockDa user_address: user, token_address: token, token_balance: balance, + token_symbol: "", + usd_price: 0 }) } }