diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec3f36a..d8571f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,7 +34,6 @@ jobs: cd adapters cd $FOLDER_NAME npm install - npm run compile - cd .. - npm install - npm run start $FOLDER_NAME \ No newline at end of file + tsc + npm run start + \ No newline at end of file diff --git a/adapters/rhomarkets/hourly_blocks.csv b/adapters/rhomarkets/hourly_blocks.csv index b93a46e..73da4b5 100644 --- a/adapters/rhomarkets/hourly_blocks.csv +++ b/adapters/rhomarkets/hourly_blocks.csv @@ -1,2 +1,2 @@ -number timestamp -4243360 1714773599 +number,block_timestamp +6916213,1719322991 \ No newline at end of file diff --git a/adapters/rhomarkets/src/sdk/abi/core.abi.ts b/adapters/rhomarkets/src/sdk/abi/core.abi.ts new file mode 100644 index 0000000..c3d5c09 --- /dev/null +++ b/adapters/rhomarkets/src/sdk/abi/core.abi.ts @@ -0,0 +1,1018 @@ +export default [ + { type: "constructor", inputs: [], stateMutability: "nonpayable" }, + { + type: "function", + name: "_become", + inputs: [ + { + name: "unitroller", + type: "address", + internalType: "contract Unitroller", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_rescueFunds", + inputs: [ + { + name: "_tokenAddress", + type: "address", + internalType: "address", + }, + { name: "_amount", type: "uint256", internalType: "uint256" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setBorrowCapGuardian", + inputs: [ + { + name: "newBorrowCapGuardian", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setBorrowPaused", + inputs: [ + { + name: "rToken", + type: "address", + internalType: "contract RToken", + }, + { name: "state", type: "bool", internalType: "bool" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setCloseFactor", + inputs: [ + { + name: "newCloseFactorMantissa", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setCollateralFactor", + inputs: [ + { + name: "rToken", + type: "address", + internalType: "contract RToken", + }, + { + name: "newCollateralFactorMantissa", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setLiquidationIncentive", + inputs: [ + { + name: "newLiquidationIncentiveMantissa", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setMarketBorrowCaps", + inputs: [ + { + name: "rTokens", + type: "address[]", + internalType: "contract RToken[]", + }, + { + name: "newBorrowCaps", + type: "uint256[]", + internalType: "uint256[]", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setMarketSupplyCaps", + inputs: [ + { + name: "rTokens", + type: "address[]", + internalType: "contract RToken[]", + }, + { + name: "newSupplyCaps", + type: "uint256[]", + internalType: "uint256[]", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setMintPaused", + inputs: [ + { + name: "rToken", + type: "address", + internalType: "contract RToken", + }, + { name: "state", type: "bool", internalType: "bool" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setPauseGuardian", + inputs: [ + { + name: "newPauseGuardian", + type: "address", + internalType: "address", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setPriceOracle", + inputs: [ + { + name: "newOracle", + type: "address", + internalType: "contract PriceOracle", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setRewardDistributor", + inputs: [ + { + name: "newRewardDistributor", + type: "address", + internalType: "contract MultiRewardDistributor", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setSeizePaused", + inputs: [{ name: "state", type: "bool", internalType: "bool" }], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setSupplyCapGuardian", + inputs: [ + { + name: "newSupplyCapGuardian", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setTransferPaused", + inputs: [{ name: "state", type: "bool", internalType: "bool" }], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_supportMarket", + inputs: [ + { + name: "rToken", + type: "address", + internalType: "contract RToken", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "accountAssets", + inputs: [ + { name: "", type: "address", internalType: "address" }, + { name: "", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "address", internalType: "contract RToken" }], + stateMutability: "view", + }, + { + type: "function", + name: "admin", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "allMarkets", + inputs: [{ name: "", type: "uint256", internalType: "uint256" }], + outputs: [{ name: "", type: "address", internalType: "contract RToken" }], + stateMutability: "view", + }, + { + type: "function", + name: "borrowAllowed", + inputs: [ + { name: "rToken", type: "address", internalType: "address" }, + { name: "borrower", type: "address", internalType: "address" }, + { name: "borrowAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "borrowCapGuardian", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "borrowCaps", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "borrowGuardianPaused", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "checkMembership", + inputs: [ + { name: "account", type: "address", internalType: "address" }, + { + name: "rToken", + type: "address", + internalType: "contract RToken", + }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "claimReward", + inputs: [ + { name: "holders", type: "address[]", internalType: "address[]" }, + { + name: "rTokens", + type: "address[]", + internalType: "contract RToken[]", + }, + { name: "borrowers", type: "bool", internalType: "bool" }, + { name: "suppliers", type: "bool", internalType: "bool" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "claimReward", + inputs: [ + { name: "holder", type: "address", internalType: "address" }, + { + name: "rTokens", + type: "address[]", + internalType: "contract RToken[]", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "claimReward", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "claimReward", + inputs: [{ name: "holder", type: "address", internalType: "address" }], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "closeFactorMantissa", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "comptrollerImplementation", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "enterAllMarkets", + inputs: [{ name: "account", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256[]", internalType: "uint256[]" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "enterMarkets", + inputs: [{ name: "rTokens", type: "address[]", internalType: "address[]" }], + outputs: [{ name: "", type: "uint256[]", internalType: "uint256[]" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "exitMarket", + inputs: [ + { + name: "rTokenAddress", + type: "address", + internalType: "address", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "getAccountLiquidity", + inputs: [{ name: "account", type: "address", internalType: "address" }], + outputs: [ + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getAllMarkets", + inputs: [], + outputs: [ + { name: "", type: "address[]", internalType: "contract RToken[]" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getAssetsIn", + inputs: [{ name: "account", type: "address", internalType: "address" }], + outputs: [ + { name: "", type: "address[]", internalType: "contract RToken[]" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getBlockNumber", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "getHypotheticalAccountLiquidity", + inputs: [ + { name: "account", type: "address", internalType: "address" }, + { + name: "rTokenModify", + type: "address", + internalType: "address", + }, + { + name: "redeemTokens", + type: "uint256", + internalType: "uint256", + }, + { name: "borrowAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [ + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "isComptroller", + inputs: [], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "isDeprecated", + inputs: [ + { + name: "rToken", + type: "address", + internalType: "contract RToken", + }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "liquidateBorrowAllowed", + inputs: [ + { + name: "rTokenBorrowed", + type: "address", + internalType: "address", + }, + { + name: "rTokenCollateral", + type: "address", + internalType: "address", + }, + { name: "liquidator", type: "address", internalType: "address" }, + { name: "borrower", type: "address", internalType: "address" }, + { name: "repayAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "liquidateCalculateSeizeTokens", + inputs: [ + { + name: "rTokenBorrowed", + type: "address", + internalType: "address", + }, + { + name: "rTokenCollateral", + type: "address", + internalType: "address", + }, + { + name: "actualRepayAmount", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [ + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "liquidationIncentiveMantissa", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "markets", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [ + { name: "isListed", type: "bool", internalType: "bool" }, + { + name: "collateralFactorMantissa", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "mintAllowed", + inputs: [ + { name: "rToken", type: "address", internalType: "address" }, + { name: "minter", type: "address", internalType: "address" }, + { name: "mintAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "mintGuardianPaused", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "oracle", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract PriceOracle", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "pauseGuardian", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "pendingAdmin", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "pendingComptrollerImplementation", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "redeemAllowed", + inputs: [ + { name: "rToken", type: "address", internalType: "address" }, + { name: "redeemer", type: "address", internalType: "address" }, + { name: "redeemTokens", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "redeemVerify", + inputs: [ + { name: "rToken", type: "address", internalType: "address" }, + { name: "redeemer", type: "address", internalType: "address" }, + { + name: "redeemAmount", + type: "uint256", + internalType: "uint256", + }, + { name: "redeemTokens", type: "uint256", internalType: "uint256" }, + ], + outputs: [], + stateMutability: "pure", + }, + { + type: "function", + name: "repayBorrowAllowed", + inputs: [ + { name: "rToken", type: "address", internalType: "address" }, + { name: "payer", type: "address", internalType: "address" }, + { name: "borrower", type: "address", internalType: "address" }, + { name: "repayAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "rewardDistributor", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract MultiRewardDistributor", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "seizeAllowed", + inputs: [ + { + name: "rTokenCollateral", + type: "address", + internalType: "address", + }, + { + name: "rTokenBorrowed", + type: "address", + internalType: "address", + }, + { name: "liquidator", type: "address", internalType: "address" }, + { name: "borrower", type: "address", internalType: "address" }, + { name: "seizeTokens", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "seizeGuardianPaused", + inputs: [], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "supplyCapGuardian", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "supplyCaps", + inputs: [{ name: "", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "transferAllowed", + inputs: [ + { name: "rToken", type: "address", internalType: "address" }, + { name: "src", type: "address", internalType: "address" }, + { name: "dst", type: "address", internalType: "address" }, + { + name: "transferTokens", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "transferGuardianPaused", + inputs: [], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "event", + name: "ActionPaused", + inputs: [ + { + name: "action", + type: "string", + indexed: false, + internalType: "string", + }, + { + name: "pauseState", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "ActionPaused", + inputs: [ + { + name: "rToken", + type: "address", + indexed: false, + internalType: "contract RToken", + }, + { + name: "action", + type: "string", + indexed: false, + internalType: "string", + }, + { + name: "pauseState", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Failure", + inputs: [ + { + name: "error", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "info", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "detail", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MarketEntered", + inputs: [ + { + name: "rToken", + type: "address", + indexed: false, + internalType: "contract RToken", + }, + { + name: "account", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MarketExited", + inputs: [ + { + name: "rToken", + type: "address", + indexed: false, + internalType: "contract RToken", + }, + { + name: "account", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MarketListed", + inputs: [ + { + name: "rToken", + type: "address", + indexed: false, + internalType: "contract RToken", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewBorrowCap", + inputs: [ + { + name: "rToken", + type: "address", + indexed: true, + internalType: "contract RToken", + }, + { + name: "newBorrowCap", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewBorrowCapGuardian", + inputs: [ + { + name: "oldBorrowCapGuardian", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newBorrowCapGuardian", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewCloseFactor", + inputs: [ + { + name: "oldCloseFactorMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newCloseFactorMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewCollateralFactor", + inputs: [ + { + name: "rToken", + type: "address", + indexed: false, + internalType: "contract RToken", + }, + { + name: "oldCollateralFactorMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newCollateralFactorMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewLiquidationIncentive", + inputs: [ + { + name: "oldLiquidationIncentiveMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newLiquidationIncentiveMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewPauseGuardian", + inputs: [ + { + name: "oldPauseGuardian", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newPauseGuardian", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewPriceOracle", + inputs: [ + { + name: "oldPriceOracle", + type: "address", + indexed: false, + internalType: "contract PriceOracle", + }, + { + name: "newPriceOracle", + type: "address", + indexed: false, + internalType: "contract PriceOracle", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewRewardDistributor", + inputs: [ + { + name: "oldRewardDistributor", + type: "address", + indexed: false, + internalType: "contract MultiRewardDistributor", + }, + { + name: "newRewardDistributor", + type: "address", + indexed: false, + internalType: "contract MultiRewardDistributor", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewSupplyCap", + inputs: [ + { + name: "rToken", + type: "address", + indexed: true, + internalType: "contract RToken", + }, + { + name: "newSupplyCap", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewSupplyCapGuardian", + inputs: [ + { + name: "oldSupplyCapGuardian", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newSupplyCapGuardian", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, +]; diff --git a/adapters/rhomarkets/src/sdk/abi/helpers.ts b/adapters/rhomarkets/src/sdk/abi/helpers.ts new file mode 100644 index 0000000..ab08dcc --- /dev/null +++ b/adapters/rhomarkets/src/sdk/abi/helpers.ts @@ -0,0 +1,20 @@ +export const bigMath = { + abs(x: bigint) { + return x < 0n ? -x : x; + }, + sign(x: bigint) { + if (x === 0n) return 0n; + return x < 0n ? -1n : 1n; + }, + pow(base: bigint, exponent: bigint) { + return base ** exponent; + }, + min(value: bigint, ...values: bigint[]) { + for (const v of values) if (v < value) value = v; + return value; + }, + max(value: bigint, ...values: bigint[]) { + for (const v of values) if (v > value) value = v; + return value; + }, +}; diff --git a/adapters/rhomarkets/src/sdk/abi/ltoken.abi.ts b/adapters/rhomarkets/src/sdk/abi/ltoken.abi.ts new file mode 100644 index 0000000..3760bd1 --- /dev/null +++ b/adapters/rhomarkets/src/sdk/abi/ltoken.abi.ts @@ -0,0 +1,951 @@ +export default [ + { + type: "function", + name: "_acceptAdmin", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_addReserves", + inputs: [{ name: "addAmount", type: "uint256", internalType: "uint256" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_reduceReserves", + inputs: [ + { name: "reduceAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setComptroller", + inputs: [ + { + name: "newComptroller", + type: "address", + internalType: "contract ComptrollerInterface", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setInterestRateModel", + inputs: [ + { + name: "newInterestRateModel", + type: "address", + internalType: "contract InterestRateModel", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setPendingAdmin", + inputs: [ + { + name: "newPendingAdmin", + type: "address", + internalType: "address payable", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setProtocolSeizeShare", + inputs: [ + { + name: "newProtocolSeizeShareMantissa", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "_setReserveFactor", + inputs: [ + { + name: "newReserveFactorMantissa", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "accrualBlockNumber", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "accrueInterest", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "admin", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address payable" }], + stateMutability: "view", + }, + { + type: "function", + name: "allowance", + inputs: [ + { name: "owner", type: "address", internalType: "address" }, + { name: "spender", type: "address", internalType: "address" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "approve", + inputs: [ + { name: "spender", type: "address", internalType: "address" }, + { name: "amount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "balanceOf", + inputs: [{ name: "owner", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "balanceOfUnderlying", + inputs: [{ name: "owner", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "borrow", + inputs: [ + { name: "borrowAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "borrowBalanceCurrent", + inputs: [{ name: "account", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "borrowBalanceStored", + inputs: [{ name: "account", type: "address", internalType: "address" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "borrowIndex", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "borrowRatePerBlock", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "comptroller", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract ComptrollerInterface", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "decimals", + inputs: [], + outputs: [{ name: "", type: "uint8", internalType: "uint8" }], + stateMutability: "view", + }, + { + type: "function", + name: "exchangeRateCurrent", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "exchangeRateStored", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "getAccountSnapshot", + inputs: [{ name: "account", type: "address", internalType: "address" }], + outputs: [ + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + { name: "", type: "uint256", internalType: "uint256" }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getCash", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "initialize", + inputs: [ + { name: "underlying_", type: "address", internalType: "address" }, + { + name: "comptroller_", + type: "address", + internalType: "contract ComptrollerInterface", + }, + { + name: "interestRateModel_", + type: "address", + internalType: "contract InterestRateModel", + }, + { + name: "initialExchangeRateMantissa_", + type: "uint256", + internalType: "uint256", + }, + { name: "name_", type: "string", internalType: "string" }, + { name: "symbol_", type: "string", internalType: "string" }, + { name: "decimals_", type: "uint8", internalType: "uint8" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "initialize", + inputs: [ + { + name: "comptroller_", + type: "address", + internalType: "contract ComptrollerInterface", + }, + { + name: "interestRateModel_", + type: "address", + internalType: "contract InterestRateModel", + }, + { + name: "initialExchangeRateMantissa_", + type: "uint256", + internalType: "uint256", + }, + { name: "name_", type: "string", internalType: "string" }, + { name: "symbol_", type: "string", internalType: "string" }, + { name: "decimals_", type: "uint8", internalType: "uint8" }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "interestRateModel", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract InterestRateModel", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "isEthDerivative", + inputs: [], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "isRToken", + inputs: [], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "view", + }, + { + type: "function", + name: "liquidateBorrow", + inputs: [ + { name: "borrower", type: "address", internalType: "address" }, + { name: "repayAmount", type: "uint256", internalType: "uint256" }, + { + name: "rTokenCollateral", + type: "address", + internalType: "contract RTokenInterface", + }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "mint", + inputs: [{ name: "mintAmount", type: "uint256", internalType: "uint256" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "mintWithPermit", + inputs: [ + { name: "mintAmount", type: "uint256", internalType: "uint256" }, + { name: "deadline", type: "uint256", internalType: "uint256" }, + { name: "v", type: "uint8", internalType: "uint8" }, + { name: "r", type: "bytes32", internalType: "bytes32" }, + { name: "s", type: "bytes32", internalType: "bytes32" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "name", + inputs: [], + outputs: [{ name: "", type: "string", internalType: "string" }], + stateMutability: "view", + }, + { + type: "function", + name: "pendingAdmin", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address payable" }], + stateMutability: "view", + }, + { + type: "function", + name: "protocolSeizeShareMantissa", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "redeem", + inputs: [ + { name: "redeemTokens", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "redeemUnderlying", + inputs: [ + { name: "redeemAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "repayBorrow", + inputs: [{ name: "repayAmount", type: "uint256", internalType: "uint256" }], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "repayBorrowBehalf", + inputs: [ + { name: "borrower", type: "address", internalType: "address" }, + { name: "repayAmount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "reserveFactorMantissa", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "seize", + inputs: [ + { name: "liquidator", type: "address", internalType: "address" }, + { name: "borrower", type: "address", internalType: "address" }, + { name: "seizeTokens", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "supplyRatePerBlock", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "sweepToken", + inputs: [ + { + name: "token", + type: "address", + internalType: "contract EIP20NonStandardInterface", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "symbol", + inputs: [], + outputs: [{ name: "", type: "string", internalType: "string" }], + stateMutability: "view", + }, + { + type: "function", + name: "totalBorrows", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "totalBorrowsCurrent", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "totalReserves", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "totalSupply", + inputs: [], + outputs: [{ name: "", type: "uint256", internalType: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "transfer", + inputs: [ + { name: "dst", type: "address", internalType: "address" }, + { name: "amount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "transferFrom", + inputs: [ + { name: "src", type: "address", internalType: "address" }, + { name: "dst", type: "address", internalType: "address" }, + { name: "amount", type: "uint256", internalType: "uint256" }, + ], + outputs: [{ name: "", type: "bool", internalType: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "underlying", + inputs: [], + outputs: [{ name: "", type: "address", internalType: "address" }], + stateMutability: "view", + }, + { + type: "event", + name: "AccrueInterest", + inputs: [ + { + name: "cashPrior", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "interestAccumulated", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "borrowIndex", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "totalBorrows", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Approval", + inputs: [ + { + name: "owner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "spender", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Borrow", + inputs: [ + { + name: "borrower", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "borrowAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "accountBorrows", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "totalBorrows", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Failure", + inputs: [ + { + name: "error", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "info", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "detail", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "LiquidateBorrow", + inputs: [ + { + name: "liquidator", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "borrower", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "repayAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "rTokenCollateral", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "seizeTokens", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Mint", + inputs: [ + { + name: "minter", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "mintAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "mintTokens", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewAdmin", + inputs: [ + { + name: "oldAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewComptroller", + inputs: [ + { + name: "oldComptroller", + type: "address", + indexed: false, + internalType: "contract ComptrollerInterface", + }, + { + name: "newComptroller", + type: "address", + indexed: false, + internalType: "contract ComptrollerInterface", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewMarketInterestRateModel", + inputs: [ + { + name: "oldInterestRateModel", + type: "address", + indexed: false, + internalType: "contract InterestRateModel", + }, + { + name: "newInterestRateModel", + type: "address", + indexed: false, + internalType: "contract InterestRateModel", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewPendingAdmin", + inputs: [ + { + name: "oldPendingAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newPendingAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewProtocolSeizeShare", + inputs: [ + { + name: "oldProtocolSeizeShareMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newProtocolSeizeShareMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewRedemptionReserveFactor", + inputs: [ + { + name: "oldRedemptionReserveFactor", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newRedemptionReserveFactor", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NewReserveFactor", + inputs: [ + { + name: "oldReserveFactorMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newReserveFactorMantissa", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Redeem", + inputs: [ + { + name: "redeemer", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "redeemAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "redeemTokens", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "RepayBorrow", + inputs: [ + { + name: "payer", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "borrower", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "repayAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "accountBorrows", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "totalBorrows", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "ReservesAdded", + inputs: [ + { + name: "benefactor", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "addAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newTotalReserves", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "ReservesReduced", + inputs: [ + { + name: "admin", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "reduceAmount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newTotalReserves", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Transfer", + inputs: [ + { + name: "from", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "to", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, +]; diff --git a/adapters/rhomarkets/src/sdk/config.ts b/adapters/rhomarkets/src/sdk/config.ts new file mode 100644 index 0000000..05bf245 --- /dev/null +++ b/adapters/rhomarkets/src/sdk/config.ts @@ -0,0 +1,24 @@ +export const enum CHAINS { + SCROLL = 534352, +} + +export const enum PROTOCOLS { + RHO_MARKETS = 1, +} + +export const SUBGRAPH_URLS = { + [CHAINS.SCROLL]: { + [PROTOCOLS.RHO_MARKETS]: { + url: "https://api.studio.thegraph.com/query/79909/rho-markets-mainnet/version/latest", + }, + }, +}; + +export const RPC_URLS = { + [CHAINS.SCROLL]: + "https://scroll-mainnet.blastapi.io/cf50a7c9-e512-45ac-ae1d-d319f1a34f06", +}; + +export const WETH_ADDRESS = { + [CHAINS.SCROLL]: "0x5300000000000000000000000000000000000004", +}; diff --git a/adapters/rhomarkets/src/sdk/index.ts b/adapters/rhomarkets/src/sdk/index.ts index 4e728a6..0a397cb 100644 --- a/adapters/rhomarkets/src/sdk/index.ts +++ b/adapters/rhomarkets/src/sdk/index.ts @@ -1,6 +1,17 @@ import fs from "fs"; import csv from "csv-parser"; +import { scroll } from "viem/chains"; import { fetchGraphQLData } from "./request"; +import { getMarketInfos } from "./marketDetails"; +import { + createPublicClient, + extractChain, + formatUnits, + http, + zeroAddress, +} from "viem"; +import { CHAINS, PROTOCOLS, RPC_URLS } from "./config"; +import ltokenAbi from "./abi/ltoken.abi"; export interface BlockData { blockNumber: number; @@ -18,17 +29,106 @@ export type OutputDataSchemaRow = { }; export const getUserTVLByBlock = async (blocks: BlockData) => { - const protocalInfos = await fetchGraphQLData(blocks.blockNumber); - - const csvRows: OutputDataSchemaRow[] = protocalInfos.map((item) => ({ - protocol: "RhoMarkets", - date: blocks.blockTimestamp, - block_number: blocks.blockNumber, - user_address: item.user_address, - market: item.market, - supply_token: item.supply_token, - borrow_token: item.borrow_token, - })); + const protocalInfos = await fetchGraphQLData( + blocks.blockNumber, + CHAINS.SCROLL, + PROTOCOLS.RHO_MARKETS + ); + + const marketInfos = await getMarketInfos( + "0x8a67AB98A291d1AEA2E1eB0a79ae4ab7f2D76041" + ); + + const marketsMapping: any = {}; + for (let marketInfo of marketInfos) { + marketsMapping[marketInfo.address] = { + address: marketInfo.address, + exchangeRate: marketInfo.exchangeRateStored, + decimals: marketInfo.decimals, + }; + } + + const publicClient = createPublicClient({ + chain: extractChain({ chains: [scroll], id: CHAINS.SCROLL }), + transport: http(RPC_URLS[CHAINS.SCROLL]), + }); + + console.log( + `Will update all borrow balances for ${protocalInfos.length} states` + ); + for (var i = 0; i < protocalInfos.length; i += 1000) { + const start = i; + const end = i + 1000; + var subStates = protocalInfos.slice(start, end); + console.log(`Updating borrow balances for ${start} - ${end}`); + + let borrowBalanceResults = await publicClient.multicall({ + contracts: subStates + .map((m) => { + return [ + { + address: m.market, + abi: ltokenAbi, + functionName: "borrowBalanceStored", + args: [m.user_address], + }, + ]; + }) + .flat() as any, + blockNumber: BigInt(blocks.blockNumber), + }); + + let supplyBalanceResults = await publicClient.multicall({ + contracts: subStates + .map((m) => { + return [ + { + address: m.market, + abi: ltokenAbi, + functionName: "balanceOf", + args: [m.user_address], + }, + ]; + }) + .flat() as any, + blockNumber: BigInt(blocks.blockNumber), + }); + + for (var j = 0; j < subStates.length; j++) { + subStates[j].borrow_token = Number( + formatUnits( + (borrowBalanceResults[j]?.result as bigint) || 0n, + marketsMapping[subStates[j].market].decimals + ) + ); + + subStates[j].supply_token = Number( + formatUnits( + (((supplyBalanceResults[j]?.result as bigint) || 0n) * + marketsMapping[subStates[j].market].exchangeRate) / + 10n ** 18n, + marketsMapping[subStates[j].market].decimals + ) + ); + } + } + + const newStates: any[] = protocalInfos.filter( + (x) => + (x.borrow_token > 0 || x.supply_token > 0) && x.market && x.user_address + ); + + const csvRows: OutputDataSchemaRow[] = newStates.map((item) => { + return { + protocol: "RhoMarkets", + date: blocks.blockTimestamp, + block_number: blocks.blockNumber, + user_address: item.user_address, + market: item.market, + supply_token: item.supply_token, + borrow_token: item.borrow_token, + }; + }); return csvRows; }; @@ -40,7 +140,7 @@ export const readBlocksFromCSV = async ( await new Promise((resolve, reject) => { fs.createReadStream(filePath) - .pipe(csv({ separator: "\t" })) // Specify the separator as '\t' for TSV files + .pipe(csv({ separator: "," })) .on("data", (row) => { const blockNumber = parseInt(row.number, 10); const blockTimestamp = parseInt(row.block_timestamp, 10); diff --git a/adapters/rhomarkets/src/sdk/marketDetails.ts b/adapters/rhomarkets/src/sdk/marketDetails.ts new file mode 100644 index 0000000..856bb4e --- /dev/null +++ b/adapters/rhomarkets/src/sdk/marketDetails.ts @@ -0,0 +1,109 @@ +import { createPublicClient, extractChain, http, getContract } from "viem"; +import { CHAINS, RPC_URLS } from "./config"; +import { scroll } from "viem/chains"; +import coreAbi from "./abi/core.abi"; +import ltokenAbi from "./abi/ltoken.abi"; + +export interface MarketInfo { + address: string; + decimals: number; + underlyingAddress: string; + underlyingSymbol: string; + exchangeRateStored: bigint; +} + +export const getMarketInfos = async ( + coreAddress: `0x${string}`, + blockNumber?: bigint +) => { + const publicClient = createPublicClient({ + chain: extractChain({ chains: [scroll], id: CHAINS.SCROLL }), + transport: http(RPC_URLS[CHAINS.SCROLL]), + }); + + const core = getContract({ + address: coreAddress, + abi: coreAbi, + client: publicClient, + }); + + const marketAddresses: `0x${string}`[] = + ((await core.read.getAllMarkets()) as any) || []; + + console.log("marketAddresses ", marketAddresses); + + const markets = marketAddresses.map((m) => + getContract({ + address: m, + abi: ltokenAbi, + client: publicClient, + }) + ); + + const underlyingResults = await publicClient.multicall({ + contracts: markets.map((m) => ({ + address: m.address, + abi: m.abi, + functionName: "underlying", + })) as any, + }); + + const decimalResults = await publicClient.multicall({ + contracts: markets.map((m) => ({ + address: m.address, + abi: m.abi, + functionName: "decimals", + })) as any, + }); + + const underlyingAddresses = underlyingResults.map( + (v) => v.result as `0x${string}` + ); + + const underlyings = underlyingAddresses.map((m) => + getContract({ + address: m as `0x${string}`, + abi: ltokenAbi, + client: publicClient, + }) + ); + + const underlyingSymbolResults = await publicClient.multicall({ + contracts: underlyings.map((m) => ({ + address: (m as any).address, + abi: (m as any).abi, + functionName: "symbol", + })) as any, + }); + + + const exchangeRateResults = await publicClient.multicall({ + contracts: markets.map((m) => ({ + address: m.address, + abi: m.abi, + functionName: "exchangeRateStored", + })) as any, + blockNumber, + }); + + const marketInfos: MarketInfo[] = []; + + for (let i = 0; i < markets.length; i++) { + const marketAddress = markets[i].address.toLowerCase(); + const underlyingAddress = underlyingAddresses[i]; + + marketInfos.push({ + address: marketAddress, + underlyingAddress, + decimals: (decimalResults[i].result as number) || 0, + underlyingSymbol: (underlyingSymbolResults[i].result as any) || "ETH", + exchangeRateStored: BigInt( + exchangeRateResults[i].status === "success" + ? (exchangeRateResults[i].result as any) + : 0 + ), + }); + } + + return marketInfos; +}; diff --git a/adapters/rhomarkets/src/sdk/request.ts b/adapters/rhomarkets/src/sdk/request.ts index a658918..06c6bd6 100644 --- a/adapters/rhomarkets/src/sdk/request.ts +++ b/adapters/rhomarkets/src/sdk/request.ts @@ -1,3 +1,6 @@ +import { zeroAddress } from "viem"; +import { CHAINS, PROTOCOLS, SUBGRAPH_URLS } from "./config"; + interface ProtocalData { timestamp: number; block_number: number; @@ -14,57 +17,117 @@ interface GraphQLResponse { errors?: any[]; } -const query = ` -query ($limit: Int, $offset: Int, $blockNumber: Int) { - data(first: $limit, skip: $offset, block: { number: $blockNumber }) { - timestamp - block_number - user_address - market - supply_token - borrow_token - } - } - -`; - -export async function fetchGraphQLData( - blockNumber: number -): Promise { +// Helper function to fetch data from Subgraph +export async function fetchSubgraphData( + limit: number, + lastId: string, + url: string +) { const query = ` - query RHO_MARKETS { - data(blockNumber: ${blockNumber}) { - timestamp - block_number - user_address - market - supply_token - borrow_token + query MyQuery { + accounts(first: ${limit}, where: { id_gt: "${lastId}" }, orderBy: id) { + id + tokens { + cTokenBalance + storedBorrowBalance + totalUnderlyingBorrowed + totalUnderlyingSupplied + accrualBlockNumber + market { + id + underlyingAddress + symbol + underlyingSymbol + blockTimestamp + underlyingDecimals + } + } } } - `; - try { - const response = await fetch( - "https://drgstmbns1.execute-api.us-east-1.amazonaws.com/default/RhoMarketPoints", - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ query }), - } - ); + let response = await fetch(url, { + method: "POST", + body: JSON.stringify({ query }), + headers: { "Content-Type": "application/json" }, + }); + + const { data } = await response.json(); + + return { + accounts: data?.accounts || [], + lastId: data?.accounts[data?.accounts.length - 1].id || "", + }; +} + +export async function fetchGraphQLData( + blockNumber: number, + chainId: CHAINS, + protocol: PROTOCOLS +): Promise { + const url = SUBGRAPH_URLS[chainId][protocol].url; + const limit = Infinity; + const offset = 0; + + const totalLimit = 1000; // Adjust total fetch limit if needed + let fetchOffset = 0; + let allData: any[] = []; + let moreDataAvailable = true; + let lastId = ""; + + let count = 0; + + while (moreDataAvailable) { + const { accounts: batchData, lastId: currentLastId } = + await fetchSubgraphData(totalLimit, lastId, url); + + lastId = currentLastId; + allData = allData.concat(batchData); + + count++; + + if (batchData.length < totalLimit) { + moreDataAvailable = false; + } else { + fetchOffset += totalLimit; + } + } + + // Check if data is returned + if (allData) { + // Process and transform the data + const flatData = allData + .flatMap((account) => + account.tokens.map( + (token: { + underlyingDecimals: any; + market: { blockTimestamp: any; id: any }; + accrualBlockNumber: any; + cTokenBalance: any; + storedBorrowBalance: any; + }) => ({ + timestamp: Number(token.market.blockTimestamp), + block_number: token.accrualBlockNumber, + user_address: account.id, + market: token.market.id, + supply_token: Number(token.cTokenBalance), + borrow_token: Number(token.storedBorrowBalance), + }) + ) + ) + .filter( + (item) => + (item.supply_token > 0 || item.borrow_token > 0) && + item.user_address !== zeroAddress + ) + .sort((a, b) => b.block_number - a.block_number); - const responseData: GraphQLResponse = await response.json(); - if (responseData.errors) { - console.error("GraphQL errors:", responseData.errors); - return []; + if (!offset && !limit) { + return flatData; // Return all data + } else { + return flatData.slice(offset, offset + limit); // Apply pagination } - return responseData.data.data; - } catch (error) { - console.error("Error fetching data:", error); + } else { return []; } } diff --git a/adapters/runScript.js b/adapters/runScript.js index f357986..e3c154c 100644 --- a/adapters/runScript.js +++ b/adapters/runScript.js @@ -36,7 +36,7 @@ const readBlocksFromCSV = async (filePath) => { await new Promise((resolve, reject) => { fs.createReadStream(filePath) - .pipe(csv({ separator: '\t' })) // Specify the separator as '\t' for TSV files + .pipe(csv({ separator: ',' })) .on('data', (row) => { const blockNumber = parseInt(row.number, 10); const blockTimestamp = parseInt(row.block_timestamp, 10); @@ -55,7 +55,7 @@ const readBlocksFromCSV = async (filePath) => { return blocks; }; -readBlocksFromCSV('block_numbers.tsv') +readBlocksFromCSV(path.join(folderPath, 'hourly_blocks.csv')) .then(async (blocks) => { const allCsvRows = []; // Array to accumulate CSV rows for all blocks const batchSize = 10; // Size of batch to trigger writing to the file