From 9e30116bdd7e5c5e0fc9bbde9420476e3bf35376 Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 19 Jun 2024 08:09:34 +0800 Subject: [PATCH] feat: support rho markets block info query --- adapters/rhomarkets/blocks.csv | 2 + adapters/rhomarkets/package.json | 35 ++++++++++++ adapters/rhomarkets/src/index.ts | 36 +++++++++++++ adapters/rhomarkets/src/sdk/index.ts | 61 +++++++++++++++++++++ adapters/rhomarkets/src/sdk/request.ts | 73 ++++++++++++++++++++++++++ adapters/rhomarkets/tsconfig.json | 12 +++++ 6 files changed, 219 insertions(+) create mode 100644 adapters/rhomarkets/blocks.csv create mode 100644 adapters/rhomarkets/package.json create mode 100644 adapters/rhomarkets/src/index.ts create mode 100644 adapters/rhomarkets/src/sdk/index.ts create mode 100644 adapters/rhomarkets/src/sdk/request.ts create mode 100644 adapters/rhomarkets/tsconfig.json diff --git a/adapters/rhomarkets/blocks.csv b/adapters/rhomarkets/blocks.csv new file mode 100644 index 0000000..eea93a4 --- /dev/null +++ b/adapters/rhomarkets/blocks.csv @@ -0,0 +1,2 @@ +number block_timestamp +4243360 1714773599 \ No newline at end of file diff --git a/adapters/rhomarkets/package.json b/adapters/rhomarkets/package.json new file mode 100644 index 0000000..875ecc9 --- /dev/null +++ b/adapters/rhomarkets/package.json @@ -0,0 +1,35 @@ +{ + "name": "rhomarkets-tvl", + "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.13.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "devDependencies": { + "@types/node": "^20.11.17", + "typescript": "^5.3.3" + } +} diff --git a/adapters/rhomarkets/src/index.ts b/adapters/rhomarkets/src/index.ts new file mode 100644 index 0000000..7e1e3da --- /dev/null +++ b/adapters/rhomarkets/src/index.ts @@ -0,0 +1,36 @@ +import fs from "fs"; +import { write } from "fast-csv"; +import { getUserTVLByBlock, readBlocksFromCSV } from "./sdk"; +import path from "path"; + +const filePath = path.join(process.cwd(), "blocks.csv"); + +readBlocksFromCSV(filePath) + .then(async (blocks: any[]) => { + 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) => { + 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); + }); diff --git a/adapters/rhomarkets/src/sdk/index.ts b/adapters/rhomarkets/src/sdk/index.ts new file mode 100644 index 0000000..4e728a6 --- /dev/null +++ b/adapters/rhomarkets/src/sdk/index.ts @@ -0,0 +1,61 @@ +import fs from "fs"; +import csv from "csv-parser"; +import { fetchGraphQLData } from "./request"; + +export interface BlockData { + blockNumber: number; + blockTimestamp: number; +} + +export type OutputDataSchemaRow = { + protocol: string; + date: number; + block_number: number; + user_address: string; + market: string; + supply_token: string | number; + borrow_token: string | number; +}; + +export const getUserTVLByBlock = async (blocks: BlockData) => { + const protocalInfos = await fetchGraphQLData(blocks.blockNumber); + + const csvRows: OutputDataSchemaRow[] = protocalInfos.map((item) => ({ + protocol: "RhoMarkets", + date: blocks.blockTimestamp, + block_number: blocks.blockNumber, + user_address: item.user_address, + market: item.market, + supply_token: item.supply_token, + borrow_token: item.borrow_token, + })); + + return csvRows; +}; + +export const readBlocksFromCSV = async ( + filePath: string +): Promise => { + const blocks: BlockData[] = []; + + await new Promise((resolve, reject) => { + fs.createReadStream(filePath) + .pipe(csv({ separator: "\t" })) // Specify the separator as '\t' for TSV files + .on("data", (row) => { + const blockNumber = parseInt(row.number, 10); + const blockTimestamp = parseInt(row.block_timestamp, 10); + + if (!isNaN(blockNumber) && blockTimestamp) { + blocks.push({ blockNumber: blockNumber, blockTimestamp }); + } + }) + .on("end", () => { + resolve(); + }) + .on("error", (err) => { + reject(err); + }); + }); + + return blocks; +}; diff --git a/adapters/rhomarkets/src/sdk/request.ts b/adapters/rhomarkets/src/sdk/request.ts new file mode 100644 index 0000000..ed998cd --- /dev/null +++ b/adapters/rhomarkets/src/sdk/request.ts @@ -0,0 +1,73 @@ +interface ProtocalData { + timestamp: number; + block_number: number; + user_address: string; + market: string; + supply_token: number; + borrow_token: number; +} + +interface GraphQLResponse { + data: { + data: ProtocalData[]; + }; + errors?: any[]; +} + +const query = ` +query ($limit: Int, $offset: Int, $blockNumber: Int) { + data(first: $limit, skip: $offset, block: { number: $blockNumber }) { + timestamp + block_number + user_address + market + supply_token + borrow_token + } + } + +`; + +export async function fetchGraphQLData( + blockNumber: number +): Promise { + // limit: number, + // offset: number, + // data(block: { number: ${blockNumber} }) { + const query = ` + query RHO_MARKETS { + data { + timestamp + block_number + user_address + market + supply_token + borrow_token + } + } + + `; + + try { + const response = await fetch( + "https://drgstmbns1.execute-api.us-east-1.amazonaws.com/default/RhoMarketPoints", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ query }), + } + ); + + const responseData: GraphQLResponse = await response.json(); + if (responseData.errors) { + console.error("GraphQL errors:", responseData.errors); + return []; + } + return responseData.data.data; + } catch (error) { + console.error("Error fetching data:", error); + return []; + } +} diff --git a/adapters/rhomarkets/tsconfig.json b/adapters/rhomarkets/tsconfig.json new file mode 100644 index 0000000..599cd43 --- /dev/null +++ b/adapters/rhomarkets/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "commonjs", + "rootDir": "src/", + "outDir": "dist/", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + } +}