From 6a81253cc8c80d296036a849297d06c5201859f7 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Tue, 26 Mar 2024 18:03:01 +0530 Subject: [PATCH 1/9] updated the logic for ZL token --- adapters/zerolend/package.json | 23 ++ adapters/zerolend/src/index.ts | 270 ++++++++++++ adapters/zerolend/yarn.lock | 728 +++++++++++++++++++++++++++++++++ 3 files changed, 1021 insertions(+) create mode 100644 adapters/zerolend/package.json create mode 100644 adapters/zerolend/src/index.ts create mode 100644 adapters/zerolend/yarn.lock diff --git a/adapters/zerolend/package.json b/adapters/zerolend/package.json new file mode 100644 index 00000000..847ed1a5 --- /dev/null +++ b/adapters/zerolend/package.json @@ -0,0 +1,23 @@ +{ + "name": "zerolend", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "ts-node src/index.ts" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@types/node": "^20.11.30", + "axios": "^1.6.8", + "ethereum-multicall": "^2.23.0", + "ethers": "^5.0.15", + "fast-csv": "^5.0.1", + "fs": "^0.0.1-security" + }, + "devDependencies": { + "ts-node": "^10.9.2", + "typescript": "^5.4.3" + } +} diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts new file mode 100644 index 00000000..bfb8804a --- /dev/null +++ b/adapters/zerolend/src/index.ts @@ -0,0 +1,270 @@ +import { ethers } from "ethers"; +import { write } from "fast-csv"; +import axios from "axios"; +import fs from "fs"; + +import { + Multicall, + ContractCallResults, + ContractCallContext, +} from "ethereum-multicall"; + +const abi = [ + { + constant: true, + inputs: [ + { + name: "_owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + name: "balance", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, +]; + +const assets = [ + { + symbol: "WETH", + aToken: "0xB4FFEf15daf4C02787bC5332580b838cE39805f5", + underlying: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", + debtToken: "0xCb2dA0F5aEce616e2Cbf29576CFc795fb15c6133", + }, + { + symbol: "USDC", + aToken: "0x2E207ecA8B6Bf77a6ac82763EEEd2A94de4f081d", + underlying: "0x176211869ca2b568f2a7d4ee941e073a821ee1ff", + debtToken: "0xa2703Dc9FbACCD6eC2e4CBfa700989D0238133f6", + }, + { + symbol: "USDT", + aToken: "0x508C39Cd02736535d5cB85f3925218E5e0e8F07A", + underlying: "0xa219439258ca9da29e9cc4ce5596924745e12b93", + debtToken: "0x476F206511a18C9956fc79726108a03E647A1817", + }, + { + symbol: "MAI", + aToken: "0x759cb97fbc452BAFD49992BA88d3C5dA4Dd9B0e7", + underlying: "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a", + debtToken: "", + }, + { + symbol: "GRAI", + aToken: "0xE7e54ca3D6F8a5561f8cee361260E537BDc5bE48", + underlying: "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487", + debtToken: "", + }, + { + symbol: "ezETH", + aToken: "0x0684FC172a0B8e6A65cF4684eDb2082272fe9050", + underlying: "0x2416092f143378750bb29b79ed961ab195cceea5", + debtToken: "", + }, +]; + +const lineaProvider = new ethers.providers.JsonRpcProvider( + "https://rpc.linea.build" +); + +const multicall = new Multicall({ + ethersProvider: lineaProvider, + tryAggregate: true, +}); + +const fetchUserBalancesMulticall = async (walletAddresses: string[]) => { + const contractCallContext: ContractCallContext[] = assets.reduce< + ContractCallContext[] + >((previous, asset) => { + const calls = [ + { + reference: `${asset.symbol}-aToken`, + contractAddress: asset.aToken, + abi, + calls: walletAddresses.map((walletAddress) => ({ + reference: `${asset.aToken}-${walletAddress}`, + methodName: "balanceOf", + methodParameters: [walletAddress], + })), + }, + ]; + + if (asset.debtToken != "") { + calls.push({ + reference: `${asset.symbol}-debtToken`, + contractAddress: asset.debtToken, + abi, + calls: walletAddresses.map((walletAddress) => ({ + reference: `${asset.debtToken}-${walletAddress}`, + methodName: "balanceOf", + methodParameters: [walletAddress], + })), + }); + } + + return [...calls, ...previous]; + }, []); + + const results: ContractCallResults = await multicall.call( + contractCallContext + ); + + const flattenedResults: { + address: string; + asset: string; + balance: string; + blockNumber: number; + }[] = []; + + const values = Object.values(results.results); + values.forEach((value) => { + value.callsReturnContext.forEach((ret) => { + const balance = ethers.BigNumber.from(ret.returnValues[0]).toString(); + + if (balance === "0") return; + + flattenedResults.push({ + address: ret.methodParameters[0], + asset: ret.reference.split("-")[0], + balance: ret.reference.includes("debt") ? "-" : "" + balance, + blockNumber: results.blockNumber, + }); + }); + }); + + const finalResults: { + address: string; + asset: string; + balance: string; + blockNumber: number; + }[] = []; + + flattenedResults.forEach((res) => { + const index = finalResults.findIndex((val) => val.asset); + if (index > 0) { + finalResults[index] = { + ...finalResults[index], + balance: ( + Number(finalResults[index].balance) + Number(res.balance) + ).toString(), + }; + } else finalResults.push(res); + }); + + return finalResults; +}; + +const writeToCSV = async (data: [string, string, string, string, string][]) => { + // File path where the CSV will be saved + const filePath = "outputData.csv"; + const headers = [ + "block_number", + "timestamp", + "user_address", + "token_address", + "token_balance", + ]; + + // Create a write stream + const fileStream = fs.createWriteStream(filePath); + + // Create a CSV writer + const csvStream: any = write([]); + + csvStream.pipe(fileStream); + csvStream.write(headers); + data.forEach(csvStream.write); + + csvStream.on("finish", () => { + console.log("CSV file has been written successfully."); + csvStream.end(); + }); +}; + +const getAddresses = async () => { + console.log("fetching users"); + const count = 1000; + + let lastAddress = "0x0000000000000000000000000000000000000000"; + const queryURL = + "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; + + const addresses: string[] = []; + + do { + const query = `query { + users(where: {id_gt: "${lastAddress}"}, first: ${count}) { + id + } + }`; + + const headers = { + "Content-Type": "application/json", + }; + + const batch = await axios.post( + queryURL, + { query }, + { headers } + ); + + const results = batch.data.data.users.map((user) => user.id); + addresses.push(...results); + lastAddress = batch.data.data.users[batch.data.data.users.length - 1].id; + + if (batch.data.data.users.length !== count) break; + } while (true); + + console.log("fetched users", addresses.length); + return addresses; +}; + +interface IAxiosReponse { + data: { + users: { + id: string; + }[]; + }; +} + +const main = async () => { + const rows: [string, string, string, string, string][] = []; + const addresses = await getAddresses(); + + const batches = 10; + + for (let index = 0; index < addresses.length / batches; index++) { + const subaddresses = addresses.slice( + index * batches, + (index + 1) * batches + ); + const balance = await fetchUserBalancesMulticall(subaddresses); + balance.forEach((row) => { + rows.push([ + row.blockNumber.toString(), + String(new Date().toISOString()), + row.address, + row.asset, + row.balance, + ]); + }); + console.log( + `Processed ${rows.length} rows`, + index, + Math.floor(addresses.length / batches) + ); + } + + await writeToCSV(rows); +}; + +main().then(() => { + console.log("Done"); +}); diff --git a/adapters/zerolend/yarn.lock b/adapters/zerolend/yarn.lock new file mode 100644 index 00000000..81de7e16 --- /dev/null +++ b/adapters/zerolend/yarn.lock @@ -0,0 +1,728 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.0.10": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@fast-csv/format@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@fast-csv/format/-/format-5.0.0.tgz#f2e557fdd4370360b418cc78636684c07b12d0ba" + 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" + +"@fast-csv/parse@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@fast-csv/parse/-/parse-5.0.0.tgz#091665753f9e58f0dda6a55ae30f582526042903" + 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" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@tsconfig/node10@^1.0.7": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.10.tgz#b7ebd3adfa7750628d100594f6726b054d2c33b2" + integrity sha512-PiaIWIoPvO6qm6t114ropMCagj6YAF24j9OkCA2mJDXFnlionEwhsBCJ8yek4aib575BI3OkART/90WsgHgLWw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/node@^20.11.30": + version "20.11.30" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f" + integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw== + dependencies: + undici-types "~5.26.4" + +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.4.1: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.6.8: + version "1.6.8" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" + integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +ethereum-multicall@^2.23.0: + version "2.23.0" + resolved "https://registry.yarnpkg.com/ethereum-multicall/-/ethereum-multicall-2.23.0.tgz#9f39e80cae6d6d587b5f64d1e78152add32bb5b3" + integrity sha512-KVboRQSXzJ/czaD9UXIuYFKF9YwDsWORGDDRNyOtkBRYg7TUk2RkmqLcu/+uXUemdb3+XRcAU7c8bfdfOGfoiQ== + dependencies: + "@ethersproject/providers" "^5.0.10" + ethers "^5.0.15" + +ethers@^5.0.15: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +fast-csv@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-5.0.1.tgz#2beaa2437ea83bd335cc3a39a41e69d9936f3987" + integrity sha512-Q43zC4NdQD5MAWOVQOF8KA+D6ddvTJjX2ib8zqysm74jZhtk6+dc8C75/OqRV6Y9CLc4kgvbC3PLG8YL4YZfgw== + dependencies: + "@fast-csv/format" "5.0.0" + "@fast-csv/parse" "5.0.0" + +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs@^0.0.1-security: + version "0.0.1-security" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw== + +lodash.groupby@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.groupby/-/lodash.groupby-4.6.0.tgz#0b08a1dcf68397c397855c3239783832df7403d1" + integrity sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.isfunction@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== + +lodash.isnil@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/lodash.isnil/-/lodash.isnil-4.0.0.tgz#49e28cd559013458c814c5479d3c663a21bfaa6c" + integrity sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng== + +lodash.isundefined@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48" + integrity sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA== + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +typescript@^5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From b253f6602df986ac19657dcbe25c3b3b656aa517 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Thu, 28 Mar 2024 15:20:42 +0530 Subject: [PATCH 2/9] fixed adapter --- adapters/zerolend/package.json | 3 +- adapters/zerolend/src/index.ts | 364 +++++++++++++-------------------- adapters/zerolend/yarn.lock | 63 ++++++ 3 files changed, 207 insertions(+), 223 deletions(-) diff --git a/adapters/zerolend/package.json b/adapters/zerolend/package.json index 847ed1a5..b8abad79 100644 --- a/adapters/zerolend/package.json +++ b/adapters/zerolend/package.json @@ -12,7 +12,8 @@ "@types/node": "^20.11.30", "axios": "^1.6.8", "ethereum-multicall": "^2.23.0", - "ethers": "^5.0.15", + "ethers": "^6", + "ethers-multicall-provider": "^6.2.0", "fast-csv": "^5.0.1", "fs": "^0.0.1-security" }, diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts index bfb8804a..89e76c89 100644 --- a/adapters/zerolend/src/index.ts +++ b/adapters/zerolend/src/index.ts @@ -1,167 +1,162 @@ import { ethers } from "ethers"; -import { write } from "fast-csv"; import axios from "axios"; +import { write } from "fast-csv"; import fs from "fs"; +import { MulticallWrapper } from "ethers-multicall-provider"; + +const lineaProvider = new ethers.JsonRpcProvider("https://rpc.linea.build "); + +const abi = ["function balanceOf(address owner) view returns (uint256)"]; + +type IKeyObject = { [symbol: string]: string }; +const assetAddresses: IKeyObject = { + MAI: "0x759cb97fbc452BAFD49992BA88d3C5dA4Dd9B0e7", + ezETH: "0x0684FC172a0B8e6A65cF4684eDb2082272fe9050", + GRAI: "0xE7e54ca3D6F8a5561f8cee361260E537BDc5bE48", + ETH: "0xB4FFEf15daf4C02787bC5332580b838cE39805f5", + debtETH: "0xCb2dA0F5aEce616e2Cbf29576CFc795fb15c6133", + USDC: "0x2E207ecA8B6Bf77a6ac82763EEEd2A94de4f081d", + debtUSDC: "0xa2703Dc9FbACCD6eC2e4CBfa700989D0238133f6", + USDT: "0x508C39Cd02736535d5cB85f3925218E5e0e8F07A", + debtUSDT: "0x476F206511a18C9956fc79726108a03E647A1817", +}; -import { - Multicall, - ContractCallResults, - ContractCallContext, -} from "ethereum-multicall"; +const underlyingAddresses: IKeyObject = { + MAI: "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a", + ezETH: "0x2416092f143378750bb29b79ed961ab195cceea5", + GRAI: "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487", + ETH: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", + USDC: "0x176211869ca2b568f2a7d4ee941e073a821ee1ff", + USDT: "0xa219439258ca9da29e9cc4ce5596924745e12b93", +}; -const abi = [ - { - constant: true, - inputs: [ - { - name: "_owner", - type: "address", - }, - ], - name: "balanceOf", - outputs: [ - { - name: "balance", - type: "uint256", - }, - ], - payable: false, - stateMutability: "view", - type: "function", - }, -]; +const getUserAssetBalance = async ( + tokenAddress: string, + walletAddress: string[] +) => { + const provider = MulticallWrapper.wrap(lineaProvider); + const contract = new ethers.Contract(tokenAddress, abi, provider); -const assets = [ - { - symbol: "WETH", - aToken: "0xB4FFEf15daf4C02787bC5332580b838cE39805f5", - underlying: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", - debtToken: "0xCb2dA0F5aEce616e2Cbf29576CFc795fb15c6133", - }, - { - symbol: "USDC", - aToken: "0x2E207ecA8B6Bf77a6ac82763EEEd2A94de4f081d", - underlying: "0x176211869ca2b568f2a7d4ee941e073a821ee1ff", - debtToken: "0xa2703Dc9FbACCD6eC2e4CBfa700989D0238133f6", - }, - { - symbol: "USDT", - aToken: "0x508C39Cd02736535d5cB85f3925218E5e0e8F07A", - underlying: "0xa219439258ca9da29e9cc4ce5596924745e12b93", - debtToken: "0x476F206511a18C9956fc79726108a03E647A1817", - }, - { - symbol: "MAI", - aToken: "0x759cb97fbc452BAFD49992BA88d3C5dA4Dd9B0e7", - underlying: "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a", - debtToken: "", - }, - { - symbol: "GRAI", - aToken: "0xE7e54ca3D6F8a5561f8cee361260E537BDc5bE48", - underlying: "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487", - debtToken: "", - }, - { - symbol: "ezETH", - aToken: "0x0684FC172a0B8e6A65cF4684eDb2082272fe9050", - underlying: "0x2416092f143378750bb29b79ed961ab195cceea5", - debtToken: "", - }, -]; + const results = await Promise.all( + walletAddress.map((w) => contract.balanceOf(w)) + ); + const resp = results.map((amount, index) => { + return { address: walletAddress[index], balance: Number(amount) }; + }); + return resp; +}; -const lineaProvider = new ethers.providers.JsonRpcProvider( - "https://rpc.linea.build" -); +export const userBalance = async (walletAddress: string[]) => { + //mai + const balanceMAI = await getUserAssetBalance( + assetAddresses.MAI, + walletAddress + ); -const multicall = new Multicall({ - ethersProvider: lineaProvider, - tryAggregate: true, -}); + //ezETH + const balanceezETH = await getUserAssetBalance( + assetAddresses.ezETH, + walletAddress + ); -const fetchUserBalancesMulticall = async (walletAddresses: string[]) => { - const contractCallContext: ContractCallContext[] = assets.reduce< - ContractCallContext[] - >((previous, asset) => { - const calls = [ - { - reference: `${asset.symbol}-aToken`, - contractAddress: asset.aToken, - abi, - calls: walletAddresses.map((walletAddress) => ({ - reference: `${asset.aToken}-${walletAddress}`, - methodName: "balanceOf", - methodParameters: [walletAddress], - })), - }, - ]; + // GRAI + const balanceGRAI = await getUserAssetBalance( + assetAddresses.GRAI, + walletAddress + ); - if (asset.debtToken != "") { - calls.push({ - reference: `${asset.symbol}-debtToken`, - contractAddress: asset.debtToken, - abi, - calls: walletAddresses.map((walletAddress) => ({ - reference: `${asset.debtToken}-${walletAddress}`, - methodName: "balanceOf", - methodParameters: [walletAddress], - })), - }); - } + //ETH + const balanceETHSupply = await getUserAssetBalance( + assetAddresses.ETH, //z0WETH + walletAddress + ); + const balanceETHBorrow = await getUserAssetBalance( + assetAddresses.debtETH, // debt WETH + walletAddress + ); - return [...calls, ...previous]; - }, []); + //usdc + const balanceUSDCSupply = await getUserAssetBalance( + assetAddresses.USDC, //z0USDC + walletAddress + ); + const balanceUSDCBorrow = await getUserAssetBalance( + assetAddresses.debtUSDC, // debt z0USDC + walletAddress + ); - const results: ContractCallResults = await multicall.call( - contractCallContext + //usdt + const balanceUSDTSupply = await getUserAssetBalance( + assetAddresses.USDT, // z0USDT + walletAddress + ); + const balanceUSDTBorrow = await getUserAssetBalance( + assetAddresses.debtUSDT, // debt z0USDT + walletAddress ); - const flattenedResults: { - address: string; - asset: string; - balance: string; - blockNumber: number; - }[] = []; + const finalResult = balanceMAI.map((mai, index) => { + return { + address: mai.address, + balance: { + MAI: mai.balance, + ezETH: balanceezETH[index].balance, + GRAI: balanceGRAI[index].balance, + ETH: balanceETHSupply[index].balance - balanceETHBorrow[index].balance, + USDC: + balanceUSDCSupply[index].balance - balanceUSDCBorrow[index].balance, + USDT: + balanceUSDTSupply[index].balance - balanceUSDTBorrow[index].balance, + }, + }; + }); + return finalResult; +}; - const values = Object.values(results.results); - values.forEach((value) => { - value.callsReturnContext.forEach((ret) => { - const balance = ethers.BigNumber.from(ret.returnValues[0]).toString(); +export const main = async () => { + const blockNumber = await lineaProvider.getBlockNumber(); + const timestamp = new Date(); + const first = 100; + let batch; + let lastAddress = "0x0000000000000000000000000000000000000000"; + const queryURL = + "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; + const rows: any = []; - if (balance === "0") return; + do { + const graphQuery = `query { + users(where: {id_gt: "${lastAddress}"}, first: ${first}) { + id + } + }`; - flattenedResults.push({ - address: ret.methodParameters[0], - asset: ret.reference.split("-")[0], - balance: ret.reference.includes("debt") ? "-" : "" + balance, - blockNumber: results.blockNumber, + const headers = { + "Content-Type": "application/json", + }; + batch = await axios.post(queryURL, { query: graphQuery }, { headers }); + const addresses = batch.data.data.users.map((user: any) => user.id); + + const balance = await userBalance(addresses); + + balance.forEach((user) => { + Object.entries(user.balance).map(([key, value]) => { + if (value !== 0) + rows.push([ + String(blockNumber), + String(timestamp.toISOString()), + user.address, + underlyingAddresses[key], // Retrieve corresponding address from assetAddresses + String(value), + ]); }); }); - }); - - const finalResults: { - address: string; - asset: string; - balance: string; - blockNumber: number; - }[] = []; - - flattenedResults.forEach((res) => { - const index = finalResults.findIndex((val) => val.asset); - if (index > 0) { - finalResults[index] = { - ...finalResults[index], - balance: ( - Number(finalResults[index].balance) + Number(res.balance) - ).toString(), - }; - } else finalResults.push(res); - }); - - return finalResults; + console.log(`Processed ${rows.length} rows`); + lastAddress = batch.data.data.users[batch.data.data.users.length - 1].id; + await userBalanceCSV(rows); + } while (batch.data.data.users.length === first); }; -const writeToCSV = async (data: [string, string, string, string, string][]) => { +export const userBalanceCSV = async (data: any) => { // File path where the CSV will be saved const filePath = "outputData.csv"; const headers = [ @@ -176,11 +171,13 @@ const writeToCSV = async (data: [string, string, string, string, string][]) => { const fileStream = fs.createWriteStream(filePath); // Create a CSV writer - const csvStream: any = write([]); + const csvStream = write([]); csvStream.pipe(fileStream); csvStream.write(headers); - data.forEach(csvStream.write); + data.forEach((row: any) => { + csvStream.write(row); + }); csvStream.on("finish", () => { console.log("CSV file has been written successfully."); @@ -188,83 +185,6 @@ const writeToCSV = async (data: [string, string, string, string, string][]) => { }); }; -const getAddresses = async () => { - console.log("fetching users"); - const count = 1000; - - let lastAddress = "0x0000000000000000000000000000000000000000"; - const queryURL = - "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; - - const addresses: string[] = []; - - do { - const query = `query { - users(where: {id_gt: "${lastAddress}"}, first: ${count}) { - id - } - }`; - - const headers = { - "Content-Type": "application/json", - }; - - const batch = await axios.post( - queryURL, - { query }, - { headers } - ); - - const results = batch.data.data.users.map((user) => user.id); - addresses.push(...results); - lastAddress = batch.data.data.users[batch.data.data.users.length - 1].id; - - if (batch.data.data.users.length !== count) break; - } while (true); - - console.log("fetched users", addresses.length); - return addresses; -}; - -interface IAxiosReponse { - data: { - users: { - id: string; - }[]; - }; -} - -const main = async () => { - const rows: [string, string, string, string, string][] = []; - const addresses = await getAddresses(); - - const batches = 10; - - for (let index = 0; index < addresses.length / batches; index++) { - const subaddresses = addresses.slice( - index * batches, - (index + 1) * batches - ); - const balance = await fetchUserBalancesMulticall(subaddresses); - balance.forEach((row) => { - rows.push([ - row.blockNumber.toString(), - String(new Date().toISOString()), - row.address, - row.asset, - row.balance, - ]); - }); - console.log( - `Processed ${rows.length} rows`, - index, - Math.floor(addresses.length / batches) - ); - } - - await writeToCSV(rows); -}; - main().then(() => { console.log("Done"); }); diff --git a/adapters/zerolend/yarn.lock b/adapters/zerolend/yarn.lock index 81de7e16..b9b4b45b 100644 --- a/adapters/zerolend/yarn.lock +++ b/adapters/zerolend/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -392,6 +397,18 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + "@tsconfig/node10@^1.0.7": version "1.0.10" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.10.tgz#b7ebd3adfa7750628d100594f6726b054d2c33b2" @@ -412,6 +429,11 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + "@types/node@^20.11.30": version "20.11.30" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f" @@ -434,6 +456,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -485,6 +512,11 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +dataloader@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.2.tgz#216dc509b5abe39d43a9b9d97e6e5e473dfbe3e0" + integrity sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -516,6 +548,14 @@ ethereum-multicall@^2.23.0: "@ethersproject/providers" "^5.0.10" ethers "^5.0.15" +ethers-multicall-provider@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ethers-multicall-provider/-/ethers-multicall-provider-6.2.0.tgz#1aefe3bbbd5035fbde52d72ea4be7c1fdab73af0" + integrity sha512-IL+PYXel11lX9hX5lHjvfQEyDGYQejpEcAtbPrmJwm3rCJiqBghHXMW6qMnywh1nQbGg9fmluQ1WOd78RGorHQ== + dependencies: + dataloader "^2.2.2" + ethers "^6.0.0" + ethers@^5.0.15: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" @@ -552,6 +592,19 @@ ethers@^5.0.15: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +ethers@^6, ethers@^6.0.0: + version "6.11.1" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.11.1.tgz#96aae00b627c2e35f9b0a4d65c7ab658259ee6af" + integrity sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + fast-csv@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-5.0.1.tgz#2beaa2437ea83bd335cc3a39a41e69d9936f3987" @@ -702,6 +755,11 @@ ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + typescript@^5.4.3: version "5.4.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" @@ -722,6 +780,11 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" From adea5b923fecf9ca5cd58ed24cc1f8cfafa45fbf Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Sun, 31 Mar 2024 21:46:09 +0530 Subject: [PATCH 3/9] removed mulitcall and fixed the speed --- adapters/zerolend/package.json | 2 - adapters/zerolend/src/index.2.ts | 190 +++++++++++++++++++++++++++++++ adapters/zerolend/src/index.ts | 180 ++++++++--------------------- 3 files changed, 235 insertions(+), 137 deletions(-) create mode 100644 adapters/zerolend/src/index.2.ts diff --git a/adapters/zerolend/package.json b/adapters/zerolend/package.json index b8abad79..2e1e48fe 100644 --- a/adapters/zerolend/package.json +++ b/adapters/zerolend/package.json @@ -11,9 +11,7 @@ "dependencies": { "@types/node": "^20.11.30", "axios": "^1.6.8", - "ethereum-multicall": "^2.23.0", "ethers": "^6", - "ethers-multicall-provider": "^6.2.0", "fast-csv": "^5.0.1", "fs": "^0.0.1-security" }, diff --git a/adapters/zerolend/src/index.2.ts b/adapters/zerolend/src/index.2.ts new file mode 100644 index 00000000..89e76c89 --- /dev/null +++ b/adapters/zerolend/src/index.2.ts @@ -0,0 +1,190 @@ +import { ethers } from "ethers"; +import axios from "axios"; +import { write } from "fast-csv"; +import fs from "fs"; +import { MulticallWrapper } from "ethers-multicall-provider"; + +const lineaProvider = new ethers.JsonRpcProvider("https://rpc.linea.build "); + +const abi = ["function balanceOf(address owner) view returns (uint256)"]; + +type IKeyObject = { [symbol: string]: string }; +const assetAddresses: IKeyObject = { + MAI: "0x759cb97fbc452BAFD49992BA88d3C5dA4Dd9B0e7", + ezETH: "0x0684FC172a0B8e6A65cF4684eDb2082272fe9050", + GRAI: "0xE7e54ca3D6F8a5561f8cee361260E537BDc5bE48", + ETH: "0xB4FFEf15daf4C02787bC5332580b838cE39805f5", + debtETH: "0xCb2dA0F5aEce616e2Cbf29576CFc795fb15c6133", + USDC: "0x2E207ecA8B6Bf77a6ac82763EEEd2A94de4f081d", + debtUSDC: "0xa2703Dc9FbACCD6eC2e4CBfa700989D0238133f6", + USDT: "0x508C39Cd02736535d5cB85f3925218E5e0e8F07A", + debtUSDT: "0x476F206511a18C9956fc79726108a03E647A1817", +}; + +const underlyingAddresses: IKeyObject = { + MAI: "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a", + ezETH: "0x2416092f143378750bb29b79ed961ab195cceea5", + GRAI: "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487", + ETH: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", + USDC: "0x176211869ca2b568f2a7d4ee941e073a821ee1ff", + USDT: "0xa219439258ca9da29e9cc4ce5596924745e12b93", +}; + +const getUserAssetBalance = async ( + tokenAddress: string, + walletAddress: string[] +) => { + const provider = MulticallWrapper.wrap(lineaProvider); + const contract = new ethers.Contract(tokenAddress, abi, provider); + + const results = await Promise.all( + walletAddress.map((w) => contract.balanceOf(w)) + ); + const resp = results.map((amount, index) => { + return { address: walletAddress[index], balance: Number(amount) }; + }); + return resp; +}; + +export const userBalance = async (walletAddress: string[]) => { + //mai + const balanceMAI = await getUserAssetBalance( + assetAddresses.MAI, + walletAddress + ); + + //ezETH + const balanceezETH = await getUserAssetBalance( + assetAddresses.ezETH, + walletAddress + ); + + // GRAI + const balanceGRAI = await getUserAssetBalance( + assetAddresses.GRAI, + walletAddress + ); + + //ETH + const balanceETHSupply = await getUserAssetBalance( + assetAddresses.ETH, //z0WETH + walletAddress + ); + const balanceETHBorrow = await getUserAssetBalance( + assetAddresses.debtETH, // debt WETH + walletAddress + ); + + //usdc + const balanceUSDCSupply = await getUserAssetBalance( + assetAddresses.USDC, //z0USDC + walletAddress + ); + const balanceUSDCBorrow = await getUserAssetBalance( + assetAddresses.debtUSDC, // debt z0USDC + walletAddress + ); + + //usdt + const balanceUSDTSupply = await getUserAssetBalance( + assetAddresses.USDT, // z0USDT + walletAddress + ); + const balanceUSDTBorrow = await getUserAssetBalance( + assetAddresses.debtUSDT, // debt z0USDT + walletAddress + ); + + const finalResult = balanceMAI.map((mai, index) => { + return { + address: mai.address, + balance: { + MAI: mai.balance, + ezETH: balanceezETH[index].balance, + GRAI: balanceGRAI[index].balance, + ETH: balanceETHSupply[index].balance - balanceETHBorrow[index].balance, + USDC: + balanceUSDCSupply[index].balance - balanceUSDCBorrow[index].balance, + USDT: + balanceUSDTSupply[index].balance - balanceUSDTBorrow[index].balance, + }, + }; + }); + return finalResult; +}; + +export const main = async () => { + const blockNumber = await lineaProvider.getBlockNumber(); + const timestamp = new Date(); + const first = 100; + let batch; + let lastAddress = "0x0000000000000000000000000000000000000000"; + const queryURL = + "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; + const rows: any = []; + + do { + const graphQuery = `query { + users(where: {id_gt: "${lastAddress}"}, first: ${first}) { + id + } + }`; + + const headers = { + "Content-Type": "application/json", + }; + batch = await axios.post(queryURL, { query: graphQuery }, { headers }); + const addresses = batch.data.data.users.map((user: any) => user.id); + + const balance = await userBalance(addresses); + + balance.forEach((user) => { + Object.entries(user.balance).map(([key, value]) => { + if (value !== 0) + rows.push([ + String(blockNumber), + String(timestamp.toISOString()), + user.address, + underlyingAddresses[key], // Retrieve corresponding address from assetAddresses + String(value), + ]); + }); + }); + console.log(`Processed ${rows.length} rows`); + lastAddress = batch.data.data.users[batch.data.data.users.length - 1].id; + await userBalanceCSV(rows); + } while (batch.data.data.users.length === first); +}; + +export const userBalanceCSV = async (data: any) => { + // File path where the CSV will be saved + const filePath = "outputData.csv"; + const headers = [ + "block_number", + "timestamp", + "user_address", + "token_address", + "token_balance", + ]; + + // Create a write stream + const fileStream = fs.createWriteStream(filePath); + + // Create a CSV writer + const csvStream = write([]); + + csvStream.pipe(fileStream); + csvStream.write(headers); + data.forEach((row: any) => { + csvStream.write(row); + }); + + csvStream.on("finish", () => { + console.log("CSV file has been written successfully."); + csvStream.end(); + }); +}; + +main().then(() => { + console.log("Done"); +}); diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts index 89e76c89..253301e9 100644 --- a/adapters/zerolend/src/index.ts +++ b/adapters/zerolend/src/index.ts @@ -1,162 +1,72 @@ import { ethers } from "ethers"; -import axios from "axios"; import { write } from "fast-csv"; +import axios from "axios"; import fs from "fs"; -import { MulticallWrapper } from "ethers-multicall-provider"; const lineaProvider = new ethers.JsonRpcProvider("https://rpc.linea.build "); -const abi = ["function balanceOf(address owner) view returns (uint256)"]; - -type IKeyObject = { [symbol: string]: string }; -const assetAddresses: IKeyObject = { - MAI: "0x759cb97fbc452BAFD49992BA88d3C5dA4Dd9B0e7", - ezETH: "0x0684FC172a0B8e6A65cF4684eDb2082272fe9050", - GRAI: "0xE7e54ca3D6F8a5561f8cee361260E537BDc5bE48", - ETH: "0xB4FFEf15daf4C02787bC5332580b838cE39805f5", - debtETH: "0xCb2dA0F5aEce616e2Cbf29576CFc795fb15c6133", - USDC: "0x2E207ecA8B6Bf77a6ac82763EEEd2A94de4f081d", - debtUSDC: "0xa2703Dc9FbACCD6eC2e4CBfa700989D0238133f6", - USDT: "0x508C39Cd02736535d5cB85f3925218E5e0e8F07A", - debtUSDT: "0x476F206511a18C9956fc79726108a03E647A1817", -}; - -const underlyingAddresses: IKeyObject = { - MAI: "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a", - ezETH: "0x2416092f143378750bb29b79ed961ab195cceea5", - GRAI: "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487", - ETH: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", - USDC: "0x176211869ca2b568f2a7d4ee941e073a821ee1ff", - USDT: "0xa219439258ca9da29e9cc4ce5596924745e12b93", -}; - -const getUserAssetBalance = async ( - tokenAddress: string, - walletAddress: string[] -) => { - const provider = MulticallWrapper.wrap(lineaProvider); - const contract = new ethers.Contract(tokenAddress, abi, provider); - - const results = await Promise.all( - walletAddress.map((w) => contract.balanceOf(w)) - ); - const resp = results.map((amount, index) => { - return { address: walletAddress[index], balance: Number(amount) }; - }); - return resp; -}; - -export const userBalance = async (walletAddress: string[]) => { - //mai - const balanceMAI = await getUserAssetBalance( - assetAddresses.MAI, - walletAddress - ); - - //ezETH - const balanceezETH = await getUserAssetBalance( - assetAddresses.ezETH, - walletAddress - ); - - // GRAI - const balanceGRAI = await getUserAssetBalance( - assetAddresses.GRAI, - walletAddress - ); - - //ETH - const balanceETHSupply = await getUserAssetBalance( - assetAddresses.ETH, //z0WETH - walletAddress - ); - const balanceETHBorrow = await getUserAssetBalance( - assetAddresses.debtETH, // debt WETH - walletAddress - ); - - //usdc - const balanceUSDCSupply = await getUserAssetBalance( - assetAddresses.USDC, //z0USDC - walletAddress - ); - const balanceUSDCBorrow = await getUserAssetBalance( - assetAddresses.debtUSDC, // debt z0USDC - walletAddress - ); - - //usdt - const balanceUSDTSupply = await getUserAssetBalance( - assetAddresses.USDT, // z0USDT - walletAddress - ); - const balanceUSDTBorrow = await getUserAssetBalance( - assetAddresses.debtUSDT, // debt z0USDT - walletAddress - ); - - const finalResult = balanceMAI.map((mai, index) => { - return { - address: mai.address, - balance: { - MAI: mai.balance, - ezETH: balanceezETH[index].balance, - GRAI: balanceGRAI[index].balance, - ETH: balanceETHSupply[index].balance - balanceETHBorrow[index].balance, - USDC: - balanceUSDCSupply[index].balance - balanceUSDCBorrow[index].balance, - USDT: - balanceUSDTSupply[index].balance - balanceUSDTBorrow[index].balance, - }, - }; - }); - return finalResult; -}; +interface IResponse { + data: { + userReserves: { + supplyBalance: string; + debtBalance: string; + reserve: string; + user: { + id: string; + }; + }[]; + }; +} export const main = async () => { const blockNumber = await lineaProvider.getBlockNumber(); const timestamp = new Date(); - const first = 100; - let batch; + const first = 1000; + let lastAddress = "0x0000000000000000000000000000000000000000"; const queryURL = - "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; - const rows: any = []; + "https://api.studio.thegraph.com/query/65585/zl-linea-points/version/latest"; + const rows: string[][] = []; do { - const graphQuery = `query { - users(where: {id_gt: "${lastAddress}"}, first: ${first}) { + const query = `query { + userReserves(where: {id_gt: "${lastAddress}"}, first: ${first}) { + supplyBalance + debtBalance + reserve + user { id } - }`; + } + }`; const headers = { "Content-Type": "application/json", }; - batch = await axios.post(queryURL, { query: graphQuery }, { headers }); - const addresses = batch.data.data.users.map((user: any) => user.id); - - const balance = await userBalance(addresses); - - balance.forEach((user) => { - Object.entries(user.balance).map(([key, value]) => { - if (value !== 0) - rows.push([ - String(blockNumber), - String(timestamp.toISOString()), - user.address, - underlyingAddresses[key], // Retrieve corresponding address from assetAddresses - String(value), - ]); - }); + const batch = await axios.post(queryURL, { query }, { headers }); + if (batch.data.data.userReserves.length <= 1) break; + + batch.data.data.userReserves.forEach((data) => { + const balance = BigInt(data.supplyBalance) - BigInt(data.debtBalance); + + if (balance !== 0n) + rows.push([ + String(blockNumber), + String(timestamp.toISOString()), + data.user.id, + data.reserve, // Retrieve corresponding address from assetAddresses + balance.toString(), + ]); + + lastAddress = data.user.id; }); + console.log(`Processed ${rows.length} rows`); - lastAddress = batch.data.data.users[batch.data.data.users.length - 1].id; - await userBalanceCSV(rows); - } while (batch.data.data.users.length === first); + await writeCSV(rows); + } while (true); }; -export const userBalanceCSV = async (data: any) => { +export const writeCSV = async (data: string[][]) => { // File path where the CSV will be saved const filePath = "outputData.csv"; const headers = [ From db6c807d067069c6947134da428f5bd241f8b2a2 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Sun, 31 Mar 2024 21:46:52 +0530 Subject: [PATCH 4/9] removed old file --- adapters/zerolend/src/index.2.ts | 190 ------------------------------- 1 file changed, 190 deletions(-) delete mode 100644 adapters/zerolend/src/index.2.ts diff --git a/adapters/zerolend/src/index.2.ts b/adapters/zerolend/src/index.2.ts deleted file mode 100644 index 89e76c89..00000000 --- a/adapters/zerolend/src/index.2.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { ethers } from "ethers"; -import axios from "axios"; -import { write } from "fast-csv"; -import fs from "fs"; -import { MulticallWrapper } from "ethers-multicall-provider"; - -const lineaProvider = new ethers.JsonRpcProvider("https://rpc.linea.build "); - -const abi = ["function balanceOf(address owner) view returns (uint256)"]; - -type IKeyObject = { [symbol: string]: string }; -const assetAddresses: IKeyObject = { - MAI: "0x759cb97fbc452BAFD49992BA88d3C5dA4Dd9B0e7", - ezETH: "0x0684FC172a0B8e6A65cF4684eDb2082272fe9050", - GRAI: "0xE7e54ca3D6F8a5561f8cee361260E537BDc5bE48", - ETH: "0xB4FFEf15daf4C02787bC5332580b838cE39805f5", - debtETH: "0xCb2dA0F5aEce616e2Cbf29576CFc795fb15c6133", - USDC: "0x2E207ecA8B6Bf77a6ac82763EEEd2A94de4f081d", - debtUSDC: "0xa2703Dc9FbACCD6eC2e4CBfa700989D0238133f6", - USDT: "0x508C39Cd02736535d5cB85f3925218E5e0e8F07A", - debtUSDT: "0x476F206511a18C9956fc79726108a03E647A1817", -}; - -const underlyingAddresses: IKeyObject = { - MAI: "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a", - ezETH: "0x2416092f143378750bb29b79ed961ab195cceea5", - GRAI: "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487", - ETH: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", - USDC: "0x176211869ca2b568f2a7d4ee941e073a821ee1ff", - USDT: "0xa219439258ca9da29e9cc4ce5596924745e12b93", -}; - -const getUserAssetBalance = async ( - tokenAddress: string, - walletAddress: string[] -) => { - const provider = MulticallWrapper.wrap(lineaProvider); - const contract = new ethers.Contract(tokenAddress, abi, provider); - - const results = await Promise.all( - walletAddress.map((w) => contract.balanceOf(w)) - ); - const resp = results.map((amount, index) => { - return { address: walletAddress[index], balance: Number(amount) }; - }); - return resp; -}; - -export const userBalance = async (walletAddress: string[]) => { - //mai - const balanceMAI = await getUserAssetBalance( - assetAddresses.MAI, - walletAddress - ); - - //ezETH - const balanceezETH = await getUserAssetBalance( - assetAddresses.ezETH, - walletAddress - ); - - // GRAI - const balanceGRAI = await getUserAssetBalance( - assetAddresses.GRAI, - walletAddress - ); - - //ETH - const balanceETHSupply = await getUserAssetBalance( - assetAddresses.ETH, //z0WETH - walletAddress - ); - const balanceETHBorrow = await getUserAssetBalance( - assetAddresses.debtETH, // debt WETH - walletAddress - ); - - //usdc - const balanceUSDCSupply = await getUserAssetBalance( - assetAddresses.USDC, //z0USDC - walletAddress - ); - const balanceUSDCBorrow = await getUserAssetBalance( - assetAddresses.debtUSDC, // debt z0USDC - walletAddress - ); - - //usdt - const balanceUSDTSupply = await getUserAssetBalance( - assetAddresses.USDT, // z0USDT - walletAddress - ); - const balanceUSDTBorrow = await getUserAssetBalance( - assetAddresses.debtUSDT, // debt z0USDT - walletAddress - ); - - const finalResult = balanceMAI.map((mai, index) => { - return { - address: mai.address, - balance: { - MAI: mai.balance, - ezETH: balanceezETH[index].balance, - GRAI: balanceGRAI[index].balance, - ETH: balanceETHSupply[index].balance - balanceETHBorrow[index].balance, - USDC: - balanceUSDCSupply[index].balance - balanceUSDCBorrow[index].balance, - USDT: - balanceUSDTSupply[index].balance - balanceUSDTBorrow[index].balance, - }, - }; - }); - return finalResult; -}; - -export const main = async () => { - const blockNumber = await lineaProvider.getBlockNumber(); - const timestamp = new Date(); - const first = 100; - let batch; - let lastAddress = "0x0000000000000000000000000000000000000000"; - const queryURL = - "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; - const rows: any = []; - - do { - const graphQuery = `query { - users(where: {id_gt: "${lastAddress}"}, first: ${first}) { - id - } - }`; - - const headers = { - "Content-Type": "application/json", - }; - batch = await axios.post(queryURL, { query: graphQuery }, { headers }); - const addresses = batch.data.data.users.map((user: any) => user.id); - - const balance = await userBalance(addresses); - - balance.forEach((user) => { - Object.entries(user.balance).map(([key, value]) => { - if (value !== 0) - rows.push([ - String(blockNumber), - String(timestamp.toISOString()), - user.address, - underlyingAddresses[key], // Retrieve corresponding address from assetAddresses - String(value), - ]); - }); - }); - console.log(`Processed ${rows.length} rows`); - lastAddress = batch.data.data.users[batch.data.data.users.length - 1].id; - await userBalanceCSV(rows); - } while (batch.data.data.users.length === first); -}; - -export const userBalanceCSV = async (data: any) => { - // File path where the CSV will be saved - const filePath = "outputData.csv"; - const headers = [ - "block_number", - "timestamp", - "user_address", - "token_address", - "token_balance", - ]; - - // Create a write stream - const fileStream = fs.createWriteStream(filePath); - - // Create a CSV writer - const csvStream = write([]); - - csvStream.pipe(fileStream); - csvStream.write(headers); - data.forEach((row: any) => { - csvStream.write(row); - }); - - csvStream.on("finish", () => { - console.log("CSV file has been written successfully."); - csvStream.end(); - }); -}; - -main().then(() => { - console.log("Done"); -}); From 60fe1551a3be42524c4b957f5ab9b000c063ea9d Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Sun, 31 Mar 2024 21:51:15 +0530 Subject: [PATCH 5/9] followed build format --- adapters/zerolend/package.json | 4 +- adapters/zerolend/tsconfig.json | 101 ++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 adapters/zerolend/tsconfig.json diff --git a/adapters/zerolend/package.json b/adapters/zerolend/package.json index 2e1e48fe..432be354 100644 --- a/adapters/zerolend/package.json +++ b/adapters/zerolend/package.json @@ -4,7 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "start": "ts-node src/index.ts" + "compile": "tsc", + "start": "node dist/index.js", + "dev": "ts-node src/index.ts" }, "author": "", "license": "ISC", diff --git a/adapters/zerolend/tsconfig.json b/adapters/zerolend/tsconfig.json new file mode 100644 index 00000000..8df9e19a --- /dev/null +++ b/adapters/zerolend/tsconfig.json @@ -0,0 +1,101 @@ +{ + "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. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "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. */ + // "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. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "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. */ + // "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. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "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. */ + // "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. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "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. */ + // "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. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "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. */ + // "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. */ + /* Type Checking */ + "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. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "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 be0aac5929e8600aa46587085a82cd83dc2d0068 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Fri, 19 Apr 2024 13:06:16 +0400 Subject: [PATCH 6/9] fixed the zerolend script to follow the template of grai --- adapters/zerolend/package.json | 20 ++++----- adapters/zerolend/src/index.ts | 79 ++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/adapters/zerolend/package.json b/adapters/zerolend/package.json index 432be354..1c94c611 100644 --- a/adapters/zerolend/package.json +++ b/adapters/zerolend/package.json @@ -3,22 +3,22 @@ "version": "1.0.0", "description": "", "main": "index.js", + "type": "commonjs", "scripts": { - "compile": "tsc", "start": "node dist/index.js", - "dev": "ts-node src/index.ts" + "compile": "tsc", + "watch": "tsc -w", + "clear": "rm -rf dist", + "test": "node " }, + "keywords": [], "author": "", - "license": "ISC", + "license": "UNLICENSED", "dependencies": { - "@types/node": "^20.11.30", - "axios": "^1.6.8", - "ethers": "^6", - "fast-csv": "^5.0.1", - "fs": "^0.0.1-security" + "fast-csv": "^5.0.1" }, "devDependencies": { - "ts-node": "^10.9.2", - "typescript": "^5.4.3" + "@types/node": "^20.11.17", + "typescript": "^5.3.3" } } diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts index 253301e9..8d2cf6b0 100644 --- a/adapters/zerolend/src/index.ts +++ b/adapters/zerolend/src/index.ts @@ -18,15 +18,42 @@ interface IResponse { }; } -export const main = async () => { - const blockNumber = await lineaProvider.getBlockNumber(); +type OutputDataSchemaRow = { + block_number: number; + timestamp: number; + user_address: string; + token_address: string; + token_balance: number; + token_symbol: string; + usd_price: number; +}; + +interface BlockData { + blockNumber: number; + blockTimestamp: number; +} + +const queryURL = + "https://api.studio.thegraph.com/query/65585/zl-linea-points/version/latest"; + +const symbolMapping: { [key: string]: string } = { + "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f": "WETH", + "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a": "MAI", + "0x176211869ca2b568f2a7d4ee941e073a821ee1ff": "USDC", + "0xa219439258ca9da29e9cc4ce5596924745e12b93": "USDT", + "0x2416092f143378750bb29b79ed961ab195cceea5": "ezETH", + "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487": "GRAI", + "0x3aab2285ddcddad8edf438c1bab47e1a9d05a9b4": "WBTC", +}; +export const main = async ( + blockNumber: number, + blockTimestamp: number +): Promise => { const timestamp = new Date(); const first = 1000; let lastAddress = "0x0000000000000000000000000000000000000000"; - const queryURL = - "https://api.studio.thegraph.com/query/65585/zl-linea-points/version/latest"; - const rows: string[][] = []; + const rows: OutputDataSchemaRow[] = []; do { const query = `query { @@ -50,23 +77,26 @@ export const main = async () => { const balance = BigInt(data.supplyBalance) - BigInt(data.debtBalance); if (balance !== 0n) - rows.push([ - String(blockNumber), - String(timestamp.toISOString()), - data.user.id, - data.reserve, // Retrieve corresponding address from assetAddresses - balance.toString(), - ]); + rows.push({ + block_number: blockNumber, + timestamp: blockTimestamp, + user_address: data.user.id, + token_address: data.reserve, + token_balance: Number(balance), + token_symbol: symbolMapping[data.reserve.toLowerCase()] || "", + usd_price: 0, + }); lastAddress = data.user.id; }); console.log(`Processed ${rows.length} rows`); - await writeCSV(rows); } while (true); + + return rows; }; -export const writeCSV = async (data: string[][]) => { +export const writeCSV = async (data: OutputDataSchemaRow[]) => { // File path where the CSV will be saved const filePath = "outputData.csv"; const headers = [ @@ -85,8 +115,14 @@ export const writeCSV = async (data: string[][]) => { csvStream.pipe(fileStream); csvStream.write(headers); - data.forEach((row: any) => { - csvStream.write(row); + data.forEach((row) => { + csvStream.write([ + row.block_number, + row.timestamp, + row.user_address, + row.token_address, + row.token_balance, + ]); }); csvStream.on("finish", () => { @@ -95,6 +131,13 @@ export const writeCSV = async (data: string[][]) => { }); }; -main().then(() => { - console.log("Done"); +export const getUserTVLByBlock = async (blocks: BlockData) => { + const { blockNumber, blockTimestamp } = blocks; + const csvRowsVessels = await main(blockNumber, blockTimestamp); + return csvRowsVessels; +}; + +main(0, 0).then(async (data) => { + console.log("Done", data); + await writeCSV(data); }); From fa37361f3ccae580908b139cff4faaa16fbb5c45 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Mon, 29 Apr 2024 22:44:27 +0300 Subject: [PATCH 7/9] Got zerolend balances of atoken and debt tokens to be captured properly. --- adapters/zerolend/src/index.ts | 57 ++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts index 8d2cf6b0..a473dc56 100644 --- a/adapters/zerolend/src/index.ts +++ b/adapters/zerolend/src/index.ts @@ -1,19 +1,21 @@ -import { ethers } from "ethers"; import { write } from "fast-csv"; import axios from "axios"; import fs from "fs"; -const lineaProvider = new ethers.JsonRpcProvider("https://rpc.linea.build "); - interface IResponse { data: { userReserves: { - supplyBalance: string; - debtBalance: string; - reserve: string; user: { id: string; }; + currentTotalDebt: string; + currentATokenBalance: string; + reserve: { + underlyingAsset: string; + symbol: string; + name: string; + }; + liquidityRate: "0"; }[]; }; } @@ -34,17 +36,8 @@ interface BlockData { } const queryURL = - "https://api.studio.thegraph.com/query/65585/zl-linea-points/version/latest"; - -const symbolMapping: { [key: string]: string } = { - "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f": "WETH", - "0xf3b001d64c656e30a62fbaaca003b1336b4ce12a": "MAI", - "0x176211869ca2b568f2a7d4ee941e073a821ee1ff": "USDC", - "0xa219439258ca9da29e9cc4ce5596924745e12b93": "USDT", - "0x2416092f143378750bb29b79ed961ab195cceea5": "ezETH", - "0x894134a25a5fac1c2c26f1d8fbf05111a3cb9487": "GRAI", - "0x3aab2285ddcddad8edf438c1bab47e1a9d05a9b4": "WBTC", -}; + "https://api.studio.thegraph.com/query/65585/zerolend-linea-market/version/latest"; + export const main = async ( blockNumber: number, blockTimestamp: number @@ -56,41 +49,51 @@ export const main = async ( const rows: OutputDataSchemaRow[] = []; do { - const query = `query { - userReserves(where: {id_gt: "${lastAddress}"}, first: ${first}) { - supplyBalance - debtBalance - reserve + const query = `{ + userReserves( + where: {and: [{or: [{currentTotalDebt_gt: 0}, {currentATokenBalance_gt: 0}]}, {user_gt: "${lastAddress}"}]} + first: ${first} + ) { user { id } + currentTotalDebt + currentATokenBalance + reserve { + underlyingAsset + symbol + name + } + liquidityRate } }`; const headers = { "Content-Type": "application/json", }; + const batch = await axios.post(queryURL, { query }, { headers }); if (batch.data.data.userReserves.length <= 1) break; batch.data.data.userReserves.forEach((data) => { - const balance = BigInt(data.supplyBalance) - BigInt(data.debtBalance); + const balance = + BigInt(data.currentATokenBalance) - BigInt(data.currentTotalDebt); if (balance !== 0n) rows.push({ block_number: blockNumber, timestamp: blockTimestamp, user_address: data.user.id, - token_address: data.reserve, + token_address: data.reserve.underlyingAsset, token_balance: Number(balance), - token_symbol: symbolMapping[data.reserve.toLowerCase()] || "", + token_symbol: data.reserve.symbol, usd_price: 0, }); lastAddress = data.user.id; }); - console.log(`Processed ${rows.length} rows`); + console.log(`Processed ${rows.length} rows`, lastAddress); } while (true); return rows; @@ -105,6 +108,7 @@ export const writeCSV = async (data: OutputDataSchemaRow[]) => { "user_address", "token_address", "token_balance", + "token_symbol", ]; // Create a write stream @@ -122,6 +126,7 @@ export const writeCSV = async (data: OutputDataSchemaRow[]) => { row.user_address, row.token_address, row.token_balance, + row.token_symbol, ]); }); From 9d7d3e244c79576f9fe423b849e649451d06d574 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Tue, 30 Apr 2024 08:51:16 +0300 Subject: [PATCH 8/9] update index --- adapters/zerolend/src/index.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts index a473dc56..5e121ad3 100644 --- a/adapters/zerolend/src/index.ts +++ b/adapters/zerolend/src/index.ts @@ -1,5 +1,4 @@ import { write } from "fast-csv"; -import axios from "axios"; import fs from "fs"; interface IResponse { @@ -68,14 +67,16 @@ export const main = async ( } }`; - const headers = { - "Content-Type": "application/json", - }; + const response = await fetch(queryURL, { + method: "POST", + body: JSON.stringify({ query }), + headers: { "Content-Type": "application/json" }, + }); + const batch: IResponse = await response.json(); - const batch = await axios.post(queryURL, { query }, { headers }); - if (batch.data.data.userReserves.length <= 1) break; + if (batch.data.userReserves.length <= 1) break; - batch.data.data.userReserves.forEach((data) => { + batch.data.userReserves.forEach((data) => { const balance = BigInt(data.currentATokenBalance) - BigInt(data.currentTotalDebt); @@ -93,7 +94,9 @@ export const main = async ( lastAddress = data.user.id; }); - console.log(`Processed ${rows.length} rows`, lastAddress); + console.log( + `Processed ${rows.length} rows. Last address is ${lastAddress}` + ); } while (true); return rows; @@ -138,8 +141,7 @@ export const writeCSV = async (data: OutputDataSchemaRow[]) => { export const getUserTVLByBlock = async (blocks: BlockData) => { const { blockNumber, blockTimestamp } = blocks; - const csvRowsVessels = await main(blockNumber, blockTimestamp); - return csvRowsVessels; + return await main(blockNumber, blockTimestamp); }; main(0, 0).then(async (data) => { From 7a19a358a6188a3e528a5fc558632c8fabffc9d1 Mon Sep 17 00:00:00 2001 From: Deadshot Ryker Date: Tue, 30 Apr 2024 08:54:40 +0300 Subject: [PATCH 9/9] fixed typescript issues --- adapters/zerolend/src/index.ts | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/adapters/zerolend/src/index.ts b/adapters/zerolend/src/index.ts index 5e121ad3..2a8b9a89 100644 --- a/adapters/zerolend/src/index.ts +++ b/adapters/zerolend/src/index.ts @@ -3,22 +3,24 @@ import fs from "fs"; interface IResponse { data: { - userReserves: { - user: { - id: string; - }; - currentTotalDebt: string; - currentATokenBalance: string; - reserve: { - underlyingAsset: string; - symbol: string; - name: string; - }; - liquidityRate: "0"; - }[]; + userReserves: IData[]; }; } +interface IData { + user: { + id: string; + }; + currentTotalDebt: string; + currentATokenBalance: string; + reserve: { + underlyingAsset: string; + symbol: string; + name: string; + }; + liquidityRate: "0"; +} + type OutputDataSchemaRow = { block_number: number; timestamp: number; @@ -76,7 +78,7 @@ export const main = async ( if (batch.data.userReserves.length <= 1) break; - batch.data.userReserves.forEach((data) => { + batch.data.userReserves.forEach((data: IData) => { const balance = BigInt(data.currentATokenBalance) - BigInt(data.currentTotalDebt);