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.

Files changed (61) hide show
  1. wayfinder_paths/adapters/balance_adapter/README.md +13 -14
  2. wayfinder_paths/adapters/balance_adapter/adapter.py +73 -32
  3. wayfinder_paths/adapters/balance_adapter/test_adapter.py +123 -0
  4. wayfinder_paths/adapters/brap_adapter/README.md +11 -16
  5. wayfinder_paths/adapters/brap_adapter/adapter.py +144 -78
  6. wayfinder_paths/adapters/brap_adapter/examples.json +63 -52
  7. wayfinder_paths/adapters/brap_adapter/test_adapter.py +127 -65
  8. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +30 -14
  9. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +121 -67
  10. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +6 -6
  11. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +12 -12
  12. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +6 -6
  13. wayfinder_paths/adapters/moonwell_adapter/adapter.py +332 -9
  14. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +13 -13
  15. wayfinder_paths/adapters/pool_adapter/README.md +9 -10
  16. wayfinder_paths/adapters/pool_adapter/adapter.py +9 -10
  17. wayfinder_paths/adapters/pool_adapter/test_adapter.py +2 -2
  18. wayfinder_paths/adapters/token_adapter/README.md +2 -14
  19. wayfinder_paths/adapters/token_adapter/adapter.py +16 -10
  20. wayfinder_paths/adapters/token_adapter/examples.json +4 -8
  21. wayfinder_paths/adapters/token_adapter/test_adapter.py +9 -7
  22. wayfinder_paths/core/clients/BRAPClient.py +102 -61
  23. wayfinder_paths/core/clients/ClientManager.py +1 -68
  24. wayfinder_paths/core/clients/HyperlendClient.py +125 -64
  25. wayfinder_paths/core/clients/LedgerClient.py +1 -4
  26. wayfinder_paths/core/clients/PoolClient.py +122 -48
  27. wayfinder_paths/core/clients/TokenClient.py +91 -36
  28. wayfinder_paths/core/clients/WalletClient.py +26 -56
  29. wayfinder_paths/core/clients/WayfinderClient.py +28 -160
  30. wayfinder_paths/core/clients/__init__.py +0 -2
  31. wayfinder_paths/core/clients/protocols.py +35 -46
  32. wayfinder_paths/core/clients/sdk_example.py +37 -22
  33. wayfinder_paths/core/constants/erc20_abi.py +0 -11
  34. wayfinder_paths/core/engine/StrategyJob.py +10 -56
  35. wayfinder_paths/core/services/base.py +1 -0
  36. wayfinder_paths/core/services/local_evm_txn.py +25 -9
  37. wayfinder_paths/core/services/local_token_txn.py +2 -6
  38. wayfinder_paths/core/services/test_local_evm_txn.py +145 -0
  39. wayfinder_paths/core/strategies/Strategy.py +16 -4
  40. wayfinder_paths/core/utils/evm_helpers.py +2 -9
  41. wayfinder_paths/policies/erc20.py +1 -1
  42. wayfinder_paths/run_strategy.py +13 -19
  43. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +77 -11
  44. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +6 -6
  45. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +107 -23
  46. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +54 -9
  47. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +6 -5
  48. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +2246 -1279
  49. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +276 -109
  50. wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +1 -1
  51. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +153 -56
  52. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +16 -12
  53. wayfinder_paths/templates/adapter/README.md +1 -1
  54. wayfinder_paths/templates/strategy/README.md +3 -3
  55. wayfinder_paths/templates/strategy/test_strategy.py +3 -2
  56. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/METADATA +14 -49
  57. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/RECORD +59 -60
  58. wayfinder_paths/abis/generic/erc20.json +0 -383
  59. wayfinder_paths/core/clients/AuthClient.py +0 -83
  60. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/LICENSE +0 -0
  61. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/WHEEL +0 -0
@@ -8,7 +8,10 @@ from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
8
8
  from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
9
9
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
10
10
  from wayfinder_paths.core.adapters.models import SWAP
11
- from wayfinder_paths.core.clients.BRAPClient import BRAPClient, BRAPQuote
11
+ from wayfinder_paths.core.clients.BRAPClient import (
12
+ BRAPClient,
13
+ BRAPQuoteResponse,
14
+ )
12
15
  from wayfinder_paths.core.clients.LedgerClient import TransactionRecord
13
16
  from wayfinder_paths.core.clients.TokenClient import TokenClient
14
17
  from wayfinder_paths.core.constants import DEFAULT_SLIPPAGE, ZERO_ADDRESS
@@ -61,7 +64,7 @@ class BRAPAdapter(BaseAdapter):
61
64
  amount: str,
62
65
  slippage: float | None = None,
63
66
  wayfinder_fee: float | None = None,
64
- ) -> tuple[bool, BRAPQuote | str]:
67
+ ) -> tuple[bool, BRAPQuoteResponse | str]:
65
68
  """
66
69
  Get a quote for a cross-chain swap operation.
67
70
 
@@ -77,19 +80,16 @@ class BRAPAdapter(BaseAdapter):
77
80
  wayfinder_fee: Wayfinder fee (optional)
78
81
 
79
82
  Returns:
80
- Tuple of (success, data) where data is quote information or error message
83
+ Tuple of (success, data) where data is quote response or error message
81
84
  """
82
85
  try:
83
86
  data = await self.brap_client.get_quote(
84
- from_token_address=from_token_address,
85
- to_token_address=to_token_address,
86
- from_chain_id=from_chain_id,
87
- to_chain_id=to_chain_id,
88
- from_address=from_address,
89
- to_address=to_address,
90
- amount1=amount,
91
- slippage=slippage,
92
- wayfinder_fee=wayfinder_fee,
87
+ from_token=from_token_address,
88
+ to_token=to_token_address,
89
+ from_chain=from_chain_id,
90
+ to_chain=to_chain_id,
91
+ from_wallet=from_address,
92
+ from_amount=amount,
93
93
  )
94
94
  return (True, data)
95
95
  except Exception as e:
@@ -130,22 +130,28 @@ class BRAPAdapter(BaseAdapter):
130
130
  """
131
131
  try:
132
132
  data = await self.brap_client.get_quote(
133
- from_token_address=from_token_address,
134
- to_token_address=to_token_address,
135
- from_chain_id=from_chain_id,
136
- to_chain_id=to_chain_id,
137
- from_address=from_address,
138
- to_address=to_address,
139
- amount1=amount,
140
- slippage=slippage,
141
- wayfinder_fee=wayfinder_fee,
133
+ from_token=from_token_address,
134
+ to_token=to_token_address,
135
+ from_chain=from_chain_id,
136
+ to_chain=to_chain_id,
137
+ from_wallet=from_address,
138
+ from_amount=amount,
142
139
  )
143
140
 
144
- quotes_container = data.get("quotes", {})
145
- # BRAP returns quotes in "all_quotes" not "quotes"
146
- all_quotes = quotes_container.get("all_quotes", []) or quotes_container.get(
147
- "quotes", []
148
- )
141
+ raw_quotes = data.get("quotes")
142
+ if isinstance(raw_quotes, list):
143
+ all_quotes = raw_quotes
144
+ best_quote = data.get("best_quote") or data.get("best_route")
145
+ else:
146
+ quotes_container = raw_quotes or {}
147
+ all_quotes = quotes_container.get(
148
+ "all_quotes", []
149
+ ) or quotes_container.get("quotes", [])
150
+ best_quote = (
151
+ quotes_container.get("best_quote")
152
+ or data.get("best_quote")
153
+ or data.get("best_route")
154
+ )
149
155
 
150
156
  # If preferred providers specified, select by provider preference
151
157
  if preferred_providers and all_quotes:
@@ -156,13 +162,6 @@ class BRAPAdapter(BaseAdapter):
156
162
  return (True, selected_quote)
157
163
  # Fall through to best_quote if no preferred provider found
158
164
 
159
- # Extract best quote from response - check nested quotes first, then top level
160
- best_quote = (
161
- quotes_container.get("best_quote")
162
- or data.get("best_quote")
163
- or data.get("best_route")
164
- )
165
-
166
165
  if not best_quote:
167
166
  return (False, "No quotes available")
168
167
 
@@ -253,8 +252,8 @@ class BRAPAdapter(BaseAdapter):
253
252
  to_token_address=to_token_address,
254
253
  from_chain_id=from_chain_id,
255
254
  to_chain_id=to_chain_id,
256
- from_address="0x0000000000000000000000000000000000000000", # Dummy address
257
- to_address="0x0000000000000000000000000000000000000000", # Dummy address
255
+ from_address="0x0000000000000000000000000000000000000000",
256
+ to_address="0x0000000000000000000000000000000000000000",
258
257
  amount=amount,
259
258
  slippage=slippage,
260
259
  )
@@ -262,22 +261,22 @@ class BRAPAdapter(BaseAdapter):
262
261
  if not success:
263
262
  return (False, quote_data)
264
263
 
265
- quotes = quote_data.get("quotes", {})
266
- best_quote = quotes.get("best_quote")
264
+ best_quote = quote_data.get("best_quote")
267
265
 
268
266
  if not best_quote:
269
267
  return (False, "No quote available for fee calculation")
270
268
 
271
269
  # Extract fee information
270
+ fee_estimate = best_quote.get("fee_estimate", {})
272
271
  fees = {
273
272
  "input_amount": best_quote.get("input_amount", 0),
274
273
  "output_amount": best_quote.get("output_amount", 0),
275
- "gas_fee": best_quote.get("gas_fee", 0),
276
- "bridge_fee": best_quote.get("bridge_fee", 0),
277
- "protocol_fee": best_quote.get("protocol_fee", 0),
278
- "total_fee": best_quote.get("total_fee", 0),
279
- "slippage": best_quote.get("slippage", 0),
280
- "price_impact": best_quote.get("price_impact", 0),
274
+ "gas_fee": best_quote.get("gas_estimate") or 0,
275
+ "bridge_fee": 0,
276
+ "protocol_fee": fee_estimate.get("fee_total_usd", 0),
277
+ "total_fee": fee_estimate.get("fee_total_usd", 0),
278
+ "slippage": 0,
279
+ "price_impact": best_quote.get("quote", {}).get("priceImpact", 0),
281
280
  }
282
281
 
283
282
  return (True, fees)
@@ -310,19 +309,26 @@ class BRAPAdapter(BaseAdapter):
310
309
  """
311
310
  try:
312
311
  data = await self.brap_client.get_quote(
313
- from_token_address=from_token_address,
314
- to_token_address=to_token_address,
315
- from_chain_id=from_chain_id,
316
- to_chain_id=to_chain_id,
317
- from_address="0x0000000000000000000000000000000000000000", # Dummy address
318
- to_address="0x0000000000000000000000000000000000000000", # Dummy address
319
- amount1=amount,
320
- slippage=slippage,
312
+ from_token=from_token_address,
313
+ to_token=to_token_address,
314
+ from_chain=from_chain_id,
315
+ to_chain=to_chain_id,
316
+ from_wallet="0x0000000000000000000000000000000000000000",
317
+ from_amount=amount,
321
318
  )
322
319
 
323
- quotes = data.get("quotes", {})
324
- all_quotes = quotes.get("all_quotes", []) or quotes.get("quotes", [])
325
- best_quote = quotes.get("best_quote")
320
+ raw_quotes = data.get("quotes")
321
+ if isinstance(raw_quotes, list):
322
+ all_quotes = raw_quotes
323
+ best_quote = data.get("best_quote") or data.get("best_route")
324
+ else:
325
+ quotes = raw_quotes or {}
326
+ all_quotes = quotes.get("all_quotes", []) or quotes.get("quotes", [])
327
+ best_quote = (
328
+ quotes.get("best_quote")
329
+ or data.get("best_quote")
330
+ or data.get("best_route")
331
+ )
326
332
 
327
333
  if not all_quotes:
328
334
  return (False, "No routes available")
@@ -339,7 +345,12 @@ class BRAPAdapter(BaseAdapter):
339
345
  "route_analysis": {
340
346
  "highest_output": sorted_quotes[0] if sorted_quotes else None,
341
347
  "lowest_fees": (
342
- min(all_quotes, key=lambda x: int(x.get("total_fee", 0)))
348
+ min(
349
+ all_quotes,
350
+ key=lambda x: float(
351
+ x.get("fee_estimate", {}).get("fee_total_usd", 0)
352
+ ),
353
+ )
343
354
  if all_quotes
344
355
  else None
345
356
  ),
@@ -422,13 +433,40 @@ class BRAPAdapter(BaseAdapter):
422
433
  chain = from_token.get("chain") or {}
423
434
  chain_id = self._chain_id(chain)
424
435
 
425
- transaction = dict(quote.get("calldata") or {})
426
- if not transaction:
436
+ calldata = quote.get("calldata") or {}
437
+ transaction = dict(calldata)
438
+ if not transaction or not transaction.get("data"):
427
439
  return (False, "Quote missing calldata")
428
440
  transaction["chainId"] = chain_id
441
+ # Always set the sender to the strategy wallet for broadcast.
442
+ # (Calldata may include either "from" or "from_address" depending on provider.)
429
443
  transaction["from"] = to_checksum_address(from_address)
430
444
 
431
- spender = transaction.get("to")
445
+ def _as_address(value: Any) -> str | None:
446
+ if not isinstance(value, str):
447
+ return None
448
+ v = value.strip()
449
+ if (
450
+ v.startswith("0x")
451
+ and len(v) == 42
452
+ and v.lower() != ZERO_ADDRESS.lower()
453
+ ):
454
+ return v
455
+ return None
456
+
457
+ spender = (
458
+ _as_address(transaction.get("allowanceTarget"))
459
+ or _as_address(transaction.get("allowance_target"))
460
+ or _as_address(transaction.get("approvalAddress"))
461
+ or _as_address(transaction.get("approval_address"))
462
+ or _as_address(transaction.get("spender"))
463
+ or _as_address(quote.get("allowanceTarget"))
464
+ or _as_address(quote.get("allowance_target"))
465
+ or _as_address(quote.get("approvalAddress"))
466
+ or _as_address(quote.get("approval_address"))
467
+ or _as_address(quote.get("spender"))
468
+ or _as_address(transaction.get("to"))
469
+ )
432
470
  approve_amount = (
433
471
  quote.get("input_amount")
434
472
  or quote.get("inputAmount")
@@ -455,13 +493,35 @@ class BRAPAdapter(BaseAdapter):
455
493
  broadcast_success, broadcast_response = await self._broadcast_transaction(
456
494
  transaction
457
495
  )
458
- self.logger.info(
459
- f"Swap broadcast result: success={broadcast_success}, "
460
- f"response={broadcast_response}"
461
- )
496
+ # Log only key fields to avoid spamming raw HexBytes logs
497
+ if isinstance(broadcast_response, dict):
498
+ tx_hash_log = broadcast_response.get("tx_hash", "unknown")
499
+ block_log = broadcast_response.get("block_number", "unknown")
500
+ status_log = (
501
+ broadcast_response.get("receipt", {}).get("status", "unknown")
502
+ if isinstance(broadcast_response.get("receipt"), dict)
503
+ else "unknown"
504
+ )
505
+ self.logger.info(
506
+ f"Swap broadcast: success={broadcast_success}, tx={tx_hash_log}, block={block_log}, status={status_log}"
507
+ )
508
+ else:
509
+ self.logger.info(f"Swap broadcast: success={broadcast_success}")
462
510
  if not broadcast_success:
463
511
  return (False, broadcast_response)
464
512
 
513
+ tx_hash = None
514
+ block_number = None
515
+ confirmations = None
516
+ confirmed_block_number = None
517
+ if isinstance(broadcast_response, dict):
518
+ tx_hash = broadcast_response.get("tx_hash") or broadcast_response.get(
519
+ "transaction_hash"
520
+ )
521
+ block_number = broadcast_response.get("block_number")
522
+ confirmations = broadcast_response.get("confirmations")
523
+ confirmed_block_number = broadcast_response.get("confirmed_block_number")
524
+
465
525
  # Record the swap operation in ledger - but don't let ledger errors fail the swap
466
526
  # since the on-chain transaction already succeeded
467
527
  try:
@@ -477,15 +537,20 @@ class BRAPAdapter(BaseAdapter):
477
537
  self.logger.warning(
478
538
  f"Ledger recording failed (swap succeeded on-chain): {e}"
479
539
  )
480
- # Return the quote with output amount so caller can proceed
481
- ledger_record = {
482
- "to_amount": quote.get("output_amount"),
483
- "from_amount": quote.get("input_amount"),
484
- "tx_hash": broadcast_response.get("tx_hash")
485
- if isinstance(broadcast_response, dict)
486
- else None,
487
- }
488
- return (True, ledger_record)
540
+ ledger_record = {}
541
+
542
+ result_payload: dict[str, Any] = {
543
+ "from_amount": quote.get("input_amount"),
544
+ "to_amount": quote.get("output_amount"),
545
+ "tx_hash": tx_hash,
546
+ "block_number": block_number,
547
+ "confirmations": confirmations,
548
+ "confirmed_block_number": confirmed_block_number,
549
+ }
550
+ if isinstance(ledger_record, dict):
551
+ result_payload.update(ledger_record)
552
+
553
+ return (True, result_payload)
489
554
 
490
555
  async def get_bridge_quote(
491
556
  self,
@@ -516,8 +581,8 @@ class BRAPAdapter(BaseAdapter):
516
581
  to_token_address=to_token_address,
517
582
  from_chain_id=from_chain_id,
518
583
  to_chain_id=to_chain_id,
519
- from_address="0x0000000000000000000000000000000000000000", # Dummy address
520
- to_address="0x0000000000000000000000000000000000000000", # Dummy address
584
+ from_address="0x0000000000000000000000000000000000000000",
585
+ to_address="0x0000000000000000000000000000000000000000",
521
586
  amount=amount,
522
587
  slippage=slippage,
523
588
  )
@@ -634,14 +699,15 @@ class BRAPAdapter(BaseAdapter):
634
699
  validation_errors.append(f"Swap not possible: {quote_data}")
635
700
  return (False, {"valid": False, "errors": validation_errors})
636
701
 
702
+ best_quote = (
703
+ quote_data.get("best_quote", {}) if isinstance(quote_data, dict) else {}
704
+ )
637
705
  return (
638
706
  True,
639
707
  {
640
708
  "valid": True,
641
709
  "quote_available": True,
642
- "estimated_output": quote_data.get("quotes", {})
643
- .get("best_quote", {})
644
- .get("output_amount", "0"),
710
+ "estimated_output": str(best_quote.get("output_amount", 0)),
645
711
  },
646
712
  )
647
713
  except Exception as e:
@@ -695,7 +761,7 @@ class BRAPAdapter(BaseAdapter):
695
761
  return await self._broadcast_transaction(approve_tx, confirmations=2)
696
762
 
697
763
  async def _broadcast_transaction(
698
- self, transaction: dict[str, Any], confirmations: int = 0
764
+ self, transaction: dict[str, Any], confirmations: int | None = None
699
765
  ) -> tuple[bool, Any]:
700
766
  return await self.wallet_provider.broadcast_transaction(
701
767
  transaction,
@@ -779,7 +845,7 @@ class BRAPAdapter(BaseAdapter):
779
845
 
780
846
  def _chain_id(self, chain: Any) -> int:
781
847
  if isinstance(chain, dict):
782
- chain_id = chain.get("id") or chain.get("chain_id")
848
+ chain_id = chain.get("id")
783
849
  else:
784
850
  chain_id = getattr(chain, "id", None)
785
851
  if chain_id is None:
@@ -14,25 +14,37 @@
14
14
  "output": {
15
15
  "success": true,
16
16
  "data": {
17
- "quotes": {
18
- "best_quote": {
19
- "input_amount": "1000000000000000000",
20
- "output_amount": "995000000000000000",
21
- "gas_fee": "5000000000000000",
22
- "bridge_fee": "2000000000000000",
23
- "protocol_fee": "1000000000000000",
24
- "total_fee": "8000000000000000",
25
- "slippage": 0.01,
26
- "price_impact": 0.005,
27
- "estimated_time": 300
28
- },
29
- "quotes": [
30
- {
31
- "route": "Route 1",
32
- "output_amount": "995000000000000000",
33
- "total_fee": "8000000000000000"
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
34
31
  }
35
- ]
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
+ }
36
48
  }
37
49
  }
38
50
  }
@@ -52,15 +64,19 @@
52
64
  "output": {
53
65
  "success": true,
54
66
  "data": {
55
- "input_amount": "1000000000000000000",
56
- "output_amount": "995000000000000000",
57
- "gas_fee": "5000000000000000",
58
- "bridge_fee": "2000000000000000",
59
- "protocol_fee": "1000000000000000",
60
- "total_fee": "8000000000000000",
61
- "slippage": 0.01,
62
- "price_impact": 0.005,
63
- "estimated_time": 300
67
+ "provider": "enso",
68
+ "input_amount": 1000000000000000000,
69
+ "output_amount": 995000000000000000,
70
+ "fee_estimate": {
71
+ "fee_total_usd": 0.08,
72
+ "fee_breakdown": []
73
+ },
74
+ "calldata": {
75
+ "data": "0x",
76
+ "to": "0x",
77
+ "value": "0",
78
+ "chainId": 8453
79
+ }
64
80
  }
65
81
  }
66
82
  },
@@ -77,14 +93,14 @@
77
93
  "output": {
78
94
  "success": true,
79
95
  "data": {
80
- "input_amount": "1000000000000000000",
81
- "output_amount": "995000000000000000",
82
- "gas_fee": "5000000000000000",
83
- "bridge_fee": "2000000000000000",
84
- "protocol_fee": "1000000000000000",
85
- "total_fee": "8000000000000000",
86
- "slippage": 0.01,
87
- "price_impact": 0.005
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
88
104
  }
89
105
  }
90
106
  },
