defi-state-querier 0.0.7__py3-none-any.whl → 0.0.9__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 (33) hide show
  1. defi_services/__init__.py +1 -1
  2. defi_services/abis/lending/morpho/__init__.py +0 -0
  3. defi_services/abis/lending/morpho/morpho_aave_v2_comptroller_abi.py +2301 -0
  4. defi_services/abis/lending/morpho/morpho_aave_v2_lens_abi.py +1208 -0
  5. defi_services/abis/lending/morpho/morpho_aave_v3_comptroller_abi.py +2994 -0
  6. defi_services/abis/lending/morpho/morpho_compound_comptroller_abi.py +2301 -0
  7. defi_services/abis/lending/morpho/morpho_compound_lens_abi.py +1402 -0
  8. defi_services/abis/lending/morpho/morpho_compound_reward_manager_abi.py +307 -0
  9. defi_services/constants/entities/lending_constant.py +6 -1
  10. defi_services/constants/entities/lending_services.py +7 -1
  11. defi_services/constants/query_constant.py +1 -0
  12. defi_services/jobs/processors/substrate_state_processor.py +97 -0
  13. defi_services/jobs/queriers/substrate_state_querier.py +84 -0
  14. defi_services/services/lending/aave_v3_services.py +4 -2
  15. defi_services/services/lending/compound_service.py +20 -2
  16. defi_services/services/lending/flux_services.py +30 -22
  17. defi_services/services/lending/iron_bank_service.py +19 -10
  18. defi_services/services/lending/lending_info/aave_v2_services.py +1 -1
  19. defi_services/services/lending/lending_info/ethereum/morpho_aave_v2_eth.py +53 -0
  20. defi_services/services/lending/lending_info/ethereum/morpho_aave_v3_eth.py +51 -0
  21. defi_services/services/lending/lending_info/ethereum/morpho_compound_eth.py +44 -0
  22. defi_services/services/lending/morpho_aave_v2_services.py +89 -0
  23. defi_services/services/lending/morpho_aave_v3_services.py +159 -0
  24. defi_services/services/lending/morpho_compound_services.py +233 -0
  25. defi_services/services/lending/onyx_service.py +23 -3
  26. defi_services/services/lending/strike_service.py +22 -3
  27. defi_services/services/lending/venus_services.py +19 -0
  28. defi_services/services/substrate_token_services.py +70 -0
  29. {defi_state_querier-0.0.7.dist-info → defi_state_querier-0.0.9.dist-info}/METADATA +1 -1
  30. {defi_state_querier-0.0.7.dist-info → defi_state_querier-0.0.9.dist-info}/RECORD +33 -17
  31. {defi_state_querier-0.0.7.dist-info → defi_state_querier-0.0.9.dist-info}/LICENSE +0 -0
  32. {defi_state_querier-0.0.7.dist-info → defi_state_querier-0.0.9.dist-info}/WHEEL +0 -0
  33. {defi_state_querier-0.0.7.dist-info → defi_state_querier-0.0.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,307 @@
1
+ import json
2
+
3
+ MORPHO_COMPOUND_REWARD_MANAGER_ABI = json.loads('''
4
+ [
5
+ {
6
+ "inputs": [],
7
+ "stateMutability": "nonpayable",
8
+ "type": "constructor"
9
+ },
10
+ {
11
+ "inputs": [],
12
+ "name": "InvalidCToken",
13
+ "type": "error"
14
+ },
15
+ {
16
+ "inputs": [],
17
+ "name": "OnlyMorpho",
18
+ "type": "error"
19
+ },
20
+ {
21
+ "inputs": [
22
+ {
23
+ "internalType": "address",
24
+ "name": "_user",
25
+ "type": "address"
26
+ },
27
+ {
28
+ "internalType": "address",
29
+ "name": "_poolToken",
30
+ "type": "address"
31
+ },
32
+ {
33
+ "internalType": "uint256",
34
+ "name": "_userBalance",
35
+ "type": "uint256"
36
+ }
37
+ ],
38
+ "name": "accrueUserBorrowUnclaimedRewards",
39
+ "outputs": [],
40
+ "stateMutability": "nonpayable",
41
+ "type": "function"
42
+ },
43
+ {
44
+ "inputs": [
45
+ {
46
+ "internalType": "address",
47
+ "name": "_user",
48
+ "type": "address"
49
+ },
50
+ {
51
+ "internalType": "address",
52
+ "name": "_poolToken",
53
+ "type": "address"
54
+ },
55
+ {
56
+ "internalType": "uint256",
57
+ "name": "_userBalance",
58
+ "type": "uint256"
59
+ }
60
+ ],
61
+ "name": "accrueUserSupplyUnclaimedRewards",
62
+ "outputs": [],
63
+ "stateMutability": "nonpayable",
64
+ "type": "function"
65
+ },
66
+ {
67
+ "inputs": [
68
+ {
69
+ "internalType": "address[]",
70
+ "name": "_poolTokens",
71
+ "type": "address[]"
72
+ },
73
+ {
74
+ "internalType": "address",
75
+ "name": "_user",
76
+ "type": "address"
77
+ }
78
+ ],
79
+ "name": "claimRewards",
80
+ "outputs": [
81
+ {
82
+ "internalType": "uint256",
83
+ "name": "totalUnclaimedRewards",
84
+ "type": "uint256"
85
+ }
86
+ ],
87
+ "stateMutability": "nonpayable",
88
+ "type": "function"
89
+ },
90
+ {
91
+ "inputs": [
92
+ {
93
+ "internalType": "address",
94
+ "name": "",
95
+ "type": "address"
96
+ },
97
+ {
98
+ "internalType": "address",
99
+ "name": "",
100
+ "type": "address"
101
+ }
102
+ ],
103
+ "name": "compBorrowerIndex",
104
+ "outputs": [
105
+ {
106
+ "internalType": "uint256",
107
+ "name": "",
108
+ "type": "uint256"
109
+ }
110
+ ],
111
+ "stateMutability": "view",
112
+ "type": "function"
113
+ },
114
+ {
115
+ "inputs": [
116
+ {
117
+ "internalType": "address",
118
+ "name": "",
119
+ "type": "address"
120
+ },
121
+ {
122
+ "internalType": "address",
123
+ "name": "",
124
+ "type": "address"
125
+ }
126
+ ],
127
+ "name": "compSupplierIndex",
128
+ "outputs": [
129
+ {
130
+ "internalType": "uint256",
131
+ "name": "",
132
+ "type": "uint256"
133
+ }
134
+ ],
135
+ "stateMutability": "view",
136
+ "type": "function"
137
+ },
138
+ {
139
+ "inputs": [],
140
+ "name": "comptroller",
141
+ "outputs": [
142
+ {
143
+ "internalType": "contract IComptroller",
144
+ "name": "",
145
+ "type": "address"
146
+ }
147
+ ],
148
+ "stateMutability": "view",
149
+ "type": "function"
150
+ },
151
+ {
152
+ "inputs": [
153
+ {
154
+ "internalType": "address",
155
+ "name": "_poolToken",
156
+ "type": "address"
157
+ }
158
+ ],
159
+ "name": "getLocalCompBorrowState",
160
+ "outputs": [
161
+ {
162
+ "components": [
163
+ {
164
+ "internalType": "uint224",
165
+ "name": "index",
166
+ "type": "uint224"
167
+ },
168
+ {
169
+ "internalType": "uint32",
170
+ "name": "block",
171
+ "type": "uint32"
172
+ }
173
+ ],
174
+ "internalType": "struct IComptroller.CompMarketState",
175
+ "name": "",
176
+ "type": "tuple"
177
+ }
178
+ ],
179
+ "stateMutability": "view",
180
+ "type": "function"
181
+ },
182
+ {
183
+ "inputs": [
184
+ {
185
+ "internalType": "address",
186
+ "name": "_poolToken",
187
+ "type": "address"
188
+ }
189
+ ],
190
+ "name": "getLocalCompSupplyState",
191
+ "outputs": [
192
+ {
193
+ "components": [
194
+ {
195
+ "internalType": "uint224",
196
+ "name": "index",
197
+ "type": "uint224"
198
+ },
199
+ {
200
+ "internalType": "uint32",
201
+ "name": "block",
202
+ "type": "uint32"
203
+ }
204
+ ],
205
+ "internalType": "struct IComptroller.CompMarketState",
206
+ "name": "",
207
+ "type": "tuple"
208
+ }
209
+ ],
210
+ "stateMutability": "view",
211
+ "type": "function"
212
+ },
213
+ {
214
+ "inputs": [
215
+ {
216
+ "internalType": "address",
217
+ "name": "_morpho",
218
+ "type": "address"
219
+ }
220
+ ],
221
+ "name": "initialize",
222
+ "outputs": [],
223
+ "stateMutability": "nonpayable",
224
+ "type": "function"
225
+ },
226
+ {
227
+ "inputs": [
228
+ {
229
+ "internalType": "address",
230
+ "name": "",
231
+ "type": "address"
232
+ }
233
+ ],
234
+ "name": "localCompBorrowState",
235
+ "outputs": [
236
+ {
237
+ "internalType": "uint224",
238
+ "name": "index",
239
+ "type": "uint224"
240
+ },
241
+ {
242
+ "internalType": "uint32",
243
+ "name": "block",
244
+ "type": "uint32"
245
+ }
246
+ ],
247
+ "stateMutability": "view",
248
+ "type": "function"
249
+ },
250
+ {
251
+ "inputs": [
252
+ {
253
+ "internalType": "address",
254
+ "name": "",
255
+ "type": "address"
256
+ }
257
+ ],
258
+ "name": "localCompSupplyState",
259
+ "outputs": [
260
+ {
261
+ "internalType": "uint224",
262
+ "name": "index",
263
+ "type": "uint224"
264
+ },
265
+ {
266
+ "internalType": "uint32",
267
+ "name": "block",
268
+ "type": "uint32"
269
+ }
270
+ ],
271
+ "stateMutability": "view",
272
+ "type": "function"
273
+ },
274
+ {
275
+ "inputs": [],
276
+ "name": "morpho",
277
+ "outputs": [
278
+ {
279
+ "internalType": "contract IMorpho",
280
+ "name": "",
281
+ "type": "address"
282
+ }
283
+ ],
284
+ "stateMutability": "view",
285
+ "type": "function"
286
+ },
287
+ {
288
+ "inputs": [
289
+ {
290
+ "internalType": "address",
291
+ "name": "",
292
+ "type": "address"
293
+ }
294
+ ],
295
+ "name": "userUnclaimedCompRewards",
296
+ "outputs": [
297
+ {
298
+ "internalType": "uint256",
299
+ "name": "",
300
+ "type": "uint256"
301
+ }
302
+ ],
303
+ "stateMutability": "view",
304
+ "type": "function"
305
+ }
306
+ ]
307
+ ''')
@@ -17,5 +17,10 @@ class Lending:
17
17
  onyx = "onyx-protocol"
18
18
  granary = "granary-finance"
19
19
  wepiggy = "wepiggy"
20
+ morpho_compound = 'morpho-compound'
21
+ morpho_aave_v2 = 'morpho-aave'
22
+ morpho_aave_v3 = 'morpho-aavev3'
20
23
  all = [strike, aave_v2, aave_v3, radiant_v2, compound, flux, onyx, granary,
21
- iron_bank, trava, valas, geist, cream, venus, liqee, strike, uwu, wepiggy]
24
+ iron_bank, trava, valas, geist, cream, venus, liqee, strike, uwu, wepiggy,
25
+ morpho_compound, morpho_aave_v2, morpho_aave_v3
26
+ ]
@@ -2,6 +2,9 @@ from defi_services.constants.chain_constant import Chain
2
2
  from defi_services.constants.entities.lending_constant import Lending
