wayfinder-paths 0.1.22__py3-none-any.whl → 0.1.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wayfinder-paths might be problematic. Click here for more details.

Files changed (63) hide show
  1. wayfinder_paths/__init__.py +0 -4
  2. wayfinder_paths/adapters/balance_adapter/README.md +0 -1
  3. wayfinder_paths/adapters/balance_adapter/adapter.py +65 -169
  4. wayfinder_paths/adapters/balance_adapter/test_adapter.py +41 -113
  5. wayfinder_paths/adapters/brap_adapter/README.md +22 -75
  6. wayfinder_paths/adapters/brap_adapter/adapter.py +187 -576
  7. wayfinder_paths/adapters/brap_adapter/examples.json +21 -140
  8. wayfinder_paths/adapters/brap_adapter/test_adapter.py +6 -234
  9. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +39 -86
  10. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +5 -1
  11. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +6 -5
  12. wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
  13. wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
  14. wayfinder_paths/adapters/moonwell_adapter/adapter.py +108 -198
  15. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +37 -23
  16. wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
  17. wayfinder_paths/core/__init__.py +0 -3
  18. wayfinder_paths/core/clients/BRAPClient.py +3 -0
  19. wayfinder_paths/core/clients/ClientManager.py +0 -7
  20. wayfinder_paths/core/clients/LedgerClient.py +196 -172
  21. wayfinder_paths/core/clients/WayfinderClient.py +0 -1
  22. wayfinder_paths/core/clients/__init__.py +0 -5
  23. wayfinder_paths/core/clients/protocols.py +0 -13
  24. wayfinder_paths/core/config.py +0 -164
  25. wayfinder_paths/core/constants/__init__.py +58 -2
  26. wayfinder_paths/core/constants/base.py +8 -22
  27. wayfinder_paths/core/constants/chains.py +36 -0
  28. wayfinder_paths/core/constants/contracts.py +39 -0
  29. wayfinder_paths/core/constants/tokens.py +9 -0
  30. wayfinder_paths/core/strategies/Strategy.py +0 -10
  31. wayfinder_paths/core/utils/evm_helpers.py +5 -15
  32. wayfinder_paths/core/utils/tokens.py +28 -0
  33. wayfinder_paths/core/utils/transaction.py +13 -7
  34. wayfinder_paths/core/utils/web3.py +5 -3
  35. wayfinder_paths/policies/enso.py +1 -2
  36. wayfinder_paths/policies/hyper_evm.py +6 -3
  37. wayfinder_paths/policies/hyperlend.py +1 -2
  38. wayfinder_paths/policies/moonwell.py +12 -7
  39. wayfinder_paths/policies/prjx.py +1 -3
  40. wayfinder_paths/run_strategy.py +97 -300
  41. wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -1
  42. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +19 -14
  43. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +12 -11
  44. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +20 -33
  45. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +21 -18
  46. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -130
  47. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +32 -42
  48. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/METADATA +2 -3
  49. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/RECORD +51 -60
  50. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/WHEEL +1 -1
  51. wayfinder_paths/core/clients/WalletClient.py +0 -41
  52. wayfinder_paths/core/engine/StrategyJob.py +0 -110
  53. wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
  54. wayfinder_paths/templates/adapter/README.md +0 -150
  55. wayfinder_paths/templates/adapter/adapter.py +0 -16
  56. wayfinder_paths/templates/adapter/examples.json +0 -8
  57. wayfinder_paths/templates/adapter/test_adapter.py +0 -30
  58. wayfinder_paths/templates/strategy/README.md +0 -186
  59. wayfinder_paths/templates/strategy/examples.json +0 -11
  60. wayfinder_paths/templates/strategy/strategy.py +0 -35
  61. wayfinder_paths/templates/strategy/test_strategy.py +0 -166
  62. wayfinder_paths/tests/test_smoke_manifest.py +0 -63
  63. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/LICENSE +0 -0
@@ -1,55 +1,5 @@
1
1
  {
2
- "get_swap_quote": {
3
- "description": "Get a quote for a cross-chain swap operation",
4
- "input": {
5
- "from_token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
6
- "to_token_address": "0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
7
- "from_chain_id": 8453,
8
- "to_chain_id": 1,
9
- "from_address": "0x1234567890123456789012345678901234567890",
10
- "to_address": "0x1234567890123456789012345678901234567890",
11
- "amount": "1000000000000000000",
12
- "slippage": 0.01
13
- },
14
- "output": {
15
- "success": true,
16
- "data": {
17
- "quotes": [
18
- {
19
- "provider": "enso",
20
- "input_amount": 1000000000000000000,
21
- "output_amount": 995000000000000000,
22
- "fee_estimate": {
23
- "fee_total_usd": 0.08,
24
- "fee_breakdown": []
25
- },
26
- "calldata": {
27
- "data": "0x",
28
- "to": "0x",
29
- "value": "0",
30
- "chainId": 8453
31
- }
32
- }
33
- ],
34
- "best_quote": {
35
- "provider": "enso",
36
- "input_amount": 1000000000000000000,
37
- "output_amount": 995000000000000000,
38
- "fee_estimate": {
39
- "fee_total_usd": 0.08,
40
- "fee_breakdown": []
41
- },
42
- "calldata": {
43
- "data": "0x",
44
- "to": "0x",
45
- "value": "0",
46
- "chainId": 8453
47
- }
48
- }
49
- }
50
- }
51
- },
52
- "get_best_quote": {
2
+ "best_quote": {
53
3
  "description": "Get the best available quote for a swap operation",
54
4
  "input": {
55
5
  "from_token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
@@ -57,9 +7,7 @@
57
7
  "from_chain_id": 8453,
58
8
  "to_chain_id": 1,
59
9
  "from_address": "0x1234567890123456789012345678901234567890",
60
- "to_address": "0x1234567890123456789012345678901234567890",
61
- "amount": "1000000000000000000",
62
- "slippage": 0.01
10
+ "amount": "1000000000000000000"
63
11
  },
64
12
  "output": {
65
13
  "success": true,
@@ -80,106 +28,39 @@
80
28
  }
81
29
  }
82
30
  },
83
- "calculate_swap_fees": {
84
- "description": "Calculate fees for a swap operation",
31
+ "swap_from_token_ids": {
32
+ "description": "Execute a swap using token IDs",
85
33
  "input": {
86
- "from_token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
87
- "to_token_address": "0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
88
- "from_chain_id": 8453,
89
- "to_chain_id": 1,
90
- "amount": "1000000000000000000",
91
- "slippage": 0.01
92
- },
93
- "output": {
94
- "success": true,
95
- "data": {
96
- "input_amount": 1000000000000000000,
97
- "output_amount": 995000000000000000,
98
- "gas_fee": 567840,
99
- "bridge_fee": 0,
100
- "protocol_fee": 0.08,
101
- "total_fee": 0.08,
102
- "slippage": 0,
103
- "price_impact": 6888
104
- }
105
- }
106
- },
107
- "compare_routes": {
108
- "description": "Compare multiple routes for a swap operation",
109
- "input": {
110
- "from_token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
111
- "to_token_address": "0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
112
- "from_chain_id": 8453,
113
- "to_chain_id": 1,
34
+ "from_token_id": "usd-coin-base",
35
+ "to_token_id": "ethereum",
36
+ "from_address": "0x1234567890123456789012345678901234567890",
114
37
  "amount": "1000000000000000000",
115
- "slippage": 0.01
38
+ "strategy_name": "my_strategy"
116
39
  },
117
40
  "output": {
118
41
  "success": true,
119
42
  "data": {
120
- "total_routes": 2,
121
- "best_route": {
122
- "provider": "enso",
123
- "output_amount": 995000000000000000,
124
- "fee_estimate": { "fee_total_usd": 0.08, "fee_breakdown": [] }
125
- },
126
- "all_routes": [
127
- {
128
- "provider": "enso",
129
- "output_amount": 995000000000000000,
130
- "fee_estimate": { "fee_total_usd": 0.08, "fee_breakdown": [] }
131
- },
132
- {
133
- "provider": "enso",
134
- "output_amount": 992000000000000000,
135
- "fee_estimate": { "fee_total_usd": 0.12, "fee_breakdown": [] }
136
- }
137
- ],
138
- "route_analysis": {
139
- "highest_output": {
140
- "output_amount": 995000000000000000
141
- },
142
- "lowest_fees": {
143
- "fee_estimate": { "fee_total_usd": 0.08, "fee_breakdown": [] }
144
- }
145
- }
43
+ "from_amount": "1000000000000000000",
44
+ "to_amount": "995000000000000000",
45
+ "tx_hash": "0xabc123..."
146
46
  }
147
47
  }
148
48
  },
149
- "estimate_gas_cost": {
150
- "description": "Estimate gas costs for a cross-chain operation",
49
+ "swap_from_quote": {
50
+ "description": "Execute a swap from a pre-fetched quote",
151
51
  "input": {
152
- "from_chain_id": 8453,
153
- "to_chain_id": 1,
154
- "operation_type": "swap"
155
- },
156
- "output": {
157
- "success": true,
158
- "data": {
159
- "from_chain": "base",
160
- "to_chain": "ethereum",
161
- "from_gas_estimate": 100000,
162
- "to_gas_estimate": 150000,
163
- "total_operations": 2,
164
- "operation_type": "swap"
165
- }
166
- }
167
- },
168
- "validate_swap_parameters": {
169
- "description": "Validate swap parameters before executing",
170
- "input": {
171
- "from_token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
172
- "to_token_address": "0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
173
- "from_chain_id": 8453,
174
- "to_chain_id": 1,
175
- "amount": "1000000000000000000"
52
+ "from_token": {"address": "0x...", "chain": {"id": 8453}},
53
+ "to_token": {"address": "0x...", "chain": {"id": 1}},
54
+ "from_address": "0x1234567890123456789012345678901234567890",
55
+ "quote": {"calldata": {"data": "0x...", "to": "0x..."}, "input_amount": "1000000000000000000"},
56
+ "strategy_name": "my_strategy"
176
57
  },
177
58
  "output": {
178
59
  "success": true,
179
60
  "data": {
180
- "valid": true,
181
- "quote_available": true,
182
- "estimated_output": "995000000000000000"
61
+ "from_amount": "1000000000000000000",
62
+ "to_amount": "995000000000000000",
63
+ "tx_hash": "0xabc123..."
183
64
  }
184
65
  }
185
66
  }
@@ -18,63 +18,7 @@ class TestBRAPAdapter:
18
18
  return adapter
19
19
 
20
20
  @pytest.mark.asyncio
21
- async def test_get_swap_quote_success(self, adapter, mock_brap_client):
22
- mock_response = {
23
- "quotes": [
24
- {
25
- "provider": "enso",
26
- "input_amount": 1000000000000000000,
27
- "output_amount": 995000000000000000,
28
- "calldata": {
29
- "data": "0x",
30
- "to": "0x",
31
- "from_address": "0x",
32
- "value": "0",
33
- "chainId": 8453,
34
- },
35
- "fee_estimate": {"fee_total_usd": 0.008, "fee_breakdown": []},
36
- }
37
- ],
38
- "best_quote": {
39
- "provider": "enso",
40
- "input_amount": 1000000000000000000,
41
- "output_amount": 995000000000000000,
42
- "calldata": {
43
- "data": "0x",
44
- "to": "0x",
45
- "from_address": "0x",
46
- "value": "0",
47
- "chainId": 8453,
48
- },
49
- "fee_estimate": {"fee_total_usd": 0.008, "fee_breakdown": []},
50
- },
51
- }
52
- mock_brap_client.get_quote = AsyncMock(return_value=mock_response)
53
-
54
- success, data = await adapter.get_swap_quote(
55
- from_token_address="0x" + "a" * 40,
56
- to_token_address="0x" + "b" * 40,
57
- from_chain_id=8453,
58
- to_chain_id=1,
59
- from_address="0x1234567890123456789012345678901234567890",
60
- to_address="0x1234567890123456789012345678901234567890",
61
- amount="1000000000000000000",
62
- slippage=0.01,
63
- )
64
-
65
- assert success
66
- assert data == mock_response
67
- mock_brap_client.get_quote.assert_called_once_with(
68
- from_token="0x" + "a" * 40,
69
- to_token="0x" + "b" * 40,
70
- from_chain=8453,
71
- to_chain=1,
72
- from_wallet="0x1234567890123456789012345678901234567890",
73
- from_amount="1000000000000000000",
74
- )
75
-
76
- @pytest.mark.asyncio
77
- async def test_get_best_quote_success(self, adapter, mock_brap_client):
21
+ async def test_best_quote_success(self, adapter, mock_brap_client):
78
22
  mock_response = {
79
23
  "quotes": [],
80
24
  "best_quote": {
@@ -93,13 +37,12 @@ class TestBRAPAdapter:
93
37
  }
94
38
  mock_brap_client.get_quote = AsyncMock(return_value=mock_response)
95
39
 
96
- success, data = await adapter.get_best_quote(
40
+ success, data = await adapter.best_quote(
97
41
  from_token_address="0x" + "a" * 40,
98
42
  to_token_address="0x" + "b" * 40,
99
43
  from_chain_id=8453,
100
44
  to_chain_id=1,
101
45
  from_address="0x1234567890123456789012345678901234567890",
102
- to_address="0x1234567890123456789012345678901234567890",
103
46
  amount="1000000000000000000",
104
47
  )
105
48
 
@@ -108,17 +51,16 @@ class TestBRAPAdapter:
108
51
  assert data["output_amount"] == 995000000000000000
109
52
 
110
53
  @pytest.mark.asyncio
111
- async def test_get_best_quote_no_quotes(self, adapter, mock_brap_client):
54
+ async def test_best_quote_no_quotes(self, adapter, mock_brap_client):
112
55
  mock_response = {"quotes": [], "best_quote": None}
113
56
  mock_brap_client.get_quote = AsyncMock(return_value=mock_response)
114
57
 
115
- success, data = await adapter.get_best_quote(
58
+ success, data = await adapter.best_quote(
116
59
  from_token_address="0x" + "a" * 40,
117
60
  to_token_address="0x" + "b" * 40,
118
61
  from_chain_id=8453,
119
62
  to_chain_id=1,
120
63
  from_address="0x1234567890123456789012345678901234567890",
121
- to_address="0x1234567890123456789012345678901234567890",
122
64
  amount="1000000000000000000",
123
65
  )
124
66
 
@@ -126,185 +68,15 @@ class TestBRAPAdapter:
126
68
  assert "No quotes available" in data
127
69
 
128
70
  @pytest.mark.asyncio
129
- async def test_calculate_swap_fees_success(self, adapter, mock_brap_client):
130
- mock_quote_response = {
131
- "quotes": [],
132
- "best_quote": {
133
- "provider": "enso",
134
- "input_amount": 1000000000000000000,
135
- "output_amount": 995000000000000000,
136
- "gas_estimate": 5000000000000000,
137
- "quote": {"priceImpact": 5},
138
- "fee_estimate": {
139
- "fee_total_usd": 0.008,
140
- "fee_breakdown": [],
141
- },
142
- "calldata": {
143
- "data": "0x",
144
- "to": "0x",
145
- "from_address": "0x",
146
- "value": "0",
147
- "chainId": 8453,
148
- },
149
- },
150
- }
151
- mock_brap_client.get_quote = AsyncMock(return_value=mock_quote_response)
152
-
153
- success, data = await adapter.calculate_swap_fees(
154
- from_token_address="0x" + "a" * 40,
155
- to_token_address="0x" + "b" * 40,
156
- from_chain_id=8453,
157
- to_chain_id=1,
158
- amount="1000000000000000000",
159
- slippage=0.01,
160
- )
161
-
162
- assert success
163
- assert data["input_amount"] == 1000000000000000000
164
- assert data["output_amount"] == 995000000000000000
165
- assert data["gas_fee"] == 5000000000000000
166
- assert data["total_fee"] == 0.008
167
-
168
- @pytest.mark.asyncio
169
- async def test_compare_routes_success(self, adapter, mock_brap_client):
170
- mock_response = {
171
- "quotes": [
172
- {
173
- "provider": "enso",
174
- "output_amount": 995000000000000000,
175
- "fee_estimate": {"fee_total_usd": 0.008, "fee_breakdown": []},
176
- "calldata": {
177
- "data": "0x",
178
- "to": "0x",
179
- "from_address": "0x",
180
- "value": "0",
181
- "chainId": 8453,
182
- },
183
- },
184
- {
185
- "provider": "enso",
186
- "output_amount": 992000000000000000,
187
- "fee_estimate": {"fee_total_usd": 0.012, "fee_breakdown": []},
188
- "calldata": {
189
- "data": "0x",
190
- "to": "0x",
191
- "from_address": "0x",
192
- "value": "0",
193
- "chainId": 8453,
194
- },
195
- },
196
- ],
197
- "best_quote": {
198
- "provider": "enso",
199
- "output_amount": 995000000000000000,
200
- "fee_estimate": {"fee_total_usd": 0.008, "fee_breakdown": []},
201
- "calldata": {
202
- "data": "0x",
203
- "to": "0x",
204
- "from_address": "0x",
205
- "value": "0",
206
- "chainId": 8453,
207
- },
208
- },
209
- }
210
- mock_brap_client.get_quote = AsyncMock(return_value=mock_response)
211
-
212
- success, data = await adapter.compare_routes(
213
- from_token_address="0x" + "a" * 40,
214
- to_token_address="0x" + "b" * 40,
215
- from_chain_id=8453,
216
- to_chain_id=1,
217
- amount="1000000000000000000",
218
- )
219
-
220
- assert success
221
- assert data["total_routes"] == 2
222
- assert len(data["all_routes"]) == 2
223
- assert data["best_route"]["output_amount"] == 995000000000000000
224
-
225
- @pytest.mark.asyncio
226
- async def test_estimate_gas_cost_success(self, adapter):
227
- success, data = await adapter.estimate_gas_cost(
228
- from_chain_id=8453, to_chain_id=1, operation_type="swap"
229
- )
230
-
231
- assert success
232
- assert data["from_chain"] == "base"
233
- assert data["to_chain"] == "ethereum"
234
- assert data["from_gas_estimate"] == 100000
235
- assert data["to_gas_estimate"] == 150000
236
- assert data["total_operations"] == 2
237
-
238
- @pytest.mark.asyncio
239
- async def test_validate_swap_parameters_success(self, adapter, mock_brap_client):
240
- mock_quote_response = {
241
- "quotes": [],
242
- "best_quote": {
243
- "output_amount": 995000000000000000,
244
- "calldata": {
245
- "data": "0x",
246
- "to": "0x",
247
- "from_address": "0x",
248
- "value": "0",
249
- "chainId": 8453,
250
- },
251
- "fee_estimate": {"fee_total_usd": 0.008, "fee_breakdown": []},
252
- },
253
- }
254
- mock_brap_client.get_quote = AsyncMock(return_value=mock_quote_response)
255
-
256
- success, data = await adapter.validate_swap_parameters(
257
- from_token_address="0x" + "a" * 40,
258
- to_token_address="0x" + "b" * 40,
259
- from_chain_id=8453,
260
- to_chain_id=1,
261
- amount="1000000000000000000",
262
- )
263
-
264
- assert success
265
- assert data["valid"] is True
266
- assert data["quote_available"] is True
267
- assert data["estimated_output"] == "995000000000000000"
268
-
269
- @pytest.mark.asyncio
270
- async def test_validate_swap_parameters_invalid_address(self, adapter):
271
- success, data = await adapter.validate_swap_parameters(
272
- from_token_address="invalid_address",
273
- to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
274
- from_chain_id=8453,
275
- to_chain_id=1,
276
- amount="1000000000000000000",
277
- )
278
-
279
- assert success is False
280
- assert data["valid"] is False
281
- assert "Invalid from_token_address" in data["errors"]
282
-
283
- @pytest.mark.asyncio
284
- async def test_validate_swap_parameters_invalid_amount(self, adapter):
285
- success, data = await adapter.validate_swap_parameters(
286
- from_token_address="0x" + "a" * 40,
287
- to_token_address="0x" + "b" * 40,
288
- from_chain_id=8453,
289
- to_chain_id=1,
290
- amount="invalid_amount",
291
- )
292
-
293
- assert success is False
294
- assert data["valid"] is False
295
- assert "Invalid amount format" in data["errors"]
296
-
297
- @pytest.mark.asyncio
298
- async def test_get_swap_quote_failure(self, adapter, mock_brap_client):
71
+ async def test_best_quote_failure(self, adapter, mock_brap_client):
299
72
  mock_brap_client.get_quote = AsyncMock(side_effect=Exception("API Error"))
300
73
 
301
- success, data = await adapter.get_swap_quote(
74
+ success, data = await adapter.best_quote(
302
75
  from_token_address="0x" + "a" * 40,
303
76
  to_token_address="0x" + "b" * 40,
304
77
  from_chain_id=8453,
305
78
  to_chain_id=1,
306
79
  from_address="0x1234567890123456789012345678901234567890",
307
- to_address="0x1234567890123456789012345678901234567890",
308
80
  amount="1000000000000000000",
309
81
  )
310
82