@switch-win/sdk 1.2.9 → 1.3.0

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/GASLESS.md +407 -0
  3. package/LIMIT-ORDERS.md +213 -205
  4. package/README.md +131 -105
  5. package/ROBINHOOD.md +201 -198
  6. package/abi/GaslessSwitchV2ABI.json +1095 -0
  7. package/dist/constants.d.ts +276 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +403 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/gasless-client.d.ts +81 -0
  12. package/dist/gasless-client.d.ts.map +1 -0
  13. package/dist/gasless-client.js +467 -0
  14. package/dist/gasless-client.js.map +1 -0
  15. package/dist/gasless-index.d.ts +5 -0
  16. package/dist/gasless-index.d.ts.map +1 -0
  17. package/dist/gasless-index.js +5 -0
  18. package/dist/gasless-index.js.map +1 -0
  19. package/dist/gasless-operators.d.ts +32 -0
  20. package/dist/gasless-operators.d.ts.map +1 -0
  21. package/dist/gasless-operators.js +132 -0
  22. package/dist/gasless-operators.js.map +1 -0
  23. package/dist/gasless-store.d.ts +18 -0
  24. package/dist/gasless-store.d.ts.map +1 -0
  25. package/dist/gasless-store.js +83 -0
  26. package/dist/gasless-store.js.map +1 -0
  27. package/dist/gasless-types.d.ts +218 -0
  28. package/dist/gasless-types.d.ts.map +1 -0
  29. package/dist/gasless-types.js +2 -0
  30. package/dist/gasless-types.js.map +1 -0
  31. package/dist/gasless.d.ts +135 -0
  32. package/dist/gasless.d.ts.map +1 -0
  33. package/dist/gasless.js +513 -0
  34. package/dist/gasless.js.map +1 -0
  35. package/dist/index.d.ts +29 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +30 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/limit-orders.d.ts +440 -0
  40. package/dist/limit-orders.d.ts.map +1 -0
  41. package/dist/limit-orders.js +387 -0
  42. package/dist/limit-orders.js.map +1 -0
  43. package/dist/networks/index.d.ts +3 -0
  44. package/dist/networks/index.d.ts.map +1 -0
  45. package/dist/networks/index.js +2 -0
  46. package/dist/networks/index.js.map +1 -0
  47. package/dist/networks/robinhood.d.ts +536 -0
  48. package/dist/networks/robinhood.d.ts.map +1 -0
  49. package/dist/networks/robinhood.js +489 -0
  50. package/dist/networks/robinhood.js.map +1 -0
  51. package/dist/types.d.ts +436 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +19 -0
  54. package/dist/types.js.map +1 -0
  55. package/examples/gasless-nextjs-proxy.ts +87 -0
  56. package/examples/gasless-operator.ts +76 -0
  57. package/examples/gasless-swap.ts +170 -0
  58. package/examples/limit-order-ethers.ts +195 -0
  59. package/examples/nextjs-proxy.ts +82 -0
  60. package/examples/react-hooks.tsx +396 -0
  61. package/examples/swap-ethers.ts +209 -0
  62. package/examples/swap-web3py.py +267 -0
  63. package/package.json +53 -12
  64. package/src/constants.ts +184 -182
  65. package/src/gasless-client.ts +823 -0
  66. package/src/gasless-index.ts +4 -0
  67. package/src/gasless-operators.ts +227 -0
  68. package/src/gasless-store.ts +137 -0
  69. package/src/gasless-types.ts +258 -0
  70. package/src/gasless.ts +756 -0
  71. package/src/index.ts +69 -63
  72. package/src/limit-orders.ts +206 -195
  73. package/src/types.ts +80 -55
package/README.md CHANGED
@@ -5,9 +5,20 @@
5
5
 
6
6
  > **Official integration kit for the Switch DEX Aggregator on PulseChain and Robinhood Chain**
7
7
 
8
- Everything partners need to integrate Switch swaps and limit orders — API docs, TypeScript types, ABIs, constants, and ready-to-use examples.
8
+ Everything partners need to integrate Switch swaps, limit orders, and GaslessSwitch — API docs, TypeScript types, ABIs, constants, and ready-to-use examples.
9
9
 
