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.

Files changed (115) hide show
  1. wayfinder_paths/CONFIG_GUIDE.md +394 -0
  2. wayfinder_paths/__init__.py +21 -0
  3. wayfinder_paths/config.example.json +20 -0
  4. wayfinder_paths/conftest.py +31 -0
  5. wayfinder_paths/core/__init__.py +13 -0
  6. wayfinder_paths/core/adapters/BaseAdapter.py +48 -0
  7. wayfinder_paths/core/adapters/__init__.py +5 -0
  8. wayfinder_paths/core/adapters/base.py +5 -0
  9. wayfinder_paths/core/clients/AuthClient.py +83 -0
  10. wayfinder_paths/core/clients/BRAPClient.py +90 -0
  11. wayfinder_paths/core/clients/ClientManager.py +231 -0
  12. wayfinder_paths/core/clients/HyperlendClient.py +151 -0
  13. wayfinder_paths/core/clients/LedgerClient.py +222 -0
  14. wayfinder_paths/core/clients/PoolClient.py +96 -0
  15. wayfinder_paths/core/clients/SimulationClient.py +180 -0
  16. wayfinder_paths/core/clients/TokenClient.py +73 -0
  17. wayfinder_paths/core/clients/TransactionClient.py +47 -0
  18. wayfinder_paths/core/clients/WalletClient.py +90 -0
  19. wayfinder_paths/core/clients/WayfinderClient.py +258 -0
  20. wayfinder_paths/core/clients/__init__.py +48 -0
  21. wayfinder_paths/core/clients/protocols.py +295 -0
  22. wayfinder_paths/core/clients/sdk_example.py +115 -0
  23. wayfinder_paths/core/config.py +369 -0
  24. wayfinder_paths/core/constants/__init__.py +26 -0
  25. wayfinder_paths/core/constants/base.py +25 -0
  26. wayfinder_paths/core/constants/erc20_abi.py +118 -0
  27. wayfinder_paths/core/constants/hyperlend_abi.py +152 -0
  28. wayfinder_paths/core/engine/VaultJob.py +182 -0
  29. wayfinder_paths/core/engine/__init__.py +5 -0
  30. wayfinder_paths/core/engine/manifest.py +97 -0
  31. wayfinder_paths/core/services/__init__.py +0 -0
  32. wayfinder_paths/core/services/base.py +177 -0
  33. wayfinder_paths/core/services/local_evm_txn.py +429 -0
  34. wayfinder_paths/core/services/local_token_txn.py +231 -0
  35. wayfinder_paths/core/services/web3_service.py +45 -0
  36. wayfinder_paths/core/settings.py +61 -0
  37. wayfinder_paths/core/strategies/Strategy.py +183 -0
  38. wayfinder_paths/core/strategies/__init__.py +5 -0
  39. wayfinder_paths/core/strategies/base.py +7 -0
  40. wayfinder_paths/core/utils/__init__.py +1 -0
  41. wayfinder_paths/core/utils/evm_helpers.py +165 -0
  42. wayfinder_paths/core/utils/wallets.py +77 -0
  43. wayfinder_paths/core/wallets/README.md +91 -0
  44. wayfinder_paths/core/wallets/WalletManager.py +56 -0
  45. wayfinder_paths/core/wallets/__init__.py +7 -0
  46. wayfinder_paths/run_strategy.py +409 -0
  47. wayfinder_paths/scripts/__init__.py +0 -0
  48. wayfinder_paths/scripts/create_strategy.py +181 -0
  49. wayfinder_paths/scripts/make_wallets.py +160 -0
  50. wayfinder_paths/scripts/validate_manifests.py +213 -0
  51. wayfinder_paths/tests/__init__.py +0 -0
  52. wayfinder_paths/tests/test_smoke_manifest.py +48 -0
  53. wayfinder_paths/tests/test_test_coverage.py +212 -0
  54. wayfinder_paths/tests/test_utils.py +64 -0
  55. wayfinder_paths/vaults/__init__.py +0 -0
  56. wayfinder_paths/vaults/adapters/__init__.py +0 -0
  57. wayfinder_paths/vaults/adapters/balance_adapter/README.md +104 -0
  58. wayfinder_paths/vaults/adapters/balance_adapter/adapter.py +257 -0
  59. wayfinder_paths/vaults/adapters/balance_adapter/examples.json +6 -0
  60. wayfinder_paths/vaults/adapters/balance_adapter/manifest.yaml +8 -0
  61. wayfinder_paths/vaults/adapters/balance_adapter/test_adapter.py +83 -0
  62. wayfinder_paths/vaults/adapters/brap_adapter/README.md +249 -0
  63. wayfinder_paths/vaults/adapters/brap_adapter/__init__.py +7 -0
  64. wayfinder_paths/vaults/adapters/brap_adapter/adapter.py +717 -0
  65. wayfinder_paths/vaults/adapters/brap_adapter/examples.json +175 -0
  66. wayfinder_paths/vaults/adapters/brap_adapter/manifest.yaml +11 -0
  67. wayfinder_paths/vaults/adapters/brap_adapter/test_adapter.py +288 -0
  68. wayfinder_paths/vaults/adapters/hyperlend_adapter/__init__.py +7 -0
  69. wayfinder_paths/vaults/adapters/hyperlend_adapter/adapter.py +298 -0
  70. wayfinder_paths/vaults/adapters/hyperlend_adapter/manifest.yaml +10 -0
  71. wayfinder_paths/vaults/adapters/hyperlend_adapter/test_adapter.py +267 -0
  72. wayfinder_paths/vaults/adapters/ledger_adapter/README.md +158 -0
  73. wayfinder_paths/vaults/adapters/ledger_adapter/__init__.py +7 -0
  74. wayfinder_paths/vaults/adapters/ledger_adapter/adapter.py +286 -0
  75. wayfinder_paths/vaults/adapters/ledger_adapter/examples.json +131 -0
  76. wayfinder_paths/vaults/adapters/ledger_adapter/manifest.yaml +11 -0
  77. wayfinder_paths/vaults/adapters/ledger_adapter/test_adapter.py +202 -0
  78. wayfinder_paths/vaults/adapters/pool_adapter/README.md +218 -0
  79. wayfinder_paths/vaults/adapters/pool_adapter/__init__.py +7 -0
  80. wayfinder_paths/vaults/adapters/pool_adapter/adapter.py +289 -0
  81. wayfinder_paths/vaults/adapters/pool_adapter/examples.json +143 -0
  82. wayfinder_paths/vaults/adapters/pool_adapter/manifest.yaml +10 -0
  83. wayfinder_paths/vaults/adapters/pool_adapter/test_adapter.py +222 -0
  84. wayfinder_paths/vaults/adapters/token_adapter/README.md +101 -0
  85. wayfinder_paths/vaults/adapters/token_adapter/__init__.py +3 -0
  86. wayfinder_paths/vaults/adapters/token_adapter/adapter.py +92 -0
  87. wayfinder_paths/vaults/adapters/token_adapter/examples.json +26 -0
  88. wayfinder_paths/vaults/adapters/token_adapter/manifest.yaml +6 -0
  89. wayfinder_paths/vaults/adapters/token_adapter/test_adapter.py +135 -0
  90. wayfinder_paths/vaults/strategies/__init__.py +0 -0
  91. wayfinder_paths/vaults/strategies/config.py +85 -0
  92. wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/README.md +99 -0
  93. wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/examples.json +16 -0
  94. wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/manifest.yaml +7 -0
  95. wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/strategy.py +2328 -0
  96. wayfinder_paths/vaults/strategies/hyperlend_stable_yield_strategy/test_strategy.py +319 -0
  97. wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/README.md +95 -0
  98. wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/examples.json +17 -0
  99. wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/manifest.yaml +17 -0
  100. wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/strategy.py +1684 -0
  101. wayfinder_paths/vaults/strategies/stablecoin_yield_strategy/test_strategy.py +350 -0
  102. wayfinder_paths/vaults/templates/adapter/README.md +105 -0
  103. wayfinder_paths/vaults/templates/adapter/adapter.py +26 -0
  104. wayfinder_paths/vaults/templates/adapter/examples.json +8 -0
  105. wayfinder_paths/vaults/templates/adapter/manifest.yaml +6 -0
  106. wayfinder_paths/vaults/templates/adapter/test_adapter.py +49 -0
  107. wayfinder_paths/vaults/templates/strategy/README.md +152 -0
  108. wayfinder_paths/vaults/templates/strategy/examples.json +11 -0
  109. wayfinder_paths/vaults/templates/strategy/manifest.yaml +8 -0
  110. wayfinder_paths/vaults/templates/strategy/strategy.py +57 -0
  111. wayfinder_paths/vaults/templates/strategy/test_strategy.py +197 -0
  112. wayfinder_paths-0.1.1.dist-info/LICENSE +21 -0
  113. wayfinder_paths-0.1.1.dist-info/METADATA +727 -0
  114. wayfinder_paths-0.1.1.dist-info/RECORD +115 -0
  115. 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
@@ -0,0 +1,7 @@
1
+ """
2
+ BRAP Adapter Package
3
+ """
4
+
5
+ from .adapter import BRAPAdapter
6
+
7
+ __all__ = ["BRAPAdapter"]