From b34505dbeb4fc821c1c20dbc446cc4ec4801c268 Mon Sep 17 00:00:00 2001 From: anhnv Date: Thu, 19 Dec 2024 13:11:02 +0700 Subject: [PATCH 1/3] WIP: tempest swell usde integration --- .env.example | 1 + constants/chains.py | 1 + constants/summary_columns.py | 2 ++ integrations/integration_ids.py | 8 ++++++++ utils/web3_utils.py | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/.env.example b/.env.example index 67d6f77..cde6c7d 100644 --- a/.env.example +++ b/.env.example @@ -5,5 +5,6 @@ SCROLL_NODE_URL='https://rpc.scroll.io' MODE_NODE_URL='https://mainnet.mode.network' FRAXTAL_NODE_URL='https://rpc.frax.com' LYRA_NODE_URL='https://rpc.derive.xyz' +SWELL_NODE_URL='https://rpc.scroll.io' DERIVE_SUBGRAPH_API_KEY='' \ No newline at end of file diff --git a/constants/chains.py b/constants/chains.py index 7b0c8d3..5ec0ac3 100644 --- a/constants/chains.py +++ b/constants/chains.py @@ -11,3 +11,4 @@ class Chain(Enum): MODE = "Mode" OPTIMISM = "Optimism" Lyra = "Lyra" + SWELL = "Scroll" diff --git a/constants/summary_columns.py b/constants/summary_columns.py index e0c35b4..0273744 100644 --- a/constants/summary_columns.py +++ b/constants/summary_columns.py @@ -38,6 +38,8 @@ class SummaryColumn(Enum): "beefy_cached_balance_example", SummaryColumnType.ETHENA_PTS, ) + + TEMPEST_SWELL_SHARDS = ("tempest_swell_shards", SummaryColumnType.ETHENA_PTS) def __init__(self, column_name: str, col_type: SummaryColumnType): self.column_name = column_name diff --git a/integrations/integration_ids.py b/integrations/integration_ids.py index 86e9618..71d26a5 100644 --- a/integrations/integration_ids.py +++ b/integrations/integration_ids.py @@ -396,6 +396,14 @@ class IntegrationID(Enum): # Upshift sUSDe UPSHIFT_UPSUSDE = ("upshift_upsusde", "Upshift upsUSDe", Token.SUSDE) + + # Tempest Finance + TEMPEST_SWELL_USDE = ( + "tempest_swell_usde_held", + "Tempest Swell USDe", + Token.USDE, + ) + def __init__(self, column_name: str, description: str, token: Token = Token.USDE): self.column_name = column_name self.description = description diff --git a/utils/web3_utils.py b/utils/web3_utils.py index c8150ef..6c2366c 100644 --- a/utils/web3_utils.py +++ b/utils/web3_utils.py @@ -29,6 +29,8 @@ w3_fraxtal = Web3(Web3.HTTPProvider(FRAXTAL_NODE_URL)) LYRA_NODE_URL = os.getenv("LYRA_NODE_URL") w3_lyra = Web3(Web3.HTTPProvider(LYRA_NODE_URL)) +SWELL_NODE_URL = os.getenv("SWELL_NODE_URL") +w3_swell = Web3(Web3.HTTPProvider(SWELL_NODE_URL)) W3_BY_CHAIN = { Chain.ETHEREUM: { @@ -55,6 +57,9 @@ Chain.Lyra: { "w3": w3_lyra, }, + Chain.SWELL: { + "w3": w3_swell, + }, } @@ -84,6 +89,10 @@ MULTICALL_ADDRESS = ( "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696" # Ethereum mainnet address ) +MULTICALL_ADDRESS_BY_CHAIN = { + Chain.SWELL: "0xcA11bde05977b3631167028862bE2a173976CA11", + Chain.SCROLL: "0xcA11bde05977b3631167028862bE2a173976CA11" +} def fetch_events_logs_with_retry( @@ -151,3 +160,27 @@ def multicall(w3: Web3, calls: list, block_identifier: BlockIdentifier = "latest decoded_results.append(decode(output_types, result[1][i])) return decoded_results + +def multicall_by_address(w3: Web3, multical_address: str, calls: list, block_identifier: BlockIdentifier = "latest"): + multicall_contract = w3.eth.contract( + address=Web3.to_checksum_address(multical_address), abi=MULTICALL_ABI + ) + + aggregate_calls = [] + for call in calls: + contract, fn_name, args = call + call_data = contract.encodeABI(fn_name=fn_name, args=args) + aggregate_calls.append((contract.address, call_data)) + + result = multicall_contract.functions.aggregate(aggregate_calls).call( + block_identifier=block_identifier + ) + + decoded_results = [] + for i, call in enumerate(calls): + contract, fn_name, _ = call + function = contract.get_function_by_name(fn_name) + output_types = [output["type"] for output in function.abi["outputs"]] + decoded_results.append(decode(output_types, result[1][i])) + + return decoded_results From 4949181144f962239cd096de97d3f372a7eee401 Mon Sep 17 00:00:00 2001 From: anhnv Date: Thu, 19 Dec 2024 13:13:32 +0700 Subject: [PATCH 2/3] WIP: tempest swell usde integration --- abi/tempest_symmetric_vault.json | 1236 ++++++++++++++++++++++++++++ constants/tempest.py | 15 + integrations/tempest_swell_usde.py | 128 +++ 3 files changed, 1379 insertions(+) create mode 100644 abi/tempest_symmetric_vault.json create mode 100644 constants/tempest.py create mode 100644 integrations/tempest_swell_usde.py diff --git a/abi/tempest_symmetric_vault.json b/abi/tempest_symmetric_vault.json new file mode 100644 index 0000000..7e8040c --- /dev/null +++ b/abi/tempest_symmetric_vault.json @@ -0,0 +1,1236 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { "inputs": [], "name": "AccessControlBadConfirmation", "type": "error" }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "bytes32", "name": "neededRole", "type": "bytes32" } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "allowance", "type": "uint256" }, + { "internalType": "uint256", "name": "needed", "type": "uint256" } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "uint256", "name": "balance", "type": "uint256" }, + { "internalType": "uint256", "name": "needed", "type": "uint256" } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "approver", "type": "address" } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "receiver", "type": "address" } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { "inputs": [], "name": "FailedCall", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "balance", "type": "uint256" }, + { "internalType": "uint256", "name": "needed", "type": "uint256" } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { "inputs": [], "name": "InvalidInitialization", "type": "error" }, + { "inputs": [], "name": "NotInitializing", "type": "error" }, + { "inputs": [], "name": "ReentrancyGuardReentrantCall", "type": "error" }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "SafeERC20FailedOperation", + "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": false, + "internalType": "int24", + "name": "baseWidth", + "type": "int24" + }, + { + "indexed": false, + "internalType": "int24", + "name": "limitWidth", + "type": "int24" + } + ], + "name": "BaseAndLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "DepositPauseToggled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "assets", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Deposits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "fee", + "type": "uint16" + } + ], + "name": "FeesSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "investedPercentage", + "type": "uint16" + } + ], + "name": "InvestedPercentageSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "liqSlippage", + "type": "uint16" + } + ], + "name": "LiqSlippageSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "MinimumDepositSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newValue", + "type": "address" + } + ], + "name": "OperatorPathSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oracle", + "type": "address" + } + ], + "name": "OracleSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "padding", + "type": "uint8" + } + ], + "name": "PaddingSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int24[]", + "name": "oldUpperTicks", + "type": "int24[]" + }, + { + "indexed": false, + "internalType": "int24[]", + "name": "oldLowerTicks", + "type": "int24[]" + }, + { + "indexed": false, + "internalType": "int24[]", + "name": "newUpperTicks", + "type": "int24[]" + }, + { + "indexed": false, + "internalType": "int24[]", + "name": "newLowerTicks", + "type": "int24[]" + } + ], + "name": "Rebalance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "swapSlippage", + "type": "uint16" + } + ], + "name": "SwapSlippageSet", + "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": "newValue", + "type": "address" + } + ], + "name": "UserPathSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "WithdrawPausedToggled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "WithdrawWithoutSwap", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "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": "value", "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": "baseWidth", + "outputs": [{ "internalType": "int24", "name": "", "type": "int24" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountToken1", "type": "uint256" } + ], + "name": "calculateAmount0ForAmount1", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountToken0", "type": "uint256" } + ], + "name": "calculateAmount1ForAmount0", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "shares", "type": "uint256" } + ], + "name": "convertToAssets", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "convertToShares", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "crocsQuery", + "outputs": [ + { "internalType": "contract CrocsQuery", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "crocsSwapDex", + "outputs": [ + { "internalType": "contract CrocsSwapDex", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTick", + "outputs": [{ "internalType": "int24", "name": "", "type": "int24" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "deposit", + "outputs": [ + { "internalType": "uint256", "name": "shares", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "deposits", + "outputs": [ + { "internalType": "uint256", "name": "shares", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "fee", + "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLpParams", + "outputs": [ + { + "components": [ + { "internalType": "int24", "name": "upperTick", "type": "int24" }, + { "internalType": "int24", "name": "lowerTick", "type": "int24" } + ], + "internalType": "struct LpParam[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "int24", "name": "_upperTick", "type": "int24" }, + { "internalType": "int24", "name": "_lowerTick", "type": "int24" } + ], + "name": "getPosition", + "outputs": [ + { "internalType": "uint128", "name": "", "type": "uint128" }, + { "internalType": "uint128", "name": "", "type": "uint128" }, + { "internalType": "uint128", "name": "", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPositions", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0Invested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Invested", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amount0Idle", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1Idle", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" } + ], + "name": "getRoleAdmin", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenAddresses", + "outputs": [ + { "internalType": "address[2]", "name": "", "type": "address[2]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "hasRole", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "string", "name": "name", "type": "string" }, + { "internalType": "string", "name": "symbol", "type": "string" }, + { "internalType": "uint8", "name": "assetIdx", "type": "uint8" }, + { "internalType": "uint8", "name": "cmdId", "type": "uint8" }, + { "internalType": "uint8", "name": "padding", "type": "uint8" }, + { "internalType": "uint16", "name": "fee", "type": "uint16" }, + { + "internalType": "uint16", + "name": "investedPercentage", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "swapSlippage", + "type": "uint16" + }, + { "internalType": "uint16", "name": "liqSlippage", "type": "uint16" }, + { + "internalType": "address", + "name": "feeRecipient", + "type": "address" + }, + { "internalType": "address", "name": "token0", "type": "address" }, + { "internalType": "address", "name": "token1", "type": "address" }, + { "internalType": "address", "name": "governor", "type": "address" }, + { "internalType": "address", "name": "cQuery", "type": "address" }, + { "internalType": "address", "name": "cSwapDex", "type": "address" }, + { "internalType": "address", "name": "oracle", "type": "address" }, + { + "internalType": "address", + "name": "operatorPath", + "type": "address" + }, + { "internalType": "address", "name": "userPath", "type": "address" }, + { + "internalType": "uint256", + "name": "minimumDeposit", + "type": "uint256" + } + ], + "internalType": "struct AmbientStrategyParameters", + "name": "aParams", + "type": "tuple" + }, + { "internalType": "int24", "name": "_baseWidth", "type": "int24" }, + { "internalType": "int24", "name": "_limitWidth", "type": "int24" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "investDust", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "investedPercentage", + "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "limitWidth", + "outputs": [{ "internalType": "int24", "name": "", "type": "int24" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liqSlippage", + "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumDeposit", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "operatorPath", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "padding", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "assets", "type": "uint256" } + ], + "name": "previewDeposit", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "assets", "type": "uint256" } + ], + "name": "previewWithdraw", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "rebalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "shares", "type": "uint256" }, + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "address", "name": "owner", "type": "address" }, + { + "internalType": "uint256", + "name": "minimumReceive", + "type": "uint256" + }, + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "redeem", + "outputs": [ + { "internalType": "uint256", "name": "assets", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "shares", "type": "uint256" }, + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "redeemWithoutSwap", + "outputs": [ + { "internalType": "uint256", "name": "amount0", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_feeRecipient", "type": "address" } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint16", "name": "_fee", "type": "uint16" }], + "name": "setFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_investedPercentage", + "type": "uint16" + } + ], + "name": "setInvestedPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_liqSlippage", "type": "uint16" } + ], + "name": "setLiqSlippage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMinimumDeposit", + "type": "uint256" + } + ], + "name": "setMinimumDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newPath", "type": "address" } + ], + "name": "setOperatorPath", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_oracle", "type": "address" } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint8", "name": "_padding", "type": "uint8" } + ], + "name": "setPadding", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_swapSlippage", "type": "uint16" } + ], + "name": "setSwapSlippage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newPath", "type": "address" } + ], + "name": "setUserPath", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } + ], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "swapSlippage", + "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "toggleDepositPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "toggleWithdrawPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "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": "value", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "int24", "name": "_baseWidth", "type": "int24" }, + { "internalType": "int24", "name": "_limitWidth", "type": "int24" }, + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "updateBaseAndLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "userPath", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "assets", "type": "uint256" }, + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "address", "name": "owner", "type": "address" }, + { + "internalType": "uint256", + "name": "minimumReceive", + "type": "uint256" + }, + { "internalType": "bool", "name": "checkSlippage", "type": "bool" } + ], + "name": "withdraw", + "outputs": [ + { "internalType": "uint256", "name": "shares", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/constants/tempest.py b/constants/tempest.py new file mode 100644 index 0000000..e349d3f --- /dev/null +++ b/constants/tempest.py @@ -0,0 +1,15 @@ +from dataclasses import dataclass + +GET_USERS_API_URL = "https://protocol-service-api.tempestdev.xyz/api/v1/users" +CHAIN_ID_SWELL = "534352" + +ABI_FILENAME = "abi/tempest_symmetric_vault.json" + +@dataclass +class VaultConfig: + address: str + genesis_block: int + +VAULTS = [ + VaultConfig(address="0x9674d655bf1a456c441157a5e8c5fa4c144e21e8", genesis_block=10717843) +] diff --git a/integrations/tempest_swell_usde.py b/integrations/tempest_swell_usde.py new file mode 100644 index 0000000..121c345 --- /dev/null +++ b/integrations/tempest_swell_usde.py @@ -0,0 +1,128 @@ +import logging +import json +from copy import deepcopy + +from integrations.cached_balances_integration import CachedBalancesIntegration +from web3 import Web3 +from constants.chains import Chain +from typing import Dict, List, Set +from eth_typing import ChecksumAddress +from utils.web3_utils import ( + W3_BY_CHAIN, + MULTICALL_ADDRESS_BY_CHAIN, + multicall_by_address +) + +import constants.tempest as c +from constants.summary_columns import SummaryColumn +from integrations.integration_ids import IntegrationID +from utils.request_utils import requests_retry_session + +class TempestCachedBalanceIntegration(CachedBalancesIntegration): + def __init__( + self, + integration_id: IntegrationID, + start_block: int, + chain: Chain, + summary_cols: List[SummaryColumn], + reward_multiplier: int = 1, + ): + super().__init__( + integration_id=integration_id, + start_block=start_block, + chain=chain, + summary_cols=summary_cols, + reward_multiplier=reward_multiplier, + balance_multiplier=1, + excluded_addresses=None, + end_block=None, + ) + self.vault_contract_by_address = {} + self.w3 = W3_BY_CHAIN[self.chain]["w3"] + with open(c.ABI_FILENAME, "r") as f: + abi = json.load(f) + for vault in c.VAULTS: + self.vault_contract_by_address[vault.address] = self.w3.eth.contract( + address=Web3.to_checksum_address(vault.address), abi=abi + ) + self.multicall_address = MULTICALL_ADDRESS_BY_CHAIN[chain] + + def get_tempest_users(self, vault_address: str) -> Set[ChecksumAddress]: + """ + Get all users of the vault. + """ + logging.info("[Tempest integration] Getting users...") + try: + response = requests_retry_session().get(c.GET_USERS_API_URL, params={"chainId": c.CHAIN_ID_SWELL, "vaultAddresses": vault_address}) + data = response.json()["data"] + return set(Web3.to_checksum_address(user) for user in data["userAddresses"]) + except Exception as e: + msg = f"Error getting users for Tempest: {e}" + logging.error(msg) + return set() + + def get_data_for_block( + self, block: int, vault_address: str, genesis_block: int + ) -> Dict[ChecksumAddress, float]: + logging.info(f"Getting data for Tempest at block {block}...") + + if block < genesis_block: + return {} + + contract = self.vault_contract_by_address[vault_address] + + # get share balance of all users + data: Dict[ChecksumAddress, float] = {} + users = list(self.get_tempest_users(vault_address)) + if len(users) == 0: + return data + balance_of_calls = [ + (contract, contract.functions.balanceOf.fn_name, [user]) + for user in users + ] + balance_of_results = multicall_by_address(self.w3, self.multicall_address, balance_of_calls, block) + + # get vault totalAssets and totalSupply + vault_calls = [(contract, contract.functions.totalAssets.fn_name, None), (contract, contract.functions.totalSupply.fn_name, None)] + vault_results = multicall_by_address(self.w3, self.multicall_address, vault_calls, block) + total_assets = vault_results[0][0] + total_supply = vault_results[1][0] + + # convert share balance to USDe balance + for i in range(0, len(users)): + data[users[i]] = balance_of_results[i][0] * total_assets / total_supply + + return data + + def get_block_balances( + self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] + ) -> Dict[int, Dict[ChecksumAddress, float]]: + logging.info("Getting block data for Tempest...") + data: Dict[int, Dict[ChecksumAddress, float]] = {} + if not blocks: + logging.error("No blocks provided to Tempest Swell USDe get_block_balances") + return data + data = deepcopy(cached_data) + for vault in c.VAULTS: + for block in blocks: + if cached_data != None and cached_data.get(block) != None: + continue + vault_data = self.get_data_for_block(block, vault_address=vault.address, genesis_block=vault.genesis_block) + for user, balance in vault_data.items(): + if block not in data: + data[block] = {} + if user not in data[block]: + data[block][user] = balance + else: + data[block][user] += balance + return data + +if __name__ == "__main__": + integration = TempestCachedBalanceIntegration( + integration_id=IntegrationID.TEMPEST_SWELL_USDE, + start_block=0, + chain=Chain.SWELL, + summary_cols=[SummaryColumn.TEMPEST_SWELL_SHARDS], + ) + balances = integration.get_block_balances(cached_data={}, blocks=[12008398]) + print(balances) From efc4f9942778dbc58c11c1db6540ddd28da775d2 Mon Sep 17 00:00:00 2001 From: anhnv Date: Fri, 20 Dec 2024 10:06:39 +0700 Subject: [PATCH 3/3] feat: update config for vault on Swell --- .env.example | 2 +- constants/chains.py | 2 +- constants/tempest.py | 6 +++--- integrations/tempest_swell_usde.py | 6 ++++-- utils/web3_utils.py | 3 +-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index cde6c7d..e8b1f5b 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,6 @@ SCROLL_NODE_URL='https://rpc.scroll.io' MODE_NODE_URL='https://mainnet.mode.network' FRAXTAL_NODE_URL='https://rpc.frax.com' LYRA_NODE_URL='https://rpc.derive.xyz' -SWELL_NODE_URL='https://rpc.scroll.io' +SWELL_NODE_URL='https://rpc.ankr.com/swell' DERIVE_SUBGRAPH_API_KEY='' \ No newline at end of file diff --git a/constants/chains.py b/constants/chains.py index 5ec0ac3..e565d64 100644 --- a/constants/chains.py +++ b/constants/chains.py @@ -11,4 +11,4 @@ class Chain(Enum): MODE = "Mode" OPTIMISM = "Optimism" Lyra = "Lyra" - SWELL = "Scroll" + SWELL = "Swell" diff --git a/constants/tempest.py b/constants/tempest.py index e349d3f..6e7e0db 100644 --- a/constants/tempest.py +++ b/constants/tempest.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -GET_USERS_API_URL = "https://protocol-service-api.tempestdev.xyz/api/v1/users" -CHAIN_ID_SWELL = "534352" +GET_USERS_API_URL = "https://protocol-service-api.tempestfinance.xyz/api/v1/users" +CHAIN_ID_SWELL = "1923" ABI_FILENAME = "abi/tempest_symmetric_vault.json" @@ -11,5 +11,5 @@ class VaultConfig: genesis_block: int VAULTS = [ - VaultConfig(address="0x9674d655bf1a456c441157a5e8c5fa4c144e21e8", genesis_block=10717843) + VaultConfig(address="0x1783eb6b8966f7a2c3aa9b913dd53353b2c8c873", genesis_block=965288) ] diff --git a/integrations/tempest_swell_usde.py b/integrations/tempest_swell_usde.py index 121c345..7881729 100644 --- a/integrations/tempest_swell_usde.py +++ b/integrations/tempest_swell_usde.py @@ -66,7 +66,7 @@ def get_data_for_block( ) -> Dict[ChecksumAddress, float]: logging.info(f"Getting data for Tempest at block {block}...") - if block < genesis_block: + if block <= genesis_block: return {} contract = self.vault_contract_by_address[vault_address] @@ -90,6 +90,8 @@ def get_data_for_block( # convert share balance to USDe balance for i in range(0, len(users)): + if balance_of_results[i][0] == 0: + continue data[users[i]] = balance_of_results[i][0] * total_assets / total_supply return data @@ -124,5 +126,5 @@ def get_block_balances( chain=Chain.SWELL, summary_cols=[SummaryColumn.TEMPEST_SWELL_SHARDS], ) - balances = integration.get_block_balances(cached_data={}, blocks=[12008398]) + balances = integration.get_block_balances(cached_data={}, blocks=[983436]) print(balances) diff --git a/utils/web3_utils.py b/utils/web3_utils.py index 6c2366c..a38c9af 100644 --- a/utils/web3_utils.py +++ b/utils/web3_utils.py @@ -90,8 +90,7 @@ "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696" # Ethereum mainnet address ) MULTICALL_ADDRESS_BY_CHAIN = { - Chain.SWELL: "0xcA11bde05977b3631167028862bE2a173976CA11", - Chain.SCROLL: "0xcA11bde05977b3631167028862bE2a173976CA11" + Chain.SWELL: "0xcA11bde05977b3631167028862bE2a173976CA11" }