wayfinder-paths 0.1.22__py3-none-any.whl → 0.1.23__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.
Potentially problematic release.
This version of wayfinder-paths might be problematic. Click here for more details.
- wayfinder_paths/__init__.py +0 -4
- wayfinder_paths/adapters/balance_adapter/README.md +0 -1
- wayfinder_paths/adapters/balance_adapter/adapter.py +65 -169
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +41 -113
- wayfinder_paths/adapters/brap_adapter/README.md +22 -75
- wayfinder_paths/adapters/brap_adapter/adapter.py +187 -576
- wayfinder_paths/adapters/brap_adapter/examples.json +21 -140
- wayfinder_paths/adapters/brap_adapter/test_adapter.py +6 -234
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +39 -86
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +5 -1
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +6 -5
- wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
- wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
- wayfinder_paths/adapters/moonwell_adapter/adapter.py +108 -198
- wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +37 -23
- wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
- wayfinder_paths/core/__init__.py +0 -3
- wayfinder_paths/core/clients/BRAPClient.py +3 -0
- wayfinder_paths/core/clients/ClientManager.py +0 -7
- wayfinder_paths/core/clients/LedgerClient.py +196 -172
- wayfinder_paths/core/clients/WayfinderClient.py +0 -1
- wayfinder_paths/core/clients/__init__.py +0 -5
- wayfinder_paths/core/clients/protocols.py +0 -13
- wayfinder_paths/core/config.py +0 -164
- wayfinder_paths/core/constants/__init__.py +58 -2
- wayfinder_paths/core/constants/base.py +8 -22
- wayfinder_paths/core/constants/chains.py +36 -0
- wayfinder_paths/core/constants/contracts.py +39 -0
- wayfinder_paths/core/constants/tokens.py +9 -0
- wayfinder_paths/core/strategies/Strategy.py +0 -10
- wayfinder_paths/core/utils/evm_helpers.py +5 -15
- wayfinder_paths/core/utils/tokens.py +28 -0
- wayfinder_paths/core/utils/transaction.py +13 -7
- wayfinder_paths/core/utils/web3.py +5 -3
- wayfinder_paths/policies/enso.py +1 -2
- wayfinder_paths/policies/hyper_evm.py +6 -3
- wayfinder_paths/policies/hyperlend.py +1 -2
- wayfinder_paths/policies/moonwell.py +12 -7
- wayfinder_paths/policies/prjx.py +1 -3
- wayfinder_paths/run_strategy.py +97 -300
- wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -1
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +19 -14
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +12 -11
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +20 -33
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +21 -18
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -130
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +32 -42
- {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/METADATA +2 -3
- {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/RECORD +51 -60
- {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/WHEEL +1 -1
- wayfinder_paths/core/clients/WalletClient.py +0 -41
- wayfinder_paths/core/engine/StrategyJob.py +0 -110
- wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
- wayfinder_paths/templates/adapter/README.md +0 -150
- wayfinder_paths/templates/adapter/adapter.py +0 -16
- wayfinder_paths/templates/adapter/examples.json +0 -8
- wayfinder_paths/templates/adapter/test_adapter.py +0 -30
- wayfinder_paths/templates/strategy/README.md +0 -186
- wayfinder_paths/templates/strategy/examples.json +0 -11
- wayfinder_paths/templates/strategy/strategy.py +0 -35
- wayfinder_paths/templates/strategy/test_strategy.py +0 -166
- wayfinder_paths/tests/test_smoke_manifest.py +0 -63
- {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/LICENSE +0 -0
wayfinder_paths/__init__.py
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
__version__ = "0.1.0"
|
|
2
2
|
|
|
3
|
-
# Re-export commonly used items for convenience
|
|
4
3
|
from wayfinder_paths.core import (
|
|
5
4
|
BaseAdapter,
|
|
6
|
-
LiquidationResult,
|
|
7
5
|
StatusDict,
|
|
8
6
|
StatusTuple,
|
|
9
7
|
Strategy,
|
|
10
|
-
StrategyJob,
|
|
11
8
|
)
|
|
12
9
|
|
|
13
10
|
__all__ = [
|
|
@@ -16,5 +13,4 @@ __all__ = [
|
|
|
16
13
|
"Strategy",
|
|
17
14
|
"StatusDict",
|
|
18
15
|
"StatusTuple",
|
|
19
|
-
"StrategyJob",
|
|
20
16
|
]
|
|
@@ -4,9 +4,8 @@ from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
|
|
|
4
4
|
from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
|
|
5
5
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
6
6
|
from wayfinder_paths.core.clients.TokenClient import TokenClient
|
|
7
|
-
from wayfinder_paths.core.clients.WalletClient import WalletClient
|
|
8
7
|
from wayfinder_paths.core.utils.evm_helpers import resolve_chain_id
|
|
9
|
-
from wayfinder_paths.core.utils.tokens import build_send_transaction
|
|
8
|
+
from wayfinder_paths.core.utils.tokens import build_send_transaction, get_token_balance
|
|
10
9
|
from wayfinder_paths.core.utils.transaction import send_transaction
|
|
11
10
|
|
|
12
11
|
|
|
@@ -22,61 +21,27 @@ class BalanceAdapter(BaseAdapter):
|
|
|
22
21
|
super().__init__("balance", config)
|
|
23
22
|
self.main_wallet_signing_callback = main_wallet_signing_callback
|
|
24
23
|
self.strategy_wallet_signing_callback = strategy_wallet_signing_callback
|
|
25
|
-
self.wallet_client = WalletClient()
|
|
26
24
|
self.token_client = TokenClient()
|
|
27
25
|
self.token_adapter = TokenAdapter()
|
|
28
26
|
self.ledger_adapter = LedgerAdapter()
|
|
29
27
|
|
|
30
|
-
def _parse_balance(self, raw: Any) -> int:
|
|
31
|
-
if raw is None:
|
|
32
|
-
return 0
|
|
33
|
-
try:
|
|
34
|
-
return int(raw)
|
|
35
|
-
except (ValueError, TypeError):
|
|
36
|
-
try:
|
|
37
|
-
return int(float(raw))
|
|
38
|
-
except (ValueError, TypeError):
|
|
39
|
-
return 0
|
|
40
|
-
|
|
41
28
|
async def get_balance(
|
|
42
29
|
self,
|
|
43
30
|
*,
|
|
44
|
-
query: str | dict[str, Any] | None = None,
|
|
45
|
-
token_id: str | None = None,
|
|
46
31
|
wallet_address: str,
|
|
32
|
+
token_id: str | None = None,
|
|
33
|
+
token_address: str | None = None,
|
|
47
34
|
chain_id: int | None = None,
|
|
48
|
-
) -> tuple[bool,
|
|
49
|
-
effective_query = query if query is not None else token_id
|
|
50
|
-
resolved = (
|
|
51
|
-
effective_query
|
|
52
|
-
if isinstance(effective_query, str)
|
|
53
|
-
else (effective_query or {}).get("token_id")
|
|
54
|
-
)
|
|
55
|
-
if not resolved:
|
|
56
|
-
return (False, "missing query")
|
|
35
|
+
) -> tuple[bool, int | str]:
|
|
57
36
|
try:
|
|
58
|
-
if
|
|
59
|
-
token_info = await self.token_client.get_token_details(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return (False, f"Token {resolved} is missing a chain id")
|
|
65
|
-
chain_id = resolved_chain_id
|
|
66
|
-
|
|
67
|
-
data = await self.wallet_client.get_token_balance_for_address(
|
|
68
|
-
wallet_address=wallet_address,
|
|
69
|
-
query=resolved,
|
|
70
|
-
chain_id=int(chain_id),
|
|
71
|
-
)
|
|
72
|
-
raw = (
|
|
73
|
-
data.get("balance_raw") or data.get("balance")
|
|
74
|
-
if isinstance(data, dict)
|
|
75
|
-
else None
|
|
76
|
-
)
|
|
77
|
-
return (True, self._parse_balance(raw))
|
|
37
|
+
if token_id and not token_address:
|
|
38
|
+
token_info = await self.token_client.get_token_details(token_id)
|
|
39
|
+
token_address = token_info["address"]
|
|
40
|
+
chain_id = chain_id or resolve_chain_id(token_info)
|
|
41
|
+
balance = await get_token_balance(token_address, chain_id, wallet_address)
|
|
42
|
+
return True, balance
|
|
78
43
|
except Exception as e:
|
|
79
|
-
return
|
|
44
|
+
return False, str(e)
|
|
80
45
|
|
|
81
46
|
async def move_from_main_wallet_to_strategy_wallet(
|
|
82
47
|
self,
|
|
@@ -84,16 +49,17 @@ class BalanceAdapter(BaseAdapter):
|
|
|
84
49
|
amount: float,
|
|
85
50
|
strategy_name: str = "unknown",
|
|
86
51
|
skip_ledger: bool = False,
|
|
87
|
-
) -> tuple[bool,
|
|
52
|
+
) -> tuple[bool, str]:
|
|
88
53
|
return await self._move_between_wallets(
|
|
89
54
|
token_id=token_id,
|
|
90
55
|
amount=amount,
|
|
91
|
-
from_wallet=self.config
|
|
92
|
-
to_wallet=self.config
|
|
93
|
-
ledger_method=self.ledger_adapter.record_deposit
|
|
56
|
+
from_wallet=self.config["main_wallet"],
|
|
57
|
+
to_wallet=self.config["strategy_wallet"],
|
|
58
|
+
ledger_method=self.ledger_adapter.record_deposit
|
|
59
|
+
if not skip_ledger
|
|
60
|
+
else None,
|
|
94
61
|
ledger_wallet="to",
|
|
95
62
|
strategy_name=strategy_name,
|
|
96
|
-
skip_ledger=skip_ledger,
|
|
97
63
|
)
|
|
98
64
|
|
|
99
65
|
async def move_from_strategy_wallet_to_main_wallet(
|
|
@@ -102,55 +68,36 @@ class BalanceAdapter(BaseAdapter):
|
|
|
102
68
|
amount: float,
|
|
103
69
|
strategy_name: str = "unknown",
|
|
104
70
|
skip_ledger: bool = False,
|
|
105
|
-
) -> tuple[bool,
|
|
71
|
+
) -> tuple[bool, str]:
|
|
106
72
|
return await self._move_between_wallets(
|
|
107
73
|
token_id=token_id,
|
|
108
74
|
amount=amount,
|
|
109
|
-
from_wallet=self.config
|
|
110
|
-
to_wallet=self.config
|
|
111
|
-
ledger_method=self.ledger_adapter.record_withdrawal
|
|
75
|
+
from_wallet=self.config["strategy_wallet"],
|
|
76
|
+
to_wallet=self.config["main_wallet"],
|
|
77
|
+
ledger_method=self.ledger_adapter.record_withdrawal
|
|
78
|
+
if not skip_ledger
|
|
79
|
+
else None,
|
|
112
80
|
ledger_wallet="from",
|
|
113
81
|
strategy_name=strategy_name,
|
|
114
|
-
skip_ledger=skip_ledger,
|
|
115
82
|
)
|
|
116
83
|
|
|
117
84
|
async def send_to_address(
|
|
118
85
|
self,
|
|
119
86
|
token_id: str,
|
|
120
87
|
amount: int,
|
|
121
|
-
from_wallet: dict[str, Any]
|
|
88
|
+
from_wallet: dict[str, Any],
|
|
122
89
|
to_address: str,
|
|
123
|
-
signing_callback
|
|
124
|
-
|
|
125
|
-
) -> tuple[bool, Any]:
|
|
126
|
-
from_address = self._wallet_address(from_wallet)
|
|
127
|
-
if not from_address:
|
|
128
|
-
return False, "from_wallet missing or invalid"
|
|
129
|
-
|
|
130
|
-
if not to_address:
|
|
131
|
-
return False, "to_address is required"
|
|
132
|
-
|
|
90
|
+
signing_callback,
|
|
91
|
+
) -> tuple[bool, str]:
|
|
133
92
|
token_info = await self.token_client.get_token_details(token_id)
|
|
134
|
-
|
|
135
|
-
return False, f"Token not found: {token_id}"
|
|
136
|
-
|
|
137
|
-
chain_id = resolve_chain_id(token_info, self.logger)
|
|
138
|
-
if chain_id is None:
|
|
139
|
-
return False, f"Token {token_id} is missing chain_id"
|
|
140
|
-
|
|
141
|
-
token_address = token_info.get("address")
|
|
142
|
-
|
|
93
|
+
chain_id = resolve_chain_id(token_info)
|
|
143
94
|
tx = await build_send_transaction(
|
|
144
|
-
from_address=
|
|
95
|
+
from_address=from_wallet["address"],
|
|
145
96
|
to_address=to_address,
|
|
146
|
-
token_address=
|
|
97
|
+
token_address=token_info["address"],
|
|
147
98
|
chain_id=chain_id,
|
|
148
|
-
amount=
|
|
99
|
+
amount=amount,
|
|
149
100
|
)
|
|
150
|
-
|
|
151
|
-
if not signing_callback:
|
|
152
|
-
return False, "signing_callback is required"
|
|
153
|
-
|
|
154
101
|
tx_hash = await send_transaction(tx, signing_callback)
|
|
155
102
|
return True, tx_hash
|
|
156
103
|
|
|
@@ -159,79 +106,63 @@ class BalanceAdapter(BaseAdapter):
|
|
|
159
106
|
*,
|
|
160
107
|
token_id: str,
|
|
161
108
|
amount: float,
|
|
162
|
-
from_wallet: dict[str, Any]
|
|
163
|
-
to_wallet: dict[str, Any]
|
|
109
|
+
from_wallet: dict[str, Any],
|
|
110
|
+
to_wallet: dict[str, Any],
|
|
164
111
|
ledger_method,
|
|
165
112
|
ledger_wallet: str,
|
|
166
113
|
strategy_name: str,
|
|
167
|
-
|
|
168
|
-
) -> tuple[bool, Any]:
|
|
169
|
-
from_address = self._wallet_address(from_wallet)
|
|
170
|
-
to_address = self._wallet_address(to_wallet)
|
|
171
|
-
if not from_address or not to_address:
|
|
172
|
-
return False, "main_wallet or strategy_wallet missing"
|
|
173
|
-
|
|
114
|
+
) -> tuple[bool, str]:
|
|
174
115
|
token_info = await self.token_client.get_token_details(token_id)
|
|
175
|
-
|
|
176
|
-
return False, f"Token not found: {token_id}"
|
|
177
|
-
|
|
178
|
-
chain_id = resolve_chain_id(token_info, self.logger)
|
|
179
|
-
if chain_id is None:
|
|
180
|
-
return False, f"Token {token_id} is missing chain_id"
|
|
181
|
-
|
|
116
|
+
chain_id = resolve_chain_id(token_info)
|
|
182
117
|
decimals = token_info.get("decimals", 18)
|
|
183
118
|
raw_amount = int(amount * (10**decimals))
|
|
184
119
|
|
|
185
|
-
|
|
186
|
-
from_address=
|
|
187
|
-
to_address=
|
|
188
|
-
token_address=token_info
|
|
120
|
+
transaction = await build_send_transaction(
|
|
121
|
+
from_address=from_wallet["address"],
|
|
122
|
+
to_address=to_wallet["address"],
|
|
123
|
+
token_address=token_info["address"],
|
|
189
124
|
chain_id=chain_id,
|
|
190
125
|
amount=raw_amount,
|
|
191
126
|
)
|
|
192
|
-
broadcast_result = await self._send_tx(tx, from_address)
|
|
193
127
|
|
|
194
|
-
|
|
195
|
-
|
|
128
|
+
main_address = self.config.get("main_wallet", {}).get("address", "").lower()
|
|
129
|
+
callback = (
|
|
130
|
+
self.main_wallet_signing_callback
|
|
131
|
+
if from_wallet["address"].lower() == main_address
|
|
132
|
+
else self.strategy_wallet_signing_callback
|
|
133
|
+
)
|
|
134
|
+
tx_hash = await send_transaction(transaction, callback)
|
|
135
|
+
|
|
136
|
+
if ledger_method:
|
|
137
|
+
wallet_for_ledger = (
|
|
138
|
+
from_wallet["address"]
|
|
139
|
+
if ledger_wallet == "from"
|
|
140
|
+
else to_wallet["address"]
|
|
141
|
+
)
|
|
196
142
|
await self._record_ledger_entry(
|
|
197
|
-
ledger_method
|
|
198
|
-
wallet_address=wallet_for_ledger,
|
|
199
|
-
token_info=token_info,
|
|
200
|
-
amount=amount,
|
|
201
|
-
strategy_name=strategy_name,
|
|
143
|
+
ledger_method, wallet_for_ledger, token_info, amount, strategy_name
|
|
202
144
|
)
|
|
203
145
|
|
|
204
|
-
return
|
|
205
|
-
|
|
206
|
-
async def _send_tx(self, tx: dict[str, Any], from_address: str) -> tuple[bool, Any]:
|
|
207
|
-
main_wallet = self.config.get("main_wallet") or {}
|
|
208
|
-
main_addr = main_wallet.get("address", "").lower()
|
|
209
|
-
|
|
210
|
-
if from_address.lower() == main_addr:
|
|
211
|
-
callback = self.main_wallet_signing_callback
|
|
212
|
-
else:
|
|
213
|
-
callback = self.strategy_wallet_signing_callback
|
|
214
|
-
|
|
215
|
-
txn_hash = await send_transaction(tx, callback)
|
|
216
|
-
return True, txn_hash
|
|
146
|
+
return True, tx_hash
|
|
217
147
|
|
|
218
148
|
async def _record_ledger_entry(
|
|
219
149
|
self,
|
|
220
|
-
*,
|
|
221
150
|
ledger_method,
|
|
222
151
|
wallet_address: str,
|
|
223
152
|
token_info: dict[str, Any],
|
|
224
153
|
amount: float,
|
|
225
154
|
strategy_name: str,
|
|
226
155
|
) -> None:
|
|
227
|
-
chain_id = resolve_chain_id(token_info, self.logger)
|
|
228
|
-
if chain_id is None:
|
|
229
|
-
return
|
|
230
|
-
|
|
231
|
-
usd_value = await self._token_amount_usd(token_info, amount)
|
|
232
156
|
try:
|
|
233
|
-
|
|
234
|
-
|
|
157
|
+
chain_id = resolve_chain_id(token_info)
|
|
158
|
+
token_id = token_info.get("token_id")
|
|
159
|
+
usd_value = (
|
|
160
|
+
await self.token_adapter.get_amount_usd(
|
|
161
|
+
token_info.get("token_id"), amount, decimals=0
|
|
162
|
+
)
|
|
163
|
+
or 0.0
|
|
164
|
+
)
|
|
165
|
+
await ledger_method(
|
|
235
166
|
wallet_address=wallet_address,
|
|
236
167
|
chain_id=chain_id,
|
|
237
168
|
token_address=token_info.get("address"),
|
|
@@ -244,40 +175,5 @@ class BalanceAdapter(BaseAdapter):
|
|
|
244
175
|
},
|
|
245
176
|
strategy_name=strategy_name,
|
|
246
177
|
)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
"Ledger entry failed",
|
|
250
|
-
wallet=wallet_address,
|
|
251
|
-
token_id=token_id,
|
|
252
|
-
amount=amount,
|
|
253
|
-
error=response,
|
|
254
|
-
)
|
|
255
|
-
except Exception as exc: # noqa: BLE001
|
|
256
|
-
token_id = token_info.get("token_id") or token_info.get("id")
|
|
257
|
-
self.logger.warning(
|
|
258
|
-
f"Ledger entry raised: {exc}",
|
|
259
|
-
wallet=wallet_address,
|
|
260
|
-
token_id=token_id,
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
async def _token_amount_usd(
|
|
264
|
-
self, token_info: dict[str, Any], amount: float
|
|
265
|
-
) -> float:
|
|
266
|
-
token_id = token_info.get("token_id")
|
|
267
|
-
if not token_id:
|
|
268
|
-
return 0.0
|
|
269
|
-
success, price_data = await self.token_adapter.get_token_price(token_id)
|
|
270
|
-
if not success or not price_data:
|
|
271
|
-
return 0.0
|
|
272
|
-
return float(price_data.get("current_price", 0.0)) * float(amount)
|
|
273
|
-
|
|
274
|
-
def _wallet_address(self, wallet: dict[str, Any] | None) -> str | None:
|
|
275
|
-
if not wallet:
|
|
276
|
-
return None
|
|
277
|
-
address = wallet.get("address")
|
|
278
|
-
if address:
|
|
279
|
-
return str(address)
|
|
280
|
-
evm_wallet = wallet.get("evm") if isinstance(wallet, dict) else None
|
|
281
|
-
if isinstance(evm_wallet, dict):
|
|
282
|
-
return evm_wallet.get("address")
|
|
283
|
-
return None
|
|
178
|
+
except Exception as exc:
|
|
179
|
+
self.logger.warning(f"Ledger entry failed: {exc}", wallet=wallet_address)
|
|
@@ -6,27 +6,15 @@ from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class TestBalanceAdapter:
|
|
9
|
-
@pytest.fixture
|
|
10
|
-
def mock_wallet_client(self):
|
|
11
|
-
mock_client = AsyncMock()
|
|
12
|
-
return mock_client
|
|
13
|
-
|
|
14
9
|
@pytest.fixture
|
|
15
10
|
def mock_token_client(self):
|
|
16
|
-
|
|
17
|
-
return mock_client
|
|
11
|
+
return AsyncMock()
|
|
18
12
|
|
|
19
13
|
@pytest.fixture
|
|
20
|
-
def adapter(self,
|
|
21
|
-
with (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return_value=mock_wallet_client,
|
|
25
|
-
),
|
|
26
|
-
patch(
|
|
27
|
-
"wayfinder_paths.adapters.balance_adapter.adapter.TokenClient",
|
|
28
|
-
return_value=mock_token_client,
|
|
29
|
-
),
|
|
14
|
+
def adapter(self, mock_token_client):
|
|
15
|
+
with patch(
|
|
16
|
+
"wayfinder_paths.adapters.balance_adapter.adapter.TokenClient",
|
|
17
|
+
return_value=mock_token_client,
|
|
30
18
|
):
|
|
31
19
|
return BalanceAdapter(config={})
|
|
32
20
|
|
|
@@ -45,118 +33,58 @@ class TestBalanceAdapter:
|
|
|
45
33
|
assert adapter.adapter_type == "BALANCE"
|
|
46
34
|
|
|
47
35
|
@pytest.mark.asyncio
|
|
48
|
-
async def
|
|
49
|
-
self, adapter, mock_token_client, mock_wallet_client
|
|
50
|
-
):
|
|
36
|
+
async def test_get_balance_with_token_id(self, adapter, mock_token_client):
|
|
51
37
|
mock_token_client.get_token_details = AsyncMock(
|
|
52
38
|
return_value={
|
|
53
39
|
"token_id": "usd-coin-base",
|
|
54
|
-
"address": "
|
|
40
|
+
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
55
41
|
"chain": {"id": 8453, "code": "base"},
|
|
56
42
|
}
|
|
57
43
|
)
|
|
58
|
-
mock_wallet_client.get_token_balance_for_address = AsyncMock(
|
|
59
|
-
return_value={"balance": 1000000}
|
|
60
|
-
)
|
|
61
44
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
45
|
+
with patch(
|
|
46
|
+
"wayfinder_paths.adapters.balance_adapter.adapter.get_token_balance",
|
|
47
|
+
new_callable=AsyncMock,
|
|
48
|
+
return_value=1000000,
|
|
49
|
+
) as mock_get_balance:
|
|
50
|
+
success, balance = await adapter.get_balance(
|
|
51
|
+
token_id="usd-coin-base",
|
|
52
|
+
wallet_address="0xWallet",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
assert success
|
|
56
|
+
assert balance == 1000000
|
|
57
|
+
mock_token_client.get_token_details.assert_called_once_with("usd-coin-base")
|
|
58
|
+
mock_get_balance.assert_called_once_with(
|
|
59
|
+
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", 8453, "0xWallet"
|
|
60
|
+
)
|
|
75
61
|
|
|
76
62
|
@pytest.mark.asyncio
|
|
77
|
-
async def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return_value=
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
wallet_address="0x123",
|
|
94
|
-
)
|
|
95
|
-
assert success
|
|
96
|
-
assert balance == 3000000
|
|
97
|
-
mock_token_client.get_token_details.assert_called_once_with("wsteth-base")
|
|
98
|
-
mock_wallet_client.get_token_balance_for_address.assert_called_once_with(
|
|
99
|
-
wallet_address="0x123",
|
|
100
|
-
query="wsteth-base",
|
|
101
|
-
chain_id=8453,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
@pytest.mark.asyncio
|
|
105
|
-
async def test_get_balance_missing_query(self, adapter):
|
|
106
|
-
success, result = await adapter.get_balance(query={}, wallet_address="0xabc")
|
|
107
|
-
assert success is False
|
|
108
|
-
assert "missing query" in str(result)
|
|
109
|
-
|
|
110
|
-
@pytest.mark.asyncio
|
|
111
|
-
async def test_get_balance_with_pool_address(
|
|
112
|
-
self, adapter, mock_token_client, mock_wallet_client
|
|
113
|
-
):
|
|
114
|
-
mock_wallet_client.get_token_balance_for_address = AsyncMock(
|
|
115
|
-
return_value={"balance": 5000000}
|
|
116
|
-
)
|
|
117
|
-
mock_token_client.get_token_details = AsyncMock()
|
|
118
|
-
|
|
119
|
-
success, balance = await adapter.get_balance(
|
|
120
|
-
query="0xPoolAddress",
|
|
121
|
-
wallet_address="0xWallet",
|
|
122
|
-
chain_id=8453,
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
assert success
|
|
126
|
-
assert balance == 5000000
|
|
127
|
-
mock_wallet_client.get_token_balance_for_address.assert_called_once_with(
|
|
128
|
-
wallet_address="0xWallet",
|
|
129
|
-
query="0xPoolAddress",
|
|
130
|
-
chain_id=8453,
|
|
131
|
-
)
|
|
132
|
-
mock_token_client.get_token_details.assert_not_called()
|
|
63
|
+
async def test_get_balance_with_token_address(self, adapter, mock_token_client):
|
|
64
|
+
with patch(
|
|
65
|
+
"wayfinder_paths.adapters.balance_adapter.adapter.get_token_balance",
|
|
66
|
+
new_callable=AsyncMock,
|
|
67
|
+
return_value=5000000,
|
|
68
|
+
) as mock_get_balance:
|
|
69
|
+
success, balance = await adapter.get_balance(
|
|
70
|
+
token_address="0xTokenAddress",
|
|
71
|
+
wallet_address="0xWallet",
|
|
72
|
+
chain_id=8453,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
assert success
|
|
76
|
+
assert balance == 5000000
|
|
77
|
+
mock_get_balance.assert_called_once_with("0xTokenAddress", 8453, "0xWallet")
|
|
78
|
+
mock_token_client.get_token_details.assert_not_called()
|
|
133
79
|
|
|
134
80
|
@pytest.mark.asyncio
|
|
135
81
|
async def test_get_balance_token_not_found(self, adapter, mock_token_client):
|
|
136
82
|
mock_token_client.get_token_details = AsyncMock(return_value=None)
|
|
137
83
|
|
|
138
84
|
success, error = await adapter.get_balance(
|
|
139
|
-
|
|
140
|
-
wallet_address="0xWallet",
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
assert success is False
|
|
144
|
-
assert "Token not found" in str(error)
|
|
145
|
-
|
|
146
|
-
@pytest.mark.asyncio
|
|
147
|
-
async def test_get_balance_missing_chain_id(self, adapter, mock_token_client):
|
|
148
|
-
mock_token_client.get_token_details = AsyncMock(
|
|
149
|
-
return_value={
|
|
150
|
-
"token_id": "token-without-chain",
|
|
151
|
-
"address": "0x123",
|
|
152
|
-
"chain": {},
|
|
153
|
-
}
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
success, error = await adapter.get_balance(
|
|
157
|
-
query="token-without-chain",
|
|
85
|
+
token_id="invalid-token",
|
|
158
86
|
wallet_address="0xWallet",
|
|
159
87
|
)
|
|
160
88
|
|
|
161
89
|
assert success is False
|
|
162
|
-
assert "
|
|
90
|
+
assert "NoneType" in error or "subscriptable" in error
|