defi-state-querier 0.0.6__py3-none-any.whl → 0.0.9__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) 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/abis/lending/radiant_v2/__init__.py +0 -0
  10. defi_services/abis/lending/radiant_v2/radiant_v2_incentive_abi.py +1016 -0
  11. defi_services/abis/lending/wepiggy/__init__.py +0 -0
  12. defi_services/abis/lending/wepiggy/wepiggy_distribution_abi.py +1047 -0
  13. defi_services/constants/chain_constant.py +1 -0
  14. defi_services/constants/entities/lending_constant.py +26 -0
  15. defi_services/constants/entities/lending_services.py +85 -0
  16. defi_services/constants/query_constant.py +1 -0
  17. defi_services/constants/token_constant.py +2 -0
  18. defi_services/jobs/processors/__init__.py +0 -0
  19. defi_services/jobs/processors/solana_state_processor.py +101 -0
  20. defi_services/jobs/{state_processor.py → processors/state_processor.py} +9 -4
  21. defi_services/jobs/processors/substrate_state_processor.py +97 -0
  22. defi_services/jobs/queriers/__init__.py +0 -0
  23. defi_services/jobs/queriers/solana_state_querier.py +83 -0
  24. defi_services/jobs/{state_querier.py → queriers/state_querier.py} +3 -2
  25. defi_services/jobs/queriers/substrate_state_querier.py +84 -0
  26. defi_services/services/lending/aave_v2_services.py +8 -7
  27. defi_services/services/lending/aave_v3_services.py +12 -9
  28. defi_services/services/lending/compound_service.py +29 -10
  29. defi_services/services/lending/cream_services.py +5 -4
  30. defi_services/services/lending/flux_services.py +34 -27
  31. defi_services/services/lending/geist_services.py +4 -3
  32. defi_services/services/lending/granary_v1_services.py +6 -7
  33. defi_services/services/lending/iron_bank_service.py +20 -13
  34. defi_services/services/lending/lending_info/aave_v2_services.py +2 -2
  35. defi_services/services/lending/lending_info/ethereum/morpho_aave_v2_eth.py +53 -0
  36. defi_services/services/lending/lending_info/ethereum/morpho_aave_v3_eth.py +51 -0
  37. defi_services/services/lending/lending_info/ethereum/morpho_compound_eth.py +44 -0
  38. defi_services/services/lending/lending_info/ethereum/wepiggy_eth.py +41 -0
  39. defi_services/services/lending/liqee_service.py +5 -26
  40. defi_services/services/lending/morpho_aave_v2_services.py +89 -0
  41. defi_services/services/lending/morpho_aave_v3_services.py +159 -0
  42. defi_services/services/lending/morpho_compound_services.py +233 -0
  43. defi_services/services/lending/onyx_service.py +32 -13
  44. defi_services/services/lending/radiant_v2_services.py +30 -3
  45. defi_services/services/lending/strike_service.py +29 -10
  46. defi_services/services/lending/trava_services.py +8 -7
  47. defi_services/services/lending/uwu_services.py +8 -7
  48. defi_services/services/lending/valas_services.py +6 -5
  49. defi_services/services/lending/venus_services.py +28 -8
  50. defi_services/services/lending/wepiggy_services.py +519 -0
  51. defi_services/services/nft_services.py +1 -1
  52. defi_services/services/solana_token_services.py +46 -0
  53. defi_services/services/substrate_token_services.py +70 -0
  54. defi_services/services/token_services.py +1 -3
  55. defi_services/utils/init_services.py +3 -3
  56. {defi_state_querier-0.0.6.dist-info → defi_state_querier-0.0.9.dist-info}/METADATA +3 -3
  57. {defi_state_querier-0.0.6.dist-info → defi_state_querier-0.0.9.dist-info}/RECORD +60 -32
  58. defi_services/constants/entities/lending.py +0 -97
  59. {defi_state_querier-0.0.6.dist-info → defi_state_querier-0.0.9.dist-info}/LICENSE +0 -0
  60. {defi_state_querier-0.0.6.dist-info → defi_state_querier-0.0.9.dist-info}/WHEEL +0 -0
  61. {defi_state_querier-0.0.6.dist-info → defi_state_querier-0.0.9.dist-info}/top_level.txt +0 -0
@@ -10,10 +10,11 @@ from defi_services.abis.lending.valas.valas_multi_fee_distribution import VALAS_
10
10
  from defi_services.abis.token.erc20_abi import ERC20_ABI
11
11
  from defi_services.constants.chain_constant import Chain
12
12
  from defi_services.constants.db_constant import DBConst
13
+ from defi_services.constants.entities.lending_constant import Lending
13
14
  from defi_services.constants.query_constant import Query
14
15
  from defi_services.constants.time_constant import TimeConstants
15
16
  from defi_services.constants.token_constant import Token
16
- from defi_services.jobs.state_querier import StateQuerier
17
+ from defi_services.jobs.queriers.state_querier import StateQuerier
17
18
  from defi_services.services.lending.lending_info.bsc.valas_bsc import VALAS_BSC