@@ -101,35 +117,30 @@
101
117
  "output": {
102
118
  "success": true,
103
119
  "data": {
104
- "total_routes": 3,
120
+ "total_routes": 2,
105
121
  "best_route": {
106
- "input_amount": "1000000000000000000",
107
- "output_amount": "995000000000000000",
108
- "total_fee": "8000000000000000"
122
+ "provider": "enso",
123
+ "output_amount": 995000000000000000,
124
+ "fee_estimate": { "fee_total_usd": 0.08, "fee_breakdown": [] }
109
125
  },
110
126
  "all_routes": [
111
127
  {
112
- "route": "Route 1",
113
- "output_amount": "995000000000000000",
114
- "total_fee": "8000000000000000",
115
- "estimated_time": 300
128
+ "provider": "enso",
129
+ "output_amount": 995000000000000000,
130
+ "fee_estimate": { "fee_total_usd": 0.08, "fee_breakdown": [] }
116
131
  },
117
132
  {
118
- "route": "Route 2",
119
- "output_amount": "992000000000000000",
120
- "total_fee": "12000000000000000",
121
- "estimated_time": 180
133
+ "provider": "enso",
134
+ "output_amount": 992000000000000000,
135
+ "fee_estimate": { "fee_total_usd": 0.12, "fee_breakdown": [] }
122
136
  }
123
137
  ],
124
138
  "route_analysis": {
125
139
  "highest_output": {
126
- "output_amount": "995000000000000000"
140
+ "output_amount": 995000000000000000
127
141
  },
128
142
  "lowest_fees": {
129
- "total_fee": "8000000000000000"
130
- },
131
- "fastest": {
132
- "estimated_time": 180
143
+ "fee_estimate": { "fee_total_usd": 0.08, "fee_breakdown": [] }
133
144
  }
134
145
  }
135
146
  }