wayfinder-paths 0.1.13__py3-none-any.whl → 0.1.15__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/README.md +13 -14
- wayfinder_paths/adapters/balance_adapter/adapter.py +73 -32
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +123 -0
- wayfinder_paths/adapters/brap_adapter/README.md +11 -16
- wayfinder_paths/adapters/brap_adapter/adapter.py +144 -78
- wayfinder_paths/adapters/brap_adapter/examples.json +63 -52
- wayfinder_paths/adapters/brap_adapter/test_adapter.py +127 -65
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +30 -14
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +121 -67
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +6 -6
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +12 -12
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +6 -6
- wayfinder_paths/adapters/moonwell_adapter/adapter.py +332 -9
- wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +13 -13
- wayfinder_paths/adapters/pool_adapter/README.md +9 -10
- wayfinder_paths/adapters/pool_adapter/adapter.py +9 -10
- wayfinder_paths/adapters/pool_adapter/test_adapter.py +2 -2
- wayfinder_paths/adapters/token_adapter/README.md +2 -14
- wayfinder_paths/adapters/token_adapter/adapter.py +16 -10
- wayfinder_paths/adapters/token_adapter/examples.json +4 -8
- wayfinder_paths/adapters/token_adapter/test_adapter.py +9 -7
- wayfinder_paths/core/clients/BRAPClient.py +102 -61
- wayfinder_paths/core/clients/ClientManager.py +1 -68
- wayfinder_paths/core/clients/HyperlendClient.py +125 -64
- wayfinder_paths/core/clients/LedgerClient.py +1 -4
- wayfinder_paths/core/clients/PoolClient.py +122 -48
- wayfinder_paths/core/clients/TokenClient.py +91 -36
- wayfinder_paths/core/clients/WalletClient.py +26 -56
- wayfinder_paths/core/clients/WayfinderClient.py +28 -160
- wayfinder_paths/core/clients/__init__.py +0 -2
- wayfinder_paths/core/clients/protocols.py +35 -46
- wayfinder_paths/core/clients/sdk_example.py +37 -22
- wayfinder_paths/core/constants/erc20_abi.py +0 -11
- wayfinder_paths/core/engine/StrategyJob.py +10 -56
- wayfinder_paths/core/services/base.py +1 -0
- wayfinder_paths/core/services/local_evm_txn.py +25 -9
- wayfinder_paths/core/services/local_token_txn.py +2 -6
- wayfinder_paths/core/services/test_local_evm_txn.py +145 -0
- wayfinder_paths/core/strategies/Strategy.py +16 -4
- wayfinder_paths/core/utils/evm_helpers.py +2 -9
- wayfinder_paths/policies/erc20.py +1 -1
- wayfinder_paths/run_strategy.py +13 -19
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +77 -11
- wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +6 -6
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +107 -23
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +54 -9
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +6 -5
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +2246 -1279
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +276 -109
- wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +1 -1
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +153 -56
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +16 -12
- wayfinder_paths/templates/adapter/README.md +1 -1
- wayfinder_paths/templates/strategy/README.md +3 -3
- wayfinder_paths/templates/strategy/test_strategy.py +3 -2
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/METADATA +14 -49
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/RECORD +59 -60
- wayfinder_paths/abis/generic/erc20.json +0 -383
- wayfinder_paths/core/clients/AuthClient.py +0 -83
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/LICENSE +0 -0
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/WHEEL +0 -0
|
@@ -34,44 +34,42 @@ class TestHyperlendAdapter:
|
|
|
34
34
|
async def test_get_stable_markets_success(self, adapter, mock_hyperlend_client):
|
|
35
35
|
"""Test successful stable markets retrieval"""
|
|
36
36
|
mock_response = {
|
|
37
|
-
"markets":
|
|
38
|
-
{
|
|
39
|
-
"chain_id": 999,
|
|
40
|
-
"underlying_token": "0x1234...",
|
|
37
|
+
"markets": {
|
|
38
|
+
"0x1234...": {
|
|
41
39
|
"symbol": "USDT",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
40
|
+
"symbol_canonical": "usdt",
|
|
41
|
+
"display_symbol": "USDT",
|
|
42
|
+
"reserve": {},
|
|
43
|
+
"decimals": 6,
|
|
44
|
+
"headroom": 1000000000000,
|
|
45
|
+
"supply_cap": 5000000000000,
|
|
46
46
|
},
|
|
47
|
-
{
|
|
48
|
-
"chain_id": 999,
|
|
49
|
-
"underlying_token": "0x5678...",
|
|
47
|
+
"0x5678...": {
|
|
50
48
|
"symbol": "USDC",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
49
|
+
"symbol_canonical": "usdc",
|
|
50
|
+
"display_symbol": "USDC",
|
|
51
|
+
"reserve": {},
|
|
52
|
+
"decimals": 6,
|
|
53
|
+
"headroom": 2000000000000,
|
|
54
|
+
"supply_cap": 10000000000000,
|
|
55
55
|
},
|
|
56
|
-
|
|
56
|
+
},
|
|
57
|
+
"notes": [],
|
|
57
58
|
}
|
|
58
59
|
mock_hyperlend_client.get_stable_markets = AsyncMock(return_value=mock_response)
|
|
59
60
|
|
|
60
61
|
success, data = await adapter.get_stable_markets(
|
|
61
|
-
chain_id=999,
|
|
62
62
|
required_underlying_tokens=1000.0,
|
|
63
63
|
buffer_bps=100,
|
|
64
64
|
min_buffer_tokens=100.0,
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
assert success
|
|
67
|
+
assert success
|
|
68
68
|
assert data == mock_response
|
|
69
69
|
mock_hyperlend_client.get_stable_markets.assert_called_once_with(
|
|
70
|
-
chain_id=999,
|
|
71
70
|
required_underlying_tokens=1000.0,
|
|
72
71
|
buffer_bps=100,
|
|
73
72
|
min_buffer_tokens=100.0,
|
|
74
|
-
is_stable_symbol=None,
|
|
75
73
|
)
|
|
76
74
|
|
|
77
75
|
@pytest.mark.asyncio
|
|
@@ -80,27 +78,29 @@ class TestHyperlendAdapter:
|
|
|
80
78
|
):
|
|
81
79
|
"""Test stable markets retrieval with only required chain_id"""
|
|
82
80
|
mock_response = {
|
|
83
|
-
"markets":
|
|
84
|
-
{
|
|
85
|
-
"chain_id": 999,
|
|
86
|
-
"underlying_token": "0x1234...",
|
|
81
|
+
"markets": {
|
|
82
|
+
"0x1234...": {
|
|
87
83
|
"symbol": "USDT",
|
|
88
|
-
"
|
|
84
|
+
"symbol_canonical": "usdt",
|
|
85
|
+
"display_symbol": "USDT",
|
|
86
|
+
"reserve": {},
|
|
87
|
+
"decimals": 6,
|
|
88
|
+
"headroom": 1000000000000,
|
|
89
|
+
"supply_cap": 5000000000000,
|
|
89
90
|
}
|
|
90
|
-
|
|
91
|
+
},
|
|
92
|
+
"notes": [],
|
|
91
93
|
}
|
|
92
94
|
mock_hyperlend_client.get_stable_markets = AsyncMock(return_value=mock_response)
|
|
93
95
|
|
|
94
|
-
success, data = await adapter.get_stable_markets(
|
|
96
|
+
success, data = await adapter.get_stable_markets()
|
|
95
97
|
|
|
96
|
-
assert success
|
|
98
|
+
assert success
|
|
97
99
|
assert data == mock_response
|
|
98
100
|
mock_hyperlend_client.get_stable_markets.assert_called_once_with(
|
|
99
|
-
chain_id=999,
|
|
100
101
|
required_underlying_tokens=None,
|
|
101
102
|
buffer_bps=None,
|
|
102
103
|
min_buffer_tokens=None,
|
|
103
|
-
is_stable_symbol=None,
|
|
104
104
|
)
|
|
105
105
|
|
|
106
106
|
@pytest.mark.asyncio
|
|
@@ -108,21 +108,19 @@ class TestHyperlendAdapter:
|
|
|
108
108
|
self, adapter, mock_hyperlend_client
|
|
109
109
|
):
|
|
110
110
|
"""Test stable markets retrieval with partial optional parameters"""
|
|
111
|
-
mock_response = {"markets": []}
|
|
111
|
+
mock_response = {"markets": {}, "notes": []}
|
|
112
112
|
mock_hyperlend_client.get_stable_markets = AsyncMock(return_value=mock_response)
|
|
113
113
|
|
|
114
114
|
success, data = await adapter.get_stable_markets(
|
|
115
|
-
|
|
115
|
+
required_underlying_tokens=500.0
|
|
116
116
|
)
|
|
117
117
|
|
|
118
|
-
assert success
|
|
118
|
+
assert success
|
|
119
119
|
assert data == mock_response
|
|
120
120
|
mock_hyperlend_client.get_stable_markets.assert_called_once_with(
|
|
121
|
-
chain_id=999,
|
|
122
121
|
required_underlying_tokens=500.0,
|
|
123
122
|
buffer_bps=None,
|
|
124
123
|
min_buffer_tokens=None,
|
|
125
|
-
is_stable_symbol=None,
|
|
126
124
|
)
|
|
127
125
|
|
|
128
126
|
@pytest.mark.asyncio
|
|
@@ -132,7 +130,7 @@ class TestHyperlendAdapter:
|
|
|
132
130
|
side_effect=Exception("API Error: Connection timeout")
|
|
133
131
|
)
|
|
134
132
|
|
|
135
|
-
success, data = await adapter.get_stable_markets(
|
|
133
|
+
success, data = await adapter.get_stable_markets()
|
|
136
134
|
|
|
137
135
|
assert success is False
|
|
138
136
|
assert "API Error: Connection timeout" in data
|
|
@@ -144,7 +142,7 @@ class TestHyperlendAdapter:
|
|
|
144
142
|
side_effect=Exception("HTTP 404 Not Found")
|
|
145
143
|
)
|
|
146
144
|
|
|
147
|
-
success, data = await adapter.get_stable_markets(
|
|
145
|
+
success, data = await adapter.get_stable_markets()
|
|
148
146
|
|
|
149
147
|
assert success is False
|
|
150
148
|
assert "404" in data or "Not Found" in data
|
|
@@ -154,14 +152,14 @@ class TestHyperlendAdapter:
|
|
|
154
152
|
self, adapter, mock_hyperlend_client
|
|
155
153
|
):
|
|
156
154
|
"""Test stable markets retrieval with empty response"""
|
|
157
|
-
mock_response = {"markets": []}
|
|
155
|
+
mock_response = {"markets": {}, "notes": []}
|
|
158
156
|
mock_hyperlend_client.get_stable_markets = AsyncMock(return_value=mock_response)
|
|
159
157
|
|
|
160
|
-
success, data = await adapter.get_stable_markets(
|
|
158
|
+
success, data = await adapter.get_stable_markets()
|
|
161
159
|
|
|
162
|
-
assert success
|
|
160
|
+
assert success
|
|
163
161
|
assert data == mock_response
|
|
164
|
-
assert len(data.get("markets",
|
|
162
|
+
assert len(data.get("markets", {})) == 0
|
|
165
163
|
|
|
166
164
|
def test_adapter_type(self, adapter):
|
|
167
165
|
"""Test adapter has adapter_type"""
|
|
@@ -186,59 +184,95 @@ class TestHyperlendAdapter:
|
|
|
186
184
|
async def test_get_stable_markets_with_is_stable_symbol(
|
|
187
185
|
self, adapter, mock_hyperlend_client
|
|
188
186
|
):
|
|
189
|
-
"""Test stable markets retrieval with is_stable_symbol parameter"""
|
|
187
|
+
"""Test stable markets retrieval with is_stable_symbol parameter (ignored by API)"""
|
|
190
188
|
mock_response = {
|
|
191
|
-
"markets":
|
|
192
|
-
{
|
|
193
|
-
"chain_id": 999,
|
|
194
|
-
"underlying_token": "0x1234...",
|
|
189
|
+
"markets": {
|
|
190
|
+
"0x1234...": {
|
|
195
191
|
"symbol": "USDT",
|
|
196
|
-
"
|
|
192
|
+
"symbol_canonical": "usdt",
|
|
193
|
+
"display_symbol": "USDT",
|
|
194
|
+
"reserve": {},
|
|
195
|
+
"decimals": 6,
|
|
196
|
+
"headroom": 1000000000000,
|
|
197
|
+
"supply_cap": 5000000000000,
|
|
197
198
|
}
|
|
198
|
-
|
|
199
|
+
},
|
|
200
|
+
"notes": [],
|
|
199
201
|
}
|
|
200
202
|
mock_hyperlend_client.get_stable_markets = AsyncMock(return_value=mock_response)
|
|
201
203
|
|
|
202
|
-
success, data = await adapter.get_stable_markets(
|
|
203
|
-
chain_id=999, is_stable_symbol=True
|
|
204
|
-
)
|
|
204
|
+
success, data = await adapter.get_stable_markets()
|
|
205
205
|
|
|
206
|
-
assert success
|
|
206
|
+
assert success
|
|
207
207
|
assert data == mock_response
|
|
208
208
|
mock_hyperlend_client.get_stable_markets.assert_called_once_with(
|
|
209
|
-
chain_id=999,
|
|
210
209
|
required_underlying_tokens=None,
|
|
211
210
|
buffer_bps=None,
|
|
212
211
|
min_buffer_tokens=None,
|
|
213
|
-
is_stable_symbol=True,
|
|
214
212
|
)
|
|
215
213
|
|
|
216
214
|
@pytest.mark.asyncio
|
|
217
215
|
async def test_get_assets_view_success(self, adapter, mock_hyperlend_client):
|
|
218
216
|
"""Test successful assets view retrieval"""
|
|
219
217
|
mock_response = {
|
|
218
|
+
"block_number": 12345,
|
|
219
|
+
"user": "0x0c737cB5934afCb5B01965141F865F795B324080",
|
|
220
|
+
"native_balance_wei": 0,
|
|
221
|
+
"native_balance": 0.0,
|
|
220
222
|
"assets": [
|
|
221
223
|
{
|
|
222
|
-
"
|
|
224
|
+
"underlying": "0x1234...",
|
|
223
225
|
"symbol": "USDT",
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
"
|
|
226
|
+
"symbol_canonical": "usdt",
|
|
227
|
+
"symbol_display": "USDT",
|
|
228
|
+
"decimals": 6,
|
|
229
|
+
"a_token": "0x...",
|
|
230
|
+
"variable_debt_token": "0x...",
|
|
231
|
+
"usage_as_collateral_enabled": True,
|
|
232
|
+
"borrowing_enabled": True,
|
|
233
|
+
"is_active": True,
|
|
234
|
+
"is_frozen": False,
|
|
235
|
+
"is_paused": False,
|
|
236
|
+
"is_siloed_borrowing": False,
|
|
237
|
+
"is_stablecoin": True,
|
|
238
|
+
"underlying_wallet_balance": 1000.0,
|
|
239
|
+
"underlying_wallet_balance_wei": 1000000000,
|
|
240
|
+
"price_usd": 1.0,
|
|
241
|
+
"supply": 500.0,
|
|
242
|
+
"variable_borrow": 0.0,
|
|
243
|
+
"supply_usd": 500.0,
|
|
244
|
+
"variable_borrow_usd": 0.0,
|
|
245
|
+
"supply_apr": 0.05,
|
|
246
|
+
"supply_apy": 0.05,
|
|
247
|
+
"variable_borrow_apr": 0.07,
|
|
248
|
+
"variable_borrow_apy": 0.07,
|
|
227
249
|
}
|
|
228
250
|
],
|
|
229
|
-
"
|
|
251
|
+
"account_data": {
|
|
252
|
+
"total_collateral_base": 500,
|
|
253
|
+
"total_debt_base": 0,
|
|
254
|
+
"available_borrows_base": 400,
|
|
255
|
+
"current_liquidation_threshold": 8000,
|
|
256
|
+
"ltv": 7500,
|
|
257
|
+
"health_factor_wad": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
|
|
258
|
+
"health_factor": 1.157920892373162e59,
|
|
259
|
+
},
|
|
260
|
+
"base_currency_info": {
|
|
261
|
+
"marketReferenceCurrencyUnit": 100000000,
|
|
262
|
+
"marketReferenceCurrencyPriceInUsd": 100000000,
|
|
263
|
+
"networkBaseTokenPriceInUsd": 0,
|
|
264
|
+
"networkBaseTokenPriceDecimals": 8,
|
|
265
|
+
},
|
|
230
266
|
}
|
|
231
267
|
mock_hyperlend_client.get_assets_view = AsyncMock(return_value=mock_response)
|
|
232
268
|
|
|
233
269
|
success, data = await adapter.get_assets_view(
|
|
234
|
-
chain_id=999,
|
|
235
270
|
user_address="0x0c737cB5934afCb5B01965141F865F795B324080",
|
|
236
271
|
)
|
|
237
272
|
|
|
238
|
-
assert success
|
|
273
|
+
assert success
|
|
239
274
|
assert data == mock_response
|
|
240
275
|
mock_hyperlend_client.get_assets_view.assert_called_once_with(
|
|
241
|
-
chain_id=999,
|
|
242
276
|
user_address="0x0c737cB5934afCb5B01965141F865F795B324080",
|
|
243
277
|
)
|
|
244
278
|
|
|
@@ -250,7 +284,6 @@ class TestHyperlendAdapter:
|
|
|
250
284
|
)
|
|
251
285
|
|
|
252
286
|
success, data = await adapter.get_assets_view(
|
|
253
|
-
chain_id=999,
|
|
254
287
|
user_address="0x0c737cB5934afCb5B01965141F865F795B324080",
|
|
255
288
|
)
|
|
256
289
|
|
|
@@ -260,15 +293,36 @@ class TestHyperlendAdapter:
|
|
|
260
293
|
@pytest.mark.asyncio
|
|
261
294
|
async def test_get_assets_view_empty_response(self, adapter, mock_hyperlend_client):
|
|
262
295
|
"""Test assets view retrieval with empty response"""
|
|
263
|
-
mock_response = {
|
|
296
|
+
mock_response = {
|
|
297
|
+
"block_number": 12345,
|
|
298
|
+
"user": "0x0c737cB5934afCb5B01965141F865F795B324080",
|
|
299
|
+
"native_balance_wei": 0,
|
|
300
|
+
"native_balance": 0.0,
|
|
301
|
+
"assets": [],
|
|
302
|
+
"account_data": {
|
|
303
|
+
"total_collateral_base": 0,
|
|
304
|
+
"total_debt_base": 0,
|
|
305
|
+
"available_borrows_base": 0,
|
|
306
|
+
"current_liquidation_threshold": 0,
|
|
307
|
+
"ltv": 0,
|
|
308
|
+
"health_factor_wad": 0,
|
|
309
|
+
"health_factor": 0.0,
|
|
310
|
+
},
|
|
311
|
+
"base_currency_info": {
|
|
312
|
+
"marketReferenceCurrencyUnit": 100000000,
|
|
313
|
+
"marketReferenceCurrencyPriceInUsd": 100000000,
|
|
314
|
+
"networkBaseTokenPriceInUsd": 0,
|
|
315
|
+
"networkBaseTokenPriceDecimals": 8,
|
|
316
|
+
},
|
|
317
|
+
}
|
|
264
318
|
mock_hyperlend_client.get_assets_view = AsyncMock(return_value=mock_response)
|
|
265
319
|
|
|
266
320
|
success, data = await adapter.get_assets_view(
|
|
267
|
-
chain_id=999,
|
|
268
321
|
user_address="0x0c737cB5934afCb5B01965141F865F795B324080",
|
|
269
322
|
)
|
|
270
323
|
|
|
271
|
-
assert success
|
|
324
|
+
assert success
|
|
272
325
|
assert data == mock_response
|
|
273
326
|
assert len(data.get("assets", [])) == 0
|
|
274
|
-
|
|
327
|
+
# New API uses account_data; total_value may not be present
|
|
328
|
+
assert data.get("account_data", {}).get("total_collateral_base") == 0
|
|
@@ -72,41 +72,41 @@ class TestHyperliquidAdapter:
|
|
|
72
72
|
async def test_get_meta_and_asset_ctxs(self, adapter):
|
|
73
73
|
"""Test fetching market metadata."""
|
|
74
74
|
success, data = await adapter.get_meta_and_asset_ctxs()
|
|
75
|
-
assert success
|
|
75
|
+
assert success
|
|
76
76
|
assert "universe" in data[0]
|
|
77
77
|
|
|
78
78
|
@pytest.mark.asyncio
|
|
79
79
|
async def test_get_spot_meta(self, adapter):
|
|
80
80
|
"""Test fetching spot metadata."""
|
|
81
81
|
success, data = await adapter.get_spot_meta()
|
|
82
|
-
assert success
|
|
82
|
+
assert success
|
|
83
83
|
|
|
84
84
|
@pytest.mark.asyncio
|
|
85
85
|
async def test_get_funding_history(self, adapter):
|
|
86
86
|
"""Test fetching funding history."""
|
|
87
87
|
success, data = await adapter.get_funding_history("ETH", 1700000000000)
|
|
88
|
-
assert success
|
|
88
|
+
assert success
|
|
89
89
|
assert isinstance(data, list)
|
|
90
90
|
|
|
91
91
|
@pytest.mark.asyncio
|
|
92
92
|
async def test_get_candles(self, adapter):
|
|
93
93
|
"""Test fetching candle data."""
|
|
94
94
|
success, data = await adapter.get_candles("ETH", "1h", 1700000000000)
|
|
95
|
-
assert success
|
|
95
|
+
assert success
|
|
96
96
|
assert isinstance(data, list)
|
|
97
97
|
|
|
98
98
|
@pytest.mark.asyncio
|
|
99
99
|
async def test_get_l2_book(self, adapter):
|
|
100
100
|
"""Test fetching order book."""
|
|
101
101
|
success, data = await adapter.get_l2_book("ETH")
|
|
102
|
-
assert success
|
|
102
|
+
assert success
|
|
103
103
|
assert "levels" in data
|
|
104
104
|
|
|
105
105
|
@pytest.mark.asyncio
|
|
106
106
|
async def test_get_user_state(self, adapter):
|
|
107
107
|
"""Test fetching user state."""
|
|
108
108
|
success, data = await adapter.get_user_state("0x1234")
|
|
109
|
-
assert success
|
|
109
|
+
assert success
|
|
110
110
|
assert "assetPositions" in data
|
|
111
111
|
|
|
112
112
|
@pytest.mark.asyncio
|
|
@@ -28,7 +28,7 @@ class TestSpotAssetIDs:
|
|
|
28
28
|
"""Verify get_spot_assets returns a populated dict."""
|
|
29
29
|
success, spot_assets = await live_adapter.get_spot_assets()
|
|
30
30
|
|
|
31
|
-
assert success
|
|
31
|
+
assert success
|
|
32
32
|
assert isinstance(spot_assets, dict)
|
|
33
33
|
assert len(spot_assets) > 0
|
|
34
34
|
|
|
@@ -37,7 +37,7 @@ class TestSpotAssetIDs:
|
|
|
37
37
|
"""PURR/USDC should be the first spot pair (index 0 + 10000 = 10000)."""
|
|
38
38
|
success, spot_assets = await live_adapter.get_spot_assets()
|
|
39
39
|
|
|
40
|
-
assert success
|
|
40
|
+
assert success
|
|
41
41
|
assert "PURR/USDC" in spot_assets
|
|
42
42
|
assert spot_assets["PURR/USDC"] == 10000
|
|
43
43
|
|
|
@@ -46,7 +46,7 @@ class TestSpotAssetIDs:
|
|
|
46
46
|
"""HYPE/USDC should have asset ID 10107."""
|
|
47
47
|
success, spot_assets = await live_adapter.get_spot_assets()
|
|
48
48
|
|
|
49
|
-
assert success
|
|
49
|
+
assert success
|
|
50
50
|
assert "HYPE/USDC" in spot_assets
|
|
51
51
|
# HYPE is index 107, so asset_id = 10107
|
|
52
52
|
assert spot_assets["HYPE/USDC"] == 10107
|
|
@@ -56,7 +56,7 @@ class TestSpotAssetIDs:
|
|
|
56
56
|
"""ETH/USDC spot pair should exist."""
|
|
57
57
|
success, spot_assets = await live_adapter.get_spot_assets()
|
|
58
58
|
|
|
59
|
-
assert success
|
|
59
|
+
assert success
|
|
60
60
|
# ETH spot may have different naming, check common variants
|
|
61
61
|
eth_pairs = [k for k in spot_assets if "ETH" in k and "USDC" in k]
|
|
62
62
|
assert len(eth_pairs) > 0, (
|
|
@@ -68,7 +68,7 @@ class TestSpotAssetIDs:
|
|
|
68
68
|
"""BTC/USDC spot pair should exist."""
|
|
69
69
|
success, spot_assets = await live_adapter.get_spot_assets()
|
|
70
70
|
|
|
71
|
-
assert success
|
|
71
|
+
assert success
|
|
72
72
|
# BTC spot may have different naming
|
|
73
73
|
btc_pairs = [k for k in spot_assets if "BTC" in k and "USDC" in k]
|
|
74
74
|
assert len(btc_pairs) > 0, (
|
|
@@ -80,7 +80,7 @@ class TestSpotAssetIDs:
|
|
|
80
80
|
"""All spot asset IDs should be >= 10000."""
|
|
81
81
|
success, spot_assets = await live_adapter.get_spot_assets()
|
|
82
82
|
|
|
83
|
-
assert success
|
|
83
|
+
assert success
|
|
84
84
|
for name, asset_id in spot_assets.items():
|
|
85
85
|
assert asset_id >= 10000, f"{name} has invalid asset_id {asset_id}"
|
|
86
86
|
|
|
@@ -89,7 +89,7 @@ class TestSpotAssetIDs:
|
|
|
89
89
|
"""Test synchronous helper after cache is populated."""
|
|
90
90
|
# First populate cache
|
|
91
91
|
success, _ = await live_adapter.get_spot_assets()
|
|
92
|
-
assert success
|
|
92
|
+
assert success
|
|
93
93
|
|
|
94
94
|
# Now use sync helper
|
|
95
95
|
purr_id = live_adapter.get_spot_asset_id("PURR", "USDC")
|
|
@@ -147,7 +147,7 @@ class TestSpotMetaStructure:
|
|
|
147
147
|
"""Spot meta should have tokens array."""
|
|
148
148
|
success, spot_meta = await live_adapter.get_spot_meta()
|
|
149
149
|
|
|
150
|
-
assert success
|
|
150
|
+
assert success
|
|
151
151
|
assert "tokens" in spot_meta
|
|
152
152
|
assert isinstance(spot_meta["tokens"], list)
|
|
153
153
|
assert len(spot_meta["tokens"]) > 0
|
|
@@ -157,7 +157,7 @@ class TestSpotMetaStructure:
|
|
|
157
157
|
"""Spot meta should have universe array with pairs."""
|
|
158
158
|
success, spot_meta = await live_adapter.get_spot_meta()
|
|
159
159
|
|
|
160
|
-
assert success
|
|
160
|
+
assert success
|
|
161
161
|
assert "universe" in spot_meta
|
|
162
162
|
assert isinstance(spot_meta["universe"], list)
|
|
163
163
|
assert len(spot_meta["universe"]) > 0
|
|
@@ -167,7 +167,7 @@ class TestSpotMetaStructure:
|
|
|
167
167
|
"""Each spot universe entry should have tokens and index."""
|
|
168
168
|
success, spot_meta = await live_adapter.get_spot_meta()
|
|
169
169
|
|
|
170
|
-
assert success
|
|
170
|
+
assert success
|
|
171
171
|
for pair in spot_meta["universe"][:5]: # Check first 5
|
|
172
172
|
assert "tokens" in pair, f"Missing tokens in {pair}"
|
|
173
173
|
assert "index" in pair, f"Missing index in {pair}"
|
|
@@ -182,7 +182,7 @@ class TestL2BookResolution:
|
|
|
182
182
|
"""PURR/USDC (10000) should return valid L2 book."""
|
|
183
183
|
success, book = await live_adapter.get_spot_l2_book(10000)
|
|
184
184
|
|
|
185
|
-
assert success
|
|
185
|
+
assert success
|
|
186
186
|
assert "levels" in book
|
|
187
187
|
|
|
188
188
|
@pytest.mark.asyncio
|
|
@@ -190,7 +190,7 @@ class TestL2BookResolution:
|
|
|
190
190
|
"""HYPE/USDC (10107) should return valid L2 book."""
|
|
191
191
|
success, book = await live_adapter.get_spot_l2_book(10107)
|
|
192
192
|
|
|
193
|
-
assert success
|
|
193
|
+
assert success
|
|
194
194
|
assert "levels" in book
|
|
195
195
|
|
|
196
196
|
|
|
@@ -45,7 +45,7 @@ class TestLedgerAdapter:
|
|
|
45
45
|
offset=0,
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
-
assert success
|
|
48
|
+
assert success
|
|
49
49
|
assert data == mock_response
|
|
50
50
|
mock_ledger_client.get_strategy_transactions.assert_called_once_with(
|
|
51
51
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
@@ -84,7 +84,7 @@ class TestLedgerAdapter:
|
|
|
84
84
|
wallet_address="0x1234567890123456789012345678901234567890"
|
|
85
85
|
)
|
|
86
86
|
|
|
87
|
-
assert success
|
|
87
|
+
assert success
|
|
88
88
|
assert data == mock_response
|
|
89
89
|
mock_ledger_client.get_strategy_net_deposit.assert_called_once_with(
|
|
90
90
|
wallet_address="0x1234567890123456789012345678901234567890"
|
|
@@ -110,7 +110,7 @@ class TestLedgerAdapter:
|
|
|
110
110
|
strategy_name="TestStrategy",
|
|
111
111
|
)
|
|
112
112
|
|
|
113
|
-
assert success
|
|
113
|
+
assert success
|
|
114
114
|
assert data == mock_response
|
|
115
115
|
mock_ledger_client.add_strategy_deposit.assert_called_once_with(
|
|
116
116
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
@@ -142,7 +142,7 @@ class TestLedgerAdapter:
|
|
|
142
142
|
strategy_name="TestStrategy",
|
|
143
143
|
)
|
|
144
144
|
|
|
145
|
-
assert success
|
|
145
|
+
assert success
|
|
146
146
|
assert data == mock_response
|
|
147
147
|
|
|
148
148
|
@pytest.mark.asyncio
|
|
@@ -177,7 +177,7 @@ class TestLedgerAdapter:
|
|
|
177
177
|
strategy_name="TestStrategy",
|
|
178
178
|
)
|
|
179
179
|
|
|
180
|
-
assert success
|
|
180
|
+
assert success
|
|
181
181
|
assert data == mock_response
|
|
182
182
|
|
|
183
183
|
@pytest.mark.asyncio
|
|
@@ -197,7 +197,7 @@ class TestLedgerAdapter:
|
|
|
197
197
|
wallet_address="0x1234567890123456789012345678901234567890", limit=10
|
|
198
198
|
)
|
|
199
199
|
|
|
200
|
-
assert success
|
|
200
|
+
assert success
|
|
201
201
|
assert data["total_transactions"] == 3
|
|
202
202
|
assert data["operations"]["deposits"] == 1
|
|
203
203
|
assert data["operations"]["withdrawals"] == 1
|