wayfinder-paths 0.1.23__py3-none-any.whl → 0.1.24__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/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/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.24.dist-info/METADATA +378 -0
- wayfinder_paths-0.1.24.dist-info/RECORD +185 -0
- {wayfinder_paths-0.1.23.dist-info → wayfinder_paths-0.1.24.dist-info}/WHEEL +1 -1
- 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.24.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
# TOKEN IDS (wayfinder token identifiers)
|
|
3
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
# Arbitrum tokens
|
|
6
|
+
USDC_ARB = "usd-coin-arbitrum"
|
|
7
|
+
USDT_ARB = "usdt0-arbitrum"
|
|
8
|
+
ETH_ARB = "ethereum-arbitrum"
|
|
9
|
+
|
|
10
|
+
# HyperEVM tokens
|
|
11
|
+
HYPE_NATIVE = "hype-hyperevm"
|
|
12
|
+
WHYPE = "wrapped-hype-hyperevm" # Wrapped HYPE (1:1 with native HYPE)
|
|
13
|
+
KHYPE_LST = "kinetic-staked-hype-hyperevm"
|
|
14
|
+
LOOPED_HYPE = "looped-hype-hyperevm"
|
|
15
|
+
USDC_HYPE = "usd-coin-hyperevm"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
# CONTRACT ADDRESSES
|
|
20
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
# HyperEVM token addresses
|
|
23
|
+
KHYPE_ADDRESS = "0xfD739d4e423301CE9385c1fb8850539D657C296D"
|
|
24
|
+
LOOPED_HYPE_ADDRESS = "0x5748ae796AE46A4F1348a1693de4b50560485562"
|
|
25
|
+
WHYPE_ADDRESS = "0x5555555555555555555555555555555555555555"
|
|
26
|
+
|
|
27
|
+
# Accountant contracts for exchange rate calculations
|
|
28
|
+
KHYPE_STAKING_ACCOUNTANT = "0x9209648Ec9D448EF57116B73A2f081835643dc7A"
|
|
29
|
+
LHYPE_ACCOUNTANT = "0xcE621a3CA6F72706678cFF0572ae8d15e5F001c3"
|
|
30
|
+
|
|
31
|
+
# Chain IDs
|
|
32
|
+
HYPEREVM_CHAIN_ID = 999
|
|
33
|
+
ARBITRUM_CHAIN_ID = 42161
|
|
34
|
+
|
|
35
|
+
# ABIs for exchange rate reads
|
|
36
|
+
KHYPE_STAKING_ACCOUNTANT_ABI = [
|
|
37
|
+
{
|
|
38
|
+
"inputs": [
|
|
39
|
+
{"internalType": "uint256", "name": "kHYPEAmount", "type": "uint256"}
|
|
40
|
+
],
|
|
41
|
+
"name": "kHYPEToHYPE",
|
|
42
|
+
"outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
|
|
43
|
+
"stateMutability": "view",
|
|
44
|
+
"type": "function",
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
LHYPE_ACCOUNTANT_ABI = [
|
|
49
|
+
{
|
|
50
|
+
"inputs": [{"internalType": "address", "name": "quote", "type": "address"}],
|
|
51
|
+
"name": "getRateInQuote",
|
|
52
|
+
"outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
|
|
53
|
+
"stateMutability": "view",
|
|
54
|
+
"type": "function",
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
# WHYPE contract ABI for unwrapping (standard WETH-like interface)
|
|
59
|
+
WHYPE_ABI = [
|
|
60
|
+
{
|
|
61
|
+
"name": "withdraw",
|
|
62
|
+
"type": "function",
|
|
63
|
+
"stateMutability": "nonpayable",
|
|
64
|
+
"inputs": [{"name": "wad", "type": "uint256"}],
|
|
65
|
+
"outputs": [],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "balanceOf",
|
|
69
|
+
"type": "function",
|
|
70
|
+
"stateMutability": "view",
|
|
71
|
+
"inputs": [{"name": "owner", "type": "address"}],
|
|
72
|
+
"outputs": [{"type": "uint256"}],
|
|
73
|
+
},
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
78
|
+
# STRATEGY THRESHOLDS
|
|
79
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
MIN_NET_DEPOSIT = 150.0 # Minimum deposit to activate strategy
|
|
82
|
+
MAX_HL_LEVERAGE = 2.0 # Maximum leverage on Hyperliquid shorts
|
|
83
|
+
PARTIAL_TRIM_THRESHOLD = 0.75 # Risk level to trigger partial trim
|
|
84
|
+
FULL_REBALANCE_THRESHOLD = 0.90 # Risk level to trigger full rebalance
|
|
85
|
+
ALLOCATION_DEVIATION_THRESHOLD = 0.03 # 3% deviation triggers rebalance
|
|
86
|
+
HORIZON_DAYS = 7 # Planning horizon in days
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
90
|
+
# BOROS CONFIGURATION
|
|
91
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
# NOTE: Boros migrated the old USDT-collateralized HYPE market. The current
|
|
94
|
+
# entry path uses HYPE collateral (via the LayerZero OFT token on Arbitrum).
|
|
95
|
+
BOROS_HYPE_MARKET_ID = 51 # HYPERLIQUID-HYPE-27FEB2026 (fallback)
|
|
96
|
+
BOROS_HYPE_TOKEN_ID = 5 # HYPE collateral token ID on Boros (current)
|
|
97
|
+
BOROS_MIN_DEPOSIT_USD = 10.50 # Minimum collateral value to bother funding
|
|
98
|
+
BOROS_MIN_TENOR_DAYS = 3 # Roll to new market if < 3 days to expiry
|
|
99
|
+
BOROS_ENABLE_MIN_TOTAL_USD = 80.0 # Skip Boros if capital below this
|
|
100
|
+
|
|
101
|
+
# LayerZero OFT bridge (HyperEVM native HYPE → Arbitrum OFT HYPE)
|
|
102
|
+
HYPE_OFT_ADDRESS = "0x007C26Ed5C33Fe6fEF62223d4c363A01F1b1dDc1"
|
|
103
|
+
LZ_EID_ARBITRUM = 30110
|
|
104
|
+
|
|
105
|
+
# Minimal IOFT ABI for quoting + sending.
|
|
106
|
+
HYPE_OFT_ABI = [
|
|
107
|
+
{
|
|
108
|
+
"inputs": [
|
|
109
|
+
{
|
|
110
|
+
"components": [
|
|
111
|
+
{"internalType": "uint32", "name": "dstEid", "type": "uint32"},
|
|
112
|
+
{"internalType": "bytes32", "name": "to", "type": "bytes32"},
|
|
113
|
+
{"internalType": "uint256", "name": "amountLD", "type": "uint256"},
|
|
114
|
+
{
|
|
115
|
+
"internalType": "uint256",
|
|
116
|
+
"name": "minAmountLD",
|
|
117
|
+
"type": "uint256",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"internalType": "bytes",
|
|
121
|
+
"name": "extraOptions",
|
|
122
|
+
"type": "bytes",
|
|
123
|
+
},
|
|
124
|
+
{"internalType": "bytes", "name": "composeMsg", "type": "bytes"},
|
|
125
|
+
{"internalType": "bytes", "name": "oftCmd", "type": "bytes"},
|
|
126
|
+
],
|
|
127
|
+
"internalType": "struct SendParam",
|
|
128
|
+
"name": "_sendParam",
|
|
129
|
+
"type": "tuple",
|
|
130
|
+
},
|
|
131
|
+
{"internalType": "bool", "name": "_payInLzToken", "type": "bool"},
|
|
132
|
+
],
|
|
133
|
+
"name": "quoteSend",
|
|
134
|
+
"outputs": [
|
|
135
|
+
{
|
|
136
|
+
"components": [
|
|
137
|
+
{"internalType": "uint256", "name": "nativeFee", "type": "uint256"},
|
|
138
|
+
{
|
|
139
|
+
"internalType": "uint256",
|
|
140
|
+
"name": "lzTokenFee",
|
|
141
|
+
"type": "uint256",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
"internalType": "struct MessagingFee",
|
|
145
|
+
"name": "",
|
|
146
|
+
"type": "tuple",
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"stateMutability": "view",
|
|
150
|
+
"type": "function",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"inputs": [
|
|
154
|
+
{
|
|
155
|
+
"components": [
|
|
156
|
+
{"internalType": "uint32", "name": "dstEid", "type": "uint32"},
|
|
157
|
+
{"internalType": "bytes32", "name": "to", "type": "bytes32"},
|
|
158
|
+
{"internalType": "uint256", "name": "amountLD", "type": "uint256"},
|
|
159
|
+
{
|
|
160
|
+
"internalType": "uint256",
|
|
161
|
+
"name": "minAmountLD",
|
|
162
|
+
"type": "uint256",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"internalType": "bytes",
|
|
166
|
+
"name": "extraOptions",
|
|
167
|
+
"type": "bytes",
|
|
168
|
+
},
|
|
169
|
+
{"internalType": "bytes", "name": "composeMsg", "type": "bytes"},
|
|
170
|
+
{"internalType": "bytes", "name": "oftCmd", "type": "bytes"},
|
|
171
|
+
],
|
|
172
|
+
"internalType": "struct SendParam",
|
|
173
|
+
"name": "_sendParam",
|
|
174
|
+
"type": "tuple",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"components": [
|
|
178
|
+
{"internalType": "uint256", "name": "nativeFee", "type": "uint256"},
|
|
179
|
+
{
|
|
180
|
+
"internalType": "uint256",
|
|
181
|
+
"name": "lzTokenFee",
|
|
182
|
+
"type": "uint256",
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
"internalType": "struct MessagingFee",
|
|
186
|
+
"name": "_fee",
|
|
187
|
+
"type": "tuple",
|
|
188
|
+
},
|
|
189
|
+
{"internalType": "address", "name": "_refundAddress", "type": "address"},
|
|
190
|
+
],
|
|
191
|
+
"name": "send",
|
|
192
|
+
"outputs": [
|
|
193
|
+
{
|
|
194
|
+
"components": [
|
|
195
|
+
{"internalType": "bytes32", "name": "guid", "type": "bytes32"},
|
|
196
|
+
{"internalType": "uint64", "name": "nonce", "type": "uint64"},
|
|
197
|
+
{
|
|
198
|
+
"components": [
|
|
199
|
+
{
|
|
200
|
+
"internalType": "uint256",
|
|
201
|
+
"name": "nativeFee",
|
|
202
|
+
"type": "uint256",
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"internalType": "uint256",
|
|
206
|
+
"name": "lzTokenFee",
|
|
207
|
+
"type": "uint256",
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
"internalType": "struct MessagingFee",
|
|
211
|
+
"name": "fee",
|
|
212
|
+
"type": "tuple",
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
"internalType": "struct MessagingReceipt",
|
|
216
|
+
"name": "",
|
|
217
|
+
"type": "tuple",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"components": [
|
|
221
|
+
{
|
|
222
|
+
"internalType": "uint256",
|
|
223
|
+
"name": "amountSentLD",
|
|
224
|
+
"type": "uint256",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"internalType": "uint256",
|
|
228
|
+
"name": "amountReceivedLD",
|
|
229
|
+
"type": "uint256",
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
"internalType": "struct OFTReceipt",
|
|
233
|
+
"name": "",
|
|
234
|
+
"type": "tuple",
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
"stateMutability": "payable",
|
|
238
|
+
"type": "function",
|
|
239
|
+
},
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
243
|
+
# GAS CONFIGURATION
|
|
244
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
MIN_HYPE_GAS = 0.1 # Minimum HYPE for HyperEVM gas
|
|
247
|
+
HYPE_DEPOSIT_REQUIREMENT = 0.1 # HYPE to ensure for gas on deposit
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
251
|
+
# EXTERNAL API ENDPOINTS
|
|
252
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
253
|
+
|
|
254
|
+
LHYPE_API_URL = "https://app.loopingcollective.org/api/external/asset/lhype"
|
|
255
|
+
KHYPE_API_URL = "https://kinetiq.xyz/api/khype"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"smoke": {
|
|
3
|
+
"deposit": {
|
|
4
|
+
"main_token_amount": 200.0,
|
|
5
|
+
"gas_token_amount": 0.01
|
|
6
|
+
},
|
|
7
|
+
"update": {},
|
|
8
|
+
"withdraw": {}
|
|
9
|
+
},
|
|
10
|
+
"canonical_deposit": {
|
|
11
|
+
"deposit": {
|
|
12
|
+
"main_token_amount": 500.0,
|
|
13
|
+
"gas_token_amount": 0.02
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"canonical_update": {
|
|
17
|
+
"update": {}
|
|
18
|
+
},
|
|
19
|
+
"canonical_status": {
|
|
20
|
+
"status": {}
|
|
21
|
+
},
|
|
22
|
+
"minimum_deposit": {
|
|
23
|
+
"deposit": {
|
|
24
|
+
"main_token_amount": 150.0,
|
|
25
|
+
"gas_token_amount": 0.01
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"error_below_minimum": {
|
|
29
|
+
"deposit": {
|
|
30
|
+
"main_token_amount": 50.0,
|
|
31
|
+
"gas_token_amount": 0.01
|
|
32
|
+
},
|
|
33
|
+
"expect": {
|
|
34
|
+
"success": false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HyperEVM / spot-leg operations for BorosHypeStrategy.
|
|
3
|
+
|
|
4
|
+
Kept as a mixin so the main strategy file stays readable without changing behavior.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from .constants import HYPE_NATIVE, KHYPE_LST, LOOPED_HYPE, MIN_HYPE_GAS
|
|
12
|
+
from .types import Inventory
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BorosHypeHyperEvmOpsMixin:
|
|
16
|
+
async def _ensure_gas_on_hyperevm(
|
|
17
|
+
self, params: dict[str, Any], inventory: Inventory
|
|
18
|
+
) -> tuple[bool, str]:
|
|
19
|
+
min_hype = float(params.get("min_hype") or MIN_HYPE_GAS)
|
|
20
|
+
need = max(0.0, min_hype - inventory.hype_hyperevm_balance)
|
|
21
|
+
if need <= 0.0:
|
|
22
|
+
return True, "HyperEVM gas already sufficient"
|
|
23
|
+
|
|
24
|
+
# Best-effort: if HYPE exists on HL spot, bridge it over.
|
|
25
|
+
if inventory.hl_spot_hype > max(0.1, need + 0.001):
|
|
26
|
+
return await self._transfer_hl_spot_to_hyperevm(
|
|
27
|
+
{"hype_amount": max(0.1, need)}, inventory
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Otherwise, we expect the upcoming BRIDGE_TO_HYPEREVM routine to bring HYPE.
|
|
31
|
+
return True, "HyperEVM gas will be provisioned during routing"
|
|
32
|
+
|
|
33
|
+
async def _ensure_gas_on_arbitrum(
|
|
34
|
+
self, params: dict[str, Any], inventory: Inventory
|
|
35
|
+
) -> tuple[bool, str]:
|
|
36
|
+
# TODO: Implement - bridge ETH or use gas station
|
|
37
|
+
return True, "Arbitrum gas routing not yet implemented"
|
|
38
|
+
|
|
39
|
+
async def _swap_hype_to_lst(
|
|
40
|
+
self, params: dict[str, Any], inventory: Inventory
|
|
41
|
+
) -> tuple[bool, str]:
|
|
42
|
+
hype_amount = params.get("hype_amount", 0.0)
|
|
43
|
+
|
|
44
|
+
if hype_amount <= 0:
|
|
45
|
+
return True, "No HYPE to swap"
|
|
46
|
+
|
|
47
|
+
if self.simulation:
|
|
48
|
+
return True, f"[SIMULATION] Swapped {hype_amount:.4f} HYPE to LSTs"
|
|
49
|
+
|
|
50
|
+
if not self.brap_adapter:
|
|
51
|
+
return False, "BRAP adapter not configured"
|
|
52
|
+
|
|
53
|
+
strategy_wallet = self._config.get("strategy_wallet", {})
|
|
54
|
+
wallet_address = strategy_wallet.get("address")
|
|
55
|
+
if not wallet_address:
|
|
56
|
+
return False, "No strategy wallet address configured"
|
|
57
|
+
|
|
58
|
+
# Normalize split fractions.
|
|
59
|
+
khype_fraction = max(0.0, float(self.hedge_cfg.khype_fraction))
|
|
60
|
+
looped_fraction = max(0.0, float(self.hedge_cfg.looped_hype_fraction))
|
|
61
|
+
total_fraction = khype_fraction + looped_fraction
|
|
62
|
+
if total_fraction <= 0:
|
|
63
|
+
khype_fraction = 0.5
|
|
64
|
+
looped_fraction = 0.5
|
|
65
|
+
total_fraction = 1.0
|
|
66
|
+
|
|
67
|
+
khype_share = khype_fraction / total_fraction
|
|
68
|
+
|
|
69
|
+
# HYPE native has 18 decimals.
|
|
70
|
+
hype_amount_wei = int(float(hype_amount) * 1e18)
|
|
71
|
+
khype_amount_wei = int(hype_amount_wei * khype_share)
|
|
72
|
+
looped_amount_wei = max(0, hype_amount_wei - khype_amount_wei)
|
|
73
|
+
|
|
74
|
+
# If one side is dust, allocate to the other.
|
|
75
|
+
min_swap_wei = int(0.02 * 1e18)
|
|
76
|
+
if 0 < khype_amount_wei < min_swap_wei:
|
|
77
|
+
looped_amount_wei += khype_amount_wei
|
|
78
|
+
khype_amount_wei = 0
|
|
79
|
+
if 0 < looped_amount_wei < min_swap_wei:
|
|
80
|
+
khype_amount_wei += looped_amount_wei
|
|
81
|
+
looped_amount_wei = 0
|
|
82
|
+
|
|
83
|
+
results: list[str] = []
|
|
84
|
+
|
|
85
|
+
if khype_amount_wei > 0:
|
|
86
|
+
ok, res = await self.brap_adapter.swap_from_token_ids(
|
|
87
|
+
from_token_id=HYPE_NATIVE,
|
|
88
|
+
to_token_id=KHYPE_LST,
|
|
89
|
+
from_address=wallet_address,
|
|
90
|
+
amount=str(khype_amount_wei),
|
|
91
|
+
slippage=0.01,
|
|
92
|
+
strategy_name="boros_hype_strategy",
|
|
93
|
+
)
|
|
94
|
+
if not ok:
|
|
95
|
+
return False, f"Swap HYPE→kHYPE failed: {res}"
|
|
96
|
+
results.append(f"kHYPE({khype_amount_wei / 1e18:.4f} HYPE)")
|
|
97
|
+
|
|
98
|
+
if looped_amount_wei > 0:
|
|
99
|
+
ok, res = await self.brap_adapter.swap_from_token_ids(
|
|
100
|
+
from_token_id=HYPE_NATIVE,
|
|
101
|
+
to_token_id=LOOPED_HYPE,
|
|
102
|
+
from_address=wallet_address,
|
|
103
|
+
amount=str(looped_amount_wei),
|
|
104
|
+
slippage=0.01,
|
|
105
|
+
strategy_name="boros_hype_strategy",
|
|
106
|
+
)
|
|
107
|
+
if not ok:
|
|
108
|
+
return False, f"Swap HYPE→looped HYPE failed: {res}"
|
|
109
|
+
results.append(f"looped({looped_amount_wei / 1e18:.4f} HYPE)")
|
|
110
|
+
|
|
111
|
+
if not results:
|
|
112
|
+
return True, "No non-dust HYPE amount to swap"
|
|
113
|
+
|
|
114
|
+
return True, f"Swapped HYPE → {', '.join(results)}"
|