10
- **Swap API:** `https://quote.switch.win`  |  **Swap chains:** PulseChain (369), Robinhood Chain (4663)  |  **Limit orders:** PulseChain and Robinhood Chain
10
+ **Version 1.3.0 has not been published on npm yet.** This release
11
+ adds GaslessSwitch V2 helpers and examples. See [GASLESS.md](GASLESS.md) for the
12
+ checked quote, approval, signing, submission, and recovery flow.
13
+
14
+ **Gasless fee policy:** Every GaslessSwitch settlement charges a fixed
15
+ **0.1% protocol fee (10 bps)**. Integrators cannot customize or waive this fee.
16
+ The operator can also receive up to **0.05%**, including settlement gas, under
17
+ the separate on-chain payout cap. If you do not want to offer the fixed gasless
18
+ fee policy, **offer regular swaps only** in your integration. See
19
+ [regular-only integration](GASLESS.md#regular-only-integration) for the steps.
20
+
21
+ **Swap API:** `https://quote.switch.win`  |  **Swap chains:** PulseChain (369), Robinhood Chain (4663)  |  **Limit orders:** PulseChain and Robinhood Chain
11
22
 
12
23
  ---
13
24
 
@@ -56,6 +67,21 @@ Switch-SDK/
56
67
 
57
68
  8. [Limit Orders](#limit-orders) — full guide in [`LIMIT-ORDERS.md`](LIMIT-ORDERS.md)
58
69
 
70
+ ### Gasless swaps
71
+
72
+ - [GaslessSwitch V2 integration](GASLESS.md) — settlement gas eligibility, tax
73
+ tokens, 0.1% protocol fee, 0.05% total operator cap, native wrapping,
74
+ durable pending orders, and settlement links.
75
+ - [Browser flow example](examples/gasless-swap.ts),
76
+ [backend proxy](examples/gasless-nextjs-proxy.ts), and
77
+ [operator execution validation](examples/gasless-operator.ts).
78
+ - Import the dedicated flow from `@switch-win/sdk/gasless`; ordinary
79
+ `buildLimitOrder` / LO signing and approval helpers target a different contract.
80
+ - [API eligibility and fallback](GASLESS.md#api-eligibility-response):
81
+ `client.quote()` exposes `decision.eligibility` for both accepted and rejected
82
+ quotes, including PLS/ETH payout, gas reserves, freshness and rejection reason.
83
+ Only `decision.eligible` enables signing; a finished simulation alone does not.
84
+
59
85
  ### General
60
86
 
61
87
  9. [Constants & Addresses](#constants--addresses)
@@ -121,12 +147,12 @@ For a production integration with tax token handling, adapter filtering, and fee
121
147
  ### Robinhood Chain
122
148
 
123
149
  Robinhood uses the same quote endpoint; set `network=robinhood`. The dedicated
124
- module includes canonical chain metadata, deployed Switch contracts, vetted
125
- routing hubs, and a URL builder that always includes the correct network.
126
- The production router exposes nineteen adapters across Uniswap, SwapHood,
127
- Up33, Sheriff, Aeon, Catnip, PancakeSwap, RobinSwap, SushiSwap, GIGA, Flap,
128
- Ramses, and Switch limit orders. `ROBINHOOD_ADAPTERS` contains a typed snapshot;
129
- fetch `/swap/adapters?network=robinhood` when runtime freshness matters.
150
+ module includes canonical chain metadata, deployed Switch contracts, vetted
151
+ routing hubs, and a URL builder that always includes the correct network.
152
+ The production router exposes nineteen adapters across Uniswap, SwapHood,
153
+ Up33, Sheriff, Aeon, Catnip, PancakeSwap, RobinSwap, SushiSwap, GIGA, Flap,
154
+ Ramses, and Switch limit orders. `ROBINHOOD_ADAPTERS` contains a typed snapshot;
155
+ fetch `/swap/adapters?network=robinhood` when runtime freshness matters.
130
156
 
131
157
  For network configuration, deployed addresses, tax handling, execution, and
132
158
  the complete frontend token list, see [`ROBINHOOD.md`](ROBINHOOD.md).
@@ -143,7 +169,7 @@ const url = buildRobinhoodQuoteUrl({
143
169
  to: ROBINHOOD_TOKENS.USDG.address,
144
170
  amount: 1_000_000_000_000_000n,
145
171
  sender: walletAddress,
146
- slippage: 100, // 1%, matching the Robinhood frontend default
172
+ slippage: 100, // 1%, matching the Robinhood frontend default
147
173
  });
148
174
 
149
175
  const response = await fetch(url, {
@@ -153,8 +179,8 @@ const response = await fetch(url, {
153
179
 
154
180
  Always approve `ROBINHOOD_SWITCH_CONTRACTS.router` for ERC-20 input, but submit
155
181
  the transaction to `quote.tx.to` so integrations remain safe across router
156
- upgrades. Robinhood limit-order deployment constants and EIP-712 domain values
157
- are exported from `src/networks/robinhood.ts`.
182
+ upgrades. Robinhood limit-order deployment constants and EIP-712 domain values
183
+ are exported from `src/networks/robinhood.ts`.
158
184
 
159
185
  ---
160
186
 
@@ -217,7 +243,7 @@ For the most accurate swap quotes — especially with tax tokens — follow this
217
243
  │ → Detect transfer taxes on both tokens │
218
244
  │ → Determine feeOnOutput based on tax results + your fee strategy │
219
245
  ├────────────────────────────────────────────────────────────────────────────┤
220
- │ Step 3: GET /swap/quote?...&feeOnOutput=true/false&adapters=0,3,7 │
246
+ │ Step 3: GET /swap/quote?...&feeOnOutput=true/false&adapters=0,3,7 │
221
247
  │ → Pass feeOnOutput + adapter filter for an exact expectedOutputAmount │
222
248
  │ → Display quote and execute swap │
223
249
  └────────────────────────────────────────────────────────────────────────────┘
@@ -230,7 +256,7 @@ The SwitchRouter contract supports two fee modes:
230
256
  - **`feeOnOutput=true`** — The full input is routed through DEX pools, then the protocol fee is deducted from the output.
231
257
  - **`feeOnOutput=false`** — The protocol fee is deducted from the input *before* routing, and the reduced amount enters the DEX pools.
232
258
 
233
- Due to AMM curve concavity (Jensen's inequality), `AMM(amount × 0.999) ≠ AMM(amount) × 0.999`. This means the backend **must know which mode you'll use** to compute an exact `expectedOutputAmount`. If the backend routes as `feeOnOutput=true` but you send the `tx` (fee on input), the expected output will be slightly over-estimated (always in the user's favor — they receive more than quoted).
259
+ Due to AMM curve concavity (Jensen's inequality), `AMM(amount × 0.999) ≠ AMM(amount) × 0.999`. This means the backend **must know which mode you'll use** to compute an exact `expectedOutputAmount`. If the backend routes as `feeOnOutput=true` but you send the `tx` (fee on input), the expected output will be slightly over-estimated (always in the user's favor — they receive more than quoted).
234
260
 
235
261
  By passing `feeOnOutput` explicitly, the backend adjusts routing to match the actual on-chain execution, giving you a spot-on estimate.
236
262
 
@@ -407,41 +433,41 @@ curl -H "x-api-key: YOUR_KEY" "https://quote.switch.win/swap/adapters?network=pu
407
433
 
408
434
  ```json
409
435
  {
410
- "adapters": [
411
- { "index": 0, "name": "UniswapV2", "address": "0x971eeb4a5080834f7df2b9d7a11dfbeaa7bc187e" },
412
- { "index": 1, "name": "SushiV2", "address": "0x5ef53d5eb4f011d9bed35e7112945f0dc96b3822" },
413
- { "index": 2, "name": "PulseXV1", "address": "0x6f5ccfca1f1d3fff70202463df05573cc1668cb6" },
414
- { "index": 3, "name": "PulseXV2", "address": "0x393e382520b93b8f662dc76295000930c06d689f" },
415
- { "index": 4, "name": "9inchV2", "address": "0x4810beadf72a1f297f4e5ff71424d98b2bf4441e" },
416
- { "index": 5, "name": "DextopV2", "address": "0xd096faccdd475f2c86f3c668958fcd435e32bdc2" },
417
- { "index": 6, "name": "9mmV2", "address": "0x67a25e62309e39e7b46f3b6f868bcf336c4ce8e2" },
418
- { "index": 7, "name": "UniswapV3", "address": "0xc39cb531f71059fd427a63bf8a2f4b822d6b9b02" },
419
- { "index": 8, "name": "9mmV3", "address": "0x32a63187814d6b81badc6c13dc9d46a8050fad12" },
420
- { "index": 9, "name": "9inchV3", "address": "0xe46ef88400997a84336e1a3c14d2528da90572b6" },
421
- { "index": 10, "name": "pDexV3", "address": "0xb718836aca6ddb8745a0cecc687467dda648bdf2" },
422
- { "index": 11, "name": "DextopV3", "address": "0x8b8024ca2a4fdb34697620b80320e76c41a67124" },
423
- { "index": 12, "name": "Phux", "address": "0x98ae0249da42f789b9745b248d346a727f37e937" },
424
- { "index": 13, "name": "Tide", "address": "0xd9a17779db4173d099064e26a5d5916717dacf5" },
425
- { "index": 14, "name": "PulseXStable", "address": "0xf3b9742c859d089b6a2e3b3228dabb2c842b57d2" },
426
- { "index": 15, "name": "AgoraX", "address": "0x79ea0ec76b510d08bf4ca9a4a53a1f9f80ea1697" },
427
- { "index": 16, "name": "JoltOTC", "address": "0x033372eb8df4baad260e20d716742a825f1f113f" },
428
- { "index": 17, "name": "SwitchLimitOrder", "address": "0x7b9761484301a8fe4a2ba47194f7646eef8e1cdd" },
429
- { "index": 18, "name": "SwitchX", "address": "0xf8744452598883792f235b92452127f4a8587db3" },
430
- { "index": 19, "name": "LibertySwapV3", "address": "0xba24bb413ab32f02073385850907ebcf0a357e70" },
431
- { "index": 20, "name": "FinvestaV3", "address": "0x012c44d0c465819ef3ceac208e0c1b272087a8b4" },
432
- { "index": 21, "name": "TrenchV2", "address": "0xaf48bb0936d9fa522650236917321d89978a8591" },
433
- { "index": 22, "name": "TrenchV3", "address": "0x01957ec5fcc079f1bb388b9f261278dac42cf2e9" }
434
- ]
435
- }
436
- ```
437
-
438
- Finvesta is a Liberty-style V3 venue with fee tiers `100`, `500`, `2500`, and
439
- `10000`. It can be selected for normal routes, but it is not transfer-tax safe.
440
- Trench V2 is a direct-pair adapter with dynamic pair-specific fees and is
441
- eligible for transfer-tax-sensitive hops. Trench V3 uses direct pool simulation
442
- across fee tiers `100`, `500`, `2500`, `3000`, and `10000`; like other V3
443
- callback adapters, it is not transfer-tax safe.
444
- Always treat the live `/swap/adapters` response as the runtime source of truth.
436
+ "adapters": [
437
+ { "index": 0, "name": "UniswapV2", "address": "0x971eeb4a5080834f7df2b9d7a11dfbeaa7bc187e" },
438
+ { "index": 1, "name": "SushiV2", "address": "0x5ef53d5eb4f011d9bed35e7112945f0dc96b3822" },
439
+ { "index": 2, "name": "PulseXV1", "address": "0x6f5ccfca1f1d3fff70202463df05573cc1668cb6" },
440
+ { "index": 3, "name": "PulseXV2", "address": "0x393e382520b93b8f662dc76295000930c06d689f" },
441
+ { "index": 4, "name": "9inchV2", "address": "0x4810beadf72a1f297f4e5ff71424d98b2bf4441e" },
442
+ { "index": 5, "name": "DextopV2", "address": "0xd096faccdd475f2c86f3c668958fcd435e32bdc2" },
443
+ { "index": 6, "name": "9mmV2", "address": "0x67a25e62309e39e7b46f3b6f868bcf336c4ce8e2" },
444
+ { "index": 7, "name": "UniswapV3", "address": "0xc39cb531f71059fd427a63bf8a2f4b822d6b9b02" },
445
+ { "index": 8, "name": "9mmV3", "address": "0x32a63187814d6b81badc6c13dc9d46a8050fad12" },
446
+ { "index": 9, "name": "9inchV3", "address": "0xe46ef88400997a84336e1a3c14d2528da90572b6" },
447
+ { "index": 10, "name": "pDexV3", "address": "0xb718836aca6ddb8745a0cecc687467dda648bdf2" },
448
+ { "index": 11, "name": "DextopV3", "address": "0x8b8024ca2a4fdb34697620b80320e76c41a67124" },
449
+ { "index": 12, "name": "Phux", "address": "0x98ae0249da42f789b9745b248d346a727f37e937" },
450
+ { "index": 13, "name": "Tide", "address": "0xd9a17779db4173d099064e26a5d5916717dacf5" },
451
+ { "index": 14, "name": "PulseXStable", "address": "0xf3b9742c859d089b6a2e3b3228dabb2c842b57d2" },
452
+ { "index": 15, "name": "AgoraX", "address": "0x79ea0ec76b510d08bf4ca9a4a53a1f9f80ea1697" },
453
+ { "index": 16, "name": "JoltOTC", "address": "0x033372eb8df4baad260e20d716742a825f1f113f" },
454
+ { "index": 17, "name": "SwitchLimitOrder", "address": "0x7b9761484301a8fe4a2ba47194f7646eef8e1cdd" },
455
+ { "index": 18, "name": "SwitchX", "address": "0xf8744452598883792f235b92452127f4a8587db3" },
456
+ { "index": 19, "name": "LibertySwapV3", "address": "0xba24bb413ab32f02073385850907ebcf0a357e70" },
457
+ { "index": 20, "name": "FinvestaV3", "address": "0x012c44d0c465819ef3ceac208e0c1b272087a8b4" },
458
+ { "index": 21, "name": "TrenchV2", "address": "0xaf48bb0936d9fa522650236917321d89978a8591" },
459
+ { "index": 22, "name": "TrenchV3", "address": "0x01957ec5fcc079f1bb388b9f261278dac42cf2e9" }
460
+ ]
461
+ }
462
+ ```
463
+
464
+ Finvesta is a Liberty-style V3 venue with fee tiers `100`, `500`, `2500`, and
465
+ `10000`. It can be selected for normal routes, but it is not transfer-tax safe.
466
+ Trench V2 is a direct-pair adapter with dynamic pair-specific fees and is
467
+ eligible for transfer-tax-sensitive hops. Trench V3 uses direct pool simulation
468
+ across fee tiers `100`, `500`, `2500`, `3000`, and `10000`; like other V3
469
+ callback adapters, it is not transfer-tax safe.
470
+ Always treat the live `/swap/adapters` response as the runtime source of truth.
445
471
 
446
472
  #### Using adapter indices to filter routing
447
473
 
@@ -451,8 +477,8 @@ Pass adapter indices as a comma-separated `adapters` param to `/swap/quote`:
451
477
  # Route only through PulseXV2 (index 3):
452
478
  GET /swap/quote?...&adapters=3
453
479
 
454
- # Route through PulseXV2 + UniswapV3:
455
- GET /swap/quote?...&adapters=3,7
480
+ # Route through PulseXV2 + UniswapV3:
481
+ GET /swap/quote?...&adapters=3,7
456
482
 
457
483
  # Exclude nothing (default — omit the param):
458
484
  GET /swap/quote?...
@@ -598,17 +624,17 @@ Returns the optimal split-route for a swap and (optionally) a ready-to-send tran
598
624
  | `sender` | No* | address | — | Sender wallet address. **Required to receive `tx` calldata in the response.** |
599
625
  | `receiver` | No | address | `sender` | Custom recipient address. If omitted, output tokens are sent to `sender`. |
600
626
  | `slippage` | No | integer | `50` | Slippage tolerance in **basis points** (bps). `50` = 0.50 %. Range: `0`–`5000`. |
601
- | `fee` | No | integer | `10` | Protocol fee in basis points (0.10 %). Range: `10`–`100`. Defaults to `10` if omitted. |
627
+ | `fee` | No | integer | `10` | Regular swap protocol fee in basis points. Range: `10`–`100`; defaults to `10`. Gasless quotes require exactly `10` for the fixed 0.1% settlement fee; see [gasless fee policy](GASLESS.md#fixed-gasless-fee). |
602
628
  | `partnerAddress` | No | address | `0x0…0` | Your partner wallet to receive 50 % of collected fees. Omit or pass `0x0` for no partner. |
603
629
  | `feeOnOutput` | No | string | `"false"` | Controls fee mode. `"true"` = fee deducted from output. `"false"` = fee deducted from input (default). Affects `expectedOutputAmount` accuracy — see [Swap Integration Flow](#swap-integration-flow). |
604
- | `adapters` | No | string | — | Comma-separated adapter indices to restrict routing (e.g. `"3"` for PulseXV2 only, `"3,7"` for PulseXV2 + UniswapV3). Get available indices from [List Adapters](#list-adapters). |
630
+ | `adapters` | No | string | — | Comma-separated adapter indices to restrict routing (e.g. `"3"` for PulseXV2 only, `"3,7"` for PulseXV2 + UniswapV3). Get available indices from [List Adapters](#list-adapters). |
605
631
 
606
632
  > \* If `sender` is omitted, the response will still contain routing data, `minAmountOut`, and tax info, but the `tx` object will be absent. This is useful for **showing estimated swap output before the user connects their wallet** — you can display prices, routes, and tax warnings without requiring a wallet connection. Once the user connects, re-fetch the quote with `sender` to get the ready-to-send `tx` object.
607
633
 
608
634
  #### Example Request
609
635
 
610
636
  ```
611
- GET /swap/quote?network=pulsechain&from=0xA1077a294dDE1B09bB078844df40758a5D0f9a27&to=0x95B303987A60C71504D99Aa1b13B4DA07b0790ab&amount=1000000000000000000&sender=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&slippage=100&fee=10&partnerAddress=0xYourPartnerWallet&feeOnOutput=true
637
+ GET /swap/quote?network=pulsechain&from=0xA1077a294dDE1B09bB078844df40758a5D0f9a27&to=0x95B303987A60C71504D99Aa1b13B4DA07b0790ab&amount=1000000000000000000&sender=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&slippage=100&fee=10&partnerAddress=0xYourPartnerWallet&feeOnOutput=true
612
638
  ```
613
639
 
614
640
  #### Example Response
@@ -680,13 +706,13 @@ GET /swap/quote?network=pulsechain&from=0xA1077a294dDE1B09bB078844df40758a5D0f9a
680
706
  // Transaction object — only present when `sender` is provided
681
707
  // ⚠️ Always use tx.to from this response — do NOT hardcode the router address
682
708
  "tx": {
683
- "to": "0x2dFc8B6e13fF7F04e37Ef97006084805D65a6F19",
709
+ "to": "0x2dFc8B6e13fF7F04e37Ef97006084805D65a6F19",
684
710
  "data": "0x...", // ABI-encoded goSwitch() calldata with feeOnOutput = false
685
711
  "value": "0" // "0" for ERC-20 input; amountIn for native-currency input
686
712
  },
687
713
  // Same swap but with fee taken from the output token instead
688
714
  "txFeeOnOutput": {
689
- "to": "0x2dFc8B6e13fF7F04e37Ef97006084805D65a6F19",
715
+ "to": "0x2dFc8B6e13fF7F04e37Ef97006084805D65a6F19",
690
716
  "data": "0x...", // ABI-encoded goSwitch() calldata with feeOnOutput = true
691
717
  "value": "0"
692
718
  }
@@ -705,11 +731,11 @@ GET /swap/quote?network=pulsechain&from=0xA1077a294dDE1B09bB078844df40758a5D0f9a
705
731
  | `toToken` | `string` | Output token address |
706
732
  | `receiver` | `string?` | Recipient address for output tokens. Same as `sender` unless a custom `receiver` was specified. |
707
733
  | `totalAmountIn` | `string` | Total input amount in wei |
708
- | `totalAmountOut` | `string` | Quoted route output in wei before the Switch protocol fee and slippage. Protocol-native quoters such as Flap Portal may already include their token-tax effect. |
734
+ | `totalAmountOut` | `string` | Quoted route output in wei before the Switch protocol fee and slippage. Protocol-native quoters such as Flap Portal may already include their token-tax effect. |
709
735
  | `expectedOutputAmount` | `string` | Expected output the user will actually receive, in wei. Accounts for sell tax, protocol fee, and buy tax — but NOT slippage. This is the most accurate value to display as the estimated received amount. When `feeOnOutput` is passed correctly, this is **exact** (matches on-chain execution). |
710
- | `minAmountOut` | `string` | Minimum acceptable output after adapter-specific tax accounting, fee, and slippage. Use the API value directly; do not recompute it by multiplying the reported tax rates. This is encoded in `tx.data` as `_minTotalAmountOut`. |
736
+ | `minAmountOut` | `string` | Minimum acceptable output after adapter-specific tax accounting, fee, and slippage. Use the API value directly; do not recompute it by multiplying the reported tax rates. This is encoded in `tx.data` as `_minTotalAmountOut`. |
711
737
  | `paths` | `SwapPath[]` | Human-readable path descriptions |
712
- | `routeAllocation` | `RouteAllocationPlan` | Human-readable structured route breakdown for display and analytics. It is not a drop-in on-chain ABI value. |
738
+ | `routeAllocation` | `RouteAllocationPlan` | Human-readable structured route breakdown for display and analytics. It is not a drop-in on-chain ABI value. |
713
739
  | `tx` | `SwapTransaction?` | Ready-to-send transaction (fee on input). Only present when `sender` is provided. |
714
740
  | `txFeeOnOutput` | `SwapTransaction?` | Ready-to-send transaction (fee on output). Only present when `sender` is provided. Choose between `tx` and `txFeeOnOutput` at send time. |
715
741
  | `fromTokenTax` | `TokenTaxResponse?` | Transfer tax info for the input token. See [Tax Tokens Deep Dive](#tax-tokens-deep-dive). |
@@ -790,16 +816,16 @@ Present on every quote response as `fromTokenTax` and `toTokenTax`. Reports whet
790
816
 
791
817
  | Field | Type | Description |
792
818
  |---|---|---|
793
- | `adapter` | `string` | Human-readable DEX adapter name (e.g. `"PulseXV2"`) |
794
- | `amountIn` | `string` | Input amount routed through this adapter |
795
- | `amountOut` | `string` | Expected output from this adapter |
796
- | `fee` | `number?` | V3 fee tier or concentrated-liquidity tick-spacing hint; zero when unused |
797
-
798
- Use the API-provided `tx.data` for execution. If you intentionally construct
799
- router or limit-order calldata yourself, each on-chain adapter leg is
800
- `{ adapter, amountIn, fee, data }`; `data` is required and should be `0x` for
801
- adapters that need no payload. The display-oriented `routeAllocation` does not
802
- contain enough information to encode every route family.
819
+ | `adapter` | `string` | Human-readable DEX adapter name (e.g. `"PulseXV2"`) |
820
+ | `amountIn` | `string` | Input amount routed through this adapter |
821
+ | `amountOut` | `string` | Expected output from this adapter |
822
+ | `fee` | `number?` | V3 fee tier or concentrated-liquidity tick-spacing hint; zero when unused |
823
+
824
+ Use the API-provided `tx.data` for execution. If you intentionally construct
825
+ router or limit-order calldata yourself, each on-chain adapter leg is
826
+ `{ adapter, amountIn, fee, data }`; `data` is required and should be `0x` for
827
+ adapters that need no payload. The display-oriented `routeAllocation` does not
828
+ contain enough information to encode every route family.
803
829
 
804
830
  ---
805
831
 
@@ -836,7 +862,7 @@ Errors are returned as JSON with an `error` field:
836
862
  | `"Amount must be greater than 0"` | `amount` is zero or negative |
837
863
  | `"Amount exceeds maximum allowed value"` | `amount` exceeds 10²⁷ (1 billion tokens @ 18 decimals) |
838
864
  | `"Slippage must be a number between 0 and 5000 (basis points)"` | `slippage` out of range |
839
- | `"Fee must be a number between 10 and 100 (basis points). Minimum fee is 0.10%."` | `fee` out of range or below minimum |
865
+ | `"Fee must be a number between 10 and 100 (basis points). Minimum fee is 0.10%."` | `fee` out of range or below minimum |
840
866
  | `"receiver must be a valid Ethereum address (0x + 40 hex chars)"` | Malformed receiver address |
841
867
  | `"partnerAddress must be a valid Ethereum address (0x + 40 hex chars)"` | Malformed partner address |
842
868
  | `"Failed to find route"` | No viable swap path exists, or route computation timed out (30s limit) |
@@ -866,7 +892,7 @@ If the swap transaction reverts on-chain, the SwitchRouter contract returns one
866
892
 
867
893
  Switch supports a **50/50 fee-sharing** model for integration partners:
868
894
 
869
- 1. Set a `fee` (e.g. `10` = 0.10 %, the current minimum) and your `partnerAddress` when calling the API.
895
+ 1. Set a `fee` (e.g. `10` = 0.10 %, the current minimum) and your `partnerAddress` when calling the API.
870
896
  2. The SwitchRouter contract automatically splits collected fees **during the swap**:
871
897
  - **50 %** sent to the protocol
872
898
  - **50 %** sent directly to your `partnerAddress`
@@ -945,15 +971,15 @@ await signer.sendTransaction(chosenTx);
945
971
 
946
972
  ## Limit Orders
947
973
 
948
- Switch Limit Orders let users place **gasless, signed orders** that are filled automatically when market conditions are met — no gas to create, no token deposits, EIP-712 signed.
949
-
950
- **→ Full integration guide: [`LIMIT-ORDERS.md`](LIMIT-ORDERS.md)**
951
-
952
- Covers both `pulsechain` and `robinhood`: creating orders, live deployment
953
- discovery, approvals, `feeOnOutput` decision rules, native PLS/ETH flows,
954
- querying, cancellation, API types, and EIP-712 details. Use
955
- `fetchLimitOrderConfig({ network })` at startup and include `network` in every
956
- orderbook request.
974
+ Switch Limit Orders let users place **gasless, signed orders** that are filled automatically when market conditions are met — no gas to create, no token deposits, EIP-712 signed.
975
+
976
+ **→ Full integration guide: [`LIMIT-ORDERS.md`](LIMIT-ORDERS.md)**
977
+
978
+ Covers both `pulsechain` and `robinhood`: creating orders, live deployment
979
+ discovery, approvals, `feeOnOutput` decision rules, native PLS/ETH flows,
980
+ querying, cancellation, API types, and EIP-712 details. Use
981
+ `fetchLimitOrderConfig({ network })` at startup and include `network` in every
982
+ orderbook request.
957
983
 
958
984
  ---
959
985
 
@@ -969,34 +995,34 @@ Robinhood constants are available from
969
995
  | Name | Value |
970
996
  |---|---|
971
997
  | **Chain** | PulseChain (Chain ID `369`); Robinhood Chain uses ID `4663` and network-specific exports |
972
- | **SwitchRouter** (current) | `0x2dFc8B6e13fF7F04e37Ef97006084805D65a6F19` |
973
- | **SwitchRouter** (legacy) | `0x0305fcb5dA680EA6fd1B01A96C1949175B99d406` |
974
- | **SwitchLimitOrder** (V3 — current protected) | `0x2afBf0aB8d958a0227742F7a8BdA00c96372E4D7` |
975
- | **SwitchLimitOrder** (V2 — legacy) | `0x8e3881bdF81Fc0211383B2e576076B654F7aFD86` |
976
- | **SwitchLimitOrder** (V1 — legacy) | `0x0e884072a891b406C0D814907A1E2310fE5F5Deb` |
977
- | **SwitchPLSFlow** (V3 — current protected) | `0x0362177FF2ad25a33a879c881a5055575C63a4cE` |
978
- | **SwitchPLSFlow** (V2 — legacy) | `0xCf5606bdC750d8626Cec32CA2E1BB207968db1D5` |
979
- | **SwitchPLSFlow** (V1 — legacy) | `0x88c9e2C83b6B7c707602e548481e58E920694E64` |
980
- | **Direct-fill quoter** | `0x23A95b0f69c993CFe6180a266A93F7560102e929` |
981
- | **Limit-order adapter** | Index `17`; `0x7B9761484301a8FE4a2BA47194F7646eEF8e1cDd` |
982
- | **LimitOrderAdmin** | `0x9C8B9012AfC0489dE612F7039665212EB88be127` |
983
- | **OperatorAccessRegistry** | `0x7dA1AB04A712479569cCaD783Ca6114b763e36Ad` |
984
- | **Native PLS sentinel** | `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` |
985
- | **WPLS** | `0xA1077a294dDE1B09bB078844df40758a5D0f9a27` |
986
- | **Finvesta V3 adapter** | Index `20`; `0x012c44d0C465819eF3CeAC208e0c1B272087a8b4` (not transfer-tax safe) |
987
- | **Finvesta V3 factory** | `0x7f5c7C5144b4B4c6e954A5b2D75C318C5467EFDc` |
988
- | **Finvesta fee tiers** | `100`, `500`, `2500`, `10000` |
989
- | **Trench V2 adapter** | Index `21`; `0xAf48bb0936D9fA522650236917321D89978A8591` (direct-pair, transfer-tax safe) |
990
- | **Trench V2 factory** | `0xA024e4574406BEf89e624c75758c700B5bED27C7` |
991
- | **Trench V3 adapter** | Index `22`; `0x01957eC5FCC079f1bB388b9f261278daC42cf2E9` (not transfer-tax safe) |
992
- | **Trench V3 factory** | `0xCAeF0a906F3323595A8faA14DF7eDee6F59220af` |
993
- | **Trench V3 fee tiers** | `100`, `500`, `2500`, `3000`, `10000` |
994
- | **Fee denominator** | `10000` (basis points) |
998
+ | **SwitchRouter** (current) | `0x2dFc8B6e13fF7F04e37Ef97006084805D65a6F19` |
999
+ | **SwitchRouter** (legacy) | `0x0305fcb5dA680EA6fd1B01A96C1949175B99d406` |
1000
+ | **SwitchLimitOrder** (V3 — current protected) | `0x2afBf0aB8d958a0227742F7a8BdA00c96372E4D7` |
1001
+ | **SwitchLimitOrder** (V2 — legacy) | `0x8e3881bdF81Fc0211383B2e576076B654F7aFD86` |
1002
+ | **SwitchLimitOrder** (V1 — legacy) | `0x0e884072a891b406C0D814907A1E2310fE5F5Deb` |
1003
+ | **SwitchPLSFlow** (V3 — current protected) | `0x0362177FF2ad25a33a879c881a5055575C63a4cE` |
1004
+ | **SwitchPLSFlow** (V2 — legacy) | `0xCf5606bdC750d8626Cec32CA2E1BB207968db1D5` |
1005
+ | **SwitchPLSFlow** (V1 — legacy) | `0x88c9e2C83b6B7c707602e548481e58E920694E64` |
1006
+ | **Direct-fill quoter** | `0x23A95b0f69c993CFe6180a266A93F7560102e929` |
1007
+ | **Limit-order adapter** | Index `17`; `0x7B9761484301a8FE4a2BA47194F7646eEF8e1cDd` |
1008
+ | **LimitOrderAdmin** | `0x9C8B9012AfC0489dE612F7039665212EB88be127` |
1009
+ | **OperatorAccessRegistry** | `0x7dA1AB04A712479569cCaD783Ca6114b763e36Ad` |
1010
+ | **Native PLS sentinel** | `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` |
1011
+ | **WPLS** | `0xA1077a294dDE1B09bB078844df40758a5D0f9a27` |
1012
+ | **Finvesta V3 adapter** | Index `20`; `0x012c44d0C465819eF3CeAC208e0c1B272087a8b4` (not transfer-tax safe) |
1013
+ | **Finvesta V3 factory** | `0x7f5c7C5144b4B4c6e954A5b2D75C318C5467EFDc` |
1014
+ | **Finvesta fee tiers** | `100`, `500`, `2500`, `10000` |
1015
+ | **Trench V2 adapter** | Index `21`; `0xAf48bb0936D9fA522650236917321D89978A8591` (direct-pair, transfer-tax safe) |
1016
+ | **Trench V2 factory** | `0xA024e4574406BEf89e624c75758c700B5bED27C7` |
1017
+ | **Trench V3 adapter** | Index `22`; `0x01957eC5FCC079f1bB388b9f261278daC42cf2E9` (not transfer-tax safe) |
1018
+ | **Trench V3 factory** | `0xCAeF0a906F3323595A8faA14DF7eDee6F59220af` |
1019
+ | **Trench V3 fee tiers** | `100`, `500`, `2500`, `3000`, `10000` |
1020
+ | **Fee denominator** | `10000` (basis points) |
995
1021
  | **Max slippage** | `5000` bps (50 %) |
996
1022
  | **Max fee** | `100` bps (1 %) |
997
- | **Regular swap fee** | `10` bps (0.10 %) — enforced on-chain by `MIN_FEE` |
998
- | **Limit-order fee** | `30` bps (0.30 %); the LimitOrder is Router-fee-exempt |
999
- | **Maximum operator excess** | `500` bps (5 %) of the protected contract's cap base |
1023
+ | **Regular swap fee** | `10` bps (0.10 %) — enforced on-chain by `MIN_FEE` |
1024
+ | **Limit-order fee** | `30` bps (0.30 %); the LimitOrder is Router-fee-exempt |
1025
+ | **Maximum operator excess** | `500` bps (5 %) of the protected contract's cap base |
1000
1026
  | **Default slippage** | `50` bps (0.50 %) |
1001
1027
  | **Swap API base** | `https://quote.switch.win` |
1002
1028
  | **Limit Order API base** | `https://quote.switch.win` |