wayfinder-paths 0.1.1__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/CONFIG_GUIDE.md +394 -0
- wayfinder_paths/__init__.py +21 -0
- wayfinder_paths/config.example.json +20 -0
- wayfinder_paths/conftest.py +31 -0
- wayfinder_paths/core/__init__.py +13 -0
- wayfinder_paths/core/adapters/BaseAdapter.py +48 -0
- wayfinder_paths/core/adapters/__init__.py +5 -0
- wayfinder_paths/core/adapters/base.py +5 -0
- wayfinder_paths/core/clients/AuthClient.py +83 -0
- wayfinder_paths/core/clients/BRAPClient.py +90 -0
- wayfinder_paths/core/clients/ClientManager.py +231 -0
- wayfinder_paths/core/clients/HyperlendClient.py +151 -0
- wayfinder_paths/core/clients/LedgerClient.py +222 -0
- wayfinder_paths/core/clients/PoolClient.py +96 -0
- wayfinder_paths/core/clients/SimulationClient.py +180 -0
- wayfinder_paths/core/clients/TokenClient.py +73 -0
- wayfinder_paths/core/clients/TransactionClient.py +47 -0
- wayfinder_paths/core/clients/WalletClient.py +90 -0
- wayfinder_paths/core/clients/WayfinderClient.py +258 -0
- wayfinder_paths/core/clients/__init__.py +48 -0
- wayfinder_paths/core/clients/protocols.py +295 -0
- wayfinder_paths/core/clients/sdk_example.py +115 -0
- wayfinder_paths/core/config.py +369 -0
- wayfinder_paths/core/constants/__init__.py +26 -0
- wayfinder_paths/core/constants/base.py +25 -0
- wayfinder_paths/core/constants/erc20_abi.py +118 -0
- wayfinder_paths/core/constants/hyperlend_abi.py +152 -0
- wayfinder_paths/core/engine/VaultJob.py +182 -0
- wayfinder_paths/core/engine/__init__.py +5 -0
- wayfinder_paths/core/engine/manifest.py +97 -0
- wayfinder_paths/core/services/__init__.py +0 -0
- wayfinder_paths/core/services/base.py +177 -0
- wayfinder_paths/core/services/local_evm_txn.py +429 -0
- wayfinder_paths/core/services/local_token_txn.py +231 -0
- wayfinder_paths/core/services/web3_service.py +45 -0
- wayfinder_paths/core/settings.py +61 -0
- wayfinder_paths/core/strategies/Strategy.py +183 -0
- wayfinder_paths/core/strategies/__init__.py +5 -0
- wayfinder_paths/core/strategies/base.py +7 -0
- wayfinder_paths/core/utils/__init__.py +1 -0
- wayfinder_paths/core/utils/evm_helpers.py +165 -0
- wayfinder_paths/core/utils/wallets.py +77 -0
- wayfinder_paths/core/wallets/README.md +91 -0
- wayfinder_paths/core/wallets/WalletManager.py +56 -0
- wayfinder_paths/core/wallets/__init__.py +7 -0
- wayfinder_paths/run_strategy.py +409 -0
- wayfinder_paths/scripts/__init__.py +0 -0
- wayfinder_paths/scripts/create_strategy.py +181 -0
- wayfinder_paths/scripts/make_wallets.py +160 -0
- wayfinder_paths/scripts/validate_manifests.py +213 -0
- wayfinder_paths/tests/__init__.py +0 -0
- wayfinder_paths/tests/test_smoke_manifest.py +48 -0
- wayfinder_paths/tests/test_test_coverage.py +212 -0
- wayfinder_paths/tests/test_utils.py +64 -0
- wayfinder_paths/vaults/__init__.py +0 -0
- wayfinder_paths/vaults/adapters/__init__.py +0 -0
- wayfinder_paths/vaults/adapters/balance_adapter/README.md +104 -0
- wayfinder_paths/vaults/adapters/balance_adapter/adapter.py +257 -0
- wayfinder_paths/vaults/adapters/balance_adapter/examples.json +6 -0
- wayfinder_paths/vaults/adapters/balance_adapter/manifest.yaml +8 -0
- wayfinder_paths/vaults/adapters/balance_adapter/test_adapter.py +83 -0
- wayfinder_paths/vaults/adapters/brap_adapter/README.md +249 -0
- wayfinder_paths/vaults/adapters/brap_adapter/__init__.py +7 -0
- wayfinder_paths/vaults/adapters/brap_adapter/adapter.py +717 -0
- wayfinder_paths/vaults/adapters/brap_adapter/examples.json +175 -0
- wayfinder_paths/vaults/adapters/brap_adapter/manifest.yaml +11 -0
- wayfinder_paths/vaults/adapters/brap_adapter/test_adapter.py +288 -0
- wayfinder_paths/vaults/adapters/hyperlend_adapter/__init__.py +7 -0
- wayfinder_paths/vaults/adapters/hyperlend_adapter/adapter.py +298 -0
- wayfinder_paths/vaults/adapters/hyperlend_adapter/manifest.yaml +10 -0
- wayfinder_paths/vaults/adapters/hyperlend_adapter/test_adapter.py +267 -0
- wayfinder_paths/vaults/adapters/ledger_adapter/README.md +158 -0
- wayfinder_paths/vaults/adapters/ledger_adapter/__init__.py +7 -0
- wayfinder_paths/vaults/adapters/ledger_adapter/adapter.py +286 -0
- wayfinder_paths/vaults/adapters/ledger_adapter/examples.json +131 -0
- wayfinder_paths/vaults/adapters/ledger_adapter/manifest.yaml +11 -0
- wayfinder_paths/vaults/adapters/ledger_adapter/test_adapter.py +202 -0
- wayfinder_paths/vaults/adapters/pool_adapter/README.md +218 -0
- wayfinder_paths/vaults/adapters/pool_adapter/__init__.py +7 -0
- wayfinder_paths/vaults/adapters/pool_adapter/adapter.py +289 -0
- wayfinder_paths/vaults/adapters/pool_adapter/examples.json +143 -0
- wayfinder_paths/vaults/adapters/pool_adapter/manifest.yaml +10 -0
- wayfinder_paths/vaults/adapters/pool_adapter/test_adapter.py +222 -0
- wayfinder_paths/vaults/adapters/token_adapter/README.md +101 -0
- wayfinder_paths/vaults/adapters/token_adapter/__init__.py +3 -0
- wayfinder_paths/vaults/adapters/token_adapter/adapter.py +92 -0
- wayfinder_paths/vaults/adapters/token_adapter/examples.json +26 -0
- wayfinder_paths/vaults/adapters/token_adapter/manifest.yaml +6 -0
- wayfinder_paths/vaults/adapters/token_adapter/test_adapter.py +135 -0
- wayfinder_paths/vaults/strategies/__init__.py +0 -0
- wayfinder_paths/vaults/strategies/config.py +85 -0
- wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/README.md +99 -0
- wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/examples.json +16 -0
- wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/manifest.yaml +7 -0
- wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/strategy.py +2328 -0
- wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/test_strategy.py +319 -0
- wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/README.md +95 -0
- wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/examples.json +17 -0
- wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/manifest.yaml +17 -0
- wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/strategy.py +1684 -0
- wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/test_strategy.py +350 -0
- wayfinder_paths/vaults/templates/adapter/README.md +105 -0
- wayfinder_paths/vaults/templates/adapter/adapter.py +26 -0
- wayfinder_paths/vaults/templates/adapter/examples.json +8 -0
- wayfinder_paths/vaults/templates/adapter/manifest.yaml +6 -0
- wayfinder_paths/vaults/templates/adapter/test_adapter.py +49 -0
- wayfinder_paths/vaults/templates/strategy/README.md +152 -0
- wayfinder_paths/vaults/templates/strategy/examples.json +11 -0
- wayfinder_paths/vaults/templates/strategy/manifest.yaml +8 -0
- wayfinder_paths/vaults/templates/strategy/strategy.py +57 -0
- wayfinder_paths/vaults/templates/strategy/test_strategy.py +197 -0
- wayfinder_paths-0.1.1.dist-info/LICENSE +21 -0
- wayfinder_paths-0.1.1.dist-info/METADATA +727 -0
- wayfinder_paths-0.1.1.dist-info/RECORD +115 -0
- wayfinder_paths-0.1.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# BRAP Adapter
|
|
2
|
+
|
|
3
|
+
A Wayfinder adapter that provides high-level operations for cross-chain swaps and quotes via the BRAP (Bridge/Router/Adapter Protocol). This adapter wraps the `BRAPClient` to offer strategy-friendly methods for getting quotes, comparing routes, and executing cross-chain transactions.
|
|
4
|
+
|
|
5
|
+
## Capabilities
|
|
6
|
+
|
|
7
|
+
- `swap.quote`: Get quotes for cross-chain swap operations
|
|
8
|
+
- `swap.execute`: Execute cross-chain swaps
|
|
9
|
+
- `bridge.quote`: Get quotes for bridge operations
|
|
10
|
+
- `bridge.execute`: Execute bridge operations
|
|
11
|
+
- `route.optimize`: Compare and optimize routes
|
|
12
|
+
- `fee.calculate`: Calculate fees and costs
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
The adapter uses the BRAPClient which automatically handles authentication and API configuration through the Wayfinder settings. Pass a `Web3Service` instance so it can broadcast transactions and reuse the shared `LocalTokenTxnService` for approvals.
|
|
17
|
+
|
|
18
|
+
The BRAPClient will automatically:
|
|
19
|
+
- Use the WAYFINDER_API_URL from settings
|
|
20
|
+
- Handle authentication via environment variables or config.json
|
|
21
|
+
- Manage token refresh and retry logic
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Initialize the Adapter
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
|
|
29
|
+
from wayfinder_paths.vaults.adapters.brap_adapter.adapter import BRAPAdapter
|
|
30
|
+
|
|
31
|
+
web3_service = DefaultWeb3Service(config)
|
|
32
|
+
adapter = BRAPAdapter(web3_service=web3_service)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Get Swap Quote
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
success, data = await adapter.get_swap_quote(
|
|
39
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
40
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
41
|
+
from_chain_id=8453, # Base
|
|
42
|
+
to_chain_id=1, # Ethereum
|
|
43
|
+
from_address="0x1234567890123456789012345678901234567890",
|
|
44
|
+
to_address="0x1234567890123456789012345678901234567890",
|
|
45
|
+
amount="1000000000000000000", # 1 token (18 decimals)
|
|
46
|
+
slippage=0.01 # 1% slippage
|
|
47
|
+
)
|
|
48
|
+
if success:
|
|
49
|
+
quotes = data.get("quotes", {})
|
|
50
|
+
best_quote = quotes.get("best_quote", {})
|
|
51
|
+
print(f"Output amount: {best_quote.get('output_amount')}")
|
|
52
|
+
print(f"Total fee: {best_quote.get('total_fee')}")
|
|
53
|
+
else:
|
|
54
|
+
print(f"Error: {data}")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Get Best Quote
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
success, data = await adapter.get_best_quote(
|
|
61
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
62
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
63
|
+
from_chain_id=8453,
|
|
64
|
+
to_chain_id=1,
|
|
65
|
+
from_address="0x1234567890123456789012345678901234567890",
|
|
66
|
+
to_address="0x1234567890123456789012345678901234567890",
|
|
67
|
+
amount="1000000000000000000"
|
|
68
|
+
)
|
|
69
|
+
if success:
|
|
70
|
+
print(f"Best output: {data.get('output_amount')}")
|
|
71
|
+
print(f"Gas fee: {data.get('gas_fee')}")
|
|
72
|
+
print(f"Bridge fee: {data.get('bridge_fee')}")
|
|
73
|
+
else:
|
|
74
|
+
print(f"Error: {data}")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Calculate Swap Fees
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
success, data = await adapter.calculate_swap_fees(
|
|
81
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
82
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
83
|
+
from_chain_id=8453,
|
|
84
|
+
to_chain_id=1,
|
|
85
|
+
amount="1000000000000000000",
|
|
86
|
+
slippage=0.01
|
|
87
|
+
)
|
|
88
|
+
if success:
|
|
89
|
+
print(f"Input amount: {data.get('input_amount')}")
|
|
90
|
+
print(f"Output amount: {data.get('output_amount')}")
|
|
91
|
+
print(f"Gas fee: {data.get('gas_fee')}")
|
|
92
|
+
print(f"Bridge fee: {data.get('bridge_fee')}")
|
|
93
|
+
print(f"Protocol fee: {data.get('protocol_fee')}")
|
|
94
|
+
print(f"Total fee: {data.get('total_fee')}")
|
|
95
|
+
print(f"Price impact: {data.get('price_impact')}")
|
|
96
|
+
else:
|
|
97
|
+
print(f"Error: {data}")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Compare Routes
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
success, data = await adapter.compare_routes(
|
|
104
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
105
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
106
|
+
from_chain_id=8453,
|
|
107
|
+
to_chain_id=1,
|
|
108
|
+
amount="1000000000000000000"
|
|
109
|
+
)
|
|
110
|
+
if success:
|
|
111
|
+
print(f"Total routes available: {data.get('total_routes')}")
|
|
112
|
+
print(f"Best route output: {data.get('best_route', {}).get('output_amount')}")
|
|
113
|
+
|
|
114
|
+
for i, route in enumerate(data.get('all_routes', [])):
|
|
115
|
+
print(f"Route {i+1}: Output {route.get('output_amount')}, Fee {route.get('total_fee')}")
|
|
116
|
+
else:
|
|
117
|
+
print(f"Error: {data}")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Estimate Gas Costs
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
success, data = await adapter.estimate_gas_cost(
|
|
124
|
+
from_chain_id=8453, # Base
|
|
125
|
+
to_chain_id=1, # Ethereum
|
|
126
|
+
operation_type="swap"
|
|
127
|
+
)
|
|
128
|
+
if success:
|
|
129
|
+
print(f"From chain: {data.get('from_chain')}")
|
|
130
|
+
print(f"To chain: {data.get('to_chain')}")
|
|
131
|
+
print(f"From gas estimate: {data.get('from_gas_estimate')}")
|
|
132
|
+
print(f"To gas estimate: {data.get('to_gas_estimate')}")
|
|
133
|
+
print(f"Total operations: {data.get('total_operations')}")
|
|
134
|
+
else:
|
|
135
|
+
print(f"Error: {data}")
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Validate Swap Parameters
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
success, data = await adapter.validate_swap_parameters(
|
|
142
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
143
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
144
|
+
from_chain_id=8453,
|
|
145
|
+
to_chain_id=1,
|
|
146
|
+
amount="1000000000000000000"
|
|
147
|
+
)
|
|
148
|
+
if success:
|
|
149
|
+
if data.get("valid"):
|
|
150
|
+
print("Parameters are valid")
|
|
151
|
+
print(f"Estimated output: {data.get('estimated_output')}")
|
|
152
|
+
else:
|
|
153
|
+
print("Parameters are invalid:")
|
|
154
|
+
for error in data.get("errors", []):
|
|
155
|
+
print(f" - {error}")
|
|
156
|
+
else:
|
|
157
|
+
print(f"Error: {data}")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Get Bridge Quote
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# Bridge operations use the same interface as swaps
|
|
164
|
+
success, data = await adapter.get_bridge_quote(
|
|
165
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
166
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
167
|
+
from_chain_id=8453,
|
|
168
|
+
to_chain_id=1,
|
|
169
|
+
amount="1000000000000000000",
|
|
170
|
+
slippage=0.01
|
|
171
|
+
)
|
|
172
|
+
if success:
|
|
173
|
+
print(f"Bridge quote received: {data.get('quotes', {}).get('best_quote', {}).get('output_amount')}")
|
|
174
|
+
else:
|
|
175
|
+
print(f"Error: {data}")
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Advanced Usage
|
|
179
|
+
|
|
180
|
+
### Route Optimization
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
# Compare multiple routes to find the best option
|
|
184
|
+
success, data = await adapter.compare_routes(
|
|
185
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
186
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
187
|
+
from_chain_id=8453,
|
|
188
|
+
to_chain_id=1,
|
|
189
|
+
amount="1000000000000000000"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if success:
|
|
193
|
+
analysis = data.get("route_analysis", {})
|
|
194
|
+
highest_output = analysis.get("highest_output")
|
|
195
|
+
lowest_fees = analysis.get("lowest_fees")
|
|
196
|
+
fastest = analysis.get("fastest")
|
|
197
|
+
|
|
198
|
+
print(f"Highest output route: {highest_output.get('output_amount')}")
|
|
199
|
+
print(f"Lowest fees route: {lowest_fees.get('total_fee')}")
|
|
200
|
+
print(f"Fastest route: {fastest.get('estimated_time')} seconds")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Fee Analysis
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
# Analyze fees for a swap operation
|
|
207
|
+
success, data = await adapter.calculate_swap_fees(
|
|
208
|
+
from_token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
209
|
+
to_token_address="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
210
|
+
from_chain_id=8453,
|
|
211
|
+
to_chain_id=1,
|
|
212
|
+
amount="1000000000000000000"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
if success:
|
|
216
|
+
input_amount = int(data.get("input_amount", 0))
|
|
217
|
+
output_amount = int(data.get("output_amount", 0))
|
|
218
|
+
total_fee = int(data.get("total_fee", 0))
|
|
219
|
+
|
|
220
|
+
# Calculate effective rate
|
|
221
|
+
effective_rate = (input_amount - output_amount) / input_amount
|
|
222
|
+
print(f"Effective rate: {effective_rate:.4f} ({effective_rate * 100:.2f}%)")
|
|
223
|
+
print(f"Total fees: {total_fee / 1e18:.6f} tokens")
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## API Endpoints
|
|
227
|
+
|
|
228
|
+
The adapter uses the following Wayfinder API endpoints:
|
|
229
|
+
|
|
230
|
+
- `POST /api/v1/public/quotes/` - Get swap/bridge quotes
|
|
231
|
+
|
|
232
|
+
## Error Handling
|
|
233
|
+
|
|
234
|
+
All methods return a tuple of `(success: bool, data: Any)` where:
|
|
235
|
+
- `success` is `True` if the operation succeeded
|
|
236
|
+
- `data` contains the response data on success or error message on failure
|
|
237
|
+
|
|
238
|
+
## Testing
|
|
239
|
+
|
|
240
|
+
Run the adapter tests:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pytest wayfinder_paths/vaults/adapters/brap_adapter/test_adapter.py -v
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Dependencies
|
|
247
|
+
|
|
248
|
+
- `BRAPClient` - Low-level API client for BRAP operations
|
|
249
|
+
- `BaseAdapter` - Base adapter class with common functionality
|