wayfinder-paths 0.1.23__py3-none-any.whl → 0.1.25__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 +2 -0
- wayfinder_paths/adapters/balance_adapter/adapter.py +250 -0
- wayfinder_paths/adapters/balance_adapter/manifest.yaml +8 -0
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -11
- wayfinder_paths/adapters/boros_adapter/__init__.py +17 -0
- wayfinder_paths/adapters/boros_adapter/adapter.py +1574 -0
- wayfinder_paths/adapters/boros_adapter/client.py +476 -0
- wayfinder_paths/adapters/boros_adapter/manifest.yaml +10 -0
- wayfinder_paths/adapters/boros_adapter/parsers.py +88 -0
- wayfinder_paths/adapters/boros_adapter/test_adapter.py +460 -0
- wayfinder_paths/adapters/boros_adapter/test_golden.py +156 -0
- wayfinder_paths/adapters/boros_adapter/types.py +70 -0
- wayfinder_paths/adapters/boros_adapter/utils.py +85 -0
- wayfinder_paths/adapters/brap_adapter/adapter.py +1 -1
- wayfinder_paths/adapters/brap_adapter/manifest.yaml +9 -0
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +161 -26
- wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +9 -0
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +77 -13
- wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +2 -9
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +585 -61
- wayfinder_paths/adapters/hyperliquid_adapter/executor.py +47 -68
- wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +14 -0
- wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +2 -3
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +17 -21
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +3 -6
- wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +4 -8
- wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +2 -2
- wayfinder_paths/adapters/ledger_adapter/manifest.yaml +7 -0
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +1 -2
- wayfinder_paths/adapters/moonwell_adapter/adapter.py +592 -400
- wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +14 -0
- wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +126 -219
- wayfinder_paths/adapters/multicall_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/multicall_adapter/adapter.py +166 -0
- wayfinder_paths/adapters/multicall_adapter/manifest.yaml +5 -0
- wayfinder_paths/adapters/multicall_adapter/test_adapter.py +97 -0
- wayfinder_paths/adapters/pendle_adapter/README.md +102 -0
- wayfinder_paths/adapters/pendle_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/pendle_adapter/adapter.py +1992 -0
- wayfinder_paths/adapters/pendle_adapter/examples.json +11 -0
- wayfinder_paths/adapters/pendle_adapter/manifest.yaml +21 -0
- wayfinder_paths/adapters/pendle_adapter/test_adapter.py +666 -0
- wayfinder_paths/adapters/pool_adapter/manifest.yaml +6 -0
- wayfinder_paths/adapters/token_adapter/examples.json +0 -4
- wayfinder_paths/adapters/token_adapter/manifest.yaml +7 -0
- wayfinder_paths/conftest.py +24 -17
- wayfinder_paths/core/__init__.py +2 -0
- wayfinder_paths/core/adapters/BaseAdapter.py +0 -25
- wayfinder_paths/core/adapters/models.py +17 -7
- wayfinder_paths/core/clients/BRAPClient.py +1 -1
- wayfinder_paths/core/clients/TokenClient.py +47 -1
- wayfinder_paths/core/clients/WayfinderClient.py +1 -2
- wayfinder_paths/core/clients/protocols.py +21 -22
- wayfinder_paths/core/clients/test_ledger_client.py +448 -0
- wayfinder_paths/core/config.py +12 -0
- wayfinder_paths/core/constants/__init__.py +15 -0
- wayfinder_paths/core/constants/base.py +6 -1
- wayfinder_paths/core/constants/contracts.py +39 -26
- wayfinder_paths/core/constants/erc20_abi.py +0 -1
- wayfinder_paths/core/constants/hyperlend_abi.py +0 -4
- wayfinder_paths/core/constants/hyperliquid.py +16 -0
- wayfinder_paths/core/constants/moonwell_abi.py +0 -15
- wayfinder_paths/core/engine/manifest.py +66 -0
- wayfinder_paths/core/strategies/Strategy.py +0 -61
- wayfinder_paths/core/strategies/__init__.py +10 -1
- wayfinder_paths/core/strategies/opa_loop.py +167 -0
- wayfinder_paths/core/utils/test_transaction.py +289 -0
- wayfinder_paths/core/utils/transaction.py +44 -1
- wayfinder_paths/core/utils/web3.py +3 -0
- wayfinder_paths/mcp/__init__.py +5 -0
- wayfinder_paths/mcp/preview.py +185 -0
- wayfinder_paths/mcp/scripting.py +84 -0
- wayfinder_paths/mcp/server.py +52 -0
- wayfinder_paths/mcp/state/profile_store.py +195 -0
- wayfinder_paths/mcp/state/store.py +89 -0
- wayfinder_paths/mcp/test_scripting.py +267 -0
- wayfinder_paths/mcp/tools/__init__.py +0 -0
- wayfinder_paths/mcp/tools/balances.py +290 -0
- wayfinder_paths/mcp/tools/discovery.py +158 -0
- wayfinder_paths/mcp/tools/execute.py +770 -0
- wayfinder_paths/mcp/tools/hyperliquid.py +931 -0
- wayfinder_paths/mcp/tools/quotes.py +288 -0
- wayfinder_paths/mcp/tools/run_script.py +286 -0
- wayfinder_paths/mcp/tools/strategies.py +188 -0
- wayfinder_paths/mcp/tools/tokens.py +46 -0
- wayfinder_paths/mcp/tools/wallets.py +354 -0
- wayfinder_paths/mcp/utils.py +129 -0
- wayfinder_paths/policies/hyperliquid.py +1 -1
- wayfinder_paths/policies/lifi.py +18 -0
- wayfinder_paths/policies/util.py +8 -2
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +28 -119
- wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +24 -53
- wayfinder_paths/strategies/boros_hype_strategy/__init__.py +3 -0
- wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +450 -0
- wayfinder_paths/strategies/boros_hype_strategy/constants.py +255 -0
- wayfinder_paths/strategies/boros_hype_strategy/examples.json +37 -0
- wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +114 -0
- wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +642 -0
- wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +36 -0
- wayfinder_paths/strategies/boros_hype_strategy/planner.py +460 -0
- wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +886 -0
- wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +494 -0
- wayfinder_paths/strategies/boros_hype_strategy/strategy.py +1194 -0
- wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +374 -0
- wayfinder_paths/strategies/boros_hype_strategy/test_strategy.py +202 -0
- wayfinder_paths/strategies/boros_hype_strategy/types.py +365 -0
- wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +997 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +3 -12
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +7 -29
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +63 -40
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +5 -15
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +0 -34
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +11 -34
- wayfinder_paths/tests/test_mcp_quote_swap.py +165 -0
- wayfinder_paths/tests/test_test_coverage.py +1 -4
- wayfinder_paths-0.1.25.dist-info/METADATA +377 -0
- wayfinder_paths-0.1.25.dist-info/RECORD +185 -0
- wayfinder_paths/scripts/create_strategy.py +0 -139
- wayfinder_paths/scripts/make_wallets.py +0 -142
- wayfinder_paths-0.1.23.dist-info/METADATA +0 -354
- wayfinder_paths-0.1.23.dist-info/RECORD +0 -120
- /wayfinder_paths/{scripts → mcp/state}/__init__.py +0 -0
- {wayfinder_paths-0.1.23.dist-info → wayfinder_paths-0.1.25.dist-info}/LICENSE +0 -0
- {wayfinder_paths-0.1.23.dist-info → wayfinder_paths-0.1.25.dist-info}/WHEEL +0 -0
wayfinder_paths/__init__.py
CHANGED
|
@@ -2,6 +2,7 @@ __version__ = "0.1.0"
|
|
|
2
2
|
|
|
3
3
|
from wayfinder_paths.core import (
|
|
4
4
|
BaseAdapter,
|
|
5
|
+
LiquidationResult,
|
|
5
6
|
StatusDict,
|
|
6
7
|
StatusTuple,
|
|
7
8
|
Strategy,
|
|
@@ -10,6 +11,7 @@ from wayfinder_paths.core import (
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"__version__",
|
|
12
13
|
"BaseAdapter",
|
|
14
|
+
"LiquidationResult",
|
|
13
15
|
"Strategy",
|
|
14
16
|
"StatusDict",
|
|
15
17
|
"StatusTuple",
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from typing import Any
|
|
2
3
|
|
|
3
4
|
from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
|
|
5
|
+
from wayfinder_paths.adapters.multicall_adapter.adapter import MulticallAdapter
|
|
4
6
|
from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
|
|
5
7
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
6
8
|
from wayfinder_paths.core.clients.TokenClient import TokenClient
|
|
9
|
+
from wayfinder_paths.core.constants import ZERO_ADDRESS
|
|
10
|
+
from wayfinder_paths.core.constants.erc20_abi import ERC20_ABI
|
|
7
11
|
from wayfinder_paths.core.utils.evm_helpers import resolve_chain_id
|
|
8
12
|
from wayfinder_paths.core.utils.tokens import build_send_transaction, get_token_balance
|
|
9
13
|
from wayfinder_paths.core.utils.transaction import send_transaction
|
|
14
|
+
from wayfinder_paths.core.utils.web3 import web3_from_chain_id
|
|
10
15
|
|
|
11
16
|
|
|
12
17
|
class BalanceAdapter(BaseAdapter):
|
|
@@ -43,6 +48,12 @@ class BalanceAdapter(BaseAdapter):
|
|
|
43
48
|
except Exception as e:
|
|
44
49
|
return False, str(e)
|
|
45
50
|
|
|
51
|
+
async def get_vault_wallet_balance(self, token_id: str) -> tuple[bool, int | str]:
|
|
52
|
+
addr = self._wallet_address(self.config.get("strategy_wallet", {}))
|
|
53
|
+
if not addr:
|
|
54
|
+
return False, "No strategy_wallet configured"
|
|
55
|
+
return await self.get_balance(wallet_address=addr, token_id=token_id)
|
|
56
|
+
|
|
46
57
|
async def move_from_main_wallet_to_strategy_wallet(
|
|
47
58
|
self,
|
|
48
59
|
token_id: str,
|
|
@@ -177,3 +188,242 @@ class BalanceAdapter(BaseAdapter):
|
|
|
177
188
|
)
|
|
178
189
|
except Exception as exc:
|
|
179
190
|
self.logger.warning(f"Ledger entry failed: {exc}", wallet=wallet_address)
|
|
191
|
+
|
|
192
|
+
@staticmethod
|
|
193
|
+
def _wallet_address(wallet: dict[str, Any] | None) -> str | None:
|
|
194
|
+
if wallet and isinstance(wallet, dict):
|
|
195
|
+
return wallet.get("address")
|
|
196
|
+
return None
|
|
197
|
+
|
|
198
|
+
async def get_wallet_balances_multicall(
|
|
199
|
+
self,
|
|
200
|
+
*,
|
|
201
|
+
assets: list[dict[str, Any]],
|
|
202
|
+
wallet_address: str | None = None,
|
|
203
|
+
default_native_decimals: int = 18,
|
|
204
|
+
) -> tuple[bool, list[dict[str, Any]] | str]:
|
|
205
|
+
"""
|
|
206
|
+
Fetch many balances via Multicall3, grouped by chain.
|
|
207
|
+
|
|
208
|
+
Each asset entry supports either:
|
|
209
|
+
- {"token_address": "0x...", "chain_id": 42161}
|
|
210
|
+
- {"token_id": "usd-coin-arbitrum"} (resolved via TokenClient)
|
|
211
|
+
Native token entries can use token_address=None/"native"/ZERO_ADDRESS.
|
|
212
|
+
|
|
213
|
+
Returns a list aligned with the input `assets`, each containing:
|
|
214
|
+
- success: bool
|
|
215
|
+
- chain_id: int | None
|
|
216
|
+
- token_address: str | None
|
|
217
|
+
- token_id: str | None
|
|
218
|
+
- balance_raw: int | None
|
|
219
|
+
- decimals: int | None
|
|
220
|
+
- balance_decimal: float | None
|
|
221
|
+
- error: str | None
|
|
222
|
+
"""
|
|
223
|
+
if not assets:
|
|
224
|
+
return True, []
|
|
225
|
+
|
|
226
|
+
base_wallet = wallet_address
|
|
227
|
+
if base_wallet is None:
|
|
228
|
+
strategy_wallet = self.config.get("strategy_wallet", {})
|
|
229
|
+
base_wallet = self._wallet_address(strategy_wallet)
|
|
230
|
+
|
|
231
|
+
results: list[dict[str, Any]] = [{"success": False} for _ in assets]
|
|
232
|
+
all_success = True
|
|
233
|
+
|
|
234
|
+
normalized: list[dict[str, Any]] = []
|
|
235
|
+
for idx, asset in enumerate(assets):
|
|
236
|
+
token_id = asset.get("token_id")
|
|
237
|
+
token_address = asset.get("token_address")
|
|
238
|
+
chain_id = asset.get("chain_id")
|
|
239
|
+
req_wallet = asset.get("wallet_address") or base_wallet
|
|
240
|
+
|
|
241
|
+
if not req_wallet:
|
|
242
|
+
results[idx] = {
|
|
243
|
+
"success": False,
|
|
244
|
+
"error": "wallet_address not provided and no strategy_wallet configured",
|
|
245
|
+
"token_id": token_id,
|
|
246
|
+
"token_address": token_address,
|
|
247
|
+
"chain_id": chain_id,
|
|
248
|
+
}
|
|
249
|
+
all_success = False
|
|
250
|
+
continue
|
|
251
|
+
|
|
252
|
+
# Optionally resolve missing chain/token address via TokenClient.
|
|
253
|
+
if token_id and (token_address is None or chain_id is None):
|
|
254
|
+
try:
|
|
255
|
+
token_info = await self.token_client.get_token_details(token_id)
|
|
256
|
+
except Exception as exc: # noqa: BLE001
|
|
257
|
+
token_info = None
|
|
258
|
+
self.logger.warning(
|
|
259
|
+
f"TokenClient lookup failed for {token_id}: {exc}"
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
if not token_info:
|
|
263
|
+
results[idx] = {
|
|
264
|
+
"success": False,
|
|
265
|
+
"error": f"Token not found: {token_id}",
|
|
266
|
+
"token_id": token_id,
|
|
267
|
+
"token_address": token_address,
|
|
268
|
+
"chain_id": chain_id,
|
|
269
|
+
"wallet_address": req_wallet,
|
|
270
|
+
}
|
|
271
|
+
all_success = False
|
|
272
|
+
continue
|
|
273
|
+
|
|
274
|
+
token_address = token_address or token_info.get("address")
|
|
275
|
+
chain_id = chain_id or resolve_chain_id(token_info)
|
|
276
|
+
|
|
277
|
+
if chain_id is None:
|
|
278
|
+
results[idx] = {
|
|
279
|
+
"success": False,
|
|
280
|
+
"error": "chain_id is required",
|
|
281
|
+
"token_id": token_id,
|
|
282
|
+
"token_address": token_address,
|
|
283
|
+
"chain_id": chain_id,
|
|
284
|
+
"wallet_address": req_wallet,
|
|
285
|
+
}
|
|
286
|
+
all_success = False
|
|
287
|
+
continue
|
|
288
|
+
|
|
289
|
+
token_addr_str = (
|
|
290
|
+
str(token_address).strip() if token_address is not None else None
|
|
291
|
+
)
|
|
292
|
+
is_native = (
|
|
293
|
+
token_addr_str is None
|
|
294
|
+
or token_addr_str == ""
|
|
295
|
+
or token_addr_str.lower() == "native"
|
|
296
|
+
or token_addr_str.lower() == ZERO_ADDRESS.lower()
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
normalized.append(
|
|
300
|
+
{
|
|
301
|
+
"index": idx,
|
|
302
|
+
"token_id": token_id,
|
|
303
|
+
"token_address": token_addr_str,
|
|
304
|
+
"chain_id": int(chain_id),
|
|
305
|
+
"wallet_address": str(req_wallet),
|
|
306
|
+
"is_native": bool(is_native),
|
|
307
|
+
}
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
# Group by chain id for separate multicall aggregates.
|
|
311
|
+
by_chain: dict[int, list[dict[str, Any]]] = {}
|
|
312
|
+
for entry in normalized:
|
|
313
|
+
by_chain.setdefault(entry["chain_id"], []).append(entry)
|
|
314
|
+
|
|
315
|
+
async def _process_chain(chain_id: int, entries: list[dict[str, Any]]) -> None:
|
|
316
|
+
nonlocal all_success
|
|
317
|
+
try:
|
|
318
|
+
async with web3_from_chain_id(chain_id) as w3:
|
|
319
|
+
multicall = MulticallAdapter(web3=w3, chain_id=chain_id)
|
|
320
|
+
|
|
321
|
+
# Deduplicate decimals calls per token (per chain).
|
|
322
|
+
token_set: set[str] = {
|
|
323
|
+
w3.to_checksum_address(e["token_address"])
|
|
324
|
+
for e in entries
|
|
325
|
+
if not e["is_native"] and e["token_address"]
|
|
326
|
+
}
|
|
327
|
+
sorted_tokens = sorted(token_set)
|
|
328
|
+
|
|
329
|
+
calls: list[Any] = []
|
|
330
|
+
decimals_call_index: dict[str, int] = {}
|
|
331
|
+
for token in sorted_tokens:
|
|
332
|
+
erc20 = w3.eth.contract(address=token, abi=ERC20_ABI)
|
|
333
|
+
calldata = erc20.encode_abi("decimals")
|
|
334
|
+
decimals_call_index[token] = len(calls)
|
|
335
|
+
calls.append(multicall.build_call(token, calldata))
|
|
336
|
+
|
|
337
|
+
balance_call_index: dict[int, int] = {}
|
|
338
|
+
for entry in entries:
|
|
339
|
+
if entry["is_native"]:
|
|
340
|
+
call = multicall.encode_eth_balance(entry["wallet_address"])
|
|
341
|
+
else:
|
|
342
|
+
token = w3.to_checksum_address(entry["token_address"])
|
|
343
|
+
call = multicall.encode_erc20_balance(
|
|
344
|
+
token, entry["wallet_address"]
|
|
345
|
+
)
|
|
346
|
+
balance_call_index[entry["index"]] = len(calls)
|
|
347
|
+
calls.append(call)
|
|
348
|
+
|
|
349
|
+
mc_res = await multicall.aggregate(calls)
|
|
350
|
+
|
|
351
|
+
decimals_by_token: dict[str, int] = {}
|
|
352
|
+
for token, call_idx in decimals_call_index.items():
|
|
353
|
+
raw_decimals = multicall.decode_uint256(
|
|
354
|
+
mc_res.return_data[call_idx]
|
|
355
|
+
)
|
|
356
|
+
decimals_by_token[token] = int(raw_decimals)
|
|
357
|
+
|
|
358
|
+
for entry in entries:
|
|
359
|
+
out_idx = entry["index"]
|
|
360
|
+
bal_idx = balance_call_index[out_idx]
|
|
361
|
+
raw_balance = multicall.decode_uint256(
|
|
362
|
+
mc_res.return_data[bal_idx]
|
|
363
|
+
)
|
|
364
|
+
if entry["is_native"]:
|
|
365
|
+
decimals = int(default_native_decimals)
|
|
366
|
+
token_address_out = None
|
|
367
|
+
else:
|
|
368
|
+
token = w3.to_checksum_address(entry["token_address"])
|
|
369
|
+
decimals = int(
|
|
370
|
+
decimals_by_token.get(token, default_native_decimals)
|
|
371
|
+
)
|
|
372
|
+
token_address_out = token
|
|
373
|
+
|
|
374
|
+
balance_decimal = (
|
|
375
|
+
float(raw_balance) / (10**decimals)
|
|
376
|
+
if decimals >= 0
|
|
377
|
+
else None
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
results[out_idx] = {
|
|
381
|
+
"success": True,
|
|
382
|
+
"token_id": entry.get("token_id"),
|
|
383
|
+
"token_address": token_address_out,
|
|
384
|
+
"chain_id": chain_id,
|
|
385
|
+
"wallet_address": entry["wallet_address"],
|
|
386
|
+
"balance_raw": int(raw_balance),
|
|
387
|
+
"decimals": int(decimals),
|
|
388
|
+
"balance_decimal": float(balance_decimal)
|
|
389
|
+
if balance_decimal is not None
|
|
390
|
+
else None,
|
|
391
|
+
"block_number": mc_res.block_number,
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
except Exception as exc: # noqa: BLE001
|
|
395
|
+
all_success = False
|
|
396
|
+
err = str(exc)
|
|
397
|
+
for entry in entries:
|
|
398
|
+
out_idx = entry["index"]
|
|
399
|
+
results[out_idx] = {
|
|
400
|
+
"success": False,
|
|
401
|
+
"error": err,
|
|
402
|
+
"token_id": entry.get("token_id"),
|
|
403
|
+
"token_address": entry.get("token_address"),
|
|
404
|
+
"chain_id": chain_id,
|
|
405
|
+
"wallet_address": entry.get("wallet_address"),
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
await asyncio.gather(
|
|
409
|
+
*[
|
|
410
|
+
_process_chain(chain_id, entries)
|
|
411
|
+
for chain_id, entries in by_chain.items()
|
|
412
|
+
]
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
# Ensure any leftover placeholder entries are marked failed.
|
|
416
|
+
for idx, out in enumerate(results):
|
|
417
|
+
if out.get("success") is True:
|
|
418
|
+
continue
|
|
419
|
+
if "error" not in out:
|
|
420
|
+
all_success = False
|
|
421
|
+
out.setdefault("error", "Unknown error")
|
|
422
|
+
out.setdefault("token_id", assets[idx].get("token_id"))
|
|
423
|
+
out.setdefault("token_address", assets[idx].get("token_address"))
|
|
424
|
+
out.setdefault("chain_id", assets[idx].get("chain_id"))
|
|
425
|
+
out.setdefault(
|
|
426
|
+
"wallet_address", assets[idx].get("wallet_address") or base_wallet
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
return all_success, results
|
|
@@ -18,17 +18,6 @@ class TestBalanceAdapter:
|
|
|
18
18
|
):
|
|
19
19
|
return BalanceAdapter(config={})
|
|
20
20
|
|
|
21
|
-
@pytest.mark.asyncio
|
|
22
|
-
async def test_health_check(self, adapter):
|
|
23
|
-
health = await adapter.health_check()
|
|
24
|
-
assert isinstance(health, dict)
|
|
25
|
-
assert health.get("status") in {"healthy", "unhealthy", "error"}
|
|
26
|
-
|
|
27
|
-
@pytest.mark.asyncio
|
|
28
|
-
async def test_connect(self, adapter):
|
|
29
|
-
ok = await adapter.connect()
|
|
30
|
-
assert isinstance(ok, bool)
|
|
31
|
-
|
|
32
21
|
def test_adapter_type(self, adapter):
|
|
33
22
|
assert adapter.adapter_type == "BALANCE"
|
|
34
23
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Boros Adapter - wraps Boros API for fixed-rate market operations."""
|
|
2
|
+
|
|
3
|
+
from .adapter import BorosAdapter
|
|
4
|
+
from .types import (
|
|
5
|
+
BorosLimitOrder,
|
|
6
|
+
BorosMarketQuote,
|
|
7
|
+
BorosTenorQuote,
|
|
8
|
+
MarginHealth,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"BorosAdapter",
|
|
13
|
+
"BorosMarketQuote",
|
|
14
|
+
"BorosTenorQuote",
|
|
15
|
+
"BorosLimitOrder",
|
|
16
|
+
"MarginHealth",
|
|
17
|
+
]
|