18
19
  from defi_services.services.protocol_services import ProtocolServices
19
20
 
@@ -28,7 +29,7 @@ class ValasInfo:
28
29
 
29
30
  class ValasStateService(ProtocolServices):
30
31
  def __init__(self, state_service: StateQuerier, chain_id: str = "0x38"):
31
- self.name = f"{chain_id}_valas-finance"
32
+ self.name = f"{chain_id}_{Lending.valas}"
32
33
  self.chain_id = chain_id
33
34
  self.pool_info = ValasInfo.mapping.get(chain_id)
34
35
  self.lending_abi = LENDING_POOL_ABI
@@ -40,7 +41,7 @@ class ValasStateService(ProtocolServices):
40
41
  # BASIC FUNCTION
41
42
  def get_service_info(self):
42
43
  info = {
43
- "valas-finance": {
44
+ Lending.valas: {
44
45
  "chain_id": self.chain_id,
45
46
  "type": "lending",
46
47
  "protocol_info": self.pool_info
@@ -387,7 +388,7 @@ class ValasStateService(ProtocolServices):
387
388
  block_number: int = "latest"
388
389
  ):
389
390
  rpc_calls = {}
390
- key = f"earnedBalances_{wallet_address}_{block_number}".lower()
391
+ key = f"earnedBalances_{self.name}_{wallet_address}_{block_number}".lower()
391
392
  rpc_calls[key] = self.get_function_multi_fee_distribution_info(
392
393
  "earnedBalances", [wallet_address], block_number)
393
394
 
@@ -396,7 +397,7 @@ class ValasStateService(ProtocolServices):
396
397
  def calculate_all_rewards_balance(
397
398
  self, decoded_data: dict, wallet_address: str, block_number: int = "latest"):
398
399
  reward_token = self.pool_info['rewardToken']
399
- key = f"earnedBalances_{wallet_address}_{block_number}".lower()
400
+ key = f"earnedBalances_{self.name}_{wallet_address}_{block_number}".lower()
400
401
  rewards = decoded_data.get(key)[0] / 10 ** 18
401
402
  result = {
402
403
  reward_token: {"amount": rewards}
@@ -6,8 +6,9 @@ from defi_services.abis.lending.venus.venus_comptroller_abi import VENUS_COMPTRO
6
6
  from defi_services.abis.lending.venus.venus_lens_abi import VENUS_LENS_ABI
7
7
  from defi_services.abis.token.erc20_abi import ERC20_ABI
8
8
  from defi_services.constants.chain_constant import Chain
9
+ from defi_services.constants.entities.lending_constant import Lending
9
10
  from defi_services.constants.token_constant import ContractAddresses, Token
10
- from defi_services.jobs.state_querier import StateQuerier
11
+ from defi_services.jobs.queriers.state_querier import StateQuerier
11
12
  from defi_services.services.lending.compound_service import CompoundStateService
12
13
  from defi_services.services.lending.lending_info.bsc.venus_bsc import VENUS_BSC
13
14
 
@@ -23,7 +24,7 @@ class VenusInfo:
23
24
  class VenusStateService(CompoundStateService):
24
25
  def __init__(self, state_service: StateQuerier, chain_id: str = "0x38"):
25
26
  super().__init__(state_service, chain_id)
26
- self.name = f"{chain_id}_venus"
27
+ self.name = f"{chain_id}_{Lending.venus}"
27
28
  self.chain_id = chain_id
28
29
  self.pool_info = VenusInfo.mapping.get(chain_id)
29
30
  self.state_service = state_service
@@ -34,7 +35,7 @@ class VenusStateService(CompoundStateService):
34
35
 
35
36
  def get_service_info(self):
36
37
  info = {
37
- "venus": {
38
+ Lending.venus: {
38
39
  "chain_id": self.chain_id,
39
40
  "type": "lending",
40
41
  "protocol_info": self.pool_info
@@ -83,10 +84,10 @@ class VenusStateService(CompoundStateService):
83
84
  ctoken = value.get("ctoken")
84
85
  speed_key = f"venusSpeeds_{ctoken}_{block_number}".lower()
85
86
  mint_key = f"mintGuardianPaused_{ctoken}_{block_number}".lower()
86
- borrow_key = f"borrowGuardianPaused_{token}_{block_number}".lower()
87
- metadata_key = f"vTokenMetadata_{token}_{block_number}".lower()
87
+ borrow_key = f"borrowGuardianPaused_{ctoken}_{block_number}".lower()
88
+ metadata_key = f"vTokenMetadata_{ctoken}_{block_number}".lower()
88
89
  if is_price_oracle:
89
- price_key = f"vTokenUnderlyingPrice_{token}_{block_number}".lower()
90
+ price_key = f"vTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
90
91
  rpc_calls[price_key] = self.get_comptroller_function_info(
91
92
  'vTokenUnderlyingPrice', [ctoken], block_number)
92
93
  rpc_calls[speed_key] = self.get_comptroller_function_info('venusSpeeds', [ctoken], block_number)
@@ -136,6 +137,25 @@ class VenusStateService(CompoundStateService):
136
137
  }
137
138
 
138
139
  # REWARDS BALANCE
140
+ def get_claimable_rewards_balance_function_info(
141
+ self,
142
+ wallet_address: str,
143
+ block_number: int = "latest",
144
+ ):
145
+ rpc_call = self.get_comptroller_function_info("venusAccrued", [wallet_address], block_number)
146
+ get_reward_id = f"venusAccrued_{self.name}_{wallet_address}_{block_number}".lower()
147
+ return {get_reward_id: rpc_call}
148
+
149
+ def calculate_claimable_rewards_balance(self, wallet_address: str, decoded_data: dict,
150
+ block_number: int = "latest"):
151
+ get_reward_id = f"venusAccrued_{self.name}_{wallet_address}_{block_number}".lower()
152
+ rewards = decoded_data.get(get_reward_id) / 10 ** 18
153
+ reward_token = self.pool_info.get("rewardToken")
154
+ result = {
155
+ reward_token: {"amount": rewards}
156
+ }
157
+ return result
158
+
139
159
  def get_rewards_balance_function_info(
140
160
  self,
141
161
  wallet_address: str,
@@ -146,11 +166,11 @@ class VenusStateService(CompoundStateService):
146
166
  Web3.toChecksumAddress(self.pool_info.get("comptrollerAddress"))
147
167
  ]
148
168
  rpc_call = self.get_lens_function_info("pendingVenus", fn_paras, block_number)
149
- get_reward_id = f"pendingVenus_{wallet_address}_{block_number}".lower()
169
+ get_reward_id = f"pendingVenus_{self.name}_{wallet_address}_{block_number}".lower()
150
170
  return {get_reward_id: rpc_call}
151
171
 
152
172
  def calculate_rewards_balance(self, wallet_address: str, decoded_data: dict, block_number: int = "latest"):
153
- get_reward_id = f"pendingVenus_{wallet_address}_{block_number}".lower()
173
+ get_reward_id = f"pendingVenus_{self.name}_{wallet_address}_{block_number}".lower()
154
174
  rewards = decoded_data.get(get_reward_id) / 10 ** 18
155
175
  reward_token = self.pool_info.get("rewardToken")
156
176
  result = {
@@ -0,0 +1,519 @@
1
+ import logging
2
+ import time
3
+
4
+ from web3 import Web3
5
+
6
+ from defi_services.abis.lending.cream.cream_comptroller_abi import CREAM_COMPTROLLER_ABI
7
+ from defi_services.abis.lending.cream.cream_lens_abi import CREAM_LENS_ABI
8
+ from defi_services.abis.lending.wepiggy.wepiggy_distribution_abi import WEPIGGY_DISTRIBUTION_ABI
9
+ from defi_services.abis.token.ctoken_abi import CTOKEN_ABI
10
+ from defi_services.abis.token.erc20_abi import ERC20_ABI
11
+ from defi_services.constants.chain_constant import Chain
12
+ from defi_services.constants.db_constant import DBConst
13
+ from defi_services.constants.entities.lending_constant import Lending
14
+ from defi_services.constants.query_constant import Query
15
+ from defi_services.constants.token_constant import ContractAddresses, Token
16
+ from defi_services.jobs.queriers.state_querier import StateQuerier
17
+ from defi_services.services.lending.lending_info.ethereum.wepiggy_eth import WEPIGGY_ETH
18
+ from defi_services.services.protocol_services import ProtocolServices
19
+
20
+ logger = logging.getLogger("Compound Lending Pool State Service")
21
+
22
+
23
+ class WepiggyInfo:
24
+ mapping = {
25
+ Chain.ethereum: WEPIGGY_ETH
26
+ }
27
+
28
+
29
+ class WepiggyStateService(ProtocolServices):
30
+ def __init__(self, state_service: StateQuerier, chain_id: str = "0x1"):
31
+ self.name = f"{chain_id}_{Lending.wepiggy}"
32
+ self.chain_id = chain_id
33
+ self.pool_info = WepiggyInfo.mapping.get(chain_id)
34
+ self.state_service = state_service
35
+ self.lens_abi = CREAM_LENS_ABI
36
+ self.distribution_abi = WEPIGGY_DISTRIBUTION_ABI
37
+ self.comptroller_abi = CREAM_COMPTROLLER_ABI
38
+
39
+ def get_service_info(self):
40
+ info = {
41
+ Lending.wepiggy: {
42
+ "chain_id": self.chain_id,
43
+ "type": "lending",
44
+ "protocol_info": self.pool_info
45
+ }
46
+ }
47
+ return info
48
+
49
+ def get_dapp_asset_info(
50
+ self,
51
+ block_number: int = "latest"):
52
+ _w3 = self.state_service.get_w3()
53
+ comptroller_contract = _w3.eth.contract(
54
+ address=_w3.toChecksumAddress(self.pool_info.get("comptrollerAddress")), abi=self.comptroller_abi)
55
+ ctokens = []
56
+ for token in comptroller_contract.functions.getAllMarkets().call(block_identifier=block_number):
57
+ if token in [ContractAddresses.LUNA.lower(), ContractAddresses.UST.lower(), ContractAddresses.LUNA,
58
+ ContractAddresses.UST]:
59
+ continue
60
+ ctokens.append(token)
61
+
62
+ lens_contract = _w3.eth.contract(
63
+ address=Web3.toChecksumAddress(self.pool_info.get("lensAddress")), abi=self.lens_abi
64
+ )
65
+ tokens = [Web3.toChecksumAddress(i) for i in ctokens]
66
+ metadata = lens_contract.functions.cTokenMetadataAll(tokens).call(block_identifier=block_number)
67
+ reserves_info = {}
68
+ for data in metadata:
69
+ underlying = data[11].lower()
70
+ ctoken = data[0].lower()
71
+ lt = data[10] / 10 ** 18
72
+ reserves_info[underlying] = {
73
+ "cToken": ctoken,
74
+ "liquidationThreshold": lt
75
+ }
76
+
77
+ return reserves_info
78
+
79
+ def get_token_list(self):
80
+ begin = time.time()
81
+ tokens = [self.pool_info.get('rewardToken'), self.pool_info.get("poolToken")]
82
+ for token in self.pool_info.get("reservesList"):
83
+ if token == Token.native_token:
84
+ tokens.append(Token.wrapped_token.get(self.chain_id))
85
+ continue
86
+ tokens.append(token)
87
+ logger.info(f"Get token list related in {time.time() - begin}s")
88
+ return tokens
89
+
90
+ def get_data(
91
+ self,
92
+ query_types: list,
93
+ wallet: str,
94
+ decoded_data: dict,
95
+ block_number: int = 'latest',
96
+ **kwargs
97
+ ):
98
+ begin = time.time()
99
+ reserves_info = kwargs.get("reserves_info", self.pool_info.get("reservesList"))
100
+ token_prices = kwargs.get("token_prices", {})
101
+ wrapped_native_token_price = token_prices.get(Token.wrapped_token.get(self.chain_id), 1)
102
+ pool_decimals = kwargs.get("pool_decimals", 18)
103
+ result = {}
104
+ if Query.deposit_borrow in query_types and wallet:
105
+ result.update(self.calculate_wallet_deposit_borrow_balance(
106
+ wallet, reserves_info, decoded_data, token_prices, wrapped_native_token_price, block_number
107
+ ))
108
+
109
+ if Query.protocol_reward in query_types and wallet:
110
+ result.update(self.calculate_rewards_balance(
111
+ wallet, decoded_data, block_number
112
+ ))
113
+
114
+ if Query.protocol_apy in query_types and wallet:
115
+ result.update(self.calculate_apy_lending_pool_function_call(
116
+ reserves_info, decoded_data, token_prices, pool_decimals, block_number
117
+ ))
118
+ logger.info(f"Process protocol data in {time.time() - begin}")
119
+ return result
120
+
121
+ def get_function_info(
122
+ self,
123
+ query_types: list,
124
+ wallet: str = None,
125
+ block_number: int = "latest",
126
+ **kwargs
127
+ ):
128
+ begin = time.time()
129
+ reserves_info = kwargs.get("reserves_info", {})
130
+ is_oracle_price = kwargs.get("is_oracle_price", False) # get price by oracle
131
+ if not reserves_info:
132
+ reserves_info = self.pool_info['reservesList']
133
+ rpc_calls = {}
134
+ if Query.deposit_borrow in query_types and wallet:
135
+ rpc_calls.update(self.get_wallet_deposit_borrow_balance_function_info(
136
+ wallet, reserves_info, block_number, is_oracle_price
137
+ ))
138
+
139
+ if Query.protocol_apy in query_types:
140
+ rpc_calls.update(self.get_apy_lending_pool_function_info(reserves_info, block_number, is_oracle_price))
141
+
142
+ if Query.protocol_reward in query_types and wallet:
143
+ rpc_calls.update(self.get_rewards_balance_function_info(wallet, block_number))
144
+
145
+ logger.info(f"Get encoded rpc calls in {time.time() - begin}s")
146
+ return rpc_calls
147
+
148
+ # CALCULATE APY LENDING POOL
149
+ def get_apy_lending_pool_function_info(
150
+ self,
151
+ reserves_info: dict,
152
+ block_number: int = "latest",
153
+ is_price_oracle: bool = False
154
+ ):
155
+ rpc_calls = {}
156
+ for token, value in reserves_info.items():
157
+ ctoken = value.get("ctoken")
158
+ speed_key = f"compSpeeds_{ctoken}_{block_number}".lower()
159
+ mint_key = f"mintGuardianPaused_{ctoken}_{block_number}".lower()
160
+ borrow_key = f"borrowGuardianPaused_{token}_{block_number}".lower()
161
+ metadata_key = f"cTokenMetadata_{ctoken}_{block_number}".lower()
162
+ if is_price_oracle:
163
+ price_key = f"cTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
164
+ rpc_calls[price_key] = self.get_comptroller_function_info('cTokenUnderlyingPrice', [ctoken],
165
+ block_number)
166
+ rpc_calls[speed_key] = self.get_comptroller_function_info('compSpeeds', [ctoken], block_number)
167
+ rpc_calls[mint_key] = self.get_comptroller_function_info('mintGuardianPaused', [ctoken], block_number)
168
+ rpc_calls[borrow_key] = self.get_comptroller_function_info('borrowGuardianPaused', [ctoken], block_number)
169
+ rpc_calls[metadata_key] = self.get_comptroller_function_info('cTokenMetadata', [ctoken], block_number)
170
+
171
+ return rpc_calls
172
+
173
+ @staticmethod
174
+ def get_apy_lending_pool(
175
+ decoded_data: dict,
176
+ reserves_info: dict,
177
+ block_number: int = "latest",
178
+ wrapped_native_token_price: float = 310,
179
+ underlying_price: dict = None,
180
+ is_oracle_price: bool = False
181
+ ):
182
+ underlying_prices, underlying_decimals, reserve_tokens_info = {}, {}, []
183
+ ctoken_speeds, borrow_paused_tokens, mint_paused_tokens = {}, {}, {}
184
+ for token, value in reserves_info.items():
185
+ ctoken = value.get('cToken')
186
+ speeds_call_id = f'compSpeeds_{ctoken}_{block_number}'.lower()
187
+ borrow_guardian_paused_call_id = f'borrowGuardianPaused_{ctoken}_{block_number}'.lower()
188
+ mint_guardian_paused_call_id = f'mintGuardianPaused_{ctoken}_{block_number}'.lower()
189
+ ctoken_speeds[ctoken] = decoded_data.get(speeds_call_id)
190
+ borrow_paused_tokens[ctoken] = decoded_data.get(borrow_guardian_paused_call_id)
191
+ mint_paused_tokens[ctoken] = decoded_data.get(mint_guardian_paused_call_id)
192
+ metadata_id = f"cTokenMetadata_{ctoken}_{block_number}".lower()
193
+ reserve_tokens_info.append(decoded_data.get(metadata_id))
194
+ if is_oracle_price:
195
+ underlying_id = f"cTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
196
+ price_token = decoded_data.get(underlying_id)
197
+ price_token = price_token[1] * wrapped_native_token_price
198
+ else:
199
+ price_token = underlying_price.get(token)
200
+
201
+ underlying_decimals[ctoken] = decoded_data.get(metadata_id)[-1]
202
+ underlying_prices[ctoken] = price_token
203
+ return {
204
+ "reserve_tokens_info": reserve_tokens_info,
205
+ "ctoken_speeds": ctoken_speeds,
206
+ "borrow_paused_tokens": borrow_paused_tokens,
207
+ "mint_paused_tokens": mint_paused_tokens,
208
+ "underlying_prices": underlying_prices,
209
+ "underlying_decimals": underlying_decimals
210
+ }
211
+
212
+ def calculate_apy_lending_pool_function_call(
213
+ self,
214
+ reserves_info: dict,
215
+ decoded_data: dict,
216
+ token_prices: dict,
217
+ pool_decimals: int = 18,
218
+ block_number: int = "latest",
219
+ is_oracle_price: bool = False,
220
+ ):
221
+ wrapped_native_token_price = token_prices.get(Token.wrapped_token.get(self.chain_id))
222
+ pool_token_price = token_prices.get(self.pool_info.get("poolToken"))
223
+ tokens_interest_rates = dict()
224
+ decode_data = self.get_apy_lending_pool(
225
+ decoded_data, reserves_info, block_number,
226
+ wrapped_native_token_price, token_prices, is_oracle_price)
227
+
228
+ mint_paused_tokens = decode_data["mint_paused_tokens"]
229
+ borrow_paused_tokens = decode_data["borrow_paused_tokens"]
230
+ reserve_tokens_info = decode_data["reserve_tokens_info"]
231
+ ctoken_speeds = decode_data["ctoken_speeds"]
232
+ for data in reserve_tokens_info:
233
+ address = data[0].lower()
234
+ underlying_token_price = float(decode_data["underlying_prices"][address])
235
+ if is_oracle_price:
236
+ underlying_token_price = underlying_token_price / 10 ** int(data[13])
237
+
238
+ token_info = {
239
+ "token": address,
240
+ "token_decimals": data[12],
241
+ "borrow_rate": data[3],
242
+ "supply_rate": data[2],
243
+ "supply": data[7],
244
+ "borrow": data[5],
245
+ "exchange_rate": data[1],
246
+ "underlying": data[11].lower(),
247
+ "underlying_price": underlying_token_price,
248
+ "underlying_decimals": data[13],
249
+ "speed": ctoken_speeds[address]
250
+ }
251
+ underlying_token = token_info['underlying']
252
+ token_info["mint_paused"] = mint_paused_tokens[address]
253
+ token_info["borrow_paused"] = borrow_paused_tokens[address]
254
+ tokens_interest_rates[underlying_token] = self._calculate_interest_rates(
255
+ token_info, pool_decimals, pool_token_price)
256
+
257
+ return tokens_interest_rates
258
+
259
+ @staticmethod
260
+ def _calculate_interest_rates(token_info: dict, pool_decimals: int, pool_price: float,
261
+ is_oracle_price: bool = False):
262
+ apx_block_speed_in_seconds = 3
263
+ exchange_rate = float(token_info["exchange_rate"]) / 10 ** (18 - 8 + token_info["underlying_decimals"])
264
+ block_per_day = int(60 * 60 * 24 / apx_block_speed_in_seconds)
265
+ venus_per_day = token_info["speed"] * block_per_day / 10 ** pool_decimals
266
+ underlying_price = float(token_info["underlying_price"])
267
+ if is_oracle_price:
268
+ underlying_price /= 10 ** (36 - int(token_info["underlying_decimals"]))
269
+ total_borrow = float(token_info["borrow"]) / 10 ** int(token_info["underlying_decimals"])
270
+ total_supply = float(token_info["supply"]) * exchange_rate / 10 ** int(token_info["underlying_decimals"])
271
+ total_borrow_usd = total_borrow * underlying_price
272
+ total_supply_usd = total_supply * underlying_price
273
+
274
+ if total_borrow_usd == 0:
275
+ borrow_apr = 0
276
+ else:
277
+ borrow_apr = (1 + (pool_price * venus_per_day / total_borrow_usd)) ** 365 - 1
278
+
279
+ if total_supply_usd == 0:
280
+ supply_apr = 0
281
+ else:
282
+ supply_apr = (1 + (pool_price * venus_per_day / total_supply_usd)) ** 365 - 1
283
+
284
+ supply_apy = ((token_info["supply_rate"] / 10 ** pool_decimals) * block_per_day + 1) ** 365 - 1
285
+ borrow_apy = ((token_info["borrow_rate"] / 10 ** pool_decimals) * block_per_day + 1) ** 365 - 1
286
+
287
+ liquidity_log = {
288
+ DBConst.total_borrow: {
289
+ DBConst.amount: total_borrow,
290
+ DBConst.value_in_usd: total_borrow_usd
291
+ },
292
+ DBConst.total_deposit: {
293
+ DBConst.amount: total_supply,
294
+ DBConst.value_in_usd: total_supply_usd
295
+ }
296
+ }
297
+ return {
298
+ DBConst.reward_borrow_apy: borrow_apr,
299
+ DBConst.reward_deposit_apy: supply_apr,
300
+ DBConst.deposit_apy: supply_apy,
301
+ DBConst.borrow_apy: borrow_apy,
302
+ DBConst.liquidity_change_logs: liquidity_log,
303
+ DBConst.mint_paused: token_info[DBConst.mint_paused],
304
+ DBConst.borrow_paused: token_info[DBConst.borrow_paused]
305
+ }
306
+
307
+ # REWARDS BALANCE
308
+ def get_rewards_balance_function_info(
309
+ self,
310
+ wallet_address: str,
311
+ block_number: int = "latest",
312
+ ):
313
+ token = self.pool_info.get("poolToken")
314
+ fn_paras = [Web3.toChecksumAddress(wallet_address),
315
+ False,
316
+ True]
317
+ rpc_call = self.get_distribution_function_info("pendingWpcAccrued", fn_paras, block_number)
318
+ get_reward_id = f"pendingWpcAccrued_{self.name}_{wallet_address}_{block_number}".lower()
319
+ return {get_reward_id: rpc_call}
320
+
321
+ def calculate_rewards_balance(self, wallet_address: str, decoded_data: dict, block_number: int = "latest"):
322
+ get_reward_id = f"pendingWpcAccrued_{self.name}_{wallet_address}_{block_number}".lower()
323
+ rewards = decoded_data.get(get_reward_id) / 10 ** 18
324
+ reward_token = self.pool_info.get("rewardToken")
325
+ result = {
326
+ reward_token: {"amount": rewards}
327
+ }
328
+ return result
329
+
330
+ # WALLET DEPOSIT BORROW BALANCE
331
+ def get_wallet_deposit_borrow_balance_function_info(
332
+ self,
333
+ wallet_address: str,
334
+ reserves_info: dict,
335
+ block_number: int = "latest",
336
+ is_oracle_price: bool = False
337
+ ):
338
+
339
+ rpc_calls = {}
340
+ for token, value in reserves_info.items():
341
+ underlying = token
342
+ ctoken = value.get('cToken')
343
+ if token == Token.native_token:
344
+ underlying = Token.wrapped_token.get(self.chain_id)
345
+ underlying_price_key = f"cTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
346
+ underlying_borrow_key = f"borrowBalanceCurrent_{ctoken}_{wallet_address}_{block_number}".lower()
347
+ underlying_balance_key = f"balanceOfUnderlying_{ctoken}_{wallet_address}_{block_number}".lower()
348
+ underlying_decimals_key = f"decimals_{underlying}_{block_number}".lower()
349
+ if is_oracle_price:
350
+ rpc_calls[underlying_price_key] = self.get_lens_function_info(
351
+ "cTokenUnderlyingPrice", [ctoken], block_number)
352
+ rpc_calls[underlying_borrow_key] = self.get_ctoken_function_info(
353
+ ctoken, "borrowBalanceCurrent", [wallet_address], block_number)
354
+ rpc_calls[underlying_balance_key] = self.get_ctoken_function_info(
355
+ ctoken, "balanceOfUnderlying", [wallet_address], block_number)
356
+ rpc_calls[underlying_decimals_key] = self.state_service.get_function_info(
357
+ underlying, ERC20_ABI, "decimals", [], block_number
358
+ )
359
+
360
+ return rpc_calls
361
+
362
+ def calculate_wallet_deposit_borrow_balance(
363
+ self, wallet_address: str, reserves_info: dict, decoded_data: dict, token_prices: dict = None,
364
+ wrapped_native_token_price: int = 310, block_number: int = "latest", is_oracle_price: bool = False):
365
+ if token_prices is None:
366
+ token_prices = {}
367
+ result = {}
368
+ for token, value in reserves_info.items():
369
+ underlying = token
370
+ ctoken = value.get("cToken")
371
+ if token == Token.native_token:
372
+ underlying = Token.wrapped_token.get(self.chain_id)
373
+ get_total_deposit_id = f"balanceOfUnderlying_{ctoken}_{wallet_address}_{block_number}".lower()
374
+ get_total_borrow_id = f"borrowBalanceCurrent_{ctoken}_{wallet_address}_{block_number}".lower()
375
+ get_decimals_id = f"decimals_{underlying}_{block_number}".lower()
376
+ decimals = decoded_data[get_decimals_id]
377
+ deposit_amount = decoded_data[get_total_deposit_id] / 10 ** decimals
378
+ borrow_amount = decoded_data[get_total_borrow_id] / 10 ** decimals
379
+ result[token] = {
380
+ "borrow_amount": borrow_amount,
381
+ "deposit_amount": deposit_amount,
382
+ }
383
+ if is_oracle_price:
384
+ get_underlying_token_price = f"cTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
385
+ token_price = decoded_data.get(get_underlying_token_price)[
386
+ 1] * wrapped_native_token_price / 10 ** decimals
387
+ elif token_prices:
388
+ token_price = token_prices.get(underlying)
389
+ else:
390
+ token_price = None
391
+ if token_price is not None:
392
+ deposit_amount_in_usd = deposit_amount * token_price
393
+ borrow_amount_in_usd = borrow_amount * token_price
394
+ result[token]['borrow_amount_in_usd'] += borrow_amount_in_usd
395
+ result[token]['deposit_amount_in_usd'] += deposit_amount_in_usd
396
+ return result
397
+
398
+ # TOKEN DEPOSIT BORROW BALANCE
399
+ def get_token_deposit_borrow_balance_function_info(
400
+ self,
401
+ reserves_info: dict,
402
+ block_number: int = "latest",
403
+ is_oracle_price: bool = False
404
+ ):
405
+ rpc_calls = {}
406
+ for token, value in reserves_info.items():
407
+ underlying = token
408
+ if token == Token.native_token:
409
+ underlying = Token.wrapped_token.get(self.chain_id)
410
+ ctoken = value.get('cToken')
411
+ underlying_price_key = f"cTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
412
+ underlying_borrow_key = f"totalBorrows_{ctoken}_{block_number}".lower()
413
+ underlying_balance_key = f"totalSupply_{ctoken}_{block_number}".lower()
414
+ underlying_decimals_key = f"decimals_{underlying}_{block_number}".lower()
415
+ ctoken_decimals_key = f"decimals_{ctoken}_{block_number}".lower()
416
+ exchange_rate_key = f"exchangeRateCurrent_{ctoken}_{block_number}".lower()
417
+ if is_oracle_price:
418
+ rpc_calls[underlying_price_key] = self.get_lens_function_info(
419
+ "cTokenUnderlyingPrice", [ctoken], block_number)
420
+ rpc_calls[underlying_borrow_key] = self.get_ctoken_function_info(
421
+ ctoken, "totalBorrows", [], block_number)
422
+ rpc_calls[underlying_balance_key] = self.get_ctoken_function_info(
423
+ ctoken, "totalSupply", [], block_number)
424
+ rpc_calls[underlying_decimals_key] = self.state_service.get_function_info(
425
+ underlying, ERC20_ABI, "decimals", [], block_number
426
+ )
427
+ rpc_calls[ctoken_decimals_key] = self.state_service.get_function_info(
428
+ ctoken, ERC20_ABI, "decimals", [], block_number
429
+ )
430
+ rpc_calls[exchange_rate_key] = self.get_ctoken_function_info(
431
+ ctoken, "exchangeRateCurrent", [], block_number)
432
+
433
+ return rpc_calls
434
+
435
+ def calculate_token_deposit_borrow_balance(
436
+ self, decoded_data: dict, reserves_info: dict, token_prices: dict = None,
437
+ block_number: int = "latest", is_oracle_price: bool = False, wrapped_native_token_price: int = 310
438
+ ):
439
+ result = {}
440
+ for token, value in reserves_info.items():
441
+ underlying = token
442
+ ctoken = value.get("cToken")
443
+ if token == Token.native_token:
444
+ underlying = Token.wrapped_token.get(self.chain_id)
445
+ get_total_deposit_id = f"totalSupply_{ctoken}_{block_number}".lower()
446
+ get_total_borrow_id = f"totalBorrows_{ctoken}_{block_number}".lower()
447
+ get_exchange_rate = f"exchangeRateCurrent_{ctoken}_{block_number}".lower()
448
+ get_decimals_id = f"decimals_{underlying}_{block_number}".lower()
449
+ get_ctoken_decimals_id = f"decimals_{ctoken}_{block_number}".lower()
450
+ decimals = decoded_data[get_decimals_id]
451
+ ctoken_decimals = decoded_data[get_ctoken_decimals_id]
452
+ exchange_rate = decoded_data[get_exchange_rate] / 10 ** (18 - 8 + decimals)
453
+ deposit_amount = decoded_data[get_total_deposit_id] * exchange_rate / 10 ** ctoken_decimals
454
+ borrow_amount = decoded_data[get_total_borrow_id] / 10 ** decimals
455
+ result[token] = {
456
+ "borrow_amount": borrow_amount,
457
+ "deposit_amount": deposit_amount
458
+ }
459
+ if is_oracle_price:
460
+ get_underlying_token_price = f"cTokenUnderlyingPrice_{ctoken}_{block_number}".lower()
461
+ token_price = decoded_data.get(get_underlying_token_price)[1] / 10 ** (36 - decimals)
462
+ if wrapped_native_token_price:
463
+ token_price *= wrapped_native_token_price
464
+ elif token_prices:
465
+ token_price = token_prices.get(underlying)
466
+ else:
467
+ token_price = None
468
+ if token_price is not None:
469
+ deposit_amount_in_usd = deposit_amount * token_price
470
+ borrow_amount_in_usd = borrow_amount * token_price
471
+ result[token]['borrow_amount_in_usd'] += borrow_amount_in_usd
472
+ result[token]['deposit_amount_in_usd'] += deposit_amount_in_usd
473
+ return result
474
+
475
+ def get_lens_function_info(self, fn_name: str, fn_paras: list, block_number: int = "latest"):
476
+ return self.state_service.get_function_info(
477
+ self.pool_info['lensAddress'], self.lens_abi, fn_name, fn_paras, block_number
478
+ )
479
+
480
+ def get_distribution_function_info(self, fn_name: str, fn_paras: list, block_number: int = "latest"):
481
+ return self.state_service.get_function_info(
482
+ self.pool_info['distributionAddress'], self.distribution_abi, fn_name, fn_paras, block_number
483
+ )
484
+
485
+ def get_comptroller_function_info(self, fn_name: str, fn_paras: list, block_number: int = "latest"):
486
+ return self.state_service.get_function_info(
487
+ self.pool_info['comptrollerAddress'], self.comptroller_abi, fn_name, fn_paras, block_number
488
+ )
489
+
490
+ def get_ctoken_function_info(self, ctoken: str, fn_name: str, fn_paras: list, block_number: int = "latest"):
491
+ return self.state_service.get_function_info(
492
+ ctoken, CTOKEN_ABI, fn_name, fn_paras, block_number
493
+ )
494
+
495
+ def get_ctoken_metadata_all(
496
+ self,
497
+ reserves_info: dict = None,
498
+ block_number: int = "latest"
499
+ ):
500
+ tokens = [Web3.toChecksumAddress(value['cToken']) for key, value in reserves_info.items()]
501
+ key = f"cTokenMetadataAll_{self.pool_info.get('lensAddress')}_{block_number}".lower()
502
+ return {
503
+ key: self.get_lens_function_info("cTokenMetadataAll", tokens, block_number)
504
+ }
505
+
506
+ def ctoken_underlying_price_all(
507
+ self, reserves_info, block_number: int = 'latest'):
508
+ tokens = [Web3.toChecksumAddress(value['cToken']) for key, value in reserves_info.items()]
509
+ key = f"cTokenUnderlyingPriceAll_{self.pool_info.get('lensAddress')}_{block_number}".lower()
510
+ return {
511
+ key: self.get_lens_function_info("cTokenUnderlyingPriceAll", tokens, block_number)
512
+ }
513
+
514
+ def get_all_markets(
515
+ self, block_number: int = 'latest'):
516
+ key = f"getAllMarkets_{self.pool_info.get('comptrollerAddress')}_{block_number}".lower()
517
+ return {
518
+ key: self.get_comptroller_function_info("getAllMarkets", [], block_number)
519
+ }
@@ -1,6 +1,6 @@
1
1
  from defi_services.abis.token.erc721_abi import ERC721_ABI
2
2
  from defi_services.constants.token_constant import Token
3
- from defi_services.jobs.state_querier import StateQuerier
3
+ from defi_services.jobs.queriers.state_querier import StateQuerier
4
4
 
5
5
 
6
6
  class NFTServices: