Skip to content

Commit

Permalink
Merge pull request #26 from metavaultorg/main
Browse files Browse the repository at this point in the history
add metavault adapter
  • Loading branch information
RamonReis authored May 3, 2024
2 parents 5d7b23b + ad8c891 commit b02b2f3
Show file tree
Hide file tree
Showing 20 changed files with 1,436 additions and 0 deletions.
32 changes: 32 additions & 0 deletions adapters/metavault/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "metavault",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist/index.js",
"compile": "tsc",
"watch": "tsc -w",
"clear": "rm -rf dist"
},
"keywords": [],
"author": "",
"license": "ISC",
"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": {
"@types/node": "^20.11.17",
"typescript": "^5.3.3"
}
}
91 changes: 91 additions & 0 deletions adapters/metavault/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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();
};

interface BlockData {
blockNumber: number;
blockTimestamp: number;
}

type OutputDataSchemaRow = {
block_number: number;
timestamp: number;
user_address: string;
token_address: string;
token_balance: number;
token_symbol?: string;
usd_price: number;
};


export const getUserTVLByBlock = async ({
blockNumber,
blockTimestamp,
}: BlockData): Promise<OutputDataSchemaRow[]> => {
return await getPoolData({ blockNumber, blockTimestamp });
}

export const getPoolData = async ({
blockNumber,
blockTimestamp,
}: BlockData): Promise<OutputDataSchemaRow[]> => {
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
);

console.log(`Block: ${blockNumber}`);
console.log("Positions: ", positions.length);

// Assuming this part of the logic remains the same
let positionsWithUSDValue = positions.map(getPositionDetailsFromPosition);
// let lpValueByUsers = getLPValueByUserAndPoolFromPositions(positionsWithUSDValue);

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,
});
}
});

} catch (error) {
console.error(`An error occurred for block ${blockNumber}:`, error);
}
return allCsvRows
}
35 changes: 35 additions & 0 deletions adapters/metavault/src/sdk/blockApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export const readBlocksFromApi = async (startTime: number, endTime: number): Promise<any[]> => {
const results = []
for (let i = startTime; i <= endTime; i += 3600) {
let response = await fetch(`https://api.lineascan.build/api?module=block&action=getblocknobytime&timestamp=${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
]
}
24 changes: 24 additions & 0 deletions adapters/metavault/src/sdk/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const enum CHAINS{
L2_CHAIN_ID = 59144,
}
export const enum PROTOCOLS{
METAVAULT = 0,
}

export const enum AMM_TYPES{
UNISWAPV3 = 0,
TRADE = 1
}

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"
}
24 changes: 24 additions & 0 deletions adapters/metavault/src/sdk/entities/positions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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]
}
}
37 changes: 37 additions & 0 deletions adapters/metavault/src/sdk/mathUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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);
Empty file.
51 changes: 51 additions & 0 deletions adapters/metavault/src/sdk/positionDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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];
}
Loading

0 comments on commit b02b2f3

Please sign in to comment.