3
3
  from defi_services.services.lending.aave_v2_services import AaveV2StateService
4
4
  from defi_services.services.lending.granary_v1_services import GranaryV1StateService
5
+ from defi_services.services.lending.morpho_aave_v2_services import MorphoAaveV2Services
6
+ from defi_services.services.lending.morpho_aave_v3_services import MorphoAaveV3Services
7
+ from defi_services.services.lending.morpho_compound_services import MorphoCompoundServices
5
8
  from defi_services.services.lending.uwu_services import UwuStateService
6
9
  from defi_services.services.lending.aave_v3_services import AaveV3StateService
7
10
  from defi_services.services.lending.compound_service import CompoundStateService
@@ -33,7 +36,10 @@ class LendingServices:
33
36
  Lending.strike: StrikeStateService,
34
37
  Lending.onyx: OnyxStateService,
35
38
  Lending.granary: GranaryV1StateService,
36
- Lending.wepiggy: WepiggyStateService
39
+ Lending.wepiggy: WepiggyStateService,
40
+ Lending.morpho_aave_v3: MorphoAaveV3Services,
41
+ Lending.morpho_aave_v2: MorphoAaveV2Services,
42
+ Lending.morpho_compound: MorphoCompoundServices
37
43
  }
38
44
  fantom = {
39
45
  Lending.trava: TravaStateService,
@@ -4,6 +4,7 @@ class Query:
4
4
  function = "function"
5
5
  params = "params"
6
6
  block_number = "block_number"
7
+ module = "module"
7
8
 
8
9
  # query types
9
10
  token_balance = 'token_balance'
@@ -0,0 +1,97 @@
1
+ import logging
2
+
3
+ from defi_services.constants.entities.lending_constant import Lending
4
+ from defi_services.constants.query_constant import Query
5
+ from defi_services.database.mongodb import MongoDB
6
+ from defi_services.jobs.queriers.substrate_state_querier import SubstrateStateQuerier
7
+ from defi_services.services.substrate_token_services import SubstrateTokenServices
8
+
9
+ logger = logging.getLogger("SubstrateStateProcessor")
10
+
11
+
12
+ class SubstrateStateProcessor:
13
+ def __init__(self, provider_uri: str, chain_id: str, mongodb: MongoDB = None):
14
+ self.mongodb = mongodb
15
+ self.state_querier = SubstrateStateQuerier(provider_uri)
16
+ self.chain_id = chain_id
17
+ self.token_service = SubstrateTokenServices(self.state_querier, chain_id)
18
+
19
+ def get_service_info(self):
20
+ info = self.token_service.get_service_info()
21
+ return info
22
+
23
+ def get_token_prices(self, tokens):
24
+ return self.mongodb.get_token_prices(tokens, self.chain_id)
25
+
26
+ def init_rpc_call_information(
27
+ self, wallet: str, query_id: str, entity_id: str, query_type: str, block_number: int = 'latest'):
28
+ queries = {}
29
+ tokens = []
30
+ rpc_calls = {}
31
+ if entity_id not in Lending.all and query_type in [Query.token_balance, Query.nft_balance]:
32
+ rpc_calls.update(self.token_service.get_function_info(wallet, entity_id, block_number))
33
+ tokens.append(entity_id)
34
+
35
+ queries[entity_id] = rpc_calls
36
+ tokens = list(set(tokens))
37
+ return {query_id: queries}, tokens
38
+
39
+ def execute_rpc_calls(self, queries: dict):
40
+ rpc_calls = {}
41
+ for query, query_info in queries.items():
42
+ for entity, entity_value in query_info.items():
43
+ rpc_calls.update(entity_value)
44
+
45
+ decoded_data = self.state_querier.query_state_data(rpc_calls)
46
+ result = {}
47
+ for query, query_info in queries.items():
48
+ query_data = {}
49
+ for entity, entity_value in query_info.items():
50
+ entity_data = {}
51
+ for key, value in entity_value.items():
52
+ entity_data[key] = decoded_data.get(key)
53
+ query_data[entity] = entity_data
54
+ result[query] = query_data
55
+
56
+ return result
57
+
58
+ def process_decoded_data(
59
+ self, query_id: str, query_type: str, wallet: str,
60
+ token_prices: dict, decoded_data: dict):
61
+ result = {
62
+ "query_id": query_id,
63
+ "query_type": query_type
64
+ }
65
+ query_value = decoded_data.get(query_id)
66
+ for entity, entity_value in query_value.items():
67
+ result["entity_id"] = entity
68
+ data = None
69
+ if entity not in Lending.all and query_type in [Query.nft_balance, Query.token_balance]:
70
+ data = self.token_service.get_data(wallet, entity, entity_value, token_prices)
71
+ result[query_type] = data
72
+
73
+ return result
74
+
75
+ def run(self, wallet: str, queries: list, block_number: int = 'latest'):
76
+ all_rpc_calls, all_tokens = {}, []
77
+ for query in queries:
78
+ query_id = query.get("query_id")
79
+ entity_id = query.get("entity_id")
80
+ query_type = query.get("query_type")
81
+ rpc_calls, tokens = self.init_rpc_call_information(
82
+ wallet, query_id, entity_id, query_type, block_number)
83
+ all_rpc_calls.update(rpc_calls)
84
+ all_tokens += tokens
85
+ result = []
86
+ decoded_data = self.execute_rpc_calls(all_rpc_calls)
87
+ token_prices = {}
88
+ if self.mongodb:
89
+ token_prices = self.get_token_prices(all_tokens)
90
+ for query in queries:
91
+ query_id = query.get("query_id")
92
+ query_type = query.get("query_type")
93
+ processed_data = self.process_decoded_data(
94
+ query_id, query_type, wallet, token_prices, decoded_data)
95
+ result.append(processed_data)
96
+
97
+ return result
@@ -0,0 +1,84 @@
1
+ import logging
2
+
3
+ from substrateinterface import SubstrateInterface
4
+ from defi_services.constants.query_constant import Query
5
+
6
+ logger = logging.getLogger("SubstrateStateQuerier")
7
+
8
+
9
+ class SubstrateStateQuerier:
10
+ def __init__(self, provider_uri):
11
+ self.provider_uri = provider_uri
12
+ self.client_querier = SubstrateInterface(provider_uri)
13
+
14
+ def get_client_querier(self):
15
+ return self.client_querier
16
+
17
+ @staticmethod
18
+ def get_function_info(module: str, fn_name: str, fn_paras: list = None, block_number: int = "latest"):
19
+ if fn_paras is None:
20
+ fn_paras = []
21
+ data = {
22
+ "module": module,
23
+ "function": fn_name,
24
+ "params": fn_paras,
25
+ "block_number": block_number
26
+ }
27
+
28
+ return data
29
+
30
+ def query_state_data(self, queries: dict):
31
+ """
32
+ Args:
33
+ queries: dict - defi state queries
34
+ - key: str - id of query
35
+ - value: dict - input of query
36
+ {
37
+ function: str - name of the function,
38
+ params: list - list parameters of function
39
+ }
40
+ ignore_error: bool - ignore error when decode result or not
41
+
42
+ Return:
43
+ + A dictionary result of queries
44
+ - key: str - id of query
45
+ - value: result of query
46
+ """
47
+ block_hash, rpc_call, list_call_id = {}, {}, []
48
+ for key, value in queries.items():
49
+ module = value.get(Query.module)
50
+ fn_paras = value.get(Query.params)
51
+ fn_name = value.get(Query.function)
52
+ block_number = value.get(Query.block_number)
53
+ if block_number not in rpc_call:
54
+ rpc_call[block_number] = []
55
+ if block_number != "latest" and block_number not in block_hash:
56
+ block_hash[block_number] = self.client_querier.get_block_hash(block_number)
57
+ eth_call = self.add_rpc_call(module=module, fn_name=fn_name, fn_paras=fn_paras)
58
+ list_call_id.append(key)
59
+ rpc_call[block_number].append(eth_call)
60
+ decoded_data = {}
61
+ for block_number, list_rpc_call in rpc_call.items():
62
+ if block_number != "latest":
63
+ response_data = self.client_querier.query_multi(list_rpc_call, block_hash.get(block_number))
64
+ else:
65
+ response_data = self.client_querier.query_multi(list_rpc_call)
66
+
67
+ decoded_data.update(self.decode_response_data(response_data, block_number))
68
+ return decoded_data
69
+
70
+ def add_rpc_call(self, module: str, fn_name: str, fn_paras: list = None):
71
+ call = self.client_querier.create_storage_key(module, fn_name, fn_paras)
72
+ return call
73
+
74
+ @staticmethod
75
+ def decode_response_data(response_data: list, block_number: int = "latest"):
76
+ decoded_data = {}
77
+ for data in response_data:
78
+ storage_key = data[0]
79
+ storage_value = data[1]
80
+ key = f"{storage_key.pallet}_{storage_key.storage_function}_{storage_key.params}_{block_number}".lower()
81
+ value = storage_value.value_serialized
82
+ decoded_data[key] = value
83
+
84
+ return decoded_data
@@ -5,6 +5,7 @@ from web3 import Web3
5
5
  from defi_services.abis.lending.aave_v3.aave_v3_incentives_abi import AAVE_V3_INCENTIVES_ABI
6
6
  from defi_services.abis.lending.aave_v3.aave_v3_lending_pool_abi import AAVE_V3_LENDING_POOL_ABI
7
7
  from defi_services.abis.lending.aave_v3.aave_v3_oracle_abi import AAVE_V3_ORACLE_ABI
8
+ from defi_services.abis.lending.morpho.morpho_aave_v3_comptroller_abi import MORPHO_AAVE_V3_COMPTROLLER_ABI
8
9
  from defi_services.abis.token.erc20_abi import ERC20_ABI
9
10
  from defi_services.constants.chain_constant import Chain
10
11
  from defi_services.constants.db_constant import DBConst
@@ -22,7 +23,7 @@ from defi_services.services.lending.lending_info.polygon.aave_v3_polygon import
22
23
  logger = logging.getLogger("Aave V3 Lending Pool State Service")
23
24
 
24
25
 
25
- class AaveInfo:
26
+ class AaveV3Info:
26
27
  mapping = {
27
28
  Chain.ethereum: AAVE_V3_ETH,
28
29
  Chain.polygon: AAVE_V3_POLYGON,
@@ -38,10 +39,11 @@ class AaveV3StateService(AaveV2StateService):
38
39
  super().__init__(state_service, chain_id)
39
40
  self.name = f"{chain_id}_{Lending.aave_v3}"
40
41
  self.chain_id = chain_id
41
- self.pool_info = AaveInfo.mapping.get(chain_id)
42
+ self.pool_info = AaveV3Info.mapping.get(chain_id)
42
43
  self.lending_abi = AAVE_V3_LENDING_POOL_ABI
43
44
  self.incentive_abi = AAVE_V3_INCENTIVES_ABI
44
45
  self.oracle_abi = AAVE_V3_ORACLE_ABI
46
+ self.comptroller_abi = MORPHO_AAVE_V3_COMPTROLLER_ABI
45
47
  self.state_service = state_service
46
48
 
47
49
  def get_service_info(self):
@@ -106,7 +106,7 @@ class CompoundStateService(ProtocolServices):
106
106
  ))
