diff --git a/adapters/mendi/package.json b/adapters/mendi/package.json new file mode 100644 index 00000000..205d93e8 --- /dev/null +++ b/adapters/mendi/package.json @@ -0,0 +1,32 @@ +{ + "name": "mendi-tvl", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node dist/index.js", + "compile": "tsc", + "watch": "tsc -w", + "clear": "rm -rf dist" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@types/big.js": "^6.2.2", + "big.js": "^6.2.1", + "bignumber.js": "^9.1.2", + "csv-parser": "^3.0.0", + "decimal.js-light": "^2.5.1", + "fast-csv": "^5.0.1", + "jsbi": "^4.3.0", + "tiny-invariant": "^1.3.1", + "toformat": "^2.0.0", + "viem": "^2.8.13" + }, + "devDependencies": { + "@types/node": "^20.11.17", + "typescript": "^5.3.3" + } +} diff --git a/adapters/mendi/src/index.ts b/adapters/mendi/src/index.ts new file mode 100644 index 00000000..8da7b46c --- /dev/null +++ b/adapters/mendi/src/index.ts @@ -0,0 +1,87 @@ +import { CHAINS, PROTOCOLS } from "./sdk/config"; +import { + getLPValueByUserAndPoolFromActivities, + getActivitiesForAddressByPoolAtBlock, + getTimestampAtBlock, +} from "./sdk/subgraphDetails"; + +(BigInt.prototype as any).toJSON = function () { + return this.toString(); +}; + +import fs from "fs"; +import { write } from "fast-csv"; +import { getMarketInfos } from "./sdk/marketDetails"; +import { bigMath } from "./sdk/abi/helpers"; + +interface BlockData { + blockNumber: number; + blockTimestamp: number; +} + +type OutputDataSchemaRow = { + block_number: number; + timestamp: number; + user_address: string; + token_address: string; + token_balance: bigint; + token_symbol: string; //token symbol should be empty string if it is not available + usd_price: number; //assign 0 if not available +}; + +export const getUserTVLByBlock = async (blocks: BlockData) => { + const marketInfos = await getMarketInfos( + "0x1b4d3b0421ddc1eb216d230bc01527422fb93103" + ); + + const csvRows: OutputDataSchemaRow[] = []; + const block = blocks.blockNumber; + + const { tokens, accountBorrows } = await getActivitiesForAddressByPoolAtBlock( + block, + "", + "", + CHAINS.LINEA, + PROTOCOLS.MENDI + ); + + console.log(`Block: ${block}`); + console.log("Tokens: ", tokens.length); + console.log("Account Borrows: ", accountBorrows.length); + + let lpValueByUsers = getLPValueByUserAndPoolFromActivities( + tokens, + accountBorrows + ); + + const timestamp = await getTimestampAtBlock(block); + + lpValueByUsers.forEach((value, owner) => { + value.forEach((amount, market) => { + if (bigMath.abs(amount) < 1) return; + + const marketInfo = marketInfos.get(market.toLowerCase()); + + // Accumulate CSV row data + csvRows.push({ + block_number: block, + timestamp: timestamp, + user_address: owner, + token_address: marketInfo?.underlyingAddress ?? "", + token_balance: amount / BigInt(1e18), + token_symbol: marketInfo?.underlyingSymbol ?? "", + usd_price: 0, + }); + }); + }); + + // Write the CSV output to a file + const ws = fs.createWriteStream("outputData.csv"); + write(csvRows, { headers: true }) + .pipe(ws) + .on("finish", () => { + console.log("CSV file has been written."); + }); + + return csvRows; +}; diff --git a/adapters/mendi/src/sdk/abi/comptroller.abi.ts b/adapters/mendi/src/sdk/abi/comptroller.abi.ts new file mode 100644 index 00000000..e862eef1 --- /dev/null +++ b/adapters/mendi/src/sdk/abi/comptroller.abi.ts @@ -0,0 +1,956 @@ +export default [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "action", + type: "string", + }, + { + indexed: false, + internalType: "bool", + name: "pauseState", + type: "bool", + }, + ], + name: "ActionPaused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + { + indexed: false, + internalType: "string", + name: "action", + type: "string", + }, + { + indexed: false, + internalType: "bool", + name: "pauseState", + type: "bool", + }, + ], + name: "ActionPaused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "error", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "info", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "detail", + type: "uint256", + }, + ], + name: "Failure", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "MarketEntered", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "MarketExited", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + ], + name: "MarketListed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "newBorrowCap", + type: "uint256", + }, + ], + name: "NewBorrowCap", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldBorrowCapGuardian", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newBorrowCapGuardian", + type: "address", + }, + ], + name: "NewBorrowCapGuardian", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldCloseFactorMantissa", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newCloseFactorMantissa", + type: "uint256", + }, + ], + name: "NewCloseFactor", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "oldCollateralFactorMantissa", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newCollateralFactorMantissa", + type: "uint256", + }, + ], + name: "NewCollateralFactor", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldLiquidationIncentiveMantissa", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newLiquidationIncentiveMantissa", + type: "uint256", + }, + ], + name: "NewLiquidationIncentive", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPauseGuardian", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPauseGuardian", + type: "address", + }, + ], + name: "NewPauseGuardian", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract PriceOracle", + name: "oldPriceOracle", + type: "address", + }, + { + indexed: false, + internalType: "contract PriceOracle", + name: "newPriceOracle", + type: "address", + }, + ], + name: "NewPriceOracle", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldRewardDistributor", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newRewardDistributor", + type: "address", + }, + ], + name: "NewRewardDistributor", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "contract CToken", + name: "cToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "newSupplyCap", + type: "uint256", + }, + ], + name: "NewSupplyCap", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldSupplyCapGuardian", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newSupplyCapGuardian", + type: "address", + }, + ], + name: "NewSupplyCapGuardian", + type: "event", + }, + { + inputs: [ + { + internalType: "contract Unitroller", + name: "unitroller", + type: "address", + }, + ], + name: "_become", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newBorrowCapGuardian", + type: "address", + }, + ], + name: "_setBorrowCapGuardian", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken", name: "cToken", type: "address" }, + { internalType: "bool", name: "state", type: "bool" }, + ], + name: "_setBorrowPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newCloseFactorMantissa", + type: "uint256", + }, + ], + name: "_setCloseFactor", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken", name: "cToken", type: "address" }, + { + internalType: "uint256", + name: "newCollateralFactorMantissa", + type: "uint256", + }, + ], + name: "_setCollateralFactor", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newLiquidationIncentiveMantissa", + type: "uint256", + }, + ], + name: "_setLiquidationIncentive", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken[]", name: "cTokens", type: "address[]" }, + { internalType: "uint256[]", name: "newBorrowCaps", type: "uint256[]" }, + ], + name: "_setMarketBorrowCaps", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken[]", name: "cTokens", type: "address[]" }, + { internalType: "uint256[]", name: "newSupplyCaps", type: "uint256[]" }, + ], + name: "_setMarketSupplyCaps", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken", name: "cToken", type: "address" }, + { internalType: "bool", name: "state", type: "bool" }, + ], + name: "_setMintPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newPauseGuardian", type: "address" }, + ], + name: "_setPauseGuardian", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract PriceOracle", + name: "newOracle", + type: "address", + }, + ], + name: "_setPriceOracle", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newRewardDistributor", + type: "address", + }, + ], + name: "_setRewardDistributor", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bool", name: "state", type: "bool" }], + name: "_setSeizePaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newSupplyCapGuardian", + type: "address", + }, + ], + name: "_setSupplyCapGuardian", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bool", name: "state", type: "bool" }], + name: "_setTransferPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken", name: "cToken", type: "address" }, + ], + name: "_supportMarket", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + ], + name: "accountAssets", + outputs: [{ internalType: "contract CToken", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "admin", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "", type: "uint256" }], + name: "allMarkets", + outputs: [{ internalType: "contract CToken", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "borrowAmount", type: "uint256" }, + ], + name: "borrowAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "borrowCapGuardian", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "borrowCaps", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "borrowGuardianPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "borrowAmount", type: "uint256" }, + ], + name: "borrowVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "contract CToken", name: "cToken", type: "address" }, + ], + name: "checkMembership", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "holder", type: "address" }, + { internalType: "contract CToken[]", name: "cTokens", type: "address[]" }, + ], + name: "claimComp", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "holders", type: "address[]" }, + { internalType: "contract CToken[]", name: "cTokens", type: "address[]" }, + { internalType: "bool", name: "borrowers", type: "bool" }, + { internalType: "bool", name: "suppliers", type: "bool" }, + ], + name: "claimComp", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "holder", type: "address" }], + name: "claimComp", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "closeFactorMantissa", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "comptrollerImplementation", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address[]", name: "cTokens", type: "address[]" }], + name: "enterMarkets", + outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cTokenAddress", type: "address" }, + ], + name: "exitMarket", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getAccountLiquidity", + outputs: [ + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getAllMarkets", + outputs: [ + { internalType: "contract CToken[]", name: "", type: "address[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getAssetsIn", + outputs: [ + { internalType: "contract CToken[]", name: "", type: "address[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getBlockNumber", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "address", name: "cTokenModify", type: "address" }, + { internalType: "uint256", name: "redeemTokens", type: "uint256" }, + { internalType: "uint256", name: "borrowAmount", type: "uint256" }, + ], + name: "getHypotheticalAccountLiquidity", + outputs: [ + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "isComptroller", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "contract CToken", name: "cToken", type: "address" }, + ], + name: "isDeprecated", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cTokenBorrowed", type: "address" }, + { internalType: "address", name: "cTokenCollateral", type: "address" }, + { internalType: "address", name: "liquidator", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "repayAmount", type: "uint256" }, + ], + name: "liquidateBorrowAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cTokenBorrowed", type: "address" }, + { internalType: "address", name: "cTokenCollateral", type: "address" }, + { internalType: "address", name: "liquidator", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "actualRepayAmount", type: "uint256" }, + { internalType: "uint256", name: "seizeTokens", type: "uint256" }, + ], + name: "liquidateBorrowVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cTokenBorrowed", type: "address" }, + { internalType: "address", name: "cTokenCollateral", type: "address" }, + { internalType: "uint256", name: "actualRepayAmount", type: "uint256" }, + ], + name: "liquidateCalculateSeizeTokens", + outputs: [ + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "liquidationIncentiveMantissa", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "markets", + outputs: [ + { internalType: "bool", name: "isListed", type: "bool" }, + { + internalType: "uint256", + name: "collateralFactorMantissa", + type: "uint256", + }, + { internalType: "bool", name: "isComped", type: "bool" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "minter", type: "address" }, + { internalType: "uint256", name: "mintAmount", type: "uint256" }, + ], + name: "mintAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "mintGuardianPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "minter", type: "address" }, + { internalType: "uint256", name: "actualMintAmount", type: "uint256" }, + { internalType: "uint256", name: "mintTokens", type: "uint256" }, + ], + name: "mintVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "oracle", + outputs: [ + { internalType: "contract PriceOracle", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pauseGuardian", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingAdmin", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingComptrollerImplementation", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "redeemer", type: "address" }, + { internalType: "uint256", name: "redeemTokens", type: "uint256" }, + ], + name: "redeemAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "redeemer", type: "address" }, + { internalType: "uint256", name: "redeemAmount", type: "uint256" }, + { internalType: "uint256", name: "redeemTokens", type: "uint256" }, + ], + name: "redeemVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "payer", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "repayAmount", type: "uint256" }, + ], + name: "repayBorrowAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "payer", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "actualRepayAmount", type: "uint256" }, + { internalType: "uint256", name: "borrowerIndex", type: "uint256" }, + ], + name: "repayBorrowVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "rewardDistributor", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cTokenCollateral", type: "address" }, + { internalType: "address", name: "cTokenBorrowed", type: "address" }, + { internalType: "address", name: "liquidator", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "seizeTokens", type: "uint256" }, + ], + name: "seizeAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "seizeGuardianPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cTokenCollateral", type: "address" }, + { internalType: "address", name: "cTokenBorrowed", type: "address" }, + { internalType: "address", name: "liquidator", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "seizeTokens", type: "uint256" }, + ], + name: "seizeVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "supplyCapGuardian", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "supplyCaps", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "src", type: "address" }, + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "transferTokens", type: "uint256" }, + ], + name: "transferAllowed", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "transferGuardianPaused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "cToken", type: "address" }, + { internalType: "address", name: "src", type: "address" }, + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "transferTokens", type: "uint256" }, + ], + name: "transferVerify", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/adapters/mendi/src/sdk/abi/ctoken.abi.ts b/adapters/mendi/src/sdk/abi/ctoken.abi.ts new file mode 100644 index 00000000..99c92286 --- /dev/null +++ b/adapters/mendi/src/sdk/abi/ctoken.abi.ts @@ -0,0 +1,1017 @@ +export default [ + { inputs: [], name: "AcceptAdminPendingAdminCheck", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "actualAddAmount", type: "uint256" }, + ], + name: "AddReservesFactorFreshCheck", + type: "error", + }, + { inputs: [], name: "BorrowCashNotAvailable", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "BorrowComptrollerRejection", + type: "error", + }, + { inputs: [], name: "BorrowFreshnessCheck", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "LiquidateAccrueBorrowInterestFailed", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "LiquidateAccrueCollateralInterestFailed", + type: "error", + }, + { inputs: [], name: "LiquidateCloseAmountIsUintMax", type: "error" }, + { inputs: [], name: "LiquidateCloseAmountIsZero", type: "error" }, + { inputs: [], name: "LiquidateCollateralFreshnessCheck", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "LiquidateComptrollerRejection", + type: "error", + }, + { inputs: [], name: "LiquidateFreshnessCheck", type: "error" }, + { inputs: [], name: "LiquidateLiquidatorIsBorrower", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "LiquidateRepayBorrowFreshFailed", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "LiquidateSeizeComptrollerRejection", + type: "error", + }, + { inputs: [], name: "LiquidateSeizeLiquidatorIsBorrower", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "MintComptrollerRejection", + type: "error", + }, + { inputs: [], name: "MintFreshnessCheck", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "RedeemComptrollerRejection", + type: "error", + }, + { inputs: [], name: "RedeemFreshnessCheck", type: "error" }, + { inputs: [], name: "RedeemTransferOutNotPossible", type: "error" }, + { inputs: [], name: "ReduceReservesAdminCheck", type: "error" }, + { inputs: [], name: "ReduceReservesCashNotAvailable", type: "error" }, + { inputs: [], name: "ReduceReservesCashValidation", type: "error" }, + { inputs: [], name: "ReduceReservesFreshCheck", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "RepayBorrowComptrollerRejection", + type: "error", + }, + { inputs: [], name: "RepayBorrowFreshnessCheck", type: "error" }, + { inputs: [], name: "SetComptrollerOwnerCheck", type: "error" }, + { inputs: [], name: "SetInterestRateModelFreshCheck", type: "error" }, + { inputs: [], name: "SetInterestRateModelOwnerCheck", type: "error" }, + { inputs: [], name: "SetPendingAdminOwnerCheck", type: "error" }, + { inputs: [], name: "SetReserveFactorAdminCheck", type: "error" }, + { inputs: [], name: "SetReserveFactorBoundsCheck", type: "error" }, + { inputs: [], name: "SetReserveFactorFreshCheck", type: "error" }, + { inputs: [], name: "SetReserveGuardianOwnerCheck", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "errorCode", type: "uint256" }], + name: "TransferComptrollerRejection", + type: "error", + }, + { inputs: [], name: "TransferNotAllowed", type: "error" }, + { inputs: [], name: "TransferNotEnough", type: "error" }, + { inputs: [], name: "TransferTooMuch", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + 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", + }, + ], + name: "AccrueInterest", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "borrower", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "borrowAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "accountBorrows", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "totalBorrows", + type: "uint256", + }, + ], + name: "Borrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint8", name: "version", type: "uint8" }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "liquidator", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "borrower", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "repayAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "cTokenCollateral", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "seizeTokens", + type: "uint256", + }, + ], + name: "LiquidateBorrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "minter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "mintAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "mintTokens", + type: "uint256", + }, + ], + name: "Mint", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "NewAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract ComptrollerInterface", + name: "oldComptroller", + type: "address", + }, + { + indexed: false, + internalType: "contract ComptrollerInterface", + name: "newComptroller", + type: "address", + }, + ], + name: "NewComptroller", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract InterestRateModel", + name: "oldInterestRateModel", + type: "address", + }, + { + indexed: false, + internalType: "contract InterestRateModel", + name: "newInterestRateModel", + type: "address", + }, + ], + name: "NewMarketInterestRateModel", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPendingAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPendingAdmin", + type: "address", + }, + ], + name: "NewPendingAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldReserveFactorMantissa", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newReserveFactorMantissa", + type: "uint256", + }, + ], + name: "NewReserveFactor", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldReserveGuardian", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newReserveGuardian", + type: "address", + }, + ], + name: "NewReserveGuardian", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "redeemer", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "redeemAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "redeemTokens", + type: "uint256", + }, + ], + name: "Redeem", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "payer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "borrower", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "repayAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "accountBorrows", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "totalBorrows", + type: "uint256", + }, + ], + name: "RepayBorrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "benefactor", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "addAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newTotalReserves", + type: "uint256", + }, + ], + name: "ReservesAdded", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "admin", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "reduceAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newTotalReserves", + type: "uint256", + }, + ], + name: "ReservesReduced", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "NO_ERROR", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "_acceptAdmin", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "addAmount", type: "uint256" }], + name: "_addReserves", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "compLikeDelegatee", type: "address" }, + ], + name: "_delegateCompLikeTo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "reduceAmount", type: "uint256" }, + ], + name: "_reduceReserves", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract ComptrollerInterface", + name: "newComptroller", + type: "address", + }, + ], + name: "_setComptroller", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract InterestRateModel", + name: "newInterestRateModel", + type: "address", + }, + ], + name: "_setInterestRateModel", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address payable", + name: "newPendingAdmin", + type: "address", + }, + ], + name: "_setPendingAdmin", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newReserveFactorMantissa", + type: "uint256", + }, + ], + name: "_setReserveFactor", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address payable", + name: "newReserveGuardian", + type: "address", + }, + ], + name: "_setReserveGuardian", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "accrualBlockNumber", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "accrueInterest", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "admin", + outputs: [{ internalType: "address payable", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "balanceOfUnderlying", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "borrowAmount", type: "uint256" }, + ], + name: "borrow", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "borrowBalanceCurrent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "borrowBalanceStored", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "borrowIndex", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "borrowRatePerBlock", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "comptroller", + outputs: [ + { + internalType: "contract ComptrollerInterface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "exchangeRateCurrent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "exchangeRateStored", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getAccountSnapshot", + outputs: [ + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getCash", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "underlying_", type: "address" }, + { + internalType: "contract ComptrollerInterface", + name: "comptroller_", + type: "address", + }, + { + internalType: "contract InterestRateModel", + name: "interestRateModel_", + type: "address", + }, + { + internalType: "uint256", + name: "initialExchangeRateMantissa_", + type: "uint256", + }, + { internalType: "string", name: "name_", type: "string" }, + { internalType: "string", name: "symbol_", type: "string" }, + { internalType: "uint8", name: "decimals_", type: "uint8" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract ComptrollerInterface", + name: "comptroller_", + type: "address", + }, + { + internalType: "contract InterestRateModel", + name: "interestRateModel_", + type: "address", + }, + { + internalType: "uint256", + name: "initialExchangeRateMantissa_", + type: "uint256", + }, + { internalType: "string", name: "name_", type: "string" }, + { internalType: "string", name: "symbol_", type: "string" }, + { internalType: "uint8", name: "decimals_", type: "uint8" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "interestRateModel", + outputs: [ + { internalType: "contract InterestRateModel", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "isCToken", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "repayAmount", type: "uint256" }, + { + internalType: "contract CTokenInterface", + name: "cTokenCollateral", + type: "address", + }, + ], + name: "liquidateBorrow", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "mintAmount", type: "uint256" }], + name: "mint", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingAdmin", + outputs: [{ internalType: "address payable", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "protocolSeizeShareMantissa", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "underlying_", type: "address" }, + { + internalType: "contract ComptrollerInterface", + name: "comptroller_", + type: "address", + }, + { + internalType: "contract InterestRateModel", + name: "interestRateModel_", + type: "address", + }, + { + internalType: "uint256", + name: "initialExchangeRateMantissa_", + type: "uint256", + }, + { internalType: "string", name: "name_", type: "string" }, + { internalType: "string", name: "symbol_", type: "string" }, + { internalType: "uint8", name: "decimals_", type: "uint8" }, + { internalType: "address payable", name: "admin_", type: "address" }, + ], + name: "proxyInitialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "redeemTokens", type: "uint256" }, + ], + name: "redeem", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "redeemAmount", type: "uint256" }, + ], + name: "redeemUnderlying", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "repayAmount", type: "uint256" }], + name: "repayBorrow", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "repayAmount", type: "uint256" }, + ], + name: "repayBorrowBehalf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "reserveFactorMantissa", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "reserveGuardian", + outputs: [{ internalType: "address payable", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "liquidator", type: "address" }, + { internalType: "address", name: "borrower", type: "address" }, + { internalType: "uint256", name: "seizeTokens", type: "uint256" }, + ], + name: "seize", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "supplyRatePerBlock", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract EIP20NonStandardInterface", + name: "token", + type: "address", + }, + ], + name: "sweepToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalBorrows", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalBorrowsCurrent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "totalReserves", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "src", type: "address" }, + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "underlying", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/adapters/mendi/src/sdk/abi/helpers.ts b/adapters/mendi/src/sdk/abi/helpers.ts new file mode 100644 index 00000000..ab08dcc2 --- /dev/null +++ b/adapters/mendi/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/mendi/src/sdk/config.ts b/adapters/mendi/src/sdk/config.ts new file mode 100644 index 00000000..1be86669 --- /dev/null +++ b/adapters/mendi/src/sdk/config.ts @@ -0,0 +1,19 @@ +export const enum CHAINS { + LINEA = 59144, +} + +export const enum PROTOCOLS { + MENDI = 1, +} + +export const SUBGRAPH_URLS = { + [CHAINS.LINEA]: { + [PROTOCOLS.MENDI]: { + url: "https://api.goldsky.com/api/public/project_cltshpix6kkj301x1b4ilh6pm/subgraphs/mendi-linea/1.4/gn", + }, + }, +}; + +export const RPC_URLS = { + [CHAINS.LINEA]: "https://rpc.linea.build", +}; diff --git a/adapters/mendi/src/sdk/marketDetails.ts b/adapters/mendi/src/sdk/marketDetails.ts new file mode 100644 index 00000000..189fd765 --- /dev/null +++ b/adapters/mendi/src/sdk/marketDetails.ts @@ -0,0 +1,129 @@ +import { createPublicClient, extractChain, http, getContract } from "viem"; +import { CHAINS, RPC_URLS } from "./config"; +import { linea } from "viem/chains"; +import comptrollerAbi from "./abi/comptroller.abi"; +import ctokenAbi from "./abi/ctoken.abi"; +import { MarketActivity } from "./subgraphDetails"; + +export interface MarketInfo { + address: string; + underlyingAddress: string; + underlyingSymbol: string; + exchangeRateStored: bigint; +} + +export const getMarketInfos = async ( + comptrollerAddress: `0x${string}`, + blockNumber?: bigint +) => { + const publicClient = createPublicClient({ + chain: extractChain({ chains: [linea], id: CHAINS.LINEA }), + transport: http(RPC_URLS[CHAINS.LINEA]), + }); + + const comptroller = getContract({ + address: comptrollerAddress, + abi: comptrollerAbi, + client: publicClient, + }); + + const marketAddresses = await comptroller.read.getAllMarkets(); + const markets = marketAddresses.map((m) => + getContract({ + address: m, + abi: ctokenAbi, + client: publicClient, + }) + ); + + const underlyingResults = await publicClient.multicall({ + contracts: markets + .map((m) => [ + { + address: m.address, + abi: m.abi, + functionName: "underlying", + }, + ]) + .flat() as any, + }); + const underlyingAddresses = underlyingResults.map( + (v) => v.result as `0x${string}` + ); + const underlyings = underlyingAddresses.map((m) => + getContract({ + address: m, + abi: ctokenAbi, + client: publicClient, + }) + ); + const underlyingSymbolResults = await publicClient.multicall({ + contracts: underlyings.map((m) => ({ + address: m.address, + abi: m.abi, + functionName: "symbol", + })) as any, + }); + + const exchangeRateResults = await publicClient.multicall({ + contracts: markets + .map((m) => [ + { + address: m.address, + abi: m.abi, + functionName: "exchangeRateStored", + }, + ]) + .flat() as any, + blockNumber, + }); + + const marketInfos = new Map(); + for (let i = 0; i < markets.length; i++) { + const marketAddress = markets[i].address.toLowerCase(); + + var marketInfo = marketInfos.get(marketAddress); + if (marketInfo === undefined) { + marketInfo = {} as MarketInfo; + marketInfos.set(marketAddress, marketInfo); + } + + marketInfo.underlyingAddress = underlyingResults[i].result as any; + marketInfo.exchangeRateStored = BigInt( + exchangeRateResults[i].status == "success" + ? (exchangeRateResults[i].result as any) + : 0 + ); + + marketInfo.underlyingSymbol = underlyingSymbolResults[i].result as any; + } + + return marketInfos; +}; + +export const getBorrowBalanceStoredByAccounts = async ( + activities: MarketActivity[], + blockNumber?: bigint +) => { + const publicClient = createPublicClient({ + chain: extractChain({ chains: [linea], id: CHAINS.LINEA }), + transport: http(RPC_URLS[CHAINS.LINEA]), + }); + + const borrowBalanceResults = await publicClient.multicall({ + contracts: activities + .map((m) => [ + { + address: m.market, + abi: ctokenAbi, + functionName: "borrowBalanceStored", + args: [m.owner], + }, + ]) + .flat() as any, + blockNumber, + }); + const borrowBalances = borrowBalanceResults.map((v) => v.result as bigint); + + return borrowBalances; +}; diff --git a/adapters/mendi/src/sdk/subgraphDetails.ts b/adapters/mendi/src/sdk/subgraphDetails.ts new file mode 100644 index 00000000..ea71d06c --- /dev/null +++ b/adapters/mendi/src/sdk/subgraphDetails.ts @@ -0,0 +1,276 @@ +import { createPublicClient, extractChain, http } from "viem"; +import { linea } from "viem/chains"; +import { CHAINS, PROTOCOLS, RPC_URLS, SUBGRAPH_URLS } from "./config"; +import { + getBorrowBalanceStoredByAccounts, + getMarketInfos, +} from "./marketDetails"; + +export interface MarketActivity { + id: string; + amount: bigint; + owner: string; + market: string; + blockNumber: number; +} + +export const getActivitiesForAddressByPoolAtBlock = async ( + blockNumber: number, + address: string, + poolId: string, + chainId: CHAINS, + protocol: PROTOCOLS +): Promise<{ tokens: MarketActivity[]; accountBorrows: MarketActivity[] }> => { + const marketInfos = await getMarketInfos( + "0x1b4d3b0421ddc1eb216d230bc01527422fb93103", + BigInt(blockNumber) + ); + address = address?.toLowerCase(); + + let bnWhereQuery = blockNumber ? `block_number_lte: ${blockNumber} \n` : ""; + let transferWhereQuery = address + ? orWhere(`to: "${address}"`, `from: "${address}"`) + : ""; + let borrowerWhereQuery = address ? `borrower: "${address}" \n` : ""; + + let skip = 0; + let fetchNext = true; + + const pageSize = 1000; + const url = SUBGRAPH_URLS[chainId][protocol].url; + + let tokens: MarketActivity[] = []; + let accountBorrows: MarketActivity[] = []; + + while (fetchNext) { + let query = ` + { + transfers( + where: { ${andWhere(bnWhereQuery, transferWhereQuery)} } + orderBy: id, first: ${pageSize}, skip: ${skip}) + { + id + from + to + amount + block_number + contractId_ + } + borrows( + where: { ${andWhere(bnWhereQuery, borrowerWhereQuery)} } + orderBy: id, first: ${pageSize}, skip: ${skip}) + { + id + borrower + accountBorrows + block_number + contractId_ + } + repayBorrows( + where: { ${andWhere(bnWhereQuery, borrowerWhereQuery)} } + orderBy: id, first: ${pageSize}, skip: ${skip}) + { + id + borrower + accountBorrows + block_number + contractId_ + } + } + `; + console.log(`Fetching ${skip} - ${skip + pageSize} / unknown`); + + let response = await fetch(url, { + method: "POST", + body: JSON.stringify({ query }), + headers: { "Content-Type": "application/json" }, + }); + let data = await response.json(); + + // tokens + const mints = data.data.transfers + .filter((m: any) => m.to != m.contractId_) + .map((m: any) => ({ + id: m.id, + amount: BigInt(m.amount), + owner: m.to, + market: m.contractId_, + blockNumber: m.block_number, + })); + + const redeems = data.data.transfers + .filter((m: any) => m.from != m.contractId_) + .map((m: any) => ({ + id: m.id, + amount: -BigInt(m.amount), + owner: m.from, + market: m.contractId_, + blockNumber: m.block_number, + })); + + // borrows + const borrows = data.data.borrows.map((m: any) => ({ + id: m.id, + amount: -BigInt(m.accountBorrows), + owner: m.borrower, + market: m.contractId_, + blockNumber: m.block_number, + })); + const repayBorrows = data.data.repayBorrows.map((m: any) => ({ + id: m.id, + amount: -BigInt(m.accountBorrows), + owner: m.borrower, + market: m.contractId_, + blockNumber: m.block_number, + })); + + tokens.push(...mints, ...redeems); + accountBorrows.push(...borrows, ...repayBorrows); + + if ( + mints.length == 0 && + redeems.length == 0 && + borrows.length == 0 && + repayBorrows.length == 0 + ) { + fetchNext = false; + } else { + skip += pageSize; + } + } + + tokens = tokens + .map((t: any) => { + const marketInfo = marketInfos.get(t.market.toLowerCase()); + if (!marketInfo) { + return undefined; + } + + return { + ...t, + amount: t.amount * marketInfo.exchangeRateStored, + }; + }) + .filter((x) => x !== undefined); + + accountBorrows = await normalizeAccountBorrows(blockNumber, accountBorrows); + accountBorrows.forEach((t: any) => (t.amount = t.amount * BigInt(1e18))); + + return { tokens, accountBorrows }; +}; + +export const normalizeAccountBorrows = async ( + blockNumber: number, + accountBorrows: MarketActivity[] +): Promise => { + const result: MarketActivity[] = []; + + accountBorrows.sort((a, b) => b.blockNumber - a.blockNumber); + + for (let i = 0; i < accountBorrows.length; i++) { + var marketActivity = accountBorrows[i]; + + var doesExist = + result.findIndex( + (x: MarketActivity) => + x.owner == marketActivity.owner && x.market == marketActivity.market + ) > -1; + if (doesExist) continue; + + result.push(marketActivity); + } + + const chuckCount = 2000; + for (let i = 0; i < result.length; i += chuckCount) { + var end = Math.min(result.length, i + chuckCount); + + var currentBorrows = await getBorrowBalanceStoredByAccounts( + result.slice(i, end), + BigInt(blockNumber) + ); + + for (let j = 0; j < currentBorrows.length; j++) { + result[i + j].amount = -BigInt(currentBorrows[j]); + } + } + + return result; +}; + +export const getLPValueByUserAndPoolFromActivities = ( + tokens: MarketActivity[], + accountBorrows: MarketActivity[] +): Map> => { + // owner => market => amount + let result = new Map>(); + + // get latest account borrows + // sort descending to block number + accountBorrows.sort((a, b) => b.blockNumber - a.blockNumber); + + for (let i = 0; i < accountBorrows.length; i++) { + let marketActivity = accountBorrows[i]; + let market = marketActivity.market; + let owner = marketActivity.owner; + let amount = marketActivity.amount; + + let userActivities = result.get(owner); + if (userActivities === undefined) { + userActivities = new Map(); + result.set(owner, userActivities); + } + + let poolActivities = userActivities.get(market); + if (poolActivities === undefined) { + userActivities.set(market, amount); + } + } + + // add token activities + for (let i = 0; i < tokens.length; i++) { + let marketActivity = tokens[i]; + + let market = marketActivity.market; + let owner = marketActivity.owner; + let amount = marketActivity.amount; + + let userActivities = result.get(owner); + if (userActivities === undefined) { + userActivities = new Map(); + result.set(owner, userActivities); + } + + let poolActivities = userActivities.get(market); + if (poolActivities === undefined) { + poolActivities = BigInt(0); + } + + poolActivities = poolActivities + amount; + userActivities.set(market, poolActivities); + } + + return result; +}; + +export const getTimestampAtBlock = async (blockNumber: number) => { + const publicClient = createPublicClient({ + chain: extractChain({ chains: [linea], id: CHAINS.LINEA }), + transport: http(RPC_URLS[CHAINS.LINEA]), + }); + + const block = await publicClient.getBlock({ + blockNumber: BigInt(blockNumber), + }); + return Number(block.timestamp * 1000n); +}; + +const andWhere = (...queries: string[]) => { + return `and: [ + ${queries.map((q) => `{ ${q} }`).join("\n")} + ]`; +}; +const orWhere = (...queries: string[]) => { + return `or: [ + ${queries.map((q) => `{ ${q} }`).join("\n")} +]`; +}; diff --git a/adapters/mendi/tsconfig.json b/adapters/mendi/tsconfig.json new file mode 100644 index 00000000..31d29c00 --- /dev/null +++ b/adapters/mendi/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "commonjs", + "rootDir": "src/", + "outDir": "dist/", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + } +}