defi-state-querier 0.5.28__py3-none-any.whl → 0.5.29__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- defi_services/__init__.py +1 -1
- defi_services/abis/lending/ionic/__init__.py +0 -0
- defi_services/abis/lending/ionic/ionic_ctoken_abi.py +1108 -0
- defi_services/abis/lending/moonwell/__init__.py +0 -0
- defi_services/abis/lending/moonwell/moonwell_comptroller_abi.py +1500 -0
- defi_services/abis/lending/moonwell/moonwell_ctoken_abi.py +1431 -0
- defi_services/abis/lending/radiant_v2/radiant_reward_converter.py +817 -0
- defi_services/abis/token/trc20_abi.py +304 -0
- defi_services/abis/vault/tcv_abi.py +1523 -0
- defi_services/constants/chain_constant.py +8 -1
- defi_services/constants/entities/dex_info_constant.py +2 -2
- defi_services/constants/entities/dex_services.py +13 -1
- defi_services/constants/entities/lending_constant.py +11 -5
- defi_services/constants/entities/lending_services.py +31 -4
- defi_services/constants/entities/vault_constant.py +2 -2
- defi_services/constants/entities/vault_services.py +7 -1
- defi_services/constants/network_constants.py +20 -361
- defi_services/constants/token_constant.py +3 -1
- defi_services/jobs/processors/cosmos_state_processor.py +3 -2
- defi_services/jobs/processors/ton_state_processor.py +5 -4
- defi_services/jobs/queriers/call_state_querier.py +2 -0
- defi_services/jobs/queriers/state_querier.py +3 -0
- defi_services/jobs/tcv.py +144 -0
- defi_services/services/dex/dex_info/uniswap_info.py +29 -1
- defi_services/services/dex/uniswap_v3_service.py +6 -2
- defi_services/services/lending/aave_v2_services.py +44 -29
- defi_services/services/lending/aave_v3_services.py +41 -20
- defi_services/services/lending/compound_v3_services.py +9 -5
- defi_services/services/lending/granary_services.py +6 -4
- defi_services/services/lending/ionic_service.py +167 -0
- defi_services/services/lending/justlend_service.py +4 -3
- defi_services/services/lending/lending_info/arbitrum/aave_v3_arbitrum.py +1 -1
- defi_services/services/lending/lending_info/arbitrum/compound_v3_arbitrum.py +96 -6
- defi_services/services/lending/lending_info/arbitrum/venus_arbitrum.py +10 -0
- defi_services/services/lending/lending_info/base/__init__.py +0 -0
- defi_services/services/lending/lending_info/base/aave_v3_base.py +61 -0
- defi_services/services/lending/lending_info/base/compound_v3_base.py +116 -0
- defi_services/services/lending/lending_info/base/granary_base.py +62 -0
- defi_services/services/lending/lending_info/base/ionic_base.py +173 -0
- defi_services/services/lending/lending_info/base/moonwell_base.py +89 -0
- defi_services/services/lending/lending_info/base/radiant_v2_base.py +57 -0
- defi_services/services/lending/lending_info/base/sonne_base.py +53 -0
- defi_services/services/lending/lending_info/base/zerolend_base.py +109 -0
- defi_services/services/lending/lending_info/bsc/aave_v3_bsc.py +68 -0
- defi_services/services/lending/lending_info/bsc/apeswap_bsc.py +1 -1
- defi_services/services/lending/lending_info/ethereum/aave_v3_eth.py +1 -140
- defi_services/services/lending/lending_info/ethereum/compound_v3_eth.py +180 -5
- defi_services/services/lending/lending_info/ethereum/old_aave_v3_eth.py +150 -0
- defi_services/services/lending/lending_info/ethereum/radiant_eth.py +69 -0
- defi_services/services/lending/lending_info/ethereum/venus_eth.py +10 -0
- defi_services/services/lending/lending_info/ethereum/zerolend_eth.py +96 -0
- defi_services/services/lending/lending_info/optimism/compound_v3_optimism.py +116 -0
- defi_services/services/lending/lending_info/optimism/moonwell_optimism.py +9 -0
- defi_services/services/lending/lending_info/polygon/compound_v3_polygon.py +35 -5
- defi_services/services/lending/lending_info/zksync/__init__.py +0 -0
- defi_services/services/lending/lending_info/zksync/aave_v3_zksync.py +47 -0
- defi_services/services/lending/lending_info/zksync/venus_zksync.py +10 -0
- defi_services/services/lending/lending_info/zksync/zerolend_zksync.py +138 -0
- defi_services/services/lending/moonwell_service.py +120 -0
- defi_services/services/lending/morpho_aave_v2_services.py +3 -3
- defi_services/services/lending/morpho_aave_v3_services.py +2 -2
- defi_services/services/lending/radiant_v2_services.py +52 -10
- defi_services/services/lending/sonne_service.py +64 -0
- defi_services/services/lending/trava_services.py +2 -2
- defi_services/services/lending/uwu_services.py +3 -3
- defi_services/services/lending/valas_services.py +2 -2
- defi_services/services/lending/venus_services.py +9 -3
- defi_services/services/lending/zerolend_services.py +36 -0
- defi_services/services/multicall/multicall_v2.py +0 -317
- defi_services/services/vault/tcv_vault_services.py +108 -0
- defi_services/services/vault/vault_info/arbitrum/__init__.py +0 -0
- defi_services/services/vault/vault_info/arbitrum/tcv_arb.py +58 -0
- {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/METADATA +1 -1
- {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/RECORD +84 -47
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/__init__.py +0 -0
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/aave_v2_event_abi.py +0 -0
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/aave_v2_incentives_abi.py +0 -0
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/lending_pool_abi.py +0 -0
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/oracle_abi.py +0 -0
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/staked_incentives_abi.py +0 -0
- /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/uwu_incentives_abi.py +0 -0
- {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/WHEEL +0 -0
- {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/licenses/LICENSE +0 -0
- {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,15 @@
|
|
1
1
|
import logging
|
2
2
|
|
3
|
+
from defi_services.abis.lending.radiant_v2.radiant_reward_converter import RADIANT_REWARD_CONVERTER_ABI
|
3
4
|
from defi_services.abis.lending.radiant_v2.radiant_v2_incentive_abi import RADIANT_V2_INCENTIVE_ABI
|
5
|
+
from defi_services.abis.token.erc20_abi import ERC20_ABI
|
4
6
|
from defi_services.constants.chain_constant import Chain
|
5
7
|
from defi_services.constants.entities.lending_constant import Lending
|
6
8
|
from defi_services.jobs.queriers.state_querier import StateQuerier
|
7
9
|
from defi_services.services.lending.lending_info.arbitrum.radiant_arbitrum import RADIANT_ARB
|
10
|
+
from defi_services.services.lending.lending_info.base.radiant_v2_base import RADIANT_BASE
|
8
11
|
from defi_services.services.lending.lending_info.bsc.radiant_bsc import RADIANT_BSC
|
12
|
+
from defi_services.services.lending.lending_info.ethereum.radiant_eth import RADIANT_ETH
|
9
13
|
from defi_services.services.lending.valas_services import ValasStateService
|
10
14
|
from defi_services.utils.apy import apr_to_apy
|
11
15
|
|
@@ -15,7 +19,9 @@ logger = logging.getLogger("Radiant Lending Pool State Service")
|
|
15
19
|
class RadiantInfo:
|
16
20
|
mapping = {
|
17
21
|
Chain.arbitrum: RADIANT_ARB,
|
18
|
-
Chain.bsc: RADIANT_BSC
|
22
|
+
Chain.bsc: RADIANT_BSC,
|
23
|
+
Chain.ethereum: RADIANT_ETH,
|
24
|
+
Chain.base: RADIANT_BASE
|
19
25
|
}
|
20
26
|
|
21
27
|
|
@@ -65,19 +71,55 @@ class RadiantStateService(ValasStateService):
|
|
65
71
|
block_number: int = "latest"
|
66
72
|
):
|
67
73
|
rpc_calls = {}
|
68
|
-
|
69
|
-
|
70
|
-
|
74
|
+
if self.chain_id != Chain.base:
|
75
|
+
key = f"allPendingRewards_{self.name}_{wallet}_{block_number}".lower()
|
76
|
+
rpc_calls[key] = self.get_function_incentive_info(
|
77
|
+
"allPendingRewards", [wallet], block_number)
|
78
|
+
else:
|
79
|
+
# key = f"viewPendingRewards_{self.name}_{wallet}_{block_number}".lower()
|
80
|
+
# rpc_calls[key] = self.get_function_reward_converter_info(
|
81
|
+
# "viewPendingRewards", [wallet], block_number)
|
82
|
+
for token in self.pool_info.get('rewardToken'):
|
83
|
+
key = f"decimals_{token}"
|
84
|
+
rpc_calls[key] = self.state_service.get_function_info(
|
85
|
+
token, ERC20_ABI, "decimals"
|
86
|
+
)
|
71
87
|
|
72
88
|
return rpc_calls
|
73
89
|
|
74
90
|
def calculate_rewards_balance(
|
75
91
|
self, wallet: str, reserves_info: dict, decoded_data: dict, block_number: int = "latest"):
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
92
|
+
if self.chain_id != Chain.base:
|
93
|
+
reward_token = self.pool_info['rewardToken']
|
94
|
+
key = f"allPendingRewards_{self.name}_{wallet}_{block_number}".lower()
|
95
|
+
rewards = decoded_data.get(key) / 10 ** 18
|
96
|
+
result = {
|
97
|
+
reward_token: {"amount": rewards}
|
98
|
+
}
|
99
|
+
else:
|
100
|
+
# key = f"viewPendingRewards_{self.name}_{wallet}_{block_number}".lower()
|
101
|
+
# rewards = decoded_data.get(key)
|
102
|
+
result = {}
|
103
|
+
w3 = self.state_service.get_w3()
|
104
|
+
contract = w3.eth.contract(w3.to_checksum_address(
|
105
|
+
self.pool_info.get('rewardConverter')), abi=RADIANT_REWARD_CONVERTER_ABI
|
106
|
+
)
|
107
|
+
rewards = contract.functions.viewPendingRewards(w3.to_checksum_address(wallet)).call()
|
108
|
+
amts = rewards[1]
|
109
|
+
tokens = rewards[0]
|
110
|
+
for idx in range(len(tokens)):
|
111
|
+
amount = amts[idx]
|
112
|
+
token = tokens[idx].lower()
|
113
|
+
if token not in self.pool_info.get('rewardToken', []):
|
114
|
+
continue
|
115
|
+
decimal_key = f"decimals_{token}"
|
116
|
+
result.update({
|
117
|
+
token.lower(): {"amount": amount / 10**decoded_data.get(decimal_key)}
|
118
|
+
})
|
82
119
|
|
83
120
|
return result
|
121
|
+
|
122
|
+
def get_function_reward_converter_info(self, fn_name: str, fn_paras=None, block_number: int = 'latest'):
|
123
|
+
return self.state_service.get_function_info(
|
124
|
+
self.pool_info['rewardConverter'], self.incentive_abi, fn_name, fn_paras, block_number
|
125
|
+
)
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
from defi_services.abis.lending.venus.venus_comptroller_abi import VENUS_COMPTROLLER_ABI
|
4
|
+
from defi_services.abis.lending.venus.vtoken_abi import VTOKEN_ABI
|
5
|
+
from defi_services.constants.chain_constant import Chain
|
6
|
+
from defi_services.constants.entities.lending_constant import Lending
|
7
|
+
from defi_services.jobs.queriers.state_querier import StateQuerier
|
8
|
+
from defi_services.services.lending.lending_info.base.sonne_base import SONNE_BASE
|
9
|
+
from defi_services.services.lending.venus_services import VenusStateService
|
10
|
+
|
11
|
+
logger = logging.getLogger("Ionic Lending Pool State Service")
|
12
|
+
|
13
|
+
|
14
|
+
class SonneInfo:
|
15
|
+
mapping = {
|
16
|
+
Chain.base: SONNE_BASE
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
class SonneStateService(VenusStateService):
|
21
|
+
def __init__(self, state_service: StateQuerier, chain_id: str = "0x38"):
|
22
|
+
super().__init__(state_service, chain_id)
|
23
|
+
self.name = f"{chain_id}_{Lending.sonne}"
|
24
|
+
self.chain_id = chain_id
|
25
|
+
self.pool_info = SonneInfo.mapping.get(chain_id)
|
26
|
+
self.state_service = state_service
|
27
|
+
self.comptroller_abi = VENUS_COMPTROLLER_ABI
|
28
|
+
self.vtoken_abi = VTOKEN_ABI
|
29
|
+
|
30
|
+
def get_service_info(self):
|
31
|
+
info = {
|
32
|
+
Lending.sonne: {
|
33
|
+
"chain_id": self.chain_id,
|
34
|
+
"type": "lending",
|
35
|
+
"protocol_info": self.pool_info
|
36
|
+
}
|
37
|
+
}
|
38
|
+
return info
|
39
|
+
|
40
|
+
def calculate_apy_lending_pool_function_call(
|
41
|
+
self,
|
42
|
+
reserves_info: dict,
|
43
|
+
decoded_data: dict,
|
44
|
+
token_prices: dict,
|
45
|
+
pool_token_price: float,
|
46
|
+
pool_decimals: int = 18,
|
47
|
+
block_number: int = "latest",
|
48
|
+
):
|
49
|
+
reserve_tokens_info = self.get_reserve_tokens_metadata(decoded_data, reserves_info, block_number)
|
50
|
+
|
51
|
+
data = {}
|
52
|
+
for token_info in reserve_tokens_info:
|
53
|
+
underlying_token = token_info['underlying']
|
54
|
+
c_token = token_info['token']
|
55
|
+
|
56
|
+
assets = {
|
57
|
+
underlying_token: self._calculate_interest_rates(
|
58
|
+
token_info, pool_decimals=pool_decimals,
|
59
|
+
apx_block_speed_in_seconds=1
|
60
|
+
)
|
61
|
+
}
|
62
|
+
data[c_token] = assets
|
63
|
+
|
64
|
+
return data
|
@@ -3,8 +3,8 @@ import time
|
|
3
3
|
|
4
4
|
from web3 import Web3
|
5
5
|
|
6
|
-
from defi_services.abis.lending.
|
7
|
-
from defi_services.abis.lending.
|
6
|
+
from defi_services.abis.lending.aave_v2_and_forks.oracle_abi import ORACLE_ABI
|
7
|
+
from defi_services.abis.lending.aave_v2_and_forks.staked_incentives_abi import STAKED_INCENTIVES_ABI
|
8
8
|
from defi_services.abis.lending.trava.trava_lending_pool_abi import TRAVA_LENDING_POOL_ABI
|
9
9
|
from defi_services.abis.token.erc20_abi import ERC20_ABI
|
10
10
|
from defi_services.constants.chain_constant import Chain
|
@@ -3,9 +3,9 @@ import time
|
|
3
3
|
|
4
4
|
from web3 import Web3
|
5
5
|
|
6
|
-
from defi_services.abis.lending.
|
7
|
-
from defi_services.abis.lending.
|
8
|
-
from defi_services.abis.lending.
|
6
|
+
from defi_services.abis.lending.aave_v2_and_forks.lending_pool_abi import LENDING_POOL_ABI
|
7
|
+
from defi_services.abis.lending.aave_v2_and_forks.oracle_abi import ORACLE_ABI
|
8
|
+
from defi_services.abis.lending.aave_v2_and_forks.uwu_incentives_abi import UWU_INCENTIVES_ABI
|
9
9
|
from defi_services.abis.token.erc20_abi import ERC20_ABI
|
10
10
|
from defi_services.constants.chain_constant import Chain
|
11
11
|
from defi_services.constants.entities.lending_constant import Lending
|
@@ -3,8 +3,8 @@ import time
|
|
3
3
|
|
4
4
|
from web3 import Web3
|
5
5
|
|
6
|
-
from defi_services.abis.lending.
|
7
|
-
from defi_services.abis.lending.
|
6
|
+
from defi_services.abis.lending.aave_v2_and_forks.lending_pool_abi import LENDING_POOL_ABI
|
7
|
+
from defi_services.abis.lending.aave_v2_and_forks.oracle_abi import ORACLE_ABI
|
8
8
|
from defi_services.abis.lending.valas.chef_incentives_controller import CHEF_INCENTIVES_CONTROLLER
|
9
9
|
from defi_services.abis.lending.valas.valas_multi_fee_distribution import VALAS_MULTI_FEE_DISTRIBUTION
|
10
10
|
from defi_services.abis.token.erc20_abi import ERC20_ABI
|
@@ -151,16 +151,22 @@ class VenusStateService(CompoundStateService):
|
|
151
151
|
|
152
152
|
def calculate_rewards_balance(
|
153
153
|
self, wallet: str, reserves_info: dict, decoded_data: dict, block_number: int = "latest"):
|
154
|
+
if not self.pool_info.get('lensAddress'):
|
155
|
+
return {}
|
156
|
+
|
154
157
|
w3 = self.state_service.get_w3()
|
155
|
-
contract = w3.eth.contract(address=w3.to_checksum_address(self.pool_info.get("lensAddress")), abi
|
158
|
+
contract = w3.eth.contract(address=w3.to_checksum_address(self.pool_info.get("lensAddress")), abi=self.lens_abi)
|
156
159
|
# get_reward_id = f"pendingRewards_{self.name}_{wallet}_{block_number}".lower()
|
157
|
-
return_data = contract.functions.pendingRewards(
|
160
|
+
return_data = contract.functions.pendingRewards(
|
161
|
+
w3.to_checksum_address(wallet),
|
162
|
+
w3.to_checksum_address(self.pool_info.get("comptrollerAddress"))).call(block_identifier=block_number)
|
163
|
+
|
158
164
|
rewards = return_data[2]
|
159
165
|
for item in return_data[-1]:
|
160
166
|
rewards += item[-1]
|
161
167
|
reward_token = self.pool_info.get("rewardToken")
|
162
168
|
result = {
|
163
|
-
reward_token: {"amount": rewards/10**18}
|
169
|
+
reward_token: {"amount": rewards / 10 ** 18}
|
164
170
|
}
|
165
171
|
return result
|
166
172
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
from defi_services.constants.chain_constant import Chain
|
4
|
+
from defi_services.constants.entities.lending_constant import Lending
|
5
|
+
from defi_services.jobs.queriers.state_querier import StateQuerier
|
6
|
+
from defi_services.services.lending.aave_v3_services import AaveV3StateService
|
7
|
+
from defi_services.services.lending.lending_info.base.zerolend_base import ZEROLEND_BASE
|
8
|
+
from defi_services.services.lending.lending_info.ethereum.zerolend_eth import ZEROLEND_ETH
|
9
|
+
from defi_services.services.lending.lending_info.zksync.zerolend_zksync import ZEROLEND_ZKSYNC
|
10
|
+
|
11
|
+
logger = logging.getLogger("ZeroLend Lending Pool State Service")
|
12
|
+
|
13
|
+
|
14
|
+
class ZeroLendInfo:
|
15
|
+
mapping = {
|
16
|
+
Chain.zksync: ZEROLEND_ZKSYNC,
|
17
|
+
Chain.ethereum: ZEROLEND_ETH,
|
18
|
+
Chain.base: ZEROLEND_BASE
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
class ZeroLendStateService(AaveV3StateService):
|
23
|
+
def __init__(self, state_service: StateQuerier, chain_id: str = Chain.zksync):
|
24
|
+
super().__init__(state_service, chain_id)
|
25
|
+
self.name = f"{chain_id}_{Lending.zerolend}"
|
26
|
+
self.pool_info = ZeroLendInfo.mapping.get(chain_id)
|
27
|
+
|
28
|
+
def get_service_info(self):
|
29
|
+
info = {
|
30
|
+
Lending.zerolend: {
|
31
|
+
"chain_id": self.chain_id,
|
32
|
+
"type": "lending",
|
33
|
+
"protocol_info": self.pool_info
|
34
|
+
}
|
35
|
+
}
|
36
|
+
return info
|
@@ -1,17 +1,10 @@
|
|
1
|
-
import csv
|
2
|
-
import json
|
3
|
-
import time
|
4
1
|
from collections import defaultdict
|
5
2
|
from typing import Tuple, List, Union, Any, Optional, Dict
|
6
3
|
|
7
4
|
from query_state_lib.base.utils.decoder import decode_eth_call_data
|
8
|
-
from query_state_lib.client.client_querier import ClientQuerier
|
9
5
|
from web3 import Web3, contract
|
10
6
|
|
11
|
-
from defi_services.abis.dex.pancakeswap.pancakeswap_lp_token_abi import LP_TOKEN_ABI
|
12
7
|
from defi_services.abis.multicall_v3_abi import MULTICALL_V3_ABI
|
13
|
-
from defi_services.abis.token.erc20_abi import ERC20_ABI
|
14
|
-
from defi_services.constants.network_constants import MulticallContract, Chains, Networks
|
15
8
|
from defi_services.services.multicall.batch_queries_service import add_rpc_call, decode_data_response, \
|
16
9
|
decode_data_response_ignore_error
|
17
10
|
from defi_services.utils.dict_utils import all_equal
|
@@ -184,313 +177,3 @@ def decode_multical_response(w3_multicall: W3Multicall, data_responses, list_cal
|
|
184
177
|
batch_idx += 1
|
185
178
|
|
186
179
|
return results
|
187
|
-
|
188
|
-
|
189
|
-
def _test_multicall(_w3: Web3, multicall_contract, wallets, tokens):
|
190
|
-
start_time = time.time()
|
191
|
-
encode_time = 0
|
192
|
-
|
193
|
-
rpc_call_id = {}
|
194
|
-
|
195
|
-
n_calls = 0
|
196
|
-
data = {}
|
197
|
-
for wallet in wallets:
|
198
|
-
start_encode_time = time.time()
|
199
|
-
data[wallet] = {}
|
200
|
-
|
201
|
-
w3_multicall = W3Multicall(_w3, address=MulticallContract.get_multicall_contract(Chains.arbitrum))
|
202
|
-
for token in tokens:
|
203
|
-
# if token['address'] == '0x0000000000000000000000000000000000000000':
|
204
|
-
# continue
|
205
|
-
|
206
|
-
w3_multicall.add(W3Multicall.Call(
|
207
|
-
Web3.to_checksum_address(token['address']), # contract address
|
208
|
-
ERC20_ABI, # method signature to call
|
209
|
-
'balanceOf',
|
210
|
-
wallet
|
211
|
-
))
|
212
|
-
|
213
|
-
decimals_call = W3Multicall.Call(
|
214
|
-
Web3.to_checksum_address(token['address']), # contract address
|
215
|
-
ERC20_ABI, # method signature to call
|
216
|
-
'decimals'
|
217
|
-
)
|
218
|
-
if decimals_call not in rpc_call_id:
|
219
|
-
w3_multicall.add(decimals_call)
|
220
|
-
rpc_call_id[decimals_call] = None
|
221
|
-
|
222
|
-
encode_time += time.time() - start_encode_time
|
223
|
-
n_calls += len(w3_multicall.calls)
|
224
|
-
|
225
|
-
# For single call
|
226
|
-
inputs = w3_multicall.get_params()
|
227
|
-
response = multicall_contract.functions.tryAggregate(*inputs).call()
|
228
|
-
results = w3_multicall.decode(response)
|
229
|
-
|
230
|
-
for token in tokens:
|
231
|
-
# if token['address'] == '0x0000000000000000000000000000000000000000':
|
232
|
-
# continue
|
233
|
-
|
234
|
-
decimals_call_id = f'decimals_{token["address"]}_latest'.lower()
|
235
|
-
balance_call_id = f'balanceOf_{token["address"]}_{wallet}_latest'.lower()
|
236
|
-
|
237
|
-
decimals = results.get(decimals_call_id)
|
238
|
-
if decimals is None:
|
239
|
-
decimals = rpc_call_id.get(decimals_call_id) or 18
|
240
|
-
else:
|
241
|
-
rpc_call_id[decimals_call_id] = decimals
|
242
|
-
|
243
|
-
balance = results.get(balance_call_id)
|
244
|
-
if balance is None:
|
245
|
-
balance = rpc_call_id.get(balance_call_id) or 0
|
246
|
-
else:
|
247
|
-
rpc_call_id[balance_call_id] = balance
|
248
|
-
balance /= 10 ** decimals
|
249
|
-
|
250
|
-
data[wallet][token['address']] = {
|
251
|
-
'name': token['name'],
|
252
|
-
'symbol': token['symbol'],
|
253
|
-
'balance': balance,
|
254
|
-
'decimals': decimals
|
255
|
-
}
|
256
|
-
|
257
|
-
with open('results_multicall.json', 'w') as f:
|
258
|
-
json.dump(data, f, indent=2)
|
259
|
-
duration = time.time() - start_time
|
260
|
-
|
261
|
-
print(f'There are {n_calls} calls')
|
262
|
-
print(f'Encode took {round(encode_time, 3)}s')
|
263
|
-
print(f'Done after {round(duration, 3)}s')
|
264
|
-
|
265
|
-
return duration, encode_time, n_calls
|
266
|
-
|
267
|
-
|
268
|
-
def _test_state_querier(client_querier: ClientQuerier, wallets, tokens):
|
269
|
-
start_time = time.time()
|
270
|
-
|
271
|
-
list_call_id = []
|
272
|
-
list_rpc_call = []
|
273
|
-
|
274
|
-
for wallet in wallets:
|
275
|
-
for token in tokens:
|
276
|
-
if token['address'] == '0x0000000000000000000000000000000000000000':
|
277
|
-
continue
|
278
|
-
|
279
|
-
add_rpc_call(
|
280
|
-
abi=ERC20_ABI, contract_address=Web3.to_checksum_address(token['address']),
|
281
|
-
fn_name="balanceOf", fn_paras=wallet, block_number='latest',
|
282
|
-
list_call_id=list_call_id, list_rpc_call=list_rpc_call
|
283
|
-
)
|
284
|
-
add_rpc_call(
|
285
|
-
abi=ERC20_ABI, contract_address=Web3.to_checksum_address(token['address']),
|
286
|
-
fn_name="decimals", block_number='latest',
|
287
|
-
list_call_id=list_call_id, list_rpc_call=list_rpc_call
|
288
|
-
)
|
289
|
-
|
290
|
-
encode_time = time.time() - start_time
|
291
|
-
print(f'There are {len(list_rpc_call)} calls')
|
292
|
-
print(f'Encode took {round(encode_time, 3)}s')
|
293
|
-
|
294
|
-
responses = client_querier.sent_batch_to_provider(list_rpc_call, batch_size=2000)
|
295
|
-
decoded_data = decode_data_response_ignore_error(data_responses=responses, list_call_id=list_call_id)
|
296
|
-
|
297
|
-
data = {}
|
298
|
-
for wallet in wallets:
|
299
|
-
data[wallet] = {}
|
300
|
-
for token in tokens:
|
301
|
-
if token['address'] == '0x0000000000000000000000000000000000000000':
|
302
|
-
continue
|
303
|
-
|
304
|
-
decimals = decoded_data.get(f'decimals_{token["address"]}_latest'.lower())
|
305
|
-
balance = decoded_data.get(f'balanceOf_{token["address"]}_{wallet}_latest'.lower()) / 10 ** decimals
|
306
|
-
|
307
|
-
data[wallet][token['address']] = {
|
308
|
-
'name': token['name'],
|
309
|
-
'symbol': token['symbol'],
|
310
|
-
'balance': balance,
|
311
|
-
'decimals': decimals
|
312
|
-
}
|
313
|
-
|
314
|
-
with open('results_querier.json', 'w') as f:
|
315
|
-
json.dump(data, f, indent=2)
|
316
|
-
duration = time.time() - start_time
|
317
|
-
print(f'Done after {round(duration, 3)}s')
|
318
|
-
|
319
|
-
return duration, encode_time, len(list_rpc_call)
|
320
|
-
|
321
|
-
|
322
|
-
def _test_multicall_with_multiprocessing(_w3: Web3, client_querier: ClientQuerier, wallets, tokens):
|
323
|
-
start_time = time.time()
|
324
|
-
|
325
|
-
w3_multicall = W3Multicall(_w3, address=MulticallContract.get_multicall_contract(Chains.arbitrum))
|
326
|
-
for wallet in wallets:
|
327
|
-
for token in tokens:
|
328
|
-
# if token['address'] == '0x0000000000000000000000000000000000000000':
|
329
|
-
# continue
|
330
|
-
|
331
|
-
w3_multicall.add(W3Multicall.Call(
|
332
|
-
Web3.to_checksum_address(token['address']), # contract address
|
333
|
-
ERC20_ABI, # method signature to call
|
334
|
-
'balanceOf',
|
335
|
-
wallet
|
336
|
-
))
|
337
|
-
|
338
|
-
w3_multicall.add(W3Multicall.Call(
|
339
|
-
Web3.to_checksum_address(token['address']), # contract address
|
340
|
-
ERC20_ABI, # method signature to call
|
341
|
-
'decimals'
|
342
|
-
))
|
343
|
-
|
344
|
-
w3_multicall.add(W3Multicall.Call(
|
345
|
-
Web3.to_checksum_address(token['address']), # contract address
|
346
|
-
LP_TOKEN_ABI, # method signature to call
|
347
|
-
'token0'
|
348
|
-
))
|
349
|
-
|
350
|
-
list_call_id, list_rpc_call = [], []
|
351
|
-
add_rpc_multicall(w3_multicall, list_rpc_call=list_rpc_call, list_call_id=list_call_id)
|
352
|
-
|
353
|
-
encode_time = time.time() - start_time
|
354
|
-
|
355
|
-
responses = client_querier.sent_batch_to_provider(list_rpc_call, batch_size=1)
|
356
|
-
decoded_data = decode_multical_response(
|
357
|
-
w3_multicall=w3_multicall, data_responses=responses,
|
358
|
-
list_call_id=list_call_id, ignore_error=True
|
359
|
-
)
|
360
|
-
|
361
|
-
data = {}
|
362
|
-
for wallet in wallets:
|
363
|
-
data[wallet] = {}
|
364
|
-
for token in tokens:
|
365
|
-
# if token['address'] == '0x0000000000000000000000000000000000000000':
|
366
|
-
# continue
|
367
|
-
|
368
|
-
decimals_call_id = f'decimals_{token["address"]}_latest'.lower()
|
369
|
-
balance_call_id = f'balanceOf_{token["address"]}_{wallet}_latest'.lower()
|
370
|
-
|
371
|
-
decimals = decoded_data.get(decimals_call_id) or 18
|
372
|
-
balance = decoded_data.get(balance_call_id, 0) / 10 ** decimals
|
373
|
-
|
374
|
-
data[wallet][token['address']] = {
|
375
|
-
'name': token['name'],
|
376
|
-
'symbol': token['symbol'],
|
377
|
-
'balance': balance,
|
378
|
-
'decimals': decimals
|
379
|
-
}
|
380
|
-
|
381
|
-
with open('results_multicall_with_multiprocessing.json', 'w') as f:
|
382
|
-
json.dump(data, f, indent=2)
|
383
|
-
duration = time.time() - start_time
|
384
|
-
|
385
|
-
print(f'There are {len(w3_multicall.calls)} calls')
|
386
|
-
print(f'Encode took {round(encode_time, 3)}s')
|
387
|
-
print(f'Done after {round(duration, 3)}s')
|
388
|
-
|
389
|
-
return duration, encode_time, len(w3_multicall.calls)
|
390
|
-
|
391
|
-
|
392
|
-
def query_multi_contracts(n_times=20, wallets_batch_size=5, wallets_distribute_similar=True):
|
393
|
-
with open('../../../.data/wallets.json') as f:
|
394
|
-
wallets = json.load(f)
|
395
|
-
wallets = ['0x6FfA563915CB3186b9Dd206D0E08bdeDcd2EA2ED']
|
396
|
-
|
397
|
-
with open('../../../.data/tokens.json') as f:
|
398
|
-
tokens_ = json.load(f)
|
399
|
-
tokens_ = [
|
400
|
-
{
|
401
|
-
"address": "0xE2035f04040A135c4dA2f96AcA742143c57c79F9",
|
402
|
-
"name": "UXUY",
|
403
|
-
"symbol": "uxuy"
|
404
|
-
},
|
405
|
-
{
|
406
|
-
"address": "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9",
|
407
|
-
"name": "Tether",
|
408
|
-
"symbol": "usdt"
|
409
|
-
},
|
410
|
-
{
|
411
|
-
"address": "0x0000000000000000000000000000000000000000",
|
412
|
-
"name": "ETH",
|
413
|
-
"symbol": "ETH"
|
414
|
-
}
|
415
|
-
]
|
416
|
-
|
417
|
-
print(f'There are maximum {len(wallets)} wallets')
|
418
|
-
print(f'There are {len(tokens_)} tokens')
|
419
|
-
|
420
|
-
if wallets_distribute_similar:
|
421
|
-
wallets_batch = [wallets[:300], wallets[:300], wallets[:300]]
|
422
|
-
else:
|
423
|
-
wallets_batch = [wallets[:300], wallets[300:600], wallets[600:900]]
|
424
|
-
|
425
|
-
# Methodology 1: Query State Lib
|
426
|
-
start_time = time.time()
|
427
|
-
client_querier = ClientQuerier(provider_url=Networks.providers['arbitrum'])
|
428
|
-
starting_time_1 = time.time() - start_time
|
429
|
-
logger.info(f'Starting state querier: {round(starting_time_1, 3)}s')
|
430
|
-
|
431
|
-
_multiple(
|
432
|
-
n_times=n_times, starting_time=starting_time_1, filename='query_state_lib',
|
433
|
-
wallets=wallets_batch[0], wallets_batch_size=wallets_batch_size, tokens=tokens_, func=_test_state_querier,
|
434
|
-
client_querier=client_querier
|
435
|
-
)
|
436
|
-
|
437
|
-
# Methodology 2: Multicall
|
438
|
-
start_time = time.time()
|
439
|
-
_w3 = Web3(Web3.HTTPProvider(Networks.providers['arbitrum']))
|
440
|
-
starting_time_2_1 = time.time() - start_time
|
441
|
-
multicall_address = MulticallContract.get_multicall_contract(Chains.arbitrum)
|
442
|
-
multicall_contract = _w3.eth.contract(Web3.to_checksum_address(multicall_address), abi=MULTICALL_V3_ABI)
|
443
|
-
starting_time_2 = time.time() - start_time
|
444
|
-
logger.info(f'Starting multicall: {round(starting_time_2, 3)}s')
|
445
|
-
|
446
|
-
_multiple(
|
447
|
-
n_times=n_times, starting_time=starting_time_2, filename='multicall',
|
448
|
-
wallets=wallets_batch[1], wallets_batch_size=wallets_batch_size, tokens=tokens_, func=_test_multicall,
|
449
|
-
_w3=_w3, multicall_contract=multicall_contract
|
450
|
-
)
|
451
|
-
|
452
|
-
# Methodology 3: Combine Multicall with multiprocessing
|
453
|
-
starting_time_3 = starting_time_1 + starting_time_2_1
|
454
|
-
logger.info(f'Starting combined: {round(starting_time_3, 3)}s')
|
455
|
-
|
456
|
-
_multiple(
|
457
|
-
n_times=n_times, starting_time=starting_time_3, filename='combined',
|
458
|
-
wallets=wallets_batch[2], wallets_batch_size=wallets_batch_size, tokens=tokens_,
|
459
|
-
func=_test_multicall_with_multiprocessing, _w3=_w3, client_querier=client_querier
|
460
|
-
)
|
461
|
-
|
462
|
-
|
463
|
-
def _multiple(n_times, starting_time, filename, wallets, wallets_batch_size, tokens, func, *args, **kwargs):
|
464
|
-
data = [['Total Time', 'Encode Time']]
|
465
|
-
overview = {
|
466
|
-
'avg_total_time': 0, 'avg_encode_time': 0,
|
467
|
-
'times': 0, 'errors': 0,
|
468
|
-
'queries': 0, 'start_time': starting_time
|
469
|
-
}
|
470
|
-
for i in range(n_times):
|
471
|
-
idx = i * wallets_batch_size
|
472
|
-
sub_wallets = wallets[idx:idx + wallets_batch_size]
|
473
|
-
try:
|
474
|
-
total_time, encode_time, n_calls = func(wallets=sub_wallets, tokens=tokens, *args, **kwargs)
|
475
|
-
|
476
|
-
overview['queries'] = n_calls
|
477
|
-
data.append([total_time, encode_time])
|
478
|
-
overview['times'] += 1
|
479
|
-
except Exception as ex:
|
480
|
-
logger.exception(ex)
|
481
|
-
overview['errors'] += 1
|
482
|
-
finally:
|
483
|
-
time.sleep(13)
|
484
|
-
|
485
|
-
with open(f'results_{filename}.csv', 'w') as f:
|
486
|
-
writer = csv.writer(f)
|
487
|
-
writer.writerows(data)
|
488
|
-
|
489
|
-
overview['avg_total_time'] = sum([t[0] for t in data[1:]]) / overview['times']
|
490
|
-
overview['avg_encode_time'] = sum([t[1] for t in data[1:]]) / overview['times']
|
491
|
-
with open(f'overview_results_{filename}.json', 'w') as f:
|
492
|
-
json.dump(overview, f, indent=2)
|
493
|
-
|
494
|
-
|
495
|
-
if __name__ == '__main__':
|
496
|
-
query_multi_contracts(n_times=1, wallets_batch_size=1, wallets_distribute_similar=True)
|