wayfinder-paths 0.1.24__py3-none-any.whl → 0.1.27__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/brap_adapter/adapter.py +7 -47
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +10 -31
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +128 -60
- wayfinder_paths/adapters/hyperliquid_adapter/exchange.py +399 -0
- wayfinder_paths/adapters/hyperliquid_adapter/executor.py +74 -0
- wayfinder_paths/adapters/hyperliquid_adapter/local_signer.py +82 -0
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +1 -1
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +1 -1
- wayfinder_paths/adapters/hyperliquid_adapter/util.py +237 -0
- wayfinder_paths/adapters/pendle_adapter/adapter.py +19 -55
- wayfinder_paths/adapters/pendle_adapter/test_adapter.py +14 -46
- wayfinder_paths/core/__init__.py +2 -0
- wayfinder_paths/core/clients/BalanceClient.py +72 -0
- wayfinder_paths/core/clients/TokenClient.py +1 -1
- wayfinder_paths/core/clients/__init__.py +2 -0
- wayfinder_paths/core/strategies/Strategy.py +3 -3
- wayfinder_paths/core/types.py +19 -0
- wayfinder_paths/core/utils/tokens.py +19 -1
- wayfinder_paths/core/utils/transaction.py +9 -7
- wayfinder_paths/mcp/tools/balances.py +122 -214
- wayfinder_paths/mcp/tools/execute.py +63 -41
- wayfinder_paths/mcp/tools/quotes.py +16 -5
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +6 -22
- wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +227 -33
- wayfinder_paths/strategies/boros_hype_strategy/constants.py +17 -1
- wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +44 -1
- wayfinder_paths/strategies/boros_hype_strategy/planner.py +87 -32
- wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +50 -28
- wayfinder_paths/strategies/boros_hype_strategy/strategy.py +71 -50
- wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +3 -1
- wayfinder_paths/strategies/boros_hype_strategy/test_strategy.py +0 -2
- wayfinder_paths/strategies/boros_hype_strategy/types.py +4 -1
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +0 -2
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -2
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +0 -2
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +0 -2
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +0 -2
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -2
- wayfinder_paths/tests/test_mcp_quote_swap.py +3 -3
- {wayfinder_paths-0.1.24.dist-info → wayfinder_paths-0.1.27.dist-info}/METADATA +2 -3
- {wayfinder_paths-0.1.24.dist-info → wayfinder_paths-0.1.27.dist-info}/RECORD +44 -39
- {wayfinder_paths-0.1.24.dist-info → wayfinder_paths-0.1.27.dist-info}/WHEEL +1 -1
- {wayfinder_paths-0.1.24.dist-info → wayfinder_paths-0.1.27.dist-info}/LICENSE +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",
|
|
@@ -11,10 +11,8 @@ from wayfinder_paths.core.adapters.models import SWAP
|
|
|
11
11
|
from wayfinder_paths.core.clients.BRAPClient import BRAPClient
|
|
12
12
|
from wayfinder_paths.core.clients.LedgerClient import TransactionRecord
|
|
13
13
|
from wayfinder_paths.core.clients.TokenClient import TokenClient
|
|
14
|
-
from wayfinder_paths.core.constants.contracts import TOKENS_REQUIRING_APPROVAL_RESET
|
|
15
14
|
from wayfinder_paths.core.utils.tokens import (
|
|
16
|
-
|
|
17
|
-
get_token_allowance,
|
|
15
|
+
ensure_allowance,
|
|
18
16
|
is_native_token,
|
|
19
17
|
)
|
|
20
18
|
from wayfinder_paths.core.utils.transaction import send_transaction
|
|
@@ -48,45 +46,6 @@ class BRAPAdapter(BaseAdapter):
|
|
|
48
46
|
return max(matching, key=lambda q: int(q.get("output_amount", 0) or 0))
|
|
49
47
|
return None
|
|
50
48
|
|
|
51
|
-
async def _handle_token_approval(
|
|
52
|
-
self,
|
|
53
|
-
*,
|
|
54
|
-
chain_id: int,
|
|
55
|
-
token_address: str,
|
|
56
|
-
owner_address: str,
|
|
57
|
-
spender_address: str,
|
|
58
|
-
amount: int,
|
|
59
|
-
) -> None:
|
|
60
|
-
token_checksum = Web3.to_checksum_address(token_address)
|
|
61
|
-
owner_checksum = Web3.to_checksum_address(owner_address)
|
|
62
|
-
spender_checksum = Web3.to_checksum_address(spender_address)
|
|
63
|
-
|
|
64
|
-
if (chain_id, token_checksum) in TOKENS_REQUIRING_APPROVAL_RESET:
|
|
65
|
-
allowance = await get_token_allowance(
|
|
66
|
-
token_checksum,
|
|
67
|
-
chain_id,
|
|
68
|
-
owner_checksum,
|
|
69
|
-
spender_checksum,
|
|
70
|
-
)
|
|
71
|
-
if allowance > 0:
|
|
72
|
-
clear_tx = await build_approve_transaction(
|
|
73
|
-
from_address=owner_checksum,
|
|
74
|
-
chain_id=chain_id,
|
|
75
|
-
token_address=token_checksum,
|
|
76
|
-
spender_address=spender_checksum,
|
|
77
|
-
amount=0,
|
|
78
|
-
)
|
|
79
|
-
await send_transaction(clear_tx, self.strategy_wallet_signing_callback)
|
|
80
|
-
|
|
81
|
-
approve_tx = await build_approve_transaction(
|
|
82
|
-
from_address=owner_checksum,
|
|
83
|
-
chain_id=chain_id,
|
|
84
|
-
token_address=token_checksum,
|
|
85
|
-
spender_address=spender_checksum,
|
|
86
|
-
amount=int(amount),
|
|
87
|
-
)
|
|
88
|
-
await send_transaction(approve_tx, self.strategy_wallet_signing_callback)
|
|
89
|
-
|
|
90
49
|
async def _record_swap_operation(
|
|
91
50
|
self,
|
|
92
51
|
from_token: dict[str, Any],
|
|
@@ -227,12 +186,13 @@ class BRAPAdapter(BaseAdapter):
|
|
|
227
186
|
and approve_amount
|
|
228
187
|
and not is_native_token(token_address)
|
|
229
188
|
):
|
|
230
|
-
await
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
spender_address=spender,
|
|
189
|
+
await ensure_allowance(
|
|
190
|
+
token_address=token_address,
|
|
191
|
+
owner=from_address,
|
|
192
|
+
spender=spender,
|
|
235
193
|
amount=int(approve_amount),
|
|
194
|
+
chain_id=chain_id,
|
|
195
|
+
signing_callback=self.strategy_wallet_signing_callback,
|
|
236
196
|
)
|
|
237
197
|
|
|
238
198
|
txn_hash = await send_transaction(
|
|
@@ -49,9 +49,6 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
49
49
|
strategy_addr = strategy_wallet.get("address")
|
|
50
50
|
|
|
51
51
|
self.strategy_wallet_address = to_checksum_address(strategy_addr)
|
|
52
|
-
self.pool_address = HYPERLEND_POOL
|
|
53
|
-
self.gateway_address = HYPERLEND_WRAPPED_TOKEN_GATEWAY
|
|
54
|
-
self.wrapped_native = HYPEREVM_WHYPE
|
|
55
52
|
|
|
56
53
|
async def get_stable_markets(
|
|
57
54
|
self,
|
|
@@ -167,12 +164,12 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
167
164
|
chain_id = int(chain_id)
|
|
168
165
|
|
|
169
166
|
if native:
|
|
170
|
-
token_addr =
|
|
167
|
+
token_addr = HYPEREVM_WHYPE
|
|
171
168
|
transaction = await self._encode_call(
|
|
172
|
-
target=
|
|
169
|
+
target=HYPERLEND_WRAPPED_TOKEN_GATEWAY,
|
|
173
170
|
abi=WRAPPED_TOKEN_GATEWAY_ABI,
|
|
174
171
|
fn_name="depositETH",
|
|
175
|
-
args=[
|
|
172
|
+
args=[HYPERLEND_POOL, strategy, 0],
|
|
176
173
|
from_address=strategy,
|
|
177
174
|
chain_id=chain_id,
|
|
178
175
|
value=qty,
|
|
@@ -182,7 +179,7 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
182
179
|
approved = await ensure_allowance(
|
|
183
180
|
token_address=token_addr,
|
|
184
181
|
owner=strategy,
|
|
185
|
-
spender=
|
|
182
|
+
spender=HYPERLEND_POOL,
|
|
186
183
|
amount=qty,
|
|
187
184
|
chain_id=chain_id,
|
|
188
185
|
signing_callback=self.strategy_wallet_signing_callback,
|
|
@@ -190,7 +187,7 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
190
187
|
if not approved[0]:
|
|
191
188
|
return approved
|
|
192
189
|
transaction = await self._encode_call(
|
|
193
|
-
target=
|
|
190
|
+
target=HYPERLEND_POOL,
|
|
194
191
|
abi=POOL_ABI,
|
|
195
192
|
fn_name="supply",
|
|
196
193
|
args=[token_addr, qty, strategy, 0],
|
|
@@ -230,19 +227,19 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
230
227
|
chain_id = int(chain_id)
|
|
231
228
|
|
|
232
229
|
if native:
|
|
233
|
-
token_addr =
|
|
230
|
+
token_addr = HYPEREVM_WHYPE
|
|
234
231
|
transaction = await self._encode_call(
|
|
235
|
-
target=
|
|
232
|
+
target=HYPERLEND_WRAPPED_TOKEN_GATEWAY,
|
|
236
233
|
abi=WRAPPED_TOKEN_GATEWAY_ABI,
|
|
237
234
|
fn_name="withdrawETH",
|
|
238
|
-
args=[
|
|
235
|
+
args=[HYPERLEND_POOL, qty, strategy],
|
|
239
236
|
from_address=strategy,
|
|
240
237
|
chain_id=chain_id,
|
|
241
238
|
)
|
|
242
239
|
else:
|
|
243
240
|
token_addr = to_checksum_address(underlying_token)
|
|
244
241
|
transaction = await self._encode_call(
|
|
245
|
-
target=
|
|
242
|
+
target=HYPERLEND_POOL,
|
|
246
243
|
abi=POOL_ABI,
|
|
247
244
|
fn_name="withdraw",
|
|
248
245
|
args=[token_addr, qty, strategy],
|
|
@@ -317,7 +314,7 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
317
314
|
operation_data = model(
|
|
318
315
|
adapter=self.adapter_type,
|
|
319
316
|
token_address=token_address,
|
|
320
|
-
pool_address=
|
|
317
|
+
pool_address=HYPERLEND_POOL,
|
|
321
318
|
amount=str(amount),
|
|
322
319
|
amount_usd=amount_usd or 0,
|
|
323
320
|
transaction_hash=txn_hash,
|
|
@@ -356,21 +353,3 @@ class HyperlendAdapter(BaseAdapter):
|
|
|
356
353
|
token_data["current_price"],
|
|
357
354
|
)
|
|
358
355
|
return current_price * float(amount) / 10 ** int(decimals)
|
|
359
|
-
|
|
360
|
-
async def _ensure_allowance(
|
|
361
|
-
self,
|
|
362
|
-
*,
|
|
363
|
-
token_address: str,
|
|
364
|
-
owner: str,
|
|
365
|
-
spender: str,
|
|
366
|
-
amount: int,
|
|
367
|
-
chain_id: int,
|
|
368
|
-
) -> tuple[bool, Any]:
|
|
369
|
-
return await ensure_allowance(
|
|
370
|
-
token_address=token_address,
|
|
371
|
-
owner=owner,
|
|
372
|
-
spender=spender,
|
|
373
|
-
amount=amount,
|
|
374
|
-
chain_id=chain_id,
|
|
375
|
-
signing_callback=self.strategy_wallet_signing_callback,
|
|
376
|
-
)
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import time
|
|
5
5
|
from decimal import ROUND_DOWN, Decimal, getcontext
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from aiocache import Cache
|
|
9
9
|
from eth_utils import to_checksum_address
|
|
@@ -21,11 +21,7 @@ from wayfinder_paths.core.constants.hyperliquid import (
|
|
|
21
21
|
from wayfinder_paths.core.constants.hyperliquid import (
|
|
22
22
|
HYPERLIQUID_BRIDGE_ADDRESS as _HYPERLIQUID_BRIDGE_ADDRESS,
|
|
23
23
|
)
|
|
24
|
-
|
|
25
|
-
if TYPE_CHECKING:
|
|
26
|
-
from wayfinder_paths.core.clients.protocols import (
|
|
27
|
-
HyperliquidExecutorProtocol as HyperliquidExecutor,
|
|
28
|
-
)
|
|
24
|
+
from wayfinder_paths.core.types import HyperliquidSignCallback
|
|
29
25
|
|
|
30
26
|
# Re-export Bridge2 constants for backwards compatibility.
|
|
31
27
|
HYPERLIQUID_BRIDGE_ADDRESS = _HYPERLIQUID_BRIDGE_ADDRESS
|
|
@@ -35,11 +31,20 @@ try:
|
|
|
35
31
|
from hyperliquid.info import Info
|
|
36
32
|
from hyperliquid.utils import constants
|
|
37
33
|
|
|
34
|
+
from wayfinder_paths.adapters.hyperliquid_adapter.exchange import Exchange
|
|
35
|
+
from wayfinder_paths.adapters.hyperliquid_adapter.local_signer import (
|
|
36
|
+
create_local_signer,
|
|
37
|
+
)
|
|
38
|
+
from wayfinder_paths.adapters.hyperliquid_adapter.util import Util
|
|
39
|
+
|
|
38
40
|
HYPERLIQUID_AVAILABLE = True
|
|
39
41
|
except ImportError:
|
|
40
42
|
HYPERLIQUID_AVAILABLE = False
|
|
41
43
|
Info = None
|
|
42
44
|
constants = None
|
|
45
|
+
Exchange = None
|
|
46
|
+
Util = None
|
|
47
|
+
create_local_signer = None
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
class HyperliquidAdapter(BaseAdapter):
|
|
@@ -62,7 +67,7 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
62
67
|
config: dict[str, Any] | None = None,
|
|
63
68
|
*,
|
|
64
69
|
simulation: bool = False,
|
|
65
|
-
|
|
70
|
+
sign_callback: HyperliquidSignCallback | None = None,
|
|
66
71
|
) -> None:
|
|
67
72
|
super().__init__("hyperliquid_adapter", config)
|
|
68
73
|
|
|
@@ -74,11 +79,36 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
74
79
|
|
|
75
80
|
self.simulation = simulation
|
|
76
81
|
self._cache = Cache(Cache.MEMORY)
|
|
77
|
-
self._executor = executor
|
|
78
82
|
|
|
79
83
|
# Initialize Hyperliquid Info client
|
|
80
84
|
self.info = Info(constants.MAINNET_API_URL, skip_ws=True)
|
|
81
85
|
|
|
86
|
+
# Initialize Util
|
|
87
|
+
self.util = Util(self.info)
|
|
88
|
+
|
|
89
|
+
# Initialize Exchange with appropriate signing type
|
|
90
|
+
self._exchange: Exchange | None = None
|
|
91
|
+
if not self.simulation:
|
|
92
|
+
if sign_callback is None:
|
|
93
|
+
# Local signing: create local signer from config
|
|
94
|
+
if not config:
|
|
95
|
+
raise ValueError(
|
|
96
|
+
"Config required for local signing (no sign_callback provided)"
|
|
97
|
+
)
|
|
98
|
+
sign_callback = create_local_signer(config)
|
|
99
|
+
signing_type = "local"
|
|
100
|
+
else:
|
|
101
|
+
# Remote signing: use provided callback (EIP-712)
|
|
102
|
+
signing_type = "eip712"
|
|
103
|
+
|
|
104
|
+
# Instantiate Exchange
|
|
105
|
+
self._exchange = Exchange(
|
|
106
|
+
info=self.info,
|
|
107
|
+
util=self.util,
|
|
108
|
+
sign_callback=sign_callback,
|
|
109
|
+
signing_type=signing_type,
|
|
110
|
+
)
|
|
111
|
+
|
|
82
112
|
# Cache asset mappings after first fetch
|
|
83
113
|
self._asset_to_sz_decimals: dict[int, int] | None = None
|
|
84
114
|
self._coin_to_asset: dict[str, int] | None = None
|
|
@@ -533,13 +563,18 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
533
563
|
)
|
|
534
564
|
return True, {"simulation": True, "status": "ok"}
|
|
535
565
|
|
|
536
|
-
if not self.
|
|
566
|
+
if not self._exchange:
|
|
537
567
|
raise NotImplementedError(
|
|
538
|
-
"No Hyperliquid
|
|
539
|
-
"
|
|
568
|
+
"No Hyperliquid exchange configured. "
|
|
569
|
+
"Provide a sign_callback or config with private key."
|
|
540
570
|
)
|
|
541
571
|
|
|
542
|
-
|
|
572
|
+
# Convert builder to BuilderInfo
|
|
573
|
+
from hyperliquid.utils.types import BuilderInfo
|
|
574
|
+
|
|
575
|
+
builder_info = BuilderInfo(b=builder.get("b"), f=builder.get("f"))
|
|
576
|
+
|
|
577
|
+
result = await self._exchange.place_market_order(
|
|
543
578
|
asset_id=asset_id,
|
|
544
579
|
is_buy=is_buy,
|
|
545
580
|
slippage=slippage,
|
|
@@ -547,7 +582,7 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
547
582
|
address=address,
|
|
548
583
|
reduce_only=reduce_only,
|
|
549
584
|
cloid=cloid,
|
|
550
|
-
builder=
|
|
585
|
+
builder=builder_info,
|
|
551
586
|
)
|
|
552
587
|
|
|
553
588
|
# Check both the API status and the order statuses for errors
|
|
@@ -575,15 +610,12 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
575
610
|
)
|
|
576
611
|
return True, {"simulation": True, "status": "ok"}
|
|
577
612
|
|
|
578
|
-
if not self.
|
|
579
|
-
raise NotImplementedError(
|
|
580
|
-
"No Hyperliquid executor configured. "
|
|
581
|
-
"Inject a HyperliquidExecutor implementation (e.g., LocalHyperliquidExecutor)."
|
|
582
|
-
)
|
|
613
|
+
if not self._exchange:
|
|
614
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
583
615
|
|
|
584
|
-
result = await self.
|
|
616
|
+
result = await self._exchange.cancel_order(
|
|
585
617
|
asset_id=asset_id,
|
|
586
|
-
order_id=
|
|
618
|
+
order_id=str(order_id) if isinstance(order_id, int) else order_id,
|
|
587
619
|
address=address,
|
|
588
620
|
)
|
|
589
621
|
|
|
@@ -596,26 +628,52 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
596
628
|
cloid: str,
|
|
597
629
|
address: str,
|
|
598
630
|
) -> tuple[bool, dict[str, Any]]:
|
|
631
|
+
"""
|
|
632
|
+
Cancel order by client order ID (CLOID).
|
|
633
|
+
|
|
634
|
+
Note: The Exchange class uses cancel_order with order_id.
|
|
635
|
+
For cloid-based cancellation, we'd need to first fetch the order_id from open orders.
|
|
636
|
+
"""
|
|
599
637
|
if self.simulation:
|
|
600
638
|
logger.info(
|
|
601
639
|
f"[SIMULATION] cancel_order_by_cloid: asset={asset_id}, cloid={cloid}"
|
|
602
640
|
)
|
|
603
641
|
return True, {"simulation": True, "status": "ok"}
|
|
604
642
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
643
|
+
# Find order_id from open orders
|
|
644
|
+
success, orders = await self.get_frontend_open_orders(address)
|
|
645
|
+
if not success:
|
|
646
|
+
return False, {
|
|
647
|
+
"status": "err",
|
|
648
|
+
"response": {"type": "error", "data": "Could not fetch open orders"},
|
|
649
|
+
}
|
|
610
650
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
651
|
+
# Find matching order by cloid
|
|
652
|
+
matching_order = None
|
|
653
|
+
for order in orders:
|
|
654
|
+
if order.get("cloid") == cloid:
|
|
655
|
+
matching_order = order
|
|
656
|
+
break
|
|
616
657
|
|
|
617
|
-
|
|
618
|
-
|
|
658
|
+
if not matching_order:
|
|
659
|
+
return False, {
|
|
660
|
+
"status": "err",
|
|
661
|
+
"response": {
|
|
662
|
+
"type": "error",
|
|
663
|
+
"data": f"Order with cloid {cloid} not found",
|
|
664
|
+
},
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
order_id = matching_order.get("oid")
|
|
668
|
+
if not order_id:
|
|
669
|
+
return False, {
|
|
670
|
+
"status": "err",
|
|
671
|
+
"response": {"type": "error", "data": "Order missing oid"},
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return await self.cancel_order(
|
|
675
|
+
asset_id=asset_id, order_id=order_id, address=address
|
|
676
|
+
)
|
|
619
677
|
|
|
620
678
|
async def spot_transfer(
|
|
621
679
|
self,
|
|
@@ -638,13 +696,15 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
638
696
|
)
|
|
639
697
|
return True, {"simulation": True, "status": "ok"}
|
|
640
698
|
|
|
641
|
-
if not self.
|
|
642
|
-
raise NotImplementedError("No Hyperliquid
|
|
699
|
+
if not self._exchange:
|
|
700
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
643
701
|
|
|
644
|
-
|
|
645
|
-
|
|
702
|
+
# Arbitrum chain ID
|
|
703
|
+
result = await self._exchange.spot_transfer(
|
|
704
|
+
signature_chain_id=42161,
|
|
646
705
|
destination=str(destination),
|
|
647
706
|
token=str(token),
|
|
707
|
+
amount=str(amount),
|
|
648
708
|
address=address,
|
|
649
709
|
)
|
|
650
710
|
|
|
@@ -760,11 +820,11 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
760
820
|
)
|
|
761
821
|
return True, {"simulation": True, "status": "ok"}
|
|
762
822
|
|
|
763
|
-
if not self.
|
|
764
|
-
raise NotImplementedError("No Hyperliquid
|
|
823
|
+
if not self._exchange:
|
|
824
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
765
825
|
|
|
766
|
-
result = await self.
|
|
767
|
-
|
|
826
|
+
result = await self._exchange.update_leverage(
|
|
827
|
+
asset=asset_id,
|
|
768
828
|
leverage=leverage,
|
|
769
829
|
is_cross=is_cross,
|
|
770
830
|
address=address,
|
|
@@ -782,12 +842,13 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
782
842
|
self.logger.info(f"[SIMULATION] transfer_spot_to_perp: {amount} USDC")
|
|
783
843
|
return True, {"simulation": True, "status": "ok"}
|
|
784
844
|
|
|
785
|
-
if not self.
|
|
786
|
-
raise NotImplementedError("No Hyperliquid
|
|
845
|
+
if not self._exchange:
|
|
846
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
787
847
|
|
|
788
|
-
result = await self.
|
|
848
|
+
result = await self._exchange.usd_class_transfer(
|
|
789
849
|
amount=amount,
|
|
790
850
|
address=address,
|
|
851
|
+
to_perp=True,
|
|
791
852
|
)
|
|
792
853
|
|
|
793
854
|
success = result.get("status") == "ok"
|
|
@@ -802,12 +863,13 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
802
863
|
self.logger.info(f"[SIMULATION] transfer_perp_to_spot: {amount} USDC")
|
|
803
864
|
return True, {"simulation": True, "status": "ok"}
|
|
804
865
|
|
|
805
|
-
if not self.
|
|
806
|
-
raise NotImplementedError("No Hyperliquid
|
|
866
|
+
if not self._exchange:
|
|
867
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
807
868
|
|
|
808
|
-
result = await self.
|
|
869
|
+
result = await self._exchange.usd_class_transfer(
|
|
809
870
|
amount=amount,
|
|
810
871
|
address=address,
|
|
872
|
+
to_perp=False,
|
|
811
873
|
)
|
|
812
874
|
|
|
813
875
|
success = result.get("status") == "ok"
|
|
@@ -828,15 +890,17 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
828
890
|
)
|
|
829
891
|
return True, {"simulation": True, "status": "ok"}
|
|
830
892
|
|
|
831
|
-
if not self.
|
|
832
|
-
raise NotImplementedError("No Hyperliquid
|
|
893
|
+
if not self._exchange:
|
|
894
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
833
895
|
|
|
834
|
-
result = await self.
|
|
896
|
+
result = await self._exchange.place_trigger_order(
|
|
835
897
|
asset_id=asset_id,
|
|
836
898
|
is_buy=is_buy,
|
|
837
899
|
trigger_price=trigger_price,
|
|
838
900
|
size=size,
|
|
839
901
|
address=address,
|
|
902
|
+
tpsl="sl",
|
|
903
|
+
is_market=True,
|
|
840
904
|
)
|
|
841
905
|
|
|
842
906
|
success = result.get("status") == "ok"
|
|
@@ -951,10 +1015,10 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
951
1015
|
self.logger.info(f"[SIMULATION] withdraw: {amount} USDC")
|
|
952
1016
|
return True, {"simulation": True, "status": "ok"}
|
|
953
1017
|
|
|
954
|
-
if not self.
|
|
955
|
-
raise NotImplementedError("No Hyperliquid
|
|
1018
|
+
if not self._exchange:
|
|
1019
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
956
1020
|
|
|
957
|
-
result = await self.
|
|
1021
|
+
result = await self._exchange.withdraw(
|
|
958
1022
|
amount=amount,
|
|
959
1023
|
address=address,
|
|
960
1024
|
)
|
|
@@ -1004,10 +1068,10 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
1004
1068
|
)
|
|
1005
1069
|
return True, {"simulation": True, "status": "ok"}
|
|
1006
1070
|
|
|
1007
|
-
if not self.
|
|
1008
|
-
raise NotImplementedError("No Hyperliquid
|
|
1071
|
+
if not self._exchange:
|
|
1072
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
1009
1073
|
|
|
1010
|
-
result = await self.
|
|
1074
|
+
result = await self._exchange.approve_builder_fee(
|
|
1011
1075
|
builder=builder,
|
|
1012
1076
|
max_fee_rate=max_fee_rate,
|
|
1013
1077
|
address=address,
|
|
@@ -1094,17 +1158,21 @@ class HyperliquidAdapter(BaseAdapter):
|
|
|
1094
1158
|
)
|
|
1095
1159
|
return True, {"simulation": True, "status": "ok"}
|
|
1096
1160
|
|
|
1097
|
-
if not self.
|
|
1098
|
-
raise NotImplementedError("No Hyperliquid
|
|
1161
|
+
if not self._exchange:
|
|
1162
|
+
raise NotImplementedError("No Hyperliquid exchange configured.")
|
|
1163
|
+
|
|
1164
|
+
# Convert builder to BuilderInfo
|
|
1165
|
+
from hyperliquid.utils.types import BuilderInfo
|
|
1166
|
+
|
|
1167
|
+
builder_info = BuilderInfo(b=builder.get("b"), f=builder.get("f"))
|
|
1099
1168
|
|
|
1100
|
-
result = await self.
|
|
1169
|
+
result = await self._exchange.place_limit_order(
|
|
1101
1170
|
asset_id=asset_id,
|
|
1102
1171
|
is_buy=is_buy,
|
|
1103
1172
|
price=price,
|
|
1104
1173
|
size=size,
|
|
1105
1174
|
address=address,
|
|
1106
|
-
|
|
1107
|
-
builder=builder,
|
|
1175
|
+
builder=builder_info,
|
|
1108
1176
|
)
|
|
1109
1177
|
|
|
1110
1178
|
success = result.get("status") == "ok"
|