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.
Files changed (84) hide show
  1. defi_services/__init__.py +1 -1
  2. defi_services/abis/lending/ionic/__init__.py +0 -0
  3. defi_services/abis/lending/ionic/ionic_ctoken_abi.py +1108 -0
  4. defi_services/abis/lending/moonwell/__init__.py +0 -0
  5. defi_services/abis/lending/moonwell/moonwell_comptroller_abi.py +1500 -0
  6. defi_services/abis/lending/moonwell/moonwell_ctoken_abi.py +1431 -0
  7. defi_services/abis/lending/radiant_v2/radiant_reward_converter.py +817 -0
  8. defi_services/abis/token/trc20_abi.py +304 -0
  9. defi_services/abis/vault/tcv_abi.py +1523 -0
  10. defi_services/constants/chain_constant.py +8 -1
  11. defi_services/constants/entities/dex_info_constant.py +2 -2
  12. defi_services/constants/entities/dex_services.py +13 -1
  13. defi_services/constants/entities/lending_constant.py +11 -5
  14. defi_services/constants/entities/lending_services.py +31 -4
  15. defi_services/constants/entities/vault_constant.py +2 -2
  16. defi_services/constants/entities/vault_services.py +7 -1
  17. defi_services/constants/network_constants.py +20 -361
  18. defi_services/constants/token_constant.py +3 -1
  19. defi_services/jobs/processors/cosmos_state_processor.py +3 -2
  20. defi_services/jobs/processors/ton_state_processor.py +5 -4
  21. defi_services/jobs/queriers/call_state_querier.py +2 -0
  22. defi_services/jobs/queriers/state_querier.py +3 -0
  23. defi_services/jobs/tcv.py +144 -0
  24. defi_services/services/dex/dex_info/uniswap_info.py +29 -1
  25. defi_services/services/dex/uniswap_v3_service.py +6 -2
  26. defi_services/services/lending/aave_v2_services.py +44 -29
  27. defi_services/services/lending/aave_v3_services.py +41 -20
  28. defi_services/services/lending/compound_v3_services.py +9 -5
  29. defi_services/services/lending/granary_services.py +6 -4
  30. defi_services/services/lending/ionic_service.py +167 -0
  31. defi_services/services/lending/justlend_service.py +4 -3
  32. defi_services/services/lending/lending_info/arbitrum/aave_v3_arbitrum.py +1 -1
  33. defi_services/services/lending/lending_info/arbitrum/compound_v3_arbitrum.py +96 -6
  34. defi_services/services/lending/lending_info/arbitrum/venus_arbitrum.py +10 -0
  35. defi_services/services/lending/lending_info/base/__init__.py +0 -0
  36. defi_services/services/lending/lending_info/base/aave_v3_base.py +61 -0
  37. defi_services/services/lending/lending_info/base/compound_v3_base.py +116 -0
  38. defi_services/services/lending/lending_info/base/granary_base.py +62 -0
  39. defi_services/services/lending/lending_info/base/ionic_base.py +173 -0
  40. defi_services/services/lending/lending_info/base/moonwell_base.py +89 -0
  41. defi_services/services/lending/lending_info/base/radiant_v2_base.py +57 -0
  42. defi_services/services/lending/lending_info/base/sonne_base.py +53 -0
  43. defi_services/services/lending/lending_info/base/zerolend_base.py +109 -0
  44. defi_services/services/lending/lending_info/bsc/aave_v3_bsc.py +68 -0
  45. defi_services/services/lending/lending_info/bsc/apeswap_bsc.py +1 -1
  46. defi_services/services/lending/lending_info/ethereum/aave_v3_eth.py +1 -140
  47. defi_services/services/lending/lending_info/ethereum/compound_v3_eth.py +180 -5
  48. defi_services/services/lending/lending_info/ethereum/old_aave_v3_eth.py +150 -0
  49. defi_services/services/lending/lending_info/ethereum/radiant_eth.py +69 -0
  50. defi_services/services/lending/lending_info/ethereum/venus_eth.py +10 -0
  51. defi_services/services/lending/lending_info/ethereum/zerolend_eth.py +96 -0
  52. defi_services/services/lending/lending_info/optimism/compound_v3_optimism.py +116 -0
  53. defi_services/services/lending/lending_info/optimism/moonwell_optimism.py +9 -0
  54. defi_services/services/lending/lending_info/polygon/compound_v3_polygon.py +35 -5
  55. defi_services/services/lending/lending_info/zksync/__init__.py +0 -0
  56. defi_services/services/lending/lending_info/zksync/aave_v3_zksync.py +47 -0
  57. defi_services/services/lending/lending_info/zksync/venus_zksync.py +10 -0
  58. defi_services/services/lending/lending_info/zksync/zerolend_zksync.py +138 -0
  59. defi_services/services/lending/moonwell_service.py +120 -0
  60. defi_services/services/lending/morpho_aave_v2_services.py +3 -3
  61. defi_services/services/lending/morpho_aave_v3_services.py +2 -2
  62. defi_services/services/lending/radiant_v2_services.py +52 -10
  63. defi_services/services/lending/sonne_service.py +64 -0
  64. defi_services/services/lending/trava_services.py +2 -2
  65. defi_services/services/lending/uwu_services.py +3 -3
  66. defi_services/services/lending/valas_services.py +2 -2
  67. defi_services/services/lending/venus_services.py +9 -3
  68. defi_services/services/lending/zerolend_services.py +36 -0
  69. defi_services/services/multicall/multicall_v2.py +0 -317
  70. defi_services/services/vault/tcv_vault_services.py +108 -0
  71. defi_services/services/vault/vault_info/arbitrum/__init__.py +0 -0
  72. defi_services/services/vault/vault_info/arbitrum/tcv_arb.py +58 -0
  73. {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/METADATA +1 -1
  74. {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/RECORD +84 -47
  75. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/__init__.py +0 -0
  76. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/aave_v2_event_abi.py +0 -0
  77. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/aave_v2_incentives_abi.py +0 -0
  78. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/lending_pool_abi.py +0 -0
  79. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/oracle_abi.py +0 -0
  80. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/staked_incentives_abi.py +0 -0
  81. /defi_services/abis/lending/{aave_v2_and_forlks → aave_v2_and_forks}/uwu_incentives_abi.py +0 -0
  82. {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/WHEEL +0 -0
  83. {defi_state_querier-0.5.28.dist-info → defi_state_querier-0.5.29.dist-info}/licenses/LICENSE +0 -0
  84. {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
- key = f"allPendingRewards_{self.name}_{wallet}_{block_number}".lower()
69
- rpc_calls[key] = self.get_function_incentive_info(
70
- "allPendingRewards", [wallet], block_number)
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
- reward_token = self.pool_info['rewardToken']
77
- key = f"allPendingRewards_{self.name}_{wallet}_{block_number}".lower()
78
- rewards = decoded_data.get(key) / 10 ** 18
79
- result = {
80
- reward_token: {"amount": rewards}
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.aave_v2_and_forlks.oracle_abi import ORACLE_ABI
7
- from defi_services.abis.lending.aave_v2_and_forlks.staked_incentives_abi import STAKED_INCENTIVES_ABI
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.aave_v2_and_forlks.lending_pool_abi import LENDING_POOL_ABI
7
- from defi_services.abis.lending.aave_v2_and_forlks.oracle_abi import ORACLE_ABI
8
- from defi_services.abis.lending.aave_v2_and_forlks.uwu_incentives_abi import UWU_INCENTIVES_ABI
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.aave_v2_and_forlks.lending_pool_abi import LENDING_POOL_ABI
7
- from defi_services.abis.lending.aave_v2_and_forlks.oracle_abi import ORACLE_ABI
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 = self.lens_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(w3.to_checksum_address(wallet), w3.to_checksum_address(self.pool_info.get("comptrollerAddress"))).call(block_identifier=block_number)
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)