diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/__init__.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/__init__.py index 7be3698b7..e2dd087f1 100644 --- a/cdp-agentkit-core/python/cdp_agentkit_core/actions/__init__.py +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/__init__.py @@ -18,6 +18,12 @@ from cdp_agentkit_core.actions.wow.create_token import WowCreateTokenAction from cdp_agentkit_core.actions.wow.sell_token import WowSellTokenAction from cdp_agentkit_core.actions.wrap_eth import WrapEthAction +from cdp_agentkit_core.actions.extra import (ExtrafiLYFListLendingAction, ExtrafiLYFLendingAPRAction, + ExtrafiLYFSupplyToLendingAction, ExtrafiLYFGetLendingPositionsAction, + ExtrafiLYFWithdrawFromLendingAction, ExtrafiLYFListFarmingAction, + ExtrafiLYFFarmingAPRAction, ExtrafiLYFInvestToFarmingHelperAction, + ExtrafiLYFInvestToFarmingAction, ExtrafiLYFGetFarmingPositionsAction, + ExtrafiLYFRepayFarmingDebtAction, ExtrafiLYFCloseFarmingPositionsAction) # WARNING: All new CdpAction subclasses must be imported above, otherwise they will not be discovered @@ -54,4 +60,16 @@ def get_all_cdp_actions() -> list[type[CdpAction]]: "MorphoWithdrawAction", "PythFetchPriceFeedIDAction", "PythFetchPriceAction", + "ExtrafiLYFListLendingAction", + "ExtrafiLYFLendingAPRAction", + "ExtrafiLYFSupplyToLendingAction", + "ExtrafiLYFGetLendingPositionsAction", + "ExtrafiLYFWithdrawFromLendingAction", + "ExtrafiLYFListFarmingAction", + "ExtrafiLYFFarmingAPRAction", + "ExtrafiLYFInvestToFarmingHelperAction", + "ExtrafiLYFInvestToFarmingAction", + "ExtrafiLYFGetFarmingPositionsAction", + "ExtrafiLYFRepayFarmingDebtAction", + "ExtrafiLYFCloseFarmingPositionsAction", ] diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/__init__.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/__init__.py new file mode 100644 index 000000000..f22589608 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/__init__.py @@ -0,0 +1,12 @@ +from .lyf_list_lending import ExtrafiLYFListLendingAction +from .lyf_lending_apr import ExtrafiLYFLendingAPRAction +from .lyf_supply_to_lending import ExtrafiLYFSupplyToLendingAction +from .lyf_get_lending_positions import ExtrafiLYFGetLendingPositionsAction +from .lyf_withdraw_from_lending import ExtrafiLYFWithdrawFromLendingAction +from .lyf_list_farming import ExtrafiLYFListFarmingAction +from .lyf_farming_apr import ExtrafiLYFFarmingAPRAction +from .lyf_invest_to_farming_helper import ExtrafiLYFInvestToFarmingHelperAction +from .lyf_invest_to_farming import ExtrafiLYFInvestToFarmingAction +from .lyf_get_farming_positions import ExtrafiLYFGetFarmingPositionsAction +from .lyf_repay_farming_debt import ExtrafiLYFRepayFarmingDebtAction +from .lyf_close_farming_position import ExtrafiLYFCloseFarmingPositionsAction diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/__init__.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/__init__.py new file mode 100644 index 000000000..60c848e0a --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/__init__.py @@ -0,0 +1,16 @@ +from .abi import (LYF_LENDING_POOL_ABI, LYF_POSITION_MANAGER_ABI, + ERC20_ABI, EXTRA_XLEND_POOL_ABI, EXTRA_XLEND_ATOKEN_ABI, PAIRS_SUGAR_V2_ABI) +from .addresses import lyf_addresses, token_addresses +from .erc20 import get_balance_of, get_decimals_of, get_symbol_of, get_allowance_of, approve_token +from .lyf_info import (get_concise_lyf_lending_pool_info, get_concise_lyf_farming_info, + get_apr_change_for_lyf_lending_pool, get_apr_and_tvl_change_for_lyf_farming, + get_pair_info, get_token_price, get_apr_and_tvl_change_for_lyf_farming) +from .lyf_viewer import (get_pool_token_address, get_lyf_lending_pool_positions, + get_lyf_farming_vaults_info, get_lyf_farming_vault_state, get_lyf_vault_borrow_available, + get_lyf_vault_related_lending_pool_ids, get_lyf_farming_apy, get_vault_position, + get_token_value, get_historical_farming_apr_tvl) +from .graph import (get_user_lending_position_pool_ids, get_farming_vault_id, + get_user_farming_vault_positions, get_vault_address) +from .misc import (format_int_leverage_to_str, format_str_leverage_to_int, amount_need_to_wrapped, + check_balance_sufficiency) +from .amm_viewer import get_amount_out diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/abi.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/abi.py new file mode 100644 index 000000000..5a761dbb8 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/abi.py @@ -0,0 +1,8172 @@ +LYF_LENDING_POOL_ABI = [ + { + "inputs": [ + { + "internalType": "address", + "name": "_addressRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_WETH9", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "reserveAmount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "eTokenAmount", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint16", + "name": "referral", + "type": "uint16" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "vaultAddress", + "type": "address" + } + ], + "name": "DisableVaultToBorrow", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "vaultAddress", + "type": "address" + } + ], + "name": "EnableVaultToBorrow", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "eTokenAddress", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "stakingAddress", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "InitReserve", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": False, + "inputs": [], + "name": "Paused", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "eTokenAmount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "underlyingTokenAmount", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Repay", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "ReserveActivated", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "ReserveBorrowDisabled", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "ReserveBorrowEnabled", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "ReserveDeActivated", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "ReserveFrozen", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "ReserveUnFreeze", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "vaultAddress", + "type": "address" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "credit", + "type": "uint256" + } + ], + "name": "SetCreditsOfVault", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "utilizationA", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "borrowingRateA", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "utilizationB", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "borrowingRateB", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "maxBorrowingRate", + "type": "uint16" + } + ], + "name": "SetInterestRateConfig", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "SetReserveCapacity", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "feeRate", + "type": "uint256" + } + ], + "name": "SetReserveFeeRate", + "type": "event" + }, + { + "anonymous": False, + "inputs": [], + "name": "UnPaused", + "type": "event" + }, + { + "inputs": [], + "name": "WETH9", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "activateReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addressRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint256", + "name": "debtId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "borrowingRateOfReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowingWhiteList", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "poolId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vaultAddress", + "type": "address" + } + ], + "name": "credits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "deActivateReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "debtId", + "type": "uint256" + } + ], + "name": "debtPositions", + "outputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowedIndex", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "eTokenAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "depositAndStake", + "outputs": [ + { + "internalType": "uint256", + "name": "eTokenAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "disableBorrowing", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + } + ], + "name": "disableVaultToBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyPauseAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "enableBorrowing", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + } + ], + "name": "enableVaultToBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "exchangeRateOfReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "freezeReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "debtId", + "type": "uint256" + } + ], + "name": "getCurrentDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "currentDebt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "latestBorrowingIndex", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "getETokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "reserveIdArr", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getPositionStatus", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "eTokenStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "eTokenUnStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "internalType": "struct ILendingPool.PositionStatus[]", + "name": "statusArr", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "debtId", + "type": "uint256" + } + ], + "name": "getReserveIdOfDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "reserveIdArr", + "type": "uint256[]" + } + ], + "name": "getReserveStatus", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "eTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowingRate", + "type": "uint256" + } + ], + "internalType": "struct ILendingPool.ReserveStatus[]", + "name": "statusArr", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "getStakingAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "getUnderlyingTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "initReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "newDebtPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "debtId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "nextDebtPositionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextReserveId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "eTokenAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint256", + "name": "debtId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "repay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "poolId", + "type": "uint256" + } + ], + "name": "reserves", + "outputs": [ + { + "internalType": "uint256", + "name": "borrowingIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentBorrowingRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "eTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "reserveCapacity", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "utilizationA", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "borrowingRateA", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "utilizationB", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "borrowingRateB", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "maxBorrowingRate", + "type": "uint128" + } + ], + "internalType": "struct DataTypes.InterestRateConfig", + "name": "borrowingRateConfig", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "lastUpdateTimestamp", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "reserveFeeRate", + "type": "uint16" + }, + { + "components": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "frozen", + "type": "bool" + }, + { + "internalType": "bool", + "name": "borrowingEnabled", + "type": "bool" + } + ], + "internalType": "struct DataTypes.Flags", + "name": "flags", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "utilizationA", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "borrowingRateA", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "utilizationB", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "borrowingRateB", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxBorrowingRate", + "type": "uint16" + } + ], + "name": "setBorrowingRateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "credit", + "type": "uint256" + } + ], + "name": "setCreditsOfVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "setReserveCapacity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "_rate", + "type": "uint16" + } + ], + "name": "setReserveFeeRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "totalBorrowsOfReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "totalLiquidityOfReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "totalLiquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "unFreezeReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unPauseAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "eTokenAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + } + ], + "name": "unStakeAndWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reserveId", + "type": "uint256" + } + ], + "name": "utilizationRateOfReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] + +LYF_POSITION_MANAGER_ABI = [ + { + "inputs": [ + { + "internalType": "address", + "name": "_addressProvider", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "percent", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Received", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Received", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "fee0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "fee1", + "type": "uint256" + } + ], + "name": "CloseOutOfRangePosition", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "percent", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Received", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Received", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Repaid", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Repaid", + "type": "uint256" + } + ], + "name": "CloseVaultPositionPartially", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Repaid", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Repaid", + "type": "uint256" + } + ], + "name": "ExactRepay", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "feeType", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeePaid", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidityAdded", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "fee0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "fee1", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256[]", + "name": "rewards", + "type": "uint256[]" + } + ], + "name": "InvestEarnedFeeToLiquidity", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Invest", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Invest", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Borrow", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Borrow", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "InvestToVaultPosition", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint16", + "name": "percent", + "type": "uint16" + }, + { + "indexed": False, + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "debtValueOfPosition", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidityValueOfPosition", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Left", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Left", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidateFee0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidateFee1", + "type": "uint256" + } + ], + "name": "LiquidateVaultPositionPartially", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "address", + "name": "manager", + "type": "address" + } + ], + "name": "NewVaultPosition", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "WETH9", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "addPermissionedCompounder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "addPermissionedLiquidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "addPermissionedRangeStopCaller", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addressProvider", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "adminSetVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "percent", + "type": "uint16" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "receiveType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minAmount0WhenRemoveLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAmount1WhenRemoveLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapExecutorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "swapPath", + "type": "bytes" + } + ], + "internalType": "struct IVeloVaultPositionManager.CloseVaultPositionPartiallyParams", + "name": "params", + "type": "tuple" + } + ], + "name": "closeOutOfRangePosition", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "percent", + "type": "uint16" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "receiveType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minAmount0WhenRemoveLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAmount1WhenRemoveLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapExecutorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "swapPath", + "type": "bytes" + } + ], + "internalType": "struct IVeloVaultPositionManager.CloseVaultPositionPartiallyParams", + "name": "params", + "type": "tuple" + } + ], + "name": "closeVaultPositionPartially", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "compounderWhitelist", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disablePermissionLessCompound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disablePermissionLessLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disablePermissonLessRangeStop", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enablePermissionLessCompound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enablePermissionLessLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enablePermissonLessRangeStop", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0ToRepay", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1ToRepay", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "internalType": "struct IVeloVaultPositionManager.ExactRepayParam", + "name": "params", + "type": "tuple" + } + ], + "name": "exactRepay", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0Repaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Repaid", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + } + ], + "name": "getVault", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bool", + "name": "frozen", + "type": "bool" + }, + { + "internalType": "bool", + "name": "borrowingEnabled", + "type": "bool" + }, + { + "internalType": "bool", + "name": "liquidateWithTWAP", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "maxLeverage", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "premiumMaxLeverage", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxPriceDiff", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidateDebtRatio", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "borrowFeeRate", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "compoundFeeRate", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidateFeeRate", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "rangeStopFeeRate", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "protocolFeeRate", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "premiumRequirement", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolFee0Accumulated", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolFee1Accumulated", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minInvestValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSwapAmount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSwapAmount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalLp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalLpShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premiumUtilizationOfReserve0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtLimit0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtPositionId0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtTotalShares0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premiumUtilizationOfReserve1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtLimit1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtPositionId1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtTotalShares1", + "type": "uint256" + } + ], + "internalType": "struct VaultTypes.VeloVaultState", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + } + ], + "name": "getVaultPosition", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "enableRangeStop", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "openedAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "current", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "token0Principal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token1Principal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPrincipal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token0Left", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token1Left", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token0InLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token1InLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debt0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debt1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowingIndex0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowingIndex1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minPriceOfRangeStop", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriceOfRangeStop", + "type": "uint256" + } + ], + "internalType": "struct VaultTypes.VeloPositionValue", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "compoundFeeReceiver", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "internalType": "struct IRouter.route[][]", + "name": "routes", + "type": "tuple[][]" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "internalType": "struct IVeloVaultPositionManager.InvestEarnedFeeToLiquidityParam", + "name": "params", + "type": "tuple" + } + ], + "name": "investEarnedFeeToLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "percent", + "type": "uint16" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bool", + "name": "receiveNativeETH", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "receiveType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minAmount0WhenRemoveLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAmount1WhenRemoveLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRepay0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRepay1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapExecutorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "swapPath", + "type": "bytes" + } + ], + "internalType": "struct IVeloVaultPositionManager.LiquidateVaultPositionPartiallyParams", + "name": "params", + "type": "tuple" + } + ], + "name": "liquidateVaultPositionPartially", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "liquidatorWhitelist", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Invest", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Borrow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Invest", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Borrow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapExecutorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "swapPath", + "type": "bytes" + } + ], + "internalType": "struct IVeloVaultPositionManager.NewOrInvestToVaultPositionParams", + "name": "params", + "type": "tuple" + } + ], + "name": "newOrInvestToVaultPosition", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeType", + "type": "uint256" + } + ], + "name": "payFeeToTreasuryCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "internalType": "struct IVeloVaultPositionManager.PayToVaultCallbackParams", + "name": "params", + "type": "tuple" + } + ], + "name": "payToVaultCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "permissionLessCompoundEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permissionLessLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permissionLessRangeStopEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rangeStopCallerWhitelist", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "removePermissionedCompounder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "removePermissionedLiquidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "removePermissionedRangeStopCaller", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "minPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPrice", + "type": "uint256" + } + ], + "name": "setRangeStop", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaultPositionId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newManager", + "type": "address" + } + ], + "name": "transferManagerOfVaultPosition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultFactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] + +ERC20_ABI = [ + { + "constant": True, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": False, + "stateMutability": "view", + "type": "function" + }, + { + "constant": False, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": False, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": True, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": False, + "stateMutability": "view", + "type": "function" + }, + { + "constant": False, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": False, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": True, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": False, + "stateMutability": "view", + "type": "function" + }, + { + "constant": True, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": False, + "stateMutability": "view", + "type": "function" + }, + { + "constant": True, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": False, + "stateMutability": "view", + "type": "function" + }, + { + "constant": False, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": False, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": True, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": False, + "stateMutability": "view", + "type": "function" + }, + { + "payable": True, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "name": "owner", + "type": "address" + }, + { + "indexed": True, + "name": "spender", + "type": "address" + }, + { + "indexed": False, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "name": "from", + "type": "address" + }, + { + "indexed": True, + "name": "to", + "type": "address" + }, + { + "indexed": False, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] + +EXTRA_XLEND_POOL_ABI = [ + { + "inputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "provider", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "backer", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "BackUnbacked", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "enum DataTypes.InterestRateMode", + "name": "interestRateMode", + "type": "uint8" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "borrowRate", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "enum DataTypes.InterestRateMode", + "name": "interestRateMode", + "type": "uint8" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "premium", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "totalDebt", + "type": "uint256" + } + ], + "name": "IsolationModeTotalDebtUpdated", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "collateralAsset", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "debtToCover", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidatedCollateralAmount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": False, + "internalType": "bool", + "name": "receiveAToken", + "type": "bool" + } + ], + "name": "LiquidationCall", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "collateralAsset", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "debtToCover", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidatedCollateralAmount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": False, + "internalType": "bool", + "name": "repayAToken", + "type": "bool" + }, + { + "indexed": False, + "internalType": "bool", + "name": "receiveAToken", + "type": "bool" + } + ], + "name": "LiquidationCallV2", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "MintUnbacked", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amountMinted", + "type": "uint256" + } + ], + "name": "MintedToTreasury", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RebalanceStableBorrowRate", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "bool", + "name": "useATokens", + "type": "bool" + } + ], + "name": "Repay", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidityRate", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "stableBorrowRate", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "variableBorrowRate", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "liquidityIndex", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "variableBorrowIndex", + "type": "uint256" + } + ], + "name": "ReserveDataUpdated", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ReserveUsedAsCollateralDisabled", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ReserveUsedAsCollateralEnabled", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": True, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": False, + "internalType": "enum DataTypes.InterestRateMode", + "name": "interestRateMode", + "type": "uint8" + } + ], + "name": "SwapBorrowRateMode", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint8", + "name": "categoryId", + "type": "uint8" + } + ], + "name": "UserEModeSet", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "ADDRESSES_PROVIDER", + "outputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BRIDGE_PROTOCOL_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FLASHLOAN_PREMIUM_TOTAL", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FLASHLOAN_PREMIUM_TO_PROTOCOL", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUMBER_RESERVES", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_STABLE_RATE_BORROW_SIZE_PERCENT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "POOL_REVISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "backUnbacked", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + } + ], + "name": "borrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "ltv", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationThreshold", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationBonus", + "type": "uint16" + }, + { + "internalType": "address", + "name": "priceSource", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "internalType": "struct DataTypes.EModeCategory", + "name": "category", + "type": "tuple" + } + ], + "name": "configureEModeCategory", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "dropReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceFromBefore", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceToBefore", + "type": "uint256" + } + ], + "name": "finalizeTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiverAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "interestRateModes", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiverAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "flashLoanSimple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getConfiguration", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.ReserveConfigurationMap", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + } + ], + "name": "getEModeCategoryData", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "ltv", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationThreshold", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationBonus", + "type": "uint16" + }, + { + "internalType": "address", + "name": "priceSource", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "internalType": "struct DataTypes.EModeCategory", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "id", + "type": "uint16" + } + ], + "name": "getReserveAddressById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveData", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.ReserveConfigurationMap", + "name": "configuration", + "type": "tuple" + }, + { + "internalType": "uint128", + "name": "liquidityIndex", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "currentLiquidityRate", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "variableBorrowIndex", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "currentVariableBorrowRate", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "currentStableBorrowRate", + "type": "uint128" + }, + { + "internalType": "uint40", + "name": "lastUpdateTimestamp", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "id", + "type": "uint16" + }, + { + "internalType": "address", + "name": "aTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "stableDebtTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "variableDebtTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "interestRateStrategyAddress", + "type": "address" + }, + { + "internalType": "uint128", + "name": "accruedToTreasury", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "unbacked", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "isolationModeTotalDebt", + "type": "uint128" + } + ], + "internalType": "struct DataTypes.ReserveData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveNormalizedIncome", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveNormalizedVariableDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getReservesList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserAccountData", + "outputs": [ + { + "internalType": "uint256", + "name": "totalCollateralBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalDebtBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableBorrowsBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentLiquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ltv", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "healthFactor", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserConfiguration", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.UserConfigurationMap", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserEMode", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "aTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "stableDebtAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "variableDebtAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "interestRateStrategyAddress", + "type": "address" + } + ], + "name": "initReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "provider", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collateralAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "debtToCover", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "receiveAToken", + "type": "bool" + } + ], + "name": "liquidationCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collateralAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "debtToCover", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "repayAToken", + "type": "bool" + }, + { + "internalType": "bool", + "name": "receiveAToken", + "type": "bool" + } + ], + "name": "liquidationCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "mintToTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "mintUnbacked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "rebalanceStableBorrowRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + } + ], + "name": "repay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + } + ], + "name": "repayWithATokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "permitV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "permitR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "permitS", + "type": "bytes32" + } + ], + "name": "repayWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "resetIsolationModeTotalDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.ReserveConfigurationMap", + "name": "configuration", + "type": "tuple" + } + ], + "name": "setConfiguration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "rateStrategyAddress", + "type": "address" + } + ], + "name": "setReserveInterestRateStrategyAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + } + ], + "name": "setReserveTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "categoryId", + "type": "uint8" + } + ], + "name": "setUserEMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "useAsCollateral", + "type": "bool" + } + ], + "name": "setUserUseReserveAsCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "permitV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "permitR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "permitS", + "type": "bytes32" + } + ], + "name": "supplyWithPermit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + } + ], + "name": "swapBorrowRateMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolFee", + "type": "uint256" + } + ], + "name": "updateBridgeProtocolFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "flashLoanPremiumTotal", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "flashLoanPremiumToProtocol", + "type": "uint128" + } + ], + "name": "updateFlashloanPremiums", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] + +EXTRA_XLEND_ATOKEN_ABI = [ + { + "inputs": [ + { + "internalType": "contract IPool", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "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": "value", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "BalanceTransfer", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "balanceIncrease", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "underlyingAsset", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "incentivesController", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint8", + "name": "aTokenDecimals", + "type": "uint8" + }, + { + "indexed": False, + "internalType": "string", + "name": "aTokenName", + "type": "string" + }, + { + "indexed": False, + "internalType": "string", + "name": "aTokenSymbol", + "type": "string" + }, + { + "indexed": False, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "balanceIncrease", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "Mint", + "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": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": False, + "internalType": "address", + "name": "oldTreasury", + "type": "address" + }, + { + "indexed": False, + "internalType": "address", + "name": "newTreasury", + "type": "address" + } + ], + "name": "TreasuryUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ATOKEN_REVISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EIP712_REVISION", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "POOL", + "outputs": [ + { + "internalType": "contract IPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESERVE_TREASURY_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_ASSET_ADDRESS", + "outputs": [ + { + "internalType": "address", + "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": "user", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "receiverOfUnderlying", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getIncentivesController", + "outputs": [ + { + "internalType": "contract IAaveIncentivesController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getPreviousIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getScaledUserBalanceAndSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "handleRepayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPool", + "name": "initializingPool", + "type": "address" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingAsset", + "type": "address" + }, + { + "internalType": "contract IAaveIncentivesController", + "name": "incentivesController", + "type": "address" + }, + { + "internalType": "uint8", + "name": "aTokenDecimals", + "type": "uint8" + }, + { + "internalType": "string", + "name": "aTokenName", + "type": "string" + }, + { + "internalType": "string", + "name": "aTokenSymbol", + "type": "string" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "mintToTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "scaledBalanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "scaledTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAaveIncentivesController", + "name": "controller", + "type": "address" + } + ], + "name": "setIncentivesController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferOnLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferUnderlyingTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTreasury", + "type": "address" + } + ], + "name": "updateTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] + +IPAIR_V2_ABI = [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BelowMinimumK", + "type": "error" + }, + { + "inputs": [], + "name": "DepositsNotEqual", + "type": "error" + }, + { + "inputs": [], + "name": "FactoryAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidityBurned", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidityMinted", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTo", + "type": "error" + }, + { + "inputs": [], + "name": "IsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "K", + "type": "error" + }, + { + "inputs": [], + "name": "NotEmergencyCouncil", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": False, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Fees", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": False, + "internalType": "uint256", + "name": "reserve0", + "type": "uint256" + }, + { + "indexed": False, + "internalType": "uint256", + "name": "reserve1", + "type": "uint256" + } + ], + "name": "Sync", + "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": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "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": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockTimestampLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "claimFees", + "outputs": [ + { + "internalType": "uint256", + "name": "claimed0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimed1", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable0", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "claimable1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentCumulativePrices", + "outputs": [ + { + "internalType": "uint256", + "name": "reserve0Cumulative", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve1Cumulative", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getK", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "_reserve0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_reserve1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_blockTimestampLast", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "index0", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "index1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + }, + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastObservation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve0Cumulative", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve1Cumulative", + "type": "uint256" + } + ], + "internalType": "struct IPool.Observation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "metadata", + "outputs": [ + { + "internalType": "uint256", + "name": "dec0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dec1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "r0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "r1", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "st", + "type": "bool" + }, + { + "internalType": "address", + "name": "t0", + "type": "address" + }, + { + "internalType": "address", + "name": "t1", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "observationLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "observations", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve0Cumulative", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve1Cumulative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "poolFees", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "points", + "type": "uint256" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "granularity", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reserve0", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reserve0CumulativeLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reserve1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reserve1CumulativeLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "points", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "window", + "type": "uint256" + } + ], + "name": "sample", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "__name", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "__symbol", + "type": "string" + } + ], + "name": "setSymbol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "skim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyIndex0", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyIndex1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "swap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sync", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token0", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokens", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] + +PAIRS_SUGAR_V2_ABI = [ + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { + "name": "_voter", + "type": "address" + }, + { + "name": "_registry", + "type": "address" + }, + { + "name": "_nfpm", + "type": "address" + }, + { + "name": "_slipstream_helper", + "type": "address" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "forSwaps", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "lp", + "type": "address" + }, + { + "name": "type", + "type": "int24" + }, + { + "name": "token0", + "type": "address" + }, + { + "name": "token1", + "type": "address" + }, + { + "name": "factory", + "type": "address" + }, + { + "name": "pool_fee", + "type": "uint256" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "tokens", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_account", + "type": "address" + }, + { + "name": "_addresses", + "type": "address[]" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "token_address", + "type": "address" + }, + { + "name": "symbol", + "type": "string" + }, + { + "name": "decimals", + "type": "uint8" + }, + { + "name": "account_balance", + "type": "uint256" + }, + { + "name": "listed", + "type": "bool" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "all", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "lp", + "type": "address" + }, + { + "name": "symbol", + "type": "string" + }, + { + "name": "decimals", + "type": "uint8" + }, + { + "name": "liquidity", + "type": "uint256" + }, + { + "name": "type", + "type": "int24" + }, + { + "name": "tick", + "type": "int24" + }, + { + "name": "sqrt_ratio", + "type": "uint160" + }, + { + "name": "token0", + "type": "address" + }, + { + "name": "reserve0", + "type": "uint256" + }, + { + "name": "staked0", + "type": "uint256" + }, + { + "name": "token1", + "type": "address" + }, + { + "name": "reserve1", + "type": "uint256" + }, + { + "name": "staked1", + "type": "uint256" + }, + { + "name": "gauge", + "type": "address" + }, + { + "name": "gauge_liquidity", + "type": "uint256" + }, + { + "name": "gauge_alive", + "type": "bool" + }, + { + "name": "fee", + "type": "address" + }, + { + "name": "bribe", + "type": "address" + }, + { + "name": "factory", + "type": "address" + }, + { + "name": "emissions", + "type": "uint256" + }, + { + "name": "emissions_token", + "type": "address" + }, + { + "name": "pool_fee", + "type": "uint256" + }, + { + "name": "unstaked_fee", + "type": "uint256" + }, + { + "name": "token0_fees", + "type": "uint256" + }, + { + "name": "token1_fees", + "type": "uint256" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "byIndex", + "inputs": [ + { + "name": "_index", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "components": [ + { + "name": "lp", + "type": "address" + }, + { + "name": "symbol", + "type": "string" + }, + { + "name": "decimals", + "type": "uint8" + }, + { + "name": "liquidity", + "type": "uint256" + }, + { + "name": "type", + "type": "int24" + }, + { + "name": "tick", + "type": "int24" + }, + { + "name": "sqrt_ratio", + "type": "uint160" + }, + { + "name": "token0", + "type": "address" + }, + { + "name": "reserve0", + "type": "uint256" + }, + { + "name": "staked0", + "type": "uint256" + }, + { + "name": "token1", + "type": "address" + }, + { + "name": "reserve1", + "type": "uint256" + }, + { + "name": "staked1", + "type": "uint256" + }, + { + "name": "gauge", + "type": "address" + }, + { + "name": "gauge_liquidity", + "type": "uint256" + }, + { + "name": "gauge_alive", + "type": "bool" + }, + { + "name": "fee", + "type": "address" + }, + { + "name": "bribe", + "type": "address" + }, + { + "name": "factory", + "type": "address" + }, + { + "name": "emissions", + "type": "uint256" + }, + { + "name": "emissions_token", + "type": "address" + }, + { + "name": "pool_fee", + "type": "uint256" + }, + { + "name": "unstaked_fee", + "type": "uint256" + }, + { + "name": "token0_fees", + "type": "uint256" + }, + { + "name": "token1_fees", + "type": "uint256" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "positions", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_account", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "id", + "type": "uint256" + }, + { + "name": "lp", + "type": "address" + }, + { + "name": "liquidity", + "type": "uint256" + }, + { + "name": "staked", + "type": "uint256" + }, + { + "name": "amount0", + "type": "uint256" + }, + { + "name": "amount1", + "type": "uint256" + }, + { + "name": "staked0", + "type": "uint256" + }, + { + "name": "staked1", + "type": "uint256" + }, + { + "name": "unstaked_earned0", + "type": "uint256" + }, + { + "name": "unstaked_earned1", + "type": "uint256" + }, + { + "name": "emissions_earned", + "type": "uint256" + }, + { + "name": "tick_lower", + "type": "int24" + }, + { + "name": "tick_upper", + "type": "int24" + }, + { + "name": "sqrt_ratio_lower", + "type": "uint160" + }, + { + "name": "sqrt_ratio_upper", + "type": "uint160" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "epochsLatest", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "ts", + "type": "uint256" + }, + { + "name": "lp", + "type": "address" + }, + { + "name": "votes", + "type": "uint256" + }, + { + "name": "emissions", + "type": "uint256" + }, + { + "name": "bribes", + "type": "tuple[]", + "components": [ + { + "name": "token", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ] + }, + { + "name": "fees", + "type": "tuple[]", + "components": [ + { + "name": "token", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ] + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "epochsByAddress", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_address", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "ts", + "type": "uint256" + }, + { + "name": "lp", + "type": "address" + }, + { + "name": "votes", + "type": "uint256" + }, + { + "name": "emissions", + "type": "uint256" + }, + { + "name": "bribes", + "type": "tuple[]", + "components": [ + { + "name": "token", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ] + }, + { + "name": "fees", + "type": "tuple[]", + "components": [ + { + "name": "token", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ] + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "rewards", + "inputs": [ + { + "name": "_limit", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_venft_id", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "venft_id", + "type": "uint256" + }, + { + "name": "lp", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "fee", + "type": "address" + }, + { + "name": "bribe", + "type": "address" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "rewardsByAddress", + "inputs": [ + { + "name": "_venft_id", + "type": "uint256" + }, + { + "name": "_pool", + "type": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "components": [ + { + "name": "venft_id", + "type": "uint256" + }, + { + "name": "lp", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "fee", + "type": "address" + }, + { + "name": "bribe", + "type": "address" + } + ] + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "registry", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "voter", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "nfpm", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "cl_helper", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address" + } + ] + } +] \ No newline at end of file diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/addresses.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/addresses.py new file mode 100644 index 000000000..e5febebdf --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/addresses.py @@ -0,0 +1,41 @@ +lyf_addresses = { + "base-mainnet": { + "EXTRA_COMMUNITY": "0x89F0885DA2553232aeEf201692F8C97E24715c83", + "EXTRA_TREASURY": "0x4059e170D325163e2eC96cF8Ca489C40B6927A8c", + "EXTRA_GOV": "0x750f7153e6c92a24089a34eC6AFe65740C9bd40A", + "FLASHLOAN_LIQUIDATE_CONTRACT": "0x84c0C64c2608eC04FDFdD15fc8eE5DF77F4E398e", + "FLASHLOAN_LIQUIDATE_CONTRACT_V2": "0x4F9bF74aAc66b7A12Cb5Fb331CE1284CC9431960", + "VeloFactoryV2": "0x420DD381b31aEf6683db6B902084cB0FFECe40Da", + "VeloRouterV2": "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43", + "VeloV3Quoter": "0x254cF9E1E6e233aa1AC962CB9B05b2cfeAaE15b0", + "AddressRegistry": "0x85603119C938750Dfb5904f8a501b64F3F3A01D2", + "VaultConfigManager": "0x0068422b1B244aB06E02685Bc1E3FEbc418A9d42", + "ReserveLogicLibraryAddress": "0xEc120bC6e12Cea127553B1f53445947B1f73A132", + "ETokenDeployerAddress": "0xeccE0f5E758D01C142ebD5Ed2565038E4c0EDd80", + "StakingRewardsDeployer": "0xcEFa665165281B7a9807BDCd4d7Ac54a54Ca1e13", + "LendingPoolContractAddress": "0xBB505c54D71E9e599cB8435b4F0cEEc05fC71cbD", + "VaultFactory": "0x155620A2E6A9392c754B73296d9655061525729B", + "VaultDeployerSelectorLib": "0xAC9E42209038bcA0B2B026906De97a032400F2b4", + "VaultPositionManager": "0xf9cFB8a62f50e10AdDE5Aa888B44cF01C5957055", + "VeTokenAddress": "0xe0BeC4F45aEF64CeC9dCB9010d4beFfB13e91466", + "VeRewardDistributor": "0xB7D8613728efCfbB18bCD63dEeC06F64441D322a", + "SwapPathManager": "0x5B5bf5A296aD2c98567B1950Cc4BC32bFA4b3308", + "ChainLinkOracle": "0x93D09944B4b520289BeAAac646673095ca0fb1c4", + "DataProviderContract": "0x4cBd1af1Db7960Db8B4962d9a0389D912C3bc0b0", + "VaultLibraries": { + "1": { + "VaultDeployerLib": "0x2C58eCe45aC754B80FD39F5e7E67a4b0E91a1525", + "VaultInitializerLib": "0x47efC0Fe6a096c98D7e022daed2309aa9286DFef", + "VaultPositionLogicLib": "0x4F4940a87d63A290d43B6550911896fF7AEe354C", + "VaultOwnerActionsLib": "0x3AFCb1Ab1A78ECDD075647566258561acbeC01D5", + "VaultRewardsLogicLib": "0xF9d40a60fD6bDc866daf0918264a30acCE1DC9Cc" + }, + }, + } +} + +token_addresses = { + "base-mainnet": { + "WETH": "0x4200000000000000000000000000000000000006", + } +} diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/amm_viewer.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/amm_viewer.py new file mode 100644 index 000000000..af680e3f9 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/amm_viewer.py @@ -0,0 +1,24 @@ +from cdp import Wallet, SmartContract +from .abi import IPAIR_V2_ABI + + +def get_amount_out(wallet: Wallet, pair_address: str, token_in_address: str, token_in_amount: str) -> int | None: + """Get the amount of token out for a given amount of token in.""" + try: + # Get the token in and token out addresses + token_out_amount = SmartContract.read( + network_id=wallet.network_id, + contract_address=pair_address, + method="getAmountOut", + abi=IPAIR_V2_ABI, + args={ + "amountIn": token_in_amount, + "tokenIn": token_in_address, + } + ) + if not isinstance(token_out_amount, int): + raise TypeError("Token out amount must be an integer") + return token_out_amount + except Exception as e: + print(f"Error getting amount out from AMM: {e}") + return None diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/erc20.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/erc20.py new file mode 100644 index 000000000..56a32e70a --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/erc20.py @@ -0,0 +1,107 @@ +from cdp import SmartContract, Wallet, Address, Transaction +from .abi import ERC20_ABI +import time + + +erc20_symbols = {} +erc20_decimals = {} + + +def get_balance_of(wallet: Wallet, contract_address: str, address: Address) -> int | None: + try: + balance = SmartContract.read( + network_id=wallet.network_id, + contract_address=contract_address, + method="balanceOf", + abi=ERC20_ABI, + args={"_owner": address.address_id}) + if not isinstance(balance, int): + raise TypeError("Balance must be an integer") + return balance + except Exception as e: + return None + + +def get_decimals_of(wallet: Wallet, contract_address: str) -> int | None: + global erc20_decimals + decimals = erc20_decimals.get(contract_address) + if decimals is not None: + return decimals + try: + decimals = SmartContract.read( + network_id=wallet.network_id, + contract_address=contract_address, + method="decimals", + abi=ERC20_ABI, + args={}) + if not isinstance(decimals, int): + raise TypeError("Decimals must be an integer") + erc20_decimals[contract_address] = decimals + return decimals + except Exception as e: + return None + + +def get_symbol_of(wallet: Wallet, contract_address: str) -> str | None: + global erc20_symbols + symbol = erc20_symbols.get(contract_address) + if symbol is not None: + return symbol + try: + symbol = SmartContract.read( + network_id=wallet.network_id, + contract_address=contract_address, + method="symbol", + abi=ERC20_ABI, + args={}) + if not isinstance(symbol, str): + raise TypeError("Symbol must be a string") + erc20_symbols[contract_address] = symbol + return symbol + except Exception as e: + return None + + +def get_allowance_of(wallet: Wallet, contract_address: str, owner: str, spender: str) -> int | None: + try: + allowance = SmartContract.read( + network_id=wallet.network_id, + contract_address=contract_address, + method="allowance", + abi=ERC20_ABI, + args={"_owner": owner, "_spender": spender}) + if not isinstance(allowance, int): + raise TypeError("Allowance must be an integer") + return allowance + except Exception as e: + return None + + +def approve_token(wallet: Wallet, token_address: str, spender_address: str, amount: int) -> bool | None: + """Approve the token for spending.""" + + allowance = get_allowance_of(wallet, token_address, wallet.default_address.address_id, spender_address) + if allowance is None: + return None + if allowance >= amount: + return True + + try: + invocation = wallet.invoke_contract( + contract_address=token_address, + method="approve", + abi=ERC20_ABI, + args={ + "_spender": spender_address, + "_value": str(amount) + } + ).wait() + while not invocation.transaction.terminal_state: + time.sleep(1) + if invocation.transaction.status == Transaction.Status.COMPLETE: + return True + else: + return False + except Exception as e: + print(f"Error approving token: {e}") + return None diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/graph.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/graph.py new file mode 100644 index 000000000..83028782d --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/graph.py @@ -0,0 +1,102 @@ +import requests +from typing import List + +PUBLIC_API_KEY = "a4998f968b8ad324eb3e47ed20c00220" +SUBGRAPH_ID = "3AceL1hTiuLK1ZUf2wwJJTKdu4sziTmwvrF6MN48wmsb" +SUBGRAPH_ENDPOINT = f"https://gateway.thegraph.com/api/{PUBLIC_API_KEY}/subgraphs/id/{SUBGRAPH_ID}" + + +def query_user_lending_position_pool_ids(user_address: str) -> str: + return f""" +{{ + userLendingPositions( + first: 10 + where: {{user_: {{id: "{user_address}"}}}} + ) {{ + reserveId + }} +}} +""" + + +def query_farming_vault_id(pair_address: str) -> str: + return f""" +{{ + vaults(where: {{paused: false, pair: "{pair_address}"}}) {{ + vaultId + }} +}} +""" + + +def query_user_farming_vault_positions(user_address: str, vault_id: str | None) -> str: + if vault_id is not None: + where_condition = f"{{manager: \"{user_address}\", vaultId: \"{vault_id}\", isActive: true}}" + else: + where_condition = f"{{manager: \"{user_address}\", isActive: true}}" + return f""" +{{ + userVaultPositions( + where: {where_condition} + ) {{ + vaultId + vaultPositionId + }} +}} +""" + + +def query_vault_address(vault_id: str) -> str: + return f""" +{{ + newVaults(where: {{vaultId: "{vault_id}"}}) {{ + vaultAddress + }} +}} +""" + + +def get_user_lending_position_pool_ids(user_address: str) -> List[str] | None: + try: + response = requests.post(SUBGRAPH_ENDPOINT, json={"query": query_user_lending_position_pool_ids(user_address)}) + response.raise_for_status() + data = response.json()["data"]["userLendingPositions"] + return [position["reserveId"] for position in data] + except Exception as e: + print(f"Error: {e}") + return None + + +def get_farming_vault_id(pair_address: str) -> str | None: + try: + json_query: dict = {"query": query_farming_vault_id(pair_address)} + response = requests.post(SUBGRAPH_ENDPOINT, json=json_query) + response.raise_for_status() + data = response.json()["data"]["vaults"] + return data[0]["vaultId"] + except Exception as e: + print(f"Error: {e}") + return None + + +def get_user_farming_vault_positions(user_address: str, vault_id: str | None) -> List[dict] | None: + try: + response = requests.post(SUBGRAPH_ENDPOINT, + json={"query": query_user_farming_vault_positions(user_address, vault_id)}) + response.raise_for_status() + data = response.json()["data"]["userVaultPositions"] + return data + except Exception as e: + print(f"Error: {e}") + return None + + +def get_vault_address(vault_id: str) -> str | None: + try: + response = requests.post(SUBGRAPH_ENDPOINT, json={"query": query_vault_address(vault_id)}) + response.raise_for_status() + data = response.json()["data"]["newVaults"] + return data[0]["vaultAddress"] + except Exception as e: + print(f"Error: {e}") + return None diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/lyf_info.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/lyf_info.py new file mode 100644 index 000000000..e4330d275 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/lyf_info.py @@ -0,0 +1,209 @@ +import requests +import time + + +pair_infos = {} +pair_timeout_at = 0 + + +def get_lyf_info() -> dict | None: + static_url = "https://extra-static.s3.ap-southeast-1.amazonaws.com/data/pools/info-base.json" + try: + response = requests.get(static_url) + if response.status_code == 200: + return response.json() + else: + return None + except Exception as e: + return None + + +def get_latest_lyf_info() -> dict | None: + lyf_info = get_lyf_info() + if lyf_info is not None: + return lyf_info[-1] + else: + return None + + +def get_latest_lyf_lending_pool_info() -> dict | None: + latest_lyf_info = get_latest_lyf_info() + if latest_lyf_info is not None: + return latest_lyf_info["lend"] + else: + return None + + +def get_latest_lyf_farming_info() -> dict | None: + latest_lyf_info = get_latest_lyf_info() + if latest_lyf_info is not None: + return latest_lyf_info["farm"] + else: + return None + + +def get_latest_available_lyf_lending_pool_info() -> list | None: + latest_lyf_lending_pool_info = get_latest_lyf_lending_pool_info() + if latest_lyf_lending_pool_info is not None: + available = [] + for info in latest_lyf_lending_pool_info: + pool_key = info.get("poolKey") + if pool_key is not None: + if info["apr"] > 0.01: + if pool_key in ["WETH"]: + available.append(info) + continue + if info["totalLiquidity"] > 200000: + if info["borrowingRate"] > 0.09: + available.append(info) + continue + return available + else: + return None + + +def get_latest_available_lyf_farming_info() -> list | None: + latest_lyf_farming_info = get_latest_lyf_farming_info() + if latest_lyf_farming_info is not None: + available = [] + for info in latest_lyf_farming_info: + tvl = info.get("tvl") + if tvl is not None: + if tvl > 200000: + available.append(info) + return available + else: + return None + + +def get_apr_change_for_lyf_lending_pool(pool_id: str) -> dict | None: + pool_info = {} + initialized = False + lyf_info = get_lyf_info() + if lyf_info is not None: + for info in lyf_info: + ts = info["ts"] + for pool in info["lend"]: + if pool["id"] == pool_id: + if not initialized: + pool_info["pool_id"] = pool["id"] + pool_info["symbol"] = pool["poolKey"] + pool_info["address"] = pool["underlyingTokenAddress"] + pool_info["apr_change"] = [] + initialized = True + apr_point = {"ts": ts, "apr": pool["apr"]} + pool_info["apr_change"].append(apr_point) + return pool_info + else: + return None + + +def get_apr_and_tvl_change_for_lyf_farming(pair_address: str) -> dict | None: + farming_info = {} + initialized = False + lyf_info = get_lyf_info() + if lyf_info is not None: + for info in lyf_info: + ts = info["ts"] + for vault in info["farm"]: + if vault["poolAddress"] == pair_address: + if not initialized: + farming_info["symbol"] = vault["poolKey"] + farming_info["address"] = vault["poolAddress"] + farming_info["stable"] = vault["stable"] + farming_info["token0"] = vault["token0"] + farming_info["token1"] = vault["token1"] + farming_info["change"] = [] + initialized = True + point = {"ts": ts, "apr": vault["apr"], "tvl": vault["tvl"]} + farming_info["change"].append(point) + return farming_info + else: + return None + + +def get_concise_lyf_lending_pool_info() -> list | None: + latest_available_lyf_lending_info = get_latest_available_lyf_lending_pool_info() + if latest_available_lyf_lending_info is not None: + concise_info = [] + for info in latest_available_lyf_lending_info: + concise_info.append({ + "pool_id": info["id"], + "symbol": info["poolKey"], + "address": info["underlyingTokenAddress"], + "apr": info["apr"] + }) + return concise_info + else: + return None + + +def get_concise_lyf_farming_info() -> list | None: + latest_available_lyf_farming_info = get_latest_available_lyf_farming_info() + if latest_available_lyf_farming_info is not None: + concise_info = [] + for info in latest_available_lyf_farming_info: + concise_info.append({ + "symbol": info["poolKey"], + "pair_address": info["poolAddress"], + "stable": info["stable"], + "token0": info["token0"], + "token1": info["token1"], + "apr": info["apr"], + "tvl": info["tvl"] + }) + return concise_info + else: + return None + + +def get_pair_info(pair_address: str) -> dict | None: + pairs = get_pair_infos() + if pairs is not None: + return pairs.get(pair_address) + else: + return None + + +def get_pair_infos() -> dict | None: + global pair_infos + global pair_timeout_at + if len(pair_infos) == 0 or pair_timeout_at < time.time(): + pair_infos = get_pair_infos_from_origin() + if pair_infos is None: + return None + pair_timeout_at = time.time() + 300 + return pair_infos + + +def get_pair_infos_from_origin() -> dict | None: + static_url = "https://v1-public-s3-publicresourcebucket-1srs3mnbpd2j.s3.us-east-2.amazonaws.com/8453-pairs.json" + try: + response = requests.get(static_url) + if response.status_code == 200: + return response.json() + else: + return None + except Exception as e: + return None + + +def get_token_price_from_origin() -> dict | None: + static_url = "https://v1-public-s3-publicresourcebucket-1srs3mnbpd2j.s3.us-east-2.amazonaws.com/8453-tokenPrices.json" + try: + response = requests.get(static_url) + if response.status_code == 200: + return response.json() + else: + return None + except Exception as e: + return None + + +def get_token_price(token_address: str) -> str | None: + token_prices = get_token_price_from_origin() + if token_prices is not None: + price = token_prices.get(token_address, "0") + return price + else: + return None diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/lyf_viewer.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/lyf_viewer.py new file mode 100644 index 000000000..cf0af0c9d --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/lyf_viewer.py @@ -0,0 +1,438 @@ +from cdp import SmartContract, Wallet +from .abi import LYF_LENDING_POOL_ABI, LYF_POSITION_MANAGER_ABI +from .addresses import lyf_addresses +from .lyf_info import (get_concise_lyf_farming_info, get_token_price, get_pair_info, + get_apr_and_tvl_change_for_lyf_farming) +from .graph import get_farming_vault_id, get_vault_address +from .erc20 import get_symbol_of, get_decimals_of +from decimal import getcontext, Decimal +from concurrent.futures import ThreadPoolExecutor, as_completed + + +getcontext().prec = 25 + + +def get_pool_token_address(wallet: Wallet, pool_id: str) -> str | None: + pool_state = get_pool_status(wallet, pool_id) + if pool_state is None: + return None + token_address = pool_state.get("underlyingTokenAddress") + return token_address + + +def get_pool_status(wallet: Wallet, pool_id: str) -> dict | None: + try: + pool_ids_array = [pool_id] + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + + reserve_status = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="getReserveStatus", + abi=LYF_LENDING_POOL_ABI, + args={"reserveIdArr": pool_ids_array} + ) + if not isinstance(reserve_status, list): + raise TypeError("Reserve status must be a list") + return reserve_status[0] + except Exception as e: + return None + + +def get_pool_state(wallet: Wallet, pool_id: str) -> dict | None: + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + + reserve_state = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="reserves", + abi=LYF_LENDING_POOL_ABI, + args={"poolId": pool_id} + ) + if not isinstance(reserve_state, dict): + raise TypeError("Reserve state must be a dictionary") + return reserve_state + except Exception as e: + return None + + +def get_lyf_lending_pool_positions(wallet: Wallet, pool_ids: list[str]) -> list | None: + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + user_positions = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="getPositionStatus", + abi=LYF_LENDING_POOL_ABI, + args={ + "reserveIdArr": pool_ids, + "user": wallet.default_address.address_id} + ) + if not isinstance(user_positions, list): + raise TypeError("User positions must be a list") + return user_positions + except Exception as e: + return None + + +def get_lyf_farming_vault_state(wallet: Wallet, vault_id: str) -> dict | None: + try: + position_manager = lyf_addresses[wallet.network_id]["VaultPositionManager"] + vault_state = SmartContract.read( + network_id=wallet.network_id, + contract_address=position_manager, + method="getVault", + abi=LYF_POSITION_MANAGER_ABI, + args={"vaultId": vault_id} + ) + if not isinstance(vault_state, dict): + raise TypeError("Vault state must be a dictionary") + return vault_state + except Exception as e: + return None + + +def fetch_vault_info(wallet, info): + vault_id = get_farming_vault_id(info["pair_address"]) + if vault_id is None: + return None + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return None + token0 = info["token0"] + token0_symbol = get_symbol_of(wallet, token0) + if token0_symbol is None: + return None + token1 = info["token1"] + token1_symbol = get_symbol_of(wallet, token1) + if token1_symbol is None: + return None + vault_address = get_vault_address(vault_id) + if vault_address is None: + return None + + return { + "vault_id": vault_id, + "vault_address": vault_address, + "symbol": info["symbol"], + "pair_address": info["pair_address"], + "stable": info["stable"], + "token0": token0, + "token0_symbol": token0_symbol, + "token1": token1, + "token1_symbol": token1_symbol, + "apr": info["apr"], + "tvl": info["tvl"], + "max_leverage": vault_state["maxLeverage"], + "liquidateDebtRatio": vault_state["liquidateDebtRatio"], + "minSwapAmount0": vault_state["minSwapAmount0"], + "minSwapAmount1": vault_state["minSwapAmount1"], + } + + +def get_lyf_farming_vaults_info(wallet: Wallet) -> list | None: + farming_info = get_concise_lyf_farming_info() + if farming_info is None: + return None + vaults_info = [] + with ThreadPoolExecutor() as executor: + futures = [executor.submit(fetch_vault_info, wallet, info) for info in farming_info] + for future in as_completed(futures): + result = future.result() + if result is not None: + vaults_info.append(result) + return vaults_info + + +def get_lyf_lending_pool_id_from_debt_position(wallet: Wallet, debt_position_id: str) -> str | None: + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + debt_positions = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="debtPositions", + abi=LYF_LENDING_POOL_ABI, + args={"debtId": debt_position_id} + ) + if not isinstance(debt_positions, dict): + raise TypeError("Debt positions must be a dictionary") + return str(debt_positions.get("reserveId")) + except Exception as e: + print(f"Error: {e}") + return None + + +def get_lyf_vault_related_lending_pool_ids(wallet: Wallet, vault_id: str) -> list | None: + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return None + pool_ids = [] + debt_position_0 = str(vault_state.get("debtPositionId0")) + token0_pool_id = get_lyf_lending_pool_id_from_debt_position(wallet, debt_position_0) + if token0_pool_id is None: + return None + pool_ids.append(token0_pool_id) + debt_position_1 = str(vault_state.get("debtPositionId1")) + token1_pool_id = get_lyf_lending_pool_id_from_debt_position(wallet, debt_position_1) + if token1_pool_id is None: + return None + pool_ids.append(token1_pool_id) + return pool_ids + + +def get_lyf_vault_borrow_credits(wallet: Wallet, pool_id: str, vault_address: str) -> int | None: + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + borrow_credits = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="credits", + abi=LYF_LENDING_POOL_ABI, + args={"poolId": pool_id, "vaultAddress": vault_address} + ) + if not isinstance(borrow_credits, int): + raise TypeError("Borrow credits must be an integer") + return borrow_credits + except Exception as e: + return None + + +def get_lyf_lending_total_available(wallet: Wallet, pool_id: str) -> int | None: + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + total_borrows = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="totalBorrowsOfReserve", + abi=LYF_LENDING_POOL_ABI, + args={"reserveId": pool_id} + ) + if not isinstance(total_borrows, int): + raise TypeError("Total available must be an integer") + total_liquidity = SmartContract.read( + network_id=wallet.network_id, + contract_address=lending_pool_address, + method="totalLiquidityOfReserve", + abi=LYF_LENDING_POOL_ABI, + args={"reserveId": pool_id} + ) + if not isinstance(total_liquidity, int): + raise TypeError("Total liquidity must be an integer") + max_borrows = int(total_liquidity * 0.8) + if total_borrows >= max_borrows: + total_available = 0 + else: + total_available = max_borrows - total_borrows + return total_available + except Exception as e: + return None + + +def get_lyf_vault_borrow_available(wallet: Wallet, pool_id: str, vault_address: str) -> int | None: + vault_credits = get_lyf_vault_borrow_credits(wallet, pool_id, vault_address) + if vault_credits is None: + return None + total_available = get_lyf_lending_total_available(wallet, pool_id) + if total_available is None: + return None + return min(vault_credits, total_available) + + +def get_basic_pair_apr_tvl(wallet: Wallet, pair_address: str) -> tuple[float, float]: + try: + pair = get_pair_info(pair_address) + if pair is not None: + token0_address = pair.get("token0") + token0_reserve = pair.get("reserve0") + token1_address = pair.get("token1") + token1_reserve = pair.get("reserve1") + liquidity = pair.get("liquidity") + gauge_liquidity = pair.get("gauge_liquidity") + emissions_address = pair.get("emissions_token") + emissions = pair.get("emissions") + + token0_value = get_token_value(wallet, token0_address, token0_reserve) + if token0_value is None: + return 0.0, 0.0 + + token1_value = get_token_value(wallet, token1_address, token1_reserve) + if token1_value is None: + return 0.0, 0.0 + + emissions_value = get_token_value(wallet, emissions_address, emissions) + if emissions_value is None: + return 0.0, 0.0 + + tvl = token0_value + token1_value + + gauge_tvl = Decimal(tvl) * (Decimal(gauge_liquidity) / Decimal(liquidity)) + + yearly_emissions = Decimal(emissions_value) * Decimal('31536000') + # 31536000 = 365 * 24 * 3600 + + apr = yearly_emissions / gauge_tvl * Decimal('100') + return float(apr), float(tvl) + else: + return 0.0, 0.0 + except Exception as e: + print(f"Error: {e}") + return 0.0, 0.0 + + +def get_update_borrow_interest(wallet: Wallet, pool_id: str, borrow_changed: str, liquidity_changed: str) -> int | None: + pool_state = get_pool_status(wallet, pool_id) + if pool_state is None: + return None + total_borrows = pool_state.get("totalBorrows") + total_liquidity = pool_state.get("totalLiquidity") + utilization_rate = ((Decimal(total_borrows) + Decimal(borrow_changed)) / + (Decimal(total_liquidity) + Decimal(liquidity_changed))) + borrowing_rate = calculate_lyf_lending_pool_borrowing_rate(wallet, utilization_rate, pool_id) + if borrowing_rate is None: + return None + return borrowing_rate + + +def get_token_value(wallet: Wallet, token_address: str, amount: int) -> float | None: + token_price = get_token_price(token_address) + if token_price is None: + return None + decimals = get_decimals_of(wallet, token_address) + if decimals is None: + return None + value = Decimal(amount) * Decimal(token_price) / (Decimal(10) ** Decimal(decimals)) + return float(value) + + +def calculate_lyf_lending_pool_borrowing_rate(wallet: Wallet, utilization_rate, pool_id) -> int | None: + max_utilization = Decimal(10) ** Decimal(18) + utilization_rate = Decimal(utilization_rate * 10 ** 18) + pool_state = get_pool_state(wallet, pool_id) + if pool_state is None: + return None + borrowing_rate_config = pool_state.get("borrowingRateConfig") + + utilization_a = Decimal(borrowing_rate_config.get("utilizationA")) + utilization_b = Decimal(borrowing_rate_config.get("utilizationB")) + borrowing_rate_a = Decimal(borrowing_rate_config.get("borrowingRateA")) + borrowing_rate_b = Decimal(borrowing_rate_config.get("borrowingRateB")) + max_borrowing_rate = Decimal(borrowing_rate_config.get("maxBorrowingRate")) + + if utilization_rate <= utilization_a: + if utilization_a == Decimal(0): + return int(borrowing_rate_a) + borrowing_rate = utilization_rate * borrowing_rate_a / utilization_a + elif utilization_rate <= utilization_b: + if utilization_b == utilization_a: + return int(borrowing_rate_b) + borrowing_rate = ((borrowing_rate_b - borrowing_rate_a) * (utilization_rate - utilization_a) + / (utilization_b - utilization_a) + borrowing_rate_a) + else: + if utilization_b >= max_utilization: + return int(max_borrowing_rate) + borrowing_rate = (max_borrowing_rate - borrowing_rate_b) * (utilization_rate - utilization_b) / ( + max_utilization - utilization_b) + borrowing_rate_b + + return int(borrowing_rate) + + +def get_lyf_base_apr(wallet: Wallet, vault_id: str, token0_supply: int, token0_borrow: int, + token1_supply: int, token1_borrow: int) -> float | None: + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return None + pair_address = vault_state.get("pair") + token0_address = vault_state.get("token0") + token1_address = vault_state.get("token1") + token0_total_amount = token0_supply + token0_borrow + token1_total_amount = token1_supply + token1_borrow + token0_total_value = get_token_value(wallet, token0_address, token0_total_amount) + token1_total_value = get_token_value(wallet, token1_address, token1_total_amount) + + apr, tvl = get_basic_pair_apr_tvl(wallet, pair_address) + if apr == 0.0 or tvl == 0.0: + return None + base_apr = ((Decimal(apr) * Decimal(tvl)) / (Decimal(token0_total_value + token1_total_value) + Decimal(tvl)) + / Decimal(100)) + return float(base_apr) + + +def get_lyf_equity_changes_and_apy(initial_equity: float, leverage: int, base_apr: float, + token0_borrow_proportion: float, token0_borrow_interest: int, + token1_borrow_interest: int) -> tuple[float, float]: + weighted_borrow_interest = (token0_borrow_proportion * token0_borrow_interest + + (1 - token0_borrow_proportion) * token1_borrow_interest) / 10 ** 18 + initial_position = initial_equity * leverage / 100 + position_after_a_year = initial_position * (1 + base_apr) + debt_after_a_year = (initial_position - initial_equity) * (1 + weighted_borrow_interest) + equity_after_a_year = (position_after_a_year - debt_after_a_year) + apr = (equity_after_a_year - initial_equity) / initial_equity + return equity_after_a_year, apr + + +def get_lyf_farming_apy(wallet: Wallet, vault_id: str, token0_supply: int, token0_borrow: int, + token1_supply: int, token1_borrow: int, leverage: int) -> float | None: + base_apr = get_lyf_base_apr(wallet, vault_id, token0_supply, token0_borrow, token1_supply, token1_borrow) + if base_apr is None: + return None + related_pool_ids = get_lyf_vault_related_lending_pool_ids(wallet, vault_id) + if related_pool_ids is None: + return None + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + token0_address = vault_state.get("token0") + token1_address = vault_state.get("token1") + try: + token0_borrow_proportion = Decimal(token0_borrow) / (Decimal(token0_borrow) + Decimal(token1_borrow)) + token0_borrow_interest = get_update_borrow_interest(wallet, related_pool_ids[0], + str(token0_borrow), '0') + if token0_borrow_interest is None: + return None + token1_borrow_interest = get_update_borrow_interest(wallet, related_pool_ids[1], + str(token1_borrow), '0') + if token1_borrow_interest is None: + return None + + token0_value = get_token_value(wallet, token0_address, token0_supply) + if token0_value is None: + return None + token1_value = get_token_value(wallet, token1_address, token1_supply) + if token1_value is None: + return None + initial_equity = token0_value + token1_value + + equity_after_a_year, apy = get_lyf_equity_changes_and_apy(initial_equity, + leverage, base_apr, float(token0_borrow_proportion), + token0_borrow_interest, token1_borrow_interest) + return apy + except Exception as e: + print(f"Error: {e}") + return None + + +def get_vault_position(wallet: Wallet, vault_id: str, position_id: str) -> dict | None: + try: + position_manager_address = lyf_addresses[wallet.network_id]["VaultPositionManager"] + vault_position = SmartContract.read( + network_id=wallet.network_id, + contract_address=position_manager_address, + method="getVaultPosition", + abi=LYF_POSITION_MANAGER_ABI, + args={"vaultId": vault_id, "vaultPositionId": position_id} + ) + if not isinstance(vault_position, dict): + raise TypeError("Vault position must be a dictionary") + return vault_position + except Exception as e: + return None + + +def get_historical_farming_apr_tvl(wallet: Wallet, vault_id: str) -> dict | None: + state = get_lyf_farming_vault_state(wallet, vault_id) + if state is None: + return None + pair_address = state.get("pair") + info = get_apr_and_tvl_change_for_lyf_farming(pair_address) + if info is None: + return None + return info diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/misc.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/misc.py new file mode 100644 index 000000000..87bf61b9b --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/helper/misc.py @@ -0,0 +1,52 @@ +from cdp import Wallet +from .addresses import token_addresses +from .erc20 import get_balance_of + +def format_int_leverage_to_str(max_leverage): + # Convert the integer to a float by dividing by 100 + leverage_float = max_leverage / 100.0 + + # Format the float value to a string with 'X' to denote times leverage + leverage_str = f"{leverage_float:.1f}X" + + return leverage_str + + +def format_str_leverage_to_int(leverage): + # Remove the 'X' from the string if it exists + leverage_str = leverage.replace("X", "") + + # Convert the string to a float by multiplying by 100 + try: + leverage_int = int(float(leverage_str) * 100) + + return leverage_int + except ValueError: + return None + + +def amount_need_to_wrapped(wallet: Wallet, invest_amount: str) -> int | None: + try: + weth_address = token_addresses[wallet.network_id]["WETH"] + weth_balance = get_balance_of(wallet, weth_address, wallet.default_address) + if weth_balance is None: + return None + if weth_balance >= int(invest_amount): + return 0 + eth_balance = wallet.balance("wei") + if eth_balance < int(invest_amount): + return None + return int(invest_amount) + except Exception as e: + return None + + +def check_balance_sufficiency(wallet: Wallet, token_address: str, amount: str) -> bool: + weth_address = token_addresses[wallet.network_id]["WETH"] + balance = get_balance_of(wallet, token_address, wallet.default_address) + if balance is None: + return False + if token_address == weth_address and balance < int(amount): + eth_balance = wallet.balance("wei") + return eth_balance >= int(amount) + return balance >= int(amount) diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_close_farming_position.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_close_farming_position.py new file mode 100644 index 000000000..2387c70f5 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_close_farming_position.py @@ -0,0 +1,129 @@ +import time +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet, Transaction +from cdp_agentkit_core.actions import CdpAction +from .helper import (addresses, get_lyf_farming_vault_state, + LYF_POSITION_MANAGER_ABI, get_decimals_of, get_vault_position) + + +EXTRA_LYF_CLOSE_FARMING_POSITIONS_PROMPT = """ +This tool is used to let users close their positions in the Extra LYF Farming Vault. +User can partially or fully close their positions by repaying the debt and withdrawing the remaining tokens. + +- Receive Token: The token to receive after closing the position. Must be one of the two tokens in farming vault pair. You need to obtain the values via ExtrafiLYFGetFarmingPositionsAction. + +Important Notes: +- Network Support: Only supported on "Base Mainnet" +- This tool belongs to the Extrafi LYF Farming series +- Users might refer to token by token symbol; you need to obtain the token address via ExtrafiLYFGetFarmingPositionsAction. +""" + + +class ExtrafiLYFCloseFarmingPositionsInput(BaseModel): + """Input argument schema for closing LYF farming vault positions action.""" + vault_id: str = Field( + ..., + description="The vault id of the LYF Farming Vault as a string representation of an integer, e.g., '18'", + ) + position_id: str = Field( + ..., + description="The position ID of the user's investment in the specified LYF Farming Vault as a string-encoded integer, e.g., '10'.", + ) + percent: str = Field( + ..., + description="The percentage of the position to be closed. Specify the percentage as a string (e.g., '50' for 50% or '100' for 100%).", + ) + receive_token: str = Field( + ..., + description="The token to receive after closing the position. Must be one of the two tokens in farming vault pair. Specify the token address as a string (e.g., '0x1234567890abcdef1234567890abcdef12345678').", + ) + + +def get_amount_without_decimals(wallet: Wallet, token_address: str, amount: str) -> int | None: + """Get the amount without decimals for the token.""" + decimals = get_decimals_of(wallet, token_address) + if decimals is None: + return None + try: + amount_without_decimals = int(float(amount) * 10 ** decimals) + return amount_without_decimals + except Exception as e: + return None + + +def lyf_close_farming_position(wallet: Wallet, vault_id: str, position_id: str, + percent: str, receive_token: str) -> str: + """ + Close the specified LYF Farming Vault position. + """ + + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return "Error: Failed to retrieve the vault state. Please check the vault id.\n" + vault_token0_address = vault_state["token0"] + vault_token1_address = vault_state["token1"] + receive_type = -1 + if vault_token0_address == receive_token: + receive_type = 0 + if vault_token1_address == receive_token: + receive_type = 1 + if receive_type == -1: + return "Error: The receive token must be one of the two tokens in the farming vault pair.\n" + + position = get_vault_position(wallet, vault_id, position_id) + if position is None: + return "Error: Failed to retrieve the vault position. Please check the position id.\n" + + if position.get("manager") != wallet.default_address.address_id: + return "Error: The position does not belong to the user.\n" + + try: + percent_ = int(percent) * 100 + except Exception as e: + return "Error: Failed to convert the percentage to an integer.\n" + if percent_ < 0 or percent_ > 10000: + return "Error: The percentage must be between 0 and 100.\n" + + position_manager_address = addresses.lyf_addresses[wallet.network_id]["VaultPositionManager"] + args = { + "params": (vault_id, + position_id, + str(percent_), + wallet.default_address.address_id, + True, + str(receive_type), + "0", + "0", + str(int(time.time()) + 600), + "0", + "",)} + + try: + invocation = wallet.invoke_contract( + contract_address=position_manager_address, + method="closeVaultPositionPartially", + abi=LYF_POSITION_MANAGER_ABI, + args=args + ).wait() + + while not invocation.transaction.terminal_state: + time.sleep(1) + + if invocation.transaction.status == Transaction.Status.COMPLETE: + return (f"Successfully closed the {percent}% position in the farming vault with transaction hash: " + f"{invocation.transaction.transaction_hash}\n") + else: + return f"Error: Failed to close the position in the farming vault.\n" + + except Exception as e: + return f"Error: Failed to close the position in the farming vault: {e}\n" + + +class ExtrafiLYFCloseFarmingPositionsAction(CdpAction): + """Action class for closing LYF farming vault positions.""" + + name: str = "extrafi_lyf_close_farming_positions_action" + description: str = EXTRA_LYF_CLOSE_FARMING_POSITIONS_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFCloseFarmingPositionsInput + func: Callable[..., str] = lyf_close_farming_position diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_farming_apr.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_farming_apr.py new file mode 100644 index 000000000..3c41a0536 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_farming_apr.py @@ -0,0 +1,56 @@ +import json +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet +from cdp_agentkit_core.actions import CdpAction +from .helper import get_historical_farming_apr_tvl + + +EXTRA_LYF_FARMING_APR_PROMPT = """ +This tool is designed to list the APR and TVL changes over a specific period for a particular LYF farming vault, aiding users in assessing the vault's historical performance to decide whether to participate in its LYF. You can summarize this data. + +Inputs: +- Vault Id +(Hint: Users may refer to a vault by the token symbol involved. You can use the ExtrafiLYFListFarmingAction tool to obtain the vault id. If multiple vault share the same token symbol, you should provide a list.) + +Important Notes: + +- Network Support: Only supported on the following networks: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the LYF Farming series +- APR Format: APR is expressed in percentage (%) and TVL in US dollars ($). +- When communicating with users, use UTC time for clarity instead of direct timestamps. + +""" + + +class ExtrafiLYFFarmingAPRInput(BaseModel): + """Input argument schema for LYF Farming APR action.""" + vault_id: str = Field( + ..., + description="The vault id of the LYF Farming vault, e.g., '18'", + ) + + +def lyf_farming_apr(wallet: Wallet, vault_id: str) -> str: + """Get the historical APR and TVL data of specified Extrafi LYF farming vault. + + Returns: + str: A message containing the historical APR and TVL data. + """ + info = get_historical_farming_apr_tvl(wallet, vault_id) + if info is not None: + reply = "Extrafi LYF Farming Vault APR and TVL:\n" + reply += json.dumps(info, indent=4) + return reply + else: + return "Error: Failed to retrieve the LYF farming vault APR and TVL.\n" + + +class ExtrafiLYFFarmingAPRAction(CdpAction): + """Get historical APR and TVL data for one Extrafi LYF farming vault.""" + + name: str = "extrafi_lyf_farming_apr_action" + description: str = EXTRA_LYF_FARMING_APR_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFFarmingAPRInput + func: Callable[..., str] = lyf_farming_apr diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_get_farming_positions.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_get_farming_positions.py new file mode 100644 index 000000000..834b38701 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_get_farming_positions.py @@ -0,0 +1,118 @@ +from collections.abc import Callable +from pydantic import BaseModel +from cdp import Wallet +from cdp_agentkit_core.actions import CdpAction +from .helper import (get_user_farming_vault_positions, get_vault_position, + get_token_value, get_lyf_farming_vault_state, get_symbol_of, get_decimals_of) +from concurrent.futures import ThreadPoolExecutor, as_completed + +EXTRA_LYF_GET_FARMING_POSITIONS_PROMPT = """ +This tool is designed to retrieve user positions in the LYF Farming Vault where funds have been invested. +The information returned includes a list of positions, featuring the farming vault id, and the number of tokens invested for each position. + +Inputs: None + +Important Notes: + +- Only supported on the following networks: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the Extrafi LYF Farming series +""" + + +class ExtrafiLYFGetFarmingPositionsInput(BaseModel): + """Input argument schema for getting LYF farming vault positions action.""" + + +def get_vault_position_info(wallet: Wallet, vault_id: str, position_id: str) -> str | None: + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return "Error: Failed to retrieve the vault state. Please check the vault id.\n" + vault_token0_address = vault_state["token0"] + vault_token1_address = vault_state["token1"] + + token0_symbol = get_symbol_of(wallet, vault_token0_address) + if token0_symbol is None: + return None + token1_symbol = get_symbol_of(wallet, vault_token1_address) + if token1_symbol is None: + return None + + position = get_vault_position(wallet, vault_id, position_id) + if position is None: + return None + token0_left = position.get("token0Left") + token1_left = position.get("token1Left") + token0_in_liquidity = position.get("token0InLiquidity") + token1_in_liquidity = position.get("token1InLiquidity") + debt0 = position.get("debt0") + debt1 = position.get("debt1") + token0_total = token0_left + token0_in_liquidity + token1_total = token1_left + token1_in_liquidity + + token0_total_with_decimals = f"{token0_total / 10 ** get_decimals_of(wallet, vault_token0_address):.6f}" + token1_total_with_decimals = f"{token1_total / 10 ** get_decimals_of(wallet, vault_token1_address):.6f}" + debt0_with_decimals = f"{debt0 / 10 ** get_decimals_of(wallet, vault_token0_address):.6f}" + debt1_with_decimals = f"{debt1 / 10 ** get_decimals_of(wallet, vault_token1_address):.6f}" + + token0_value = get_token_value(wallet, vault_token0_address, token0_total) + if token0_value is None: + return None + token1_value = get_token_value(wallet, vault_token1_address, token1_total) + if token1_value is None: + return None + + debt0_value = debt0 * token0_value / token0_total + debt1_value = debt1 * token1_value / token1_total + + total_position_value = token0_value + token1_value + total_debt_value = debt0_value + debt1_value + + equity_value = total_position_value - total_debt_value + + debt_ratio = total_debt_value / total_position_value + + return (f"Vault ID: {vault_id}, Position ID: {position_id}, " + f"Token0 {token0_symbol}({vault_token0_address}) Position Value: ${token0_value} ({token0_total_with_decimals} {token0_symbol}), " + f"Token1 {token1_symbol}({vault_token1_address}) Position Value: ${token1_value} ({token1_total_with_decimals} {token1_symbol}), " + f"Total Position Value: ${total_position_value:.2f}, " + f"{"Debt Value"}: ${total_debt_value:.2f} ({debt0_with_decimals} {token0_symbol}, " + f"{debt1_with_decimals} {token1_symbol}), " + f"Equity Value: ${equity_value}, Debt Ratio: {debt_ratio:.2f}") + + +def lyf_get_farming_positions(wallet: Wallet) -> str: + """ + Get user positions in the Extrafi LYF farming vaults. + + Returns: + str: A message containing the user positions in the LYF farming vaults. + """ + + positions = get_user_farming_vault_positions(wallet.default_address.address_id, None) + if positions is None: + return "Error: Failed to retrieve the existing farming vault positions for user.\n" + + reply = "Extrafi LYF Farming Vault Positions:\n" + position_info = [] + with ThreadPoolExecutor() as executor: + futures = [executor.submit(get_vault_position_info, wallet, position["vaultId"], position["vaultPositionId"]) + for position in positions] + for future in as_completed(futures): + position_info.append(future.result()) + + for info in position_info: + if info is None: + return "Error: Failed to retrieve the vault position information.\n" + reply += info + "\n" + + return reply + + +class ExtrafiLYFGetFarmingPositionsAction(CdpAction): + """Get user positions in the Extrafi LYF farming vaults action.""" + + name: str = "extrafi_lyf_get_farming_positions_action" + description: str = EXTRA_LYF_GET_FARMING_POSITIONS_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFGetFarmingPositionsInput + func: Callable[..., str] = lyf_get_farming_positions diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_get_lending_positions.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_get_lending_positions.py new file mode 100644 index 000000000..263dfc870 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_get_lending_positions.py @@ -0,0 +1,64 @@ +from collections.abc import Callable +from pydantic import BaseModel +from cdp_agentkit_core.actions import CdpAction +from cdp import Wallet +from .helper import (get_user_lending_position_pool_ids, get_lyf_lending_pool_positions, get_pool_token_address, + get_decimals_of, get_symbol_of) + + +EXTRA_LYF_GET_LENDING_POSITIONS_PROMPT = """ +This tool is designed to retrieve user positions in the LYF Lending Pool where funds have been supplied. The information returned includes a list of positions, featuring the lending pool id, and the number of tokens supplied for each position. + +Inputs: None + +Important Notes: + +- Only supported on the following networks: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the Extrafi LYF Lending series +""" + + +class ExtrafiLYFGetLendingPositionsInput(BaseModel): + """Input argument schema for getting LYF lending pool positions action.""" + + +def lyf_get_lending_positions(wallet: Wallet) -> str: + """Get user positions in the Extrafi LYF lending pools. + + Returns: + str: A message containing the user positions in the LYF lending pools. + """ + + pool_ids = get_user_lending_position_pool_ids(wallet.default_address.address_id) + if pool_ids is not None: + positions = get_lyf_lending_pool_positions(wallet, pool_ids) + if positions is not None: + reply = "Extrafi LYF Lending Pool Positions:\n" + for position in positions: + pool_id = str(position["reserveId"]) + token_address = get_pool_token_address(wallet, pool_id) + if token_address is None: + return "Error: Failed to retrieve the LYF lending pool token address.\n" + symbol = get_symbol_of(wallet, token_address) + if symbol is None: + return "Error: Failed to retrieve the LYF lending pool token symbol.\n" + decimals = get_decimals_of(wallet, token_address) + if decimals is None: + return "Error: Failed to retrieve the LYF lending pool token decimals.\n" + amount = float(position["liquidity"]) / (10 ** decimals) + reply += f"Pool ID: {position['reserveId']}, Amount: {amount} {symbol}\n" + return reply + else: + return "Error: Failed to retrieve the LYF lending pool positions.\n" + else: + return "Error: Failed to retrieve the LYF lending pool ids.\n" + + +class ExtrafiLYFGetLendingPositionsAction(CdpAction): + """Get user positions in the Extrafi LYF lending pools action.""" + + name: str = "extrafi_lyf_get_lending_positions_action" + description: str = EXTRA_LYF_GET_LENDING_POSITIONS_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFGetLendingPositionsInput + func: Callable[..., str] = lyf_get_lending_positions diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_invest_to_farming.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_invest_to_farming.py new file mode 100644 index 000000000..afb30d044 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_invest_to_farming.py @@ -0,0 +1,152 @@ +import time +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet, Transaction +from cdp_agentkit_core.actions import CdpAction +from .helper import (addresses, get_lyf_farming_vault_state, approve_token, + LYF_POSITION_MANAGER_ABI, amount_need_to_wrapped) + +EXTRA_LYF_INVEST_TO_FARMING_PROMPT = """ +This tool is used to let users invest in Extra LYF Farming. + +Before using this tool, you must first call ExtrafiLYFInvestToFarmingHelperAction to obtain the necessary parameters for this tool and have users confirm them. + +Background: +Users engage in leveraged yield farming through investment farming vaults to seek higher APR returns. In LYF scenarios, users contribute their own funds and borrow additional capital from the LYF Lending Pool for AMM liquidity mining. + +Important Notes: + +- Network Support: Only supported on "Base Mainnet" +- This tool belongs to the Extrafi LYF Farming series +- This tool only accepts parameters provided by ExtrafiLYFInvestToFarmingHelperAction +""" + + +class ExtrafiLYFInvestToFarmingInput(BaseModel): + """Input argument schema for ExtrafiLYFInvestToFarmingAction.""" + vault_id: str = Field( + ..., + description="The vault id of the LYF Farming Vault as a string representation of an integer, e.g., '18'", + ) + position_id: str = Field( + ..., + description="The existing position ID of the user's investment in the specified LYF Farming Vault as a string-encoded integer, e.g., '10'. A value of '0' indicates a new position.", + ) + amount_0_invest: str = Field( + ..., + description="The amount of token0 the user wishes to invest.", + ) + amount_0_borrow: str = Field( + ..., + description="The amount of token0 the user wishes to borrow.", + ) + amount_1_invest: str = Field( + ..., + description="The amount of token1 the user wishes to invest.", + ) + amount_1_borrow: str = Field( + ..., + description="The amount of token1 the user wishes to borrow.", + ) + + +def lyf_invest_to_farming(wallet: Wallet, vault_id: str, position_id: str, amount_0_invest: str, + amount_0_borrow: str, amount_1_invest: str, amount_1_borrow: str) -> str: + """ + Invest in the specified LYF Farming Vault. + + Returns: + str: A message containing the result of the investment. + """ + + weth_address = addresses.token_addresses[wallet.network_id]["WETH"] + position_manager_address = addresses.lyf_addresses[wallet.network_id]["VaultPositionManager"] + + try: + amount_0_invest_int = int(amount_0_invest) + amount_1_invest_int = int(amount_1_invest) + except Exception as e: + return "Error: Failed to convert the invest amount to an integer.\n" + + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return "Error: Failed to retrieve the vault state. Please check the vault id.\n" + vault_token0_address = vault_state["token0"] + vault_token1_address = vault_state["token1"] + + # Check the allowance + if amount_0_invest_int > 0: + approval_result = approve_token(wallet, vault_token0_address, position_manager_address, amount_0_invest_int) + if approval_result is None or not approval_result: + return "Error: Failed to approve token0 for spending.\n" + if amount_1_invest_int > 0: + approval_result = approve_token(wallet, vault_token1_address, position_manager_address, amount_1_invest_int) + if approval_result is None or not approval_result: + return "Error: Failed to approve token1 for spending.\n" + + eth_wrapping = 0 + if vault_token0_address == weth_address: + wrapping_amount = amount_need_to_wrapped(wallet, amount_0_invest) + if wrapping_amount is None: + return "Error: Failed to check the wrapping amount for ETH.\n" + eth_wrapping = wrapping_amount + + if vault_token1_address == weth_address: + wrapping_amount = amount_need_to_wrapped(wallet, amount_1_invest) + if wrapping_amount is None: + return "Error: Failed to check the wrapping amount for ETH.\n" + eth_wrapping = wrapping_amount + + args = { + "params": (vault_id, + position_id, + amount_0_invest, + amount_0_borrow, + amount_1_invest, + amount_1_borrow, + "0", + "0", + str(int(time.time()) + 600), + "0", + "") + } + + try: + if eth_wrapping > 0: + invocation = wallet.invoke_contract( + contract_address=position_manager_address, + method="newOrInvestToVaultPosition", + abi=LYF_POSITION_MANAGER_ABI, + args=args, + amount=str(eth_wrapping), + asset_id="wei" + ).wait() + else: + invocation = wallet.invoke_contract( + contract_address=position_manager_address, + method="newOrInvestToVaultPosition", + abi=LYF_POSITION_MANAGER_ABI, + args=args + ).wait() + + while not invocation.transaction.terminal_state: + time.sleep(1) + + if invocation.transaction.status == Transaction.Status.COMPLETE: + return (f"Success: Invested in the farming vault with transaction hash: " + f"{invocation.transaction.transaction_hash}\n") + else: + return (f"Error: Failed to invest in the farming vault with transaction hash: " + f"{invocation.transaction.transaction_hash}\n") + + except Exception as e: + return f"Error: Failed to invest in the farming vault: {e}\n" + + +class ExtrafiLYFInvestToFarmingAction(CdpAction): + """Invest in the specified LYF Farming Vault action.""" + + name: str = "extrafi_lyf_invest_to_farming_action" + description: str = EXTRA_LYF_INVEST_TO_FARMING_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFInvestToFarmingInput + func: Callable[..., str] = lyf_invest_to_farming diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_invest_to_farming_helper.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_invest_to_farming_helper.py new file mode 100644 index 000000000..202ed4613 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_invest_to_farming_helper.py @@ -0,0 +1,234 @@ +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet +from cdp_agentkit_core.actions import CdpAction +from .helper import (get_lyf_farming_vault_state, format_str_leverage_to_int, + get_decimals_of, get_balance_of, + get_user_farming_vault_positions, get_amount_out, + get_lyf_vault_borrow_available, addresses, + get_lyf_vault_related_lending_pool_ids, get_vault_address, get_lyf_farming_apy) + +EXTRA_LYF_INVEST_TO_FARMING_HELPER_PROMPT = """ +This tool calculates and generates required parameters for ExtrafiLYFInvestToFarmingAction, allowing you to proceed with the action once users confirm these parameters. + +Background: +Users engage in leveraged yield farming through invest farming vaults to seek higher APR returns. In LYF scenarios, users contribute their own funds and borrow additional capital from the LYF Lending Pool for AMM liquidity mining. + +Important Notes: + +- Network Support: Only supported "Base Mainnet" +- Each Vault contains two tokens, referred to as token0 and token1. +- Users may provide only one of these tokens. +- Users MUST give which token they wish to borrow when the leverage is greater than 1! User can borrow the same token they supply. +- Users might refer to tokens or vaults by token symbols; you need to obtain the values via ExtrafiLYFListFarmingAction. +- The tool will automatically scale the token amount to the appropriate unit, such as ERC20 decimals or Ethereum's wei. Just enter the amount in natural language. +""" + + +class ExtrafiLYFInvestToFarmingHelperInput(BaseModel): + """Input argument schema for LYF invest to farming helper action.""" + vault_id: str = Field( + ..., + description="The vault id of the LYF Farming Vault as a string representation of an integer, e.g., '18'", + ) + token0_address: str = Field( + ..., + description="The address of the token the user wishes to invest, which must be one of the two tokens in the vault, e.g., '0x9Ef15597B0B900bfceE4A77204F72bd20C85d7c8'", + ) + token0_amount: str = Field( + ..., + description="The amount of token0 the user wishes to invest. Specify the token amount as a string (e.g., '1000.01' for USDC or '0.00001' for ETH)", + ) + token1_address: str = Field( + ..., + description="The address of the token the user wishes to invest, which must be one of the two tokens in the vault. If the user wishes to invest only in one token, enter an empty string here", + ) + token1_amount: str = Field( + ..., + description="The amount of token1 the user wishes to invest. Specify the token amount as a string; if the user wishes to invest in only one token, enter an empty string here", + ) + leverage: str = Field( + ..., + description="Specify the desired leverage without exceeding the vault's maximum allowed by ExtrafiLYFListFarmingAction. The minimum leverage is 1. (e.g., '2.2' for 2.2x leverage)", + ) + borrow_token_address: str = Field( + ..., + description="When leverage is greater than 1, user MUST specify the token address to borrow. When the leverage is 1, enter an empty string here", + ) + + +def lyf_invest_to_farming_helper(wallet: Wallet, vault_id: str, token0_address: str, token0_amount: str, + token1_address: str, token1_amount: str, leverage: str, + borrow_token_address: str) -> str: + """ + Calculate and generate required parameters for LYF invest to farming action. + + Returns: + str: A message containing the required parameters for LYF invest to farming action. + """ + + # Get vault state + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return "Error: Failed to retrieve the vault state. Please check the vault id.\n" + + # check leverage: + max_leverage = vault_state["maxLeverage"] + leverage_int = format_str_leverage_to_int(leverage) + if leverage_int is None: + return "Error: Failed to convert the leverage to an integer. Please check the leverage.\n" + + if leverage_int < 100 or leverage_int > max_leverage: + return "Error: The leverage should be between 1 and max_leverage.\n" + + # check token addresses: + vault_token0_address = vault_state["token0"] + vault_token1_address = vault_state["token1"] + vault_address = get_vault_address(vault_id) + if vault_address is None: + return "Error: Failed to retrieve the vault address.\n" + pair_address = vault_state["pair"] + + if token0_address != vault_token0_address and token0_address != vault_token1_address: + return "Error: Token0 address is not in the vault.\n" + if token1_address != "" and token1_address != vault_token1_address and token1_address != vault_token0_address: + return "Error: Token1 address is not in the vault.\n" + + if token0_address == token1_address: + return "Error: Token0 and Token1 addresses are the same.\n" + + # check borrow token address: + if (leverage_int > 100 and borrow_token_address != vault_token0_address and + borrow_token_address != vault_token1_address): + return "Error: Borrow token address is not in the vault.\n" + + # Adjust the token amount to address potential issues with the incorrect order of token0 and token1. + if token0_address == vault_token1_address: + token0_amount, token1_amount = token1_amount, token0_amount + + # check ETH balance: + eth_balance_reply = "" + eth_balance = wallet.default_address.balance("wei") + weth_address = addresses.token_addresses[wallet.network_id]["WETH"] + + # check token amounts: + token0_amount_with_decimals = 0 + if token0_amount != "": + token0_decimals = get_decimals_of(wallet, vault_token0_address) + if token0_decimals is None: + return "Error: Failed to retrieve the decimals of token0.\n" + try: + token0_amount_with_decimals = int(float(token0_amount) * 10 ** token0_decimals) + except Exception as e: + return "Error: Failed to convert token0 amount to the decimal value.\n" + + token0_balance_with_decimals = get_balance_of(wallet, vault_token0_address, wallet.default_address) + if token0_balance_with_decimals is None: + return "Error: Failed to retrieve the user balance of token0.\n" + if token0_amount_with_decimals > token0_balance_with_decimals: + if vault_token0_address != weth_address or token0_amount_with_decimals > eth_balance: + return f"Error: Insufficient balance of token {vault_token0_address}.\n" + else: + eth_balance_reply = (f"Not enough WETH left, ExtrafiLYFInvestToFarmingAction will wrap " + f"{token0_amount_with_decimals} wei ETH balance for User.\n") + + token1_amount_with_decimals = 0 + if token1_amount != "": + token1_decimals = get_decimals_of(wallet, vault_token1_address) + if token1_decimals is None: + return "Error: Failed to retrieve the decimals of token1.\n" + try: + token1_amount_with_decimals = int(float(token1_amount) * 10 ** token1_decimals) + except Exception as e: + return "Error: Failed to convert token1 amount to the decimal value.\n" + + token1_balance_with_decimals = get_balance_of(wallet, vault_token1_address, wallet.default_address) + if token1_balance_with_decimals is None: + return "Error: Failed to retrieve the user balance of token1.\n" + if token1_amount_with_decimals > token1_balance_with_decimals: + if vault_token1_address != weth_address or token1_amount_with_decimals > eth_balance: + return f"Error: Insufficient balance of token {vault_token1_address}.\n" + else: + eth_balance_reply = (f"Not enough WETH left, ExtrafiLYFInvestToFarmingAction will wrap " + f"{token1_amount_with_decimals} wei ETH balance for User.\n") + + # get existed position id + positions = get_user_farming_vault_positions(wallet.default_address.address_id, vault_id) + if positions is None: + return "Error: Failed to retrieve the existing farming vault positions. \n" + + if len(positions) > 0: + position_id = str(positions[0]["vaultPositionId"]) + else: + position_id = "0" + + # calculate borrow amount + # calculate all invest token amount in token0 + token1_amount_in_token0 = 0 + if token1_amount_with_decimals != 0: + token1_amount_in_token0 = get_amount_out(wallet, + pair_address, + vault_token1_address, + str(token1_amount_with_decimals)) + total_amount_in_token0 = token0_amount_with_decimals + token1_amount_in_token0 + borrow_amount_in_token0 = (leverage_int - 100) * total_amount_in_token0 // 100 + borrow_amount_in_token1 = 0 + if borrow_token_address == vault_token1_address: + borrow_amount_in_token1 = get_amount_out(wallet, + pair_address, + vault_token0_address, + str(borrow_amount_in_token0)) + borrow_amount_in_token0 = 0 + + related_lending_pool_ids = get_lyf_vault_related_lending_pool_ids(wallet, vault_id) + if related_lending_pool_ids is None: + return "Error: Failed to retrieve the lending pool ids related to the farming vault's debts.\n" + if borrow_amount_in_token0 != 0: + token0_available_for_borrow = get_lyf_vault_borrow_available(wallet, + related_lending_pool_ids[0], + vault_address) + if token0_available_for_borrow is None: + return "Error: Failed to retrieve the available borrow amount of token0.\n" + if borrow_amount_in_token0 > token0_available_for_borrow: + return (f"Error: Insufficient available borrow amount of token0, the available amount is " + f"{token0_available_for_borrow}, but the required amount is {borrow_amount_in_token0}, " + f"try to reduce the leverage or borrow another token instead\n") + if borrow_amount_in_token1 != 0: + token1_available_for_borrow = get_lyf_vault_borrow_available(wallet, + related_lending_pool_ids[1], + vault_address) + if token1_available_for_borrow is None: + return "Error: Failed to retrieve the available borrow amount of token1.\n" + if borrow_amount_in_token1 > token1_available_for_borrow: + return (f"Error: Insufficient available borrow amount of token1, the available amount is " + f"{token1_available_for_borrow}, but the required amount is {borrow_amount_in_token1}, " + f"try to reduce the leverage or borrow another token instead\n") + + apy = get_lyf_farming_apy(wallet, vault_id, token0_amount_with_decimals, + borrow_amount_in_token0, token1_amount_with_decimals, + borrow_amount_in_token1, leverage_int) + if apy is None: + return "Error: Failed to retrieve the APY of the farming vault.\n" + apy = apy * 100 + + reply = f"ExtrafiLYFInvestToFarmingInput parameters generated:\n" + reply += (f"vault_id: {vault_id}, vault_position_id: {position_id}, " + f"amount_0_invest: {token0_amount_with_decimals}, " + f"amount_0_borrow: {borrow_amount_in_token0}, " + f"amount_1_invest: {token1_amount_with_decimals}, " + f"amount_1_borrow: {borrow_amount_in_token1}, " + f"amount_0_min: 0, amount_1_min: 0\n\n") + reply += (f"Other information:\n" + f"APY calculated: {apy}%\n") + if eth_balance_reply != "": + reply += eth_balance_reply + return reply + + +class ExtrafiLYFInvestToFarmingHelperAction(CdpAction): + """Generate required parameters for LYF invest to farming action.""" + + name: str = "extrafi_lyf_invest_to_farming_helper_action" + description: str = EXTRA_LYF_INVEST_TO_FARMING_HELPER_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFInvestToFarmingHelperInput + func: Callable[..., str] = lyf_invest_to_farming_helper diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_lending_apr.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_lending_apr.py new file mode 100644 index 000000000..4c7252cfe --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_lending_apr.py @@ -0,0 +1,57 @@ +import json +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp_agentkit_core.actions import CdpAction +from .helper import get_apr_change_for_lyf_lending_pool + + +EXTRA_LYF_LENDING_APR_PROMPT = """ +This tool is designed to list the APR changes of a specific LYF Lending Pool, useful for users who wish to check if the APR of a lending pool is stable. You can summarize this data. + +Inputs: +- Pool id +(Hint: Users often provide a token symbol. Use tool ExtrafiLYFListLending to obtain the Pool id. If multiple pool ids exist for the same symbol, select the one with the highest APR.) + +Output: +Includes basic information about the Lending Pool and a list of APRs with timestamps. + +Important Notes: + +- Network Support: Only supported on the following networks: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the Extrafi LYF Lending series +- APR Format: APR values are expressed as decimals, e.g., 0.05 indicates a 5% annualized rate. +- When communicating with users, you can use UTC time for clarity instead of directly using timestamps. +""" + + +class ExtrafiLYFLendingAPRInput(BaseModel): + """Input argument schema for LYF lending APR action.""" + pool_id: str = Field( + ..., + description="The pool id of the LYF Lending Pool as a string representation of an integer, e.g., '20'", + ) + + +def lyf_lending_apr(pool_id: str) -> str: + """Get the historical APR data of specified Extrafi LYF lending pool. + + Returns: + str: A message containing the historical APR data. + """ + apr = get_apr_change_for_lyf_lending_pool(pool_id) + if apr is not None: + reply = "Extrafi LYF Lending Pool APR:\n" + reply += json.dumps(apr, indent=4) + return reply + else: + return "Error: Failed to retrieve the LYF lending pool APR.\n" + + +class ExtrafiLYFLendingAPRAction(CdpAction): + """Get historical APR data for one Extrafi LYF lending pool.""" + + name: str = "extrafi_lyf_lending_apr_action" + description: str = EXTRA_LYF_LENDING_APR_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFLendingAPRInput + func: Callable[..., str] = lyf_lending_apr diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_list_farming.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_list_farming.py new file mode 100644 index 000000000..1c0a2865a --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_list_farming.py @@ -0,0 +1,56 @@ +from collections.abc import Callable +from pydantic import BaseModel +from cdp_agentkit_core.actions import CdpAction +from cdp import Wallet +from .helper import get_lyf_farming_vaults_info, format_int_leverage_to_str + + +EXTRA_LYF_LIST_FARMING_PROMPT = """ +This tool lists all Farming Vaults supported by Extrafi LYF (Leveraged Yield Farming), which enable users to engage in LYF. It provides details such as the vault's address, AMM pair symbol, stability status of the pair, addresses of the tokens in the pair, the APR (as a percentage), and the TVL (Total Value Locked) in US dollars. + +Input: +None. + +Important Notes: + +- LYF Vault Definition: Users borrow tokens from the LYF Lending Pool to pair with their tokens for leveraged yield farming. Risks include increased debt ratios due to rising values of borrowed tokens, potentially leading to liquidation if thresholds are exceeded. Additionally, the volatility of the token pair may cause impermanent losses. +- Stable Definition: Vaults with tokens that have correlated values (e.g., wstETH and ETH, USDC and USDz) are marked as stable. +- Supported only on: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the Extrafi LYF Farming series +""" + + +class ExtrafiLYFListFarmingInput(BaseModel): + """Input argument schema for LYF list farming action.""" + + +def lyf_list_farming(wallet: Wallet) -> str: + """List all the farming vaults supported by Extrafi LYF (Leveraged Yield Farming). + + Returns: + str: A message containing the farming vaults information. + """ + vaults = get_lyf_farming_vaults_info(wallet) + if vaults is not None: + reply = "Extrafi LYF Farming Vaults Information:\n" + for vault in vaults: + max_leverage = format_int_leverage_to_str(vault["max_leverage"]) + reply += (f"Vault id: {vault['vault_id']}, Vault Symbol: {vault['symbol']}, " + f"Vault Address: {vault['vault_address']}, " + f"Stable Pair: {vault['stable']}, Token0 address: {vault['token0']}, " + f"Token0 Symbol: {vault['token0_symbol']}, Token1 address: {vault['token1']}, " + f"Token1 Symbol: {vault['token1_symbol']}, " + f"Max leverage: {max_leverage}, APR: {vault['apr']}%, TVL: ${vault['tvl']}\n") + return reply + else: + return "Error: Failed to retrieve the LYF farming vaults information.\n" + + +class ExtrafiLYFListFarmingAction(CdpAction): + """Get Extrafi LYF farming vaults action.""" + + name: str = "extrafi_lyf_list_farming_action" + description: str = EXTRA_LYF_LIST_FARMING_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFListFarmingInput + func: Callable[..., str] = lyf_list_farming diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_list_lending.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_list_lending.py new file mode 100644 index 000000000..99e20b94a --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_list_lending.py @@ -0,0 +1,55 @@ +from collections.abc import Callable +from pydantic import BaseModel +from cdp_agentkit_core.actions import CdpAction +from .helper import get_concise_lyf_lending_pool_info + + +EXTRA_LYF_LIST_LENDING_PROMPT = """ +This tool lists all lending pools supported by Extrafi LYF (Leveraged Yield Farming), providing details such as pool id, token symbol, token address, and the latest APR. + +Input: +None. + +This tool is typically used to provide users with information to help them decide which pool to fund. Generally, users make their decision based on: + +1. Whether they possess tokens related to the pool; +2. Whether the APR of the pool meets their income expectations; +3. Risk factors, especially if tokens are mainstream and relatively price-stable + +Important Notes: + +- LYF Lending Pool Definition: These are sources of funds for leveraged yield farming, with APRs based on borrowing demands. It is crucial to differentiate LYF Lending Pools from Xlend's Supply Pools. +- Only supported on the following networks: + - Base Mainnet (ie, 'base', 'base-mainnnet') +- This tool belongs to the Extrafi LYF Lending series +- APR Format: APR values are decimal, e.g., 0.05 indicates a 5% annualized rate. +""" + + +class ExtrafiLYFListLendingInput(BaseModel): + """Input argument schema for lyf list lending action.""" + + +def lyf_list_lending() -> str: + """List all the lending pools supported by Extrafi LYF (Leveraged Yield Farming). + + Returns: + str: A message containing the lending pools information. + """ + pools = get_concise_lyf_lending_pool_info() + if pools is not None: + reply = "Extrafi LYF Lending Pools Information:\n" + for pool in pools: + reply += f"Pool ID: {pool['pool_id']}, Symbol: {pool['symbol']}, Token Address: {pool['address']}, APR: {pool['apr']}\n" + return reply + else: + return "Error: Failed to retrieve the lyf lending pools information.\n" + + +class ExtrafiLYFListLendingAction(CdpAction): + """Get Extrafi LYF lending pools action.""" + + name: str = "extrafi_lyf_list_lending_action" + description: str = EXTRA_LYF_LIST_LENDING_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFListLendingInput + func: Callable[..., str] = lyf_list_lending diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_repay_farming_debt.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_repay_farming_debt.py new file mode 100644 index 000000000..b05ab3d40 --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_repay_farming_debt.py @@ -0,0 +1,161 @@ +import time +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet, Transaction +from cdp_agentkit_core.actions import CdpAction +from .helper import (addresses, approve_token, amount_need_to_wrapped, get_lyf_farming_vault_state, + LYF_POSITION_MANAGER_ABI, get_decimals_of, check_balance_sufficiency, get_symbol_of) + + +EXTRA_LYF_REPAY_FARMING_DEBT_PROMPT = """ +This tool is used to let users repay the specified token debt in the specified Extra LYF Farming Vault, position. + +Tool ExtrafiLYFListFarmingAction can help you get the user's existing Farming position information, so you can determine the input parameters needed for this tool. + +Important Notes: +- Network Support: Only supported on "Base Mainnet" +- This tool belongs to the Extrafi LYF Farming series +- Users must have enough tokens to repay the Repay Amount in the parameters. If the repaid tokens are more than the actual debt in the smart contract, the contract will automatically refund the excess tokens. +- Users might refer to tokens or vaults by token symbols; you need to obtain the values via ExtrafiLYFListFarmingAction. +- The tool will automatically scale the token amount to the appropriate unit, such as ERC20 decimals or Ethereum's wei. Just enter the amount in natural language. +""" + + +class ExtrafiLYFRepayFarmingDebtInput(BaseModel): + """Input argument schema for ExtrafiLYFRepayFarmingDebtAction.""" + vault_id: str = Field( + ..., + description="The vault id of the LYF Farming Vault as a string representation of an integer, e.g., '18'", + ) + position_id: str = Field( + ..., + description="The position ID of the user's investment in the specified LYF Farming Vault as a string-encoded integer, e.g., '10'.", + ) + amount0_repay: str = Field( + ..., + description="The amount of token0 the user wishes to repay. Specify the token amount as a string (e.g., '1000.01' for USDC or '0.00001' for ETH)", + ) + amount1_repay: str = Field( + ..., + description="The amount of token1 the user wishes to repay. Specify the token amount as a string (e.g., '1000.01' for USDC or '0.00001' for ETH)", + ) + + +def get_amount_without_decimals(wallet: Wallet, token_address: str, amount: str) -> int | None: + """Get the amount without decimals for the token.""" + decimals = get_decimals_of(wallet, token_address) + if decimals is None: + return None + try: + amount_without_decimals = int(float(amount) * 10 ** decimals) + return amount_without_decimals + except Exception as e: + return None + + +def lyf_repay_farming_debt(wallet: Wallet, vault_id: str, position_id: str, + amount0_repay: str, amount1_repay: str) -> str: + """ + Repay the specified token debt in the specified Extra LYF Farming Vault, position. + """ + + vault_state = get_lyf_farming_vault_state(wallet, vault_id) + if vault_state is None: + return "Error: Failed to retrieve the vault state. Please check the vault id.\n" + vault_token0_address = vault_state["token0"] + vault_token1_address = vault_state["token1"] + token0_symbol = get_symbol_of(wallet, vault_token0_address) + if token0_symbol is None: + return "Error: Failed to retrieve the token0 symbol.\n" + token1_symbol = get_symbol_of(wallet, vault_token1_address) + if token1_symbol is None: + return "Error: Failed to retrieve the token1 symbol.\n" + + weth_address = addresses.token_addresses[wallet.network_id]["WETH"] + position_manager_address = addresses.lyf_addresses[wallet.network_id]["VaultPositionManager"] + + amount0_repay_ = get_amount_without_decimals(wallet, vault_token0_address, amount0_repay) + if amount0_repay_ is None: + return "Error: Failed to convert the token0 repay amount to an integer.\n" + amount1_repay_ = get_amount_without_decimals(wallet, vault_token1_address, amount1_repay) + if amount1_repay_ is None: + return "Error: Failed to convert the token1 repay amount to an integer.\n" + + # Check the allowance + eth_wrapping = 0 + if amount0_repay_ > 0: + ok = check_balance_sufficiency(wallet, vault_token0_address, str(amount0_repay_)) + if ok is None: + return f"Error: Failed to check the balance sufficiency for {token0_symbol}.\n" + if not ok: + return f"Error: Insufficient balance for {token0_symbol}.\n" + approval_result = approve_token(wallet, vault_token0_address, position_manager_address, amount0_repay_) + if approval_result is None or not approval_result: + return f"Error: Failed to approve {token0_symbol} for spending.\n" + if vault_token0_address == weth_address: + wrapping_amount = amount_need_to_wrapped(wallet, str(amount0_repay_)) + if wrapping_amount is None: + return "Error: Failed to check the wrapping amount for ETH.\n" + eth_wrapping = wrapping_amount + if amount1_repay_ > 0: + ok = check_balance_sufficiency(wallet, vault_token1_address, str(amount1_repay_)) + if ok is None: + return f"Error: Failed to check the balance sufficiency for {token1_symbol}.\n" + if not ok: + return f"Error: Insufficient balance for {token1_symbol}.\n" + approval_result = approve_token(wallet, vault_token1_address, position_manager_address, amount1_repay_) + if approval_result is None or not approval_result: + return f"Error: Failed to approve {token0_symbol} for spending.\n" + if vault_token1_address == weth_address: + wrapping_amount = amount_need_to_wrapped(wallet, str(amount1_repay_)) + if wrapping_amount is None: + return "Error: Failed to check the wrapping amount for ETH.\n" + eth_wrapping = wrapping_amount + + args = { + "params": (vault_id, + position_id, + str(amount0_repay_), + str(amount1_repay_), + True, + str(int(time.time()) + 600)) + } + + try: + if eth_wrapping > 0: + invocation = wallet.invoke_contract( + contract_address=position_manager_address, + method="exactRepay", + abi=LYF_POSITION_MANAGER_ABI, + args=args, + amount=str(eth_wrapping), + asset_id="wei" + ).wait() + else: + invocation = wallet.invoke_contract( + contract_address=position_manager_address, + method="exactRepay", + abi=LYF_POSITION_MANAGER_ABI, + args=args + ).wait() + + while not invocation.transaction.terminal_state: + time.sleep(1) + + if invocation.transaction.status == Transaction.Status.COMPLETE: + return (f"Successfully repaid the debt in the farming vault with transaction hash: " + f"{invocation.transaction.transaction_hash}\n") + else: + return f"Error: Failed to repay the debt in the farming vault.\n" + + except Exception as e: + return f"Error: {str(e)}. Failed to repay the debt in the farming vault.\n" + + +class ExtrafiLYFRepayFarmingDebtAction(CdpAction): + """Action to repay the specified token debt in the specified Extra LYF Farming Vault, position.""" + + name: str = "extrafi_lyf_repay_farming_debt_action" + description: str = EXTRA_LYF_REPAY_FARMING_DEBT_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFRepayFarmingDebtInput + func: Callable[..., str] = lyf_repay_farming_debt diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_supply_to_lending.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_supply_to_lending.py new file mode 100644 index 000000000..12e373cef --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_supply_to_lending.py @@ -0,0 +1,113 @@ +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet +from cdp_agentkit_core.actions import CdpAction +from .helper import (get_pool_token_address, get_balance_of, get_decimals_of, token_addresses, lyf_addresses, + LYF_LENDING_POOL_ABI) + +EXTRA_LYF_SUPPLY_TO_LENDING_PROMPT = """ +This tool facilitates supplying capital to the Extrafi LYF Lending Pool through a series of on-chain operations to earn interests. + +Inputs: + +- Pool id: Users typically provide the token symbol. You should use tool ExtrafiLYFListLending to retrieve the Pool id. If multiple pool ids exist for the same symbol, choose the one with the highest APR. +- Amount: Amount: Specify the token amount as a string (e.g., "1000.01" for USDC or "0.00001" for ETH). The tool will automatically scale this value to the appropriate unit, such as ERC20 decimals or Ethereum's wei. + +Important Notes: + +- Network Support: Only supported on the following networks: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the Extrafi LYF Lending series +- WETH Pool Selection: If a WETH pool is selected and the user does not have sufficient WETH, the tool will assist in wrapping ETH to WETH automatically, do not ask user to swap or wrap first. +- When returning blockchain explorer url, use https://basescan.org/tx/ as the prefix. +""" + + +class ExtrafiLYFSupplyToLendingInput(BaseModel): + """Input argument schema for LYF supply to lending pool action.""" + pool_id: str = Field( + ..., + description="The pool id of the LYF Lending Pool as a string representation of an integer, e.g., '20'", + ) + amount: str = Field( + ..., + description="The amount without decimals to supply to the LYF Lending Pool as a string representation of a float, e.g., '10.01'", + ) + + +def lyf_supply_to_lending(wallet: Wallet, pool_id: str, amount: str) -> str: + """Supply capital to the LYF lending pool. + + Returns: + str: A message containing the result of supplying. + """ + + # Get the token address of the pool + token_address = get_pool_token_address(wallet, pool_id) + if token_address is None: + return "Error: Failed to retrieve the token address of the pool.\n" + + # get the balance and decimals + decimals = get_decimals_of(wallet, token_address) + if decimals is None: + return "Error: Failed to retrieve the decimals of the token.\n" + balance = get_balance_of(wallet, token_address, wallet.default_address) + if balance is None: + return "Error: Failed to retrieve the user balance of the token.\n" + + # Convert the amount to the decimal value + wrap_eth = False + amount_with_decimals = int(float(amount) * 10 ** decimals) + if amount_with_decimals > balance: + if token_address != token_addresses["base-mainnet"]["WETH"]: + return "Error: Insufficient balance to supply to the pool.\n" + else: + eth_balance = wallet.balance("wei") + if amount_with_decimals >= eth_balance: + return "Error: Insufficient ETH balance to wrap to WETH.\n" + else: + wrap_eth = True + + # Supply to the pool + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + if wrap_eth: + invocation = wallet.invoke_contract( + contract_address=lending_pool_address, + method="depositAndStake", + abi=LYF_LENDING_POOL_ABI, + args={ + "reserveId": pool_id, + "amount": str(amount_with_decimals), + "onBehalfOf": wallet.default_address.address_id, + "referralCode": "0", + }, + amount=str(amount_with_decimals), + asset_id="wei" + ).wait() + return f"Supplied to lending pool with transaction hash: {invocation.transaction.transaction_hash}\n" + else: + invocation = wallet.invoke_contract( + contract_address=lending_pool_address, + method="depositAndStake", + abi=LYF_LENDING_POOL_ABI, + args={ + "reserveId": pool_id, + "amount": str(amount_with_decimals), + "onBehalfOf": wallet.default_address.address_id, + "referralCode": "0", + } + ).wait() + return f"Supplied to lending pool with transaction hash: {invocation.transaction.transaction_hash}\n" + + except Exception as e: + return f"Error supplying to the pool {e!s}\n" + + +class ExtrafiLYFSupplyToLendingAction(CdpAction): + """Supply to Extrafi LYF lending pools action.""" + + name: str = "extrafi_lyf_supply_to_lending_action" + description: str = EXTRA_LYF_SUPPLY_TO_LENDING_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFSupplyToLendingInput + func: Callable[..., str] = lyf_supply_to_lending diff --git a/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_withdraw_from_lending.py b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_withdraw_from_lending.py new file mode 100644 index 000000000..196f2bcaa --- /dev/null +++ b/cdp-agentkit-core/python/cdp_agentkit_core/actions/extra/lyf_withdraw_from_lending.py @@ -0,0 +1,110 @@ +from collections.abc import Callable +from pydantic import BaseModel, Field +from cdp import Wallet +from cdp_agentkit_core.actions import CdpAction +from .helper import (get_lyf_lending_pool_positions, get_pool_token_address, get_decimals_of, lyf_addresses, + LYF_LENDING_POOL_ABI) + +EXTRA_LYF_WITHDRAW_FROM_LENDING_PROMPT = """ +This tool is used to withdraw funds from an existing position in the Extrafi LYF Lending Pool, provided that the user has previously supplied funds to the respective lending pool. + +Inputs: + +- Pool id: Users typically provide the token symbol. You should use the ExtrafiLYFGetLendingPositionsAction tool to find the corresponding pool id. +- Amount: Specify the token amount as a string (e.g., "1000.01" for USDC or "0.00001" for ETH). The amount must not exceed the amount in the corresponding position reported by the ExtrafiLYFGetLendingPositionsAction tool. The tool will automatically scale this value to the appropriate unit, such as ERC20 decimals or Ethereum's wei. + +Important Notes: + +- Only supported on the following networks: + - Base Mainnet (i.e., 'base', 'base-mainnet') +- This tool belongs to the Extrafi LYF Lending series +- When returning blockchain explorer url, use https://basescan.org/tx/ as the prefix. +""" + + +class ExtrafiLYFWithdrawFromLendingInput(BaseModel): + """Input argument schema for LYF withdraw from lending pool action.""" + pool_id: str = Field( + ..., + description="The pool id of the LYF Lending Pool as a string representation of an integer, e.g., '20'", + ) + amount: str = Field( + ..., + description="The amount without decimals to supply to the LYF Lending Pool as a string representation of a float, e.g., '10.01'", + ) + + +def get_etoken_amount(total_liquidity: int, etoken_staked: int, decimals: int, amount: str) -> int | None: + """Get the amount of eToken to withdraw from the pool.""" + try: + # Convert the amount to the decimal value + amount_with_decimals = int(float(amount) * 10 ** decimals) + if amount_with_decimals > total_liquidity: + return None + quote = float(amount_with_decimals) / float(total_liquidity) + if quote > 0.9: + return etoken_staked + etoken_amount = int(amount_with_decimals * etoken_staked / total_liquidity) + if etoken_amount > etoken_staked: + return etoken_staked + return etoken_amount + except Exception as e: + return None + + +def lyf_withdraw_from_lending(wallet: Wallet, pool_id: str, amount: str) -> str: + """Withdraw funds from the LYF lending pool. + + Returns: + str: A message containing the result of withdrawing. + """ + + # Get user positions + positions = get_lyf_lending_pool_positions(wallet, [pool_id]) + if positions is None: + return ("Error: Failed to retrieve the user positions in the LYF lending pool. " + "User may not have such position in this pool id.\n") + + position = positions[0] + + # Get the token address of the pool + token_address = get_pool_token_address(wallet, pool_id) + if token_address is None: + return "Error: Failed to retrieve the token address of the pool.\n" + + # get the decimals + decimals = get_decimals_of(wallet, token_address) + if decimals is None: + return "Error: Failed to retrieve the decimals of the token.\n" + + # Get the amount of eToken to withdraw + etoken_amount = get_etoken_amount(position["liquidity"], position["eTokenStaked"], decimals, amount) + if etoken_amount is None: + return "Error: Failed to calculate the eToken amount to withdraw. Please check the amount.\n" + + # Withdraw from the pool + try: + lending_pool_address = lyf_addresses[wallet.network_id]["LendingPoolContractAddress"] + invocation = wallet.invoke_contract( + contract_address=lending_pool_address, + method="unStakeAndWithdraw", + abi=LYF_LENDING_POOL_ABI, + args={ + "reserveId": pool_id, + "eTokenAmount": str(etoken_amount), + "to": wallet.default_address.address_id, + "receiveNativeETH": True, + } + ).wait() + return f"Withdrawn from lending pool with transaction hash: {invocation.transaction.transaction_hash}\n" + except Exception as e: + return f"Error withdrawing from the pool {e!s}\n" + + +class ExtrafiLYFWithdrawFromLendingAction(CdpAction): + """Withdraw funds from the Extrafi LYF Lending Pool action.""" + + name: str = "extrafi_lyf_withdraw_from_lending_action" + description: str = EXTRA_LYF_WITHDRAW_FROM_LENDING_PROMPT + args_schema: type[BaseModel] | None = ExtrafiLYFWithdrawFromLendingInput + func: Callable[..., str] = lyf_withdraw_from_lending