107
107
 
108
108
  if Query.protocol_reward in query_types and wallet:
109
- result.update(self.calculate_rewards_balance(
109
+ result.update(self.calculate_claimable_rewards_balance(
110
110
  wallet, decoded_data, block_number
111
111
  ))
112
112
 
@@ -139,7 +139,7 @@ class CompoundStateService(ProtocolServices):
139
139
  rpc_calls.update(self.get_apy_lending_pool_function_info(reserves_info, block_number, is_oracle_price))
140
140
 
141
141
  if Query.protocol_reward in query_types and wallet:
142
- rpc_calls.update(self.get_rewards_balance_function_info(wallet, block_number))
142
+ rpc_calls.update(self.get_claimable_rewards_balance_function_info(wallet, block_number))
143
143
 
144
144
  logger.info(f"Get encoded rpc calls in {time.time() - begin}s")
145
145
  return rpc_calls
@@ -304,6 +304,24 @@ class CompoundStateService(ProtocolServices):
304
304
  }
305
305
 
306
306
  # REWARDS BALANCE
307
+ def get_claimable_rewards_balance_function_info(
308
+ self,
309
+ wallet_address: str,
310
+ block_number: int = "latest",
311
+ ):
312
+ rpc_call = self.get_comptroller_function_info("compAccrued", [wallet_address], block_number)
313
+ get_reward_id = f"compAccrued_{self.name}_{wallet_address}_{block_number}".lower()
314
+ return {get_reward_id: rpc_call}
315
+
316
+ def calculate_claimable_rewards_balance(self, wallet_address: str, decoded_data: dict, block_number: int = "latest"):
317
+ get_reward_id = f"compAccrued_{self.name}_{wallet_address}_{block_number}".lower()
318
+ rewards = decoded_data.get(get_reward_id) / 10 ** 18
319
+ reward_token = self.pool_info.get("rewardToken")
320
+ result = {
321
+ reward_token: {"amount": rewards}
322
+ }
323
+ return result
324
+
307
325
  def get_rewards_balance_function_info(
308
326
  self,
309
327
  wallet_address: str,