@switch-win/sdk 1.2.2 → 1.2.3

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.
package/README.md CHANGED
@@ -121,8 +121,11 @@ For a production integration with tax token handling, adapter filtering, and fee
121
121
  ### Robinhood Chain
122
122
 
123
123
  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.
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 fourteen adapters across Uniswap, SwapHood,
127
+ Up33, Sheriff, Aeon, Catnip, PancakeSwap, RobinSwap, SushiSwap, and Switch limit
128
+ orders.
126
129
 
127
130
  For network configuration, deployed addresses, tax handling, execution, and
128
131
  the complete frontend token list, see [`ROBINHOOD.md`](ROBINHOOD.md).
@@ -139,7 +142,7 @@ const url = buildRobinhoodQuoteUrl({
139
142
  to: ROBINHOOD_TOKENS.USDG.address,
140
143
  amount: 1_000_000_000_000_000n,
141
144
  sender: walletAddress,
142
- slippage: 50,
145
+ slippage: 100, // 1%, matching the Robinhood frontend default
143
146
  });
144
147
 
145
148
  const response = await fetch(url, {
@@ -917,11 +920,15 @@ await signer.sendTransaction(chosenTx);
917
920
 
918
921
  ## Limit Orders
919
922
 
920
- 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.
921
-
922
- **→ Full integration guide: [`LIMIT-ORDERS.md`](LIMIT-ORDERS.md)**
923
-
924
- Covers: creating orders, approvals, `feeOnOutput` decision guide (tax tokens & operator flexibility), querying, cancellation, API reference, types, and EIP-712 details.
923
+ 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.
924
+
925
+ **→ Full integration guide: [`LIMIT-ORDERS.md`](LIMIT-ORDERS.md)**
926
+
927
+ Covers both `pulsechain` and `robinhood`: creating orders, live deployment
928
+ discovery, approvals, `feeOnOutput` decision rules, native PLS/ETH flows,
929
+ querying, cancellation, API types, and EIP-712 details. Use
930
+ `fetchLimitOrderConfig({ network })` at startup and include `network` in every
931
+ orderbook request.
925
932
 
926
933
  ---
927
934
 
package/ROBINHOOD.md CHANGED
@@ -11,8 +11,8 @@ Production integration reference for Switch swaps on Robinhood Chain mainnet.
11
11
  | Explorer | `https://robinhoodchain.blockscout.com` |
12
12
  | Quote API | `https://quote.switch.win/swap/quote` |
13
13
  | Tax API | `https://quote.switch.win/swap/checkTax` |
14
- | Supported liquidity | Uniswap V2, V3, and hookless static-fee V4 |
15
- | Limit orders | Not currently available |
14
+ | Supported liquidity | 14 adapters: Uniswap V2/V3/V4, Switch limit orders, SwapHood, Up33, Sheriff, Aeon, Catnip, PancakeSwap, RobinSwap, and SushiSwap |
15
+ | Limit orders | Available: EIP-712 ERC-20 orders plus native ETH flow |
16
16
 
17
17
  ## Contents
18
18
 
@@ -111,6 +111,16 @@ await window.ethereum.request({
111
111
  | SwitchLimitOrder | `0x752c50DDd3B426cAE3D7A995F313Ac74ac6B0230` |
112
112
  | Native ETH flow | `0x029FfC6aF9112eA078f1D6f4a98826DDB2136cf6` |
113
113
  | Switch Limit Order adapter (index 3) | `0x412F625072c10e58C619D1e0b3C95cd3d5689871` |
114
+ | SwapHood V2 adapter (index 4) | `0x6D8746f02e52944c13824fA691c6f4186E463354` |
115
+ | SwapHood V3 adapter (index 5) | `0x9645dE0AcB48F0AAefdBEb423F0558457907DE98` |
116
+ | Up33 CL adapter (index 6) | `0x388179D2FB0ABcE9b03068916aF8a3c4dfD023c8` |
117
+ | Sheriff V2 adapter (index 7) | `0xBDB3EB0355981500f58C9bc77c3E61762844A146` |
118
+ | Sheriff Algebra adapter (index 8) | `0xeFE1affb0e2Bb8A9F7d9D30751bAF679996ADA26` |
119
+ | Aeon Algebra adapter (index 9) | `0x20615954FB87360139e7DdDB519359498EbD1904` |
120
+ | Catnip V2 adapter (index 10) | `0x5b2Ca358d56490Dc86224D502522314De7707237` |
121
+ | PancakeSwap V2 adapter (index 11) | `0x3B6e71A59553143937Fef74a7B50AFD24528786E` |
122
+ | RobinSwap V3 adapter (index 12) | `0x798f77D63b46b0E019de206E111e5ea5CC16BEc8` |
123
+ | SushiSwap V3 adapter (index 13) | `0xca3EA0Fd6E31f94c81B6586836790adE638313ED` |
114
124
 
115
125
  The V4 adapter was created in
116
126
  [deployment transaction `0x60d5...34a7`](https://robinhoodchain.blockscout.com/tx/0x60d56466a8162a643a15ecde98322ec05ea23d44d03fbd817df4ddbaef4834a7)
@@ -162,6 +172,26 @@ Submit signed orders to `POST /limit-orders?network=robinhood`. For
162
172
  `feeOnOutput=false`, approve `ROBINHOOD_SWITCH_CONTRACTS.limitOrder`; for
163
173
  `feeOnOutput=true`, approve `ROBINHOOD_SWITCH_CONTRACTS.router`.
164
174
 
175
+ Applications should fetch `/limit-orders/config?network=robinhood` at startup
176
+ instead of relying only on static addresses. The SDK exposes this as:
177
+
178
+ ```ts
179
+ const config = await fetchLimitOrderConfig({ network: "robinhood" });
180
+ const signing = getNetworkEIP712SigningParams(
181
+ "robinhood",
182
+ config.limitOrderContract,
183
+ );
184
+ const approvalTarget = getLimitOrderApprovalTarget(
185
+ "robinhood",
186
+ order.feeOnOutput,
187
+ { limitOrderContract: config.limitOrderContract },
188
+ );
189
+ ```
190
+
191
+ Include `limitOrderContract: config.limitOrderContract` with the submitted
192
+ signed order. Every returned order also carries its own deployment address;
193
+ operators must fill and makers must cancel against that per-order address.
194
+
165
195
  Native ETH input orders are created on-chain through
166
196
  `ROBINHOOD_SWITCH_CONTRACTS.nativeEthFlow` and are indexed from its events; do
167
197
  not POST them as signed EOA orders. Native ETH output is represented by WETH in
@@ -221,9 +251,10 @@ The canonical Robinhood V4 infrastructure is available through
221
251
  | Universal Router | `0x8876789976decbfcbbbe364623c63652db8c0904` |
222
252
  | Permit2 | `0x000000000022D473030F116dDEE9F6B43aC78BA3` |
223
253
 
224
- Tax-token safety is unchanged: if either side is detected as a transfer-tax
225
- token, the complete route is restricted to Uniswap V2 adapter index `0`.
226
- Uniswap V3 and V4 are both excluded from that quote.
254
+ Tax-token safety is unchanged: if either side is detected as a transfer-tax
255
+ token, the complete route is restricted to direct-pair V2 adapters `0`, `4`,
256
+ `7`, `10`, and `11`. Concentrated-liquidity adapters are excluded from that
257
+ quote.
227
258
 
228
259
  ## Swap integration flow
229
260
 
@@ -239,8 +270,9 @@ Use the same sequence as a PulseChain integration:
239
270
  6. Show `expectedOutputAmount`, `minAmountOut`, route allocation, and detected
240
271
  taxes to the user.
241
272
 
242
- Any swap involving a tax token is routed entirely through Uniswap V2. This
243
- also applies when both input and output are tax tokens.
273
+ Any swap involving a tax token is routed entirely through the tax-safe
274
+ direct-pair V2 adapter set (`0`, `4`, `7`, `10`, and `11`). This also applies
275
+ when both input and output are tax tokens.
244
276
 
245
277
  ## Quickstart
246
278
 
@@ -257,7 +289,7 @@ const url = buildRobinhoodQuoteUrl({
257
289
  to: ROBINHOOD_TOKENS.USDG.address,
258
290
  amount: 1_000_000_000_000_000n,
259
291
  sender: walletAddress,
260
- slippage: 50, // 0.50%, expressed in basis points
292
+ slippage: 100, // 1.00%, the Robinhood frontend default
261
293
  feeOnOutput,
262
294
  });
263
295
 
@@ -281,7 +313,7 @@ Equivalent curl request:
281
313
 
282
314
  ```bash
283
315
  curl -H "x-api-key: YOUR_KEY" \
284
- "https://quote.switch.win/swap/quote?network=robinhood&from=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&to=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&amount=1000000000000000&sender=0xYOUR_WALLET&slippage=50"
316
+ "https://quote.switch.win/swap/quote?network=robinhood&from=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&to=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&amount=1000000000000000&sender=0xYOUR_WALLET&slippage=100"
285
317
  ```
286
318
 
287
319
  Omit `sender` for a display-only quote. Fetch again with the sender immediately
@@ -374,7 +406,7 @@ const quoteUrl = buildRobinhoodQuoteUrl({
374
406
  to: tokenOut,
375
407
  amount: amountIn,
376
408
  sender: walletAddress,
377
- slippage: 50,
409
+ slippage: 100,
378
410
  feeOnOutput,
379
411
  });
380
412
 
@@ -441,17 +473,28 @@ Robinhood currently returns:
441
473
 
442
474
  | Index | Adapter |
443
475
  |---:|---|
444
- | `0` | Uniswap V2 |
445
- | `1` | Uniswap V3 |
446
- | `2` | Uniswap V4 |
476
+ | `0` | Uniswap V2 |
477
+ | `1` | Uniswap V3 |
478
+ | `2` | Uniswap V4 |
479
+ | `3` | Switch Limit Orders |
480
+ | `4` | SwapHood V2 |
481
+ | `5` | SwapHood V3 |
482
+ | `6` | Up33 CL |
483
+ | `7` | Sheriff V2 |
484
+ | `8` | Sheriff Algebra |
485
+ | `9` | Aeon Algebra |
486
+ | `10` | Catnip V2 |
487
+ | `11` | PancakeSwap V2 |
488
+ | `12` | RobinSwap V3 |
489
+ | `13` | SushiSwap V3 |
447
490
 
448
491
  Treat the endpoint response, not this document, as the source of truth for
449
492
  which adapters are currently selectable.
450
493
 
451
- Do not permanently hard-code the available adapter list in an integration.
452
- Fetch it when presenting routing-source controls. If a quote involves a tax
453
- token, the backend overrides routing to tax-safe adapter `0`; an explicit
454
- filter that excludes adapter `0` is rejected.
494
+ Do not permanently hard-code the available adapter list in an integration.
495
+ Fetch it when presenting routing-source controls. If a quote involves a tax
496
+ token, the backend restricts routing to tax-safe adapters `0`, `4`, `7`, `10`,
497
+ and `11`; an explicit filter that excludes all of them is rejected.
455
498
 
456
499
  ### Check token tax
457
500
 
@@ -487,7 +530,7 @@ GET https://quote.switch.win/swap/quote
487
530
  | `amount` | Yes | Raw input amount. |
488
531
  | `sender` | No | Required when transaction calldata is needed. |
489
532
  | `receiver` | No | Output recipient; defaults to `sender`. |
490
- | `slippage` | No | Basis points; default `50` (`0.5%`). |
533
+ | `slippage` | No | Basis points; API fallback `50` (`0.5%`). The Switch Robinhood frontend explicitly requests `100` (`1%`). |
491
534
  | `fee` | No | Partner/protocol fee in basis points. |
492
535
  | `partnerAddress` | No | Fee-sharing recipient. |
493
536
  | `feeOnOutput` | No | `true` takes the fee from output; `false` takes it from input. |
@@ -529,7 +572,7 @@ Common Robinhood errors include:
529
572
  - Missing or unsupported `network`.
530
573
  - Invalid token, sender, receiver, or partner address.
531
574
  - Invalid raw amount, slippage, fee, gas price, or adapter filter.
532
- - A tax-token quote explicitly excluded the Uniswap V2 adapter.
575
+ - A tax-token quote explicitly excluded every tax-safe direct-pair V2 adapter.
533
576
  - No viable route across the currently active adapters, or insufficient liquidity.
534
577
  - RPC timeout or public-RPC rate limiting.
535
578
  - Missing executable transaction because `sender` was omitted.
@@ -576,7 +619,13 @@ into the UI separately from this list.
576
619
  | TENDIES | TENDIES | `0x45242320DBB855EeA8Fd36804C6487E10E97FCF9` | 18 |
577
620
  | GME | GameStop | `0x7e86381A763F0Ecca2bDF27C54eAC403ddD48123` | 18 |
578
621
  | 4663 | 4663 | `0xd4052415613B34Af236024B895574c467f65b6dD` | 18 |
579
- | MARIAN | Lady Marian | `0x01637b14B7378B99dE75A64d50656d98488D9a4d` | 18 |
622
+ | MARIAN | Lady Marian | `0x01637b14B7378B99dE75A64d50656d98488D9a4d` | 18 |
623
+ | Index | The Index | `0x56910D4409F3a0C78C64DD8D0545FF0705389870` | 18 |
624
+ | VEX | ProjectVex | `0x8Ff92566f2e81BDd68EDfAa8cde73942A723796b` | 18 |
625
+ | HOODIE | HOODIE | `0xC72c01AAB5f5678dc1d6f5C6d2B417d91D402Ba3` | 18 |
626
+ | WISHBONE | WISHBONE | `0x77581054581B9c525E7dd7a0155DE43867532d03` | 18 |
627
+ | VLAD | The Green Bull | `0x31BE8f7485e36928C9De86566c62da82d4B6BF81` | 18 |
628
+ | AEON | Aeon | `0xd4c93eD1843606f92CccA078941f3d52A585982f` | 18 |
580
629
 
581
630
  The ordered list is exported as `ROBINHOOD_FRONTEND_TOKEN_LIST`.
582
631
 
@@ -586,22 +635,38 @@ Always identify tokens by address and obtain a fresh quote and tax check.
586
635
 
587
636
  ### Routing configuration
588
637
 
589
- Switch currently evaluates:
590
-
591
- - Uniswap V2 adapter index `0`.
592
- - Uniswap V3 adapter index `1`.
593
- - V3 fee tiers `100`, `500`, `3000`, and `10000`.
594
- - Trusted routing hubs WETH, USDG, VIRTUAL, and CASHCAT.
595
-
596
- The prepared V4 integration reserves adapter index `2`. Once activated, it
597
- discovers hookless static-fee V4 pools by complete `PoolKey` rather than
598
- applying the V3 fee-tier list. Native-ETH V4 currencies are normalized through the WETH/native
599
- alias described above. Until `/swap/adapters` returns index `2`, V4 is not part
600
- of live production quotes.
601
-
602
- If either side is detected as a transfer-tax token, the backend restricts the
603
- entire route (including every split and intermediate hop) to Uniswap V2. V3 is
604
- not considered for that quote, and V4 will remain excluded after activation.
638
+ The production router currently exposes fourteen ordered adapters:
639
+
640
+ | Index | Venue | Routing family |
641
+ |---:|---|---|
642
+ | `0` | Uniswap V2 | Direct-pair V2 |
643
+ | `1` | Uniswap V3 | V3 tiers `100`, `500`, `3000`, `10000` |
644
+ | `2` | Uniswap V4 | Complete hookless static-fee `PoolKey` |
645
+ | `3` | Switch limit orders | Signed/on-chain order liquidity |
646
+ | `4` | SwapHood V2 | Pair-owned variable-fee V2 |
647
+ | `5` | SwapHood V3 | Pancake V3 tiers `100`, `500`, `2500`, `10000` |
648
+ | `6` | Up33 | Slipstream CL tick spacings `1`, `10`, `50`, `60`, `100`, `200`, `2000` |
649
+ | `7` | Sheriff V2 | Pair-owned variable-fee V2 |
650
+ | `8` | Sheriff | Algebra Integral |
651
+ | `9` | Aeon | Algebra Integral with plugin-aware fees |
652
+ | `10` | Catnip | Direct-pair V2, fixed 30 bps |
653
+ | `11` | PancakeSwap | Direct-pair V2, fixed 25 bps |
654
+ | `12` | RobinSwap | V3 tiers `100`, `500`, `2500`, `3000`, `10000` |
655
+ | `13` | SushiSwap | V3 tiers `500`, `3000`, `10000` |
656
+
657
+ V4 pools are discovered by complete `PoolKey`, not by applying a V3 fee-tier
658
+ list. Native-ETH V4 currencies are normalized through the WETH/native alias
659
+ described above. V3-style and Up33 route legs preserve the exact fee tier or
660
+ tick spacing that won the quote for every direct and multi-hop allocation.
661
+
662
+ Trusted routing hubs are WETH, USDG, VIRTUAL, CASHCAT, HOODRAT, TENDIES,
663
+ JUGGERNAUT, MARIAN, and WALLET. The expanded set was selected from the
664
+ 2026-07-16 pair-connectivity audit and zero-tax checks. VEX is excluded because
665
+ it is taxed; INDEX remains an endpoint token but is excluded because its
666
+ dominant liquidity depends on V4 hooks that are not yet supported. If either side is
667
+ detected as a transfer-tax token, the backend restricts the entire route to
668
+ direct-pair V2 adapters `0`, `4`, `7`, `10`, and `11`; concentrated-liquidity
669
+ and limit-order adapters are excluded.
605
670
 
606
671
  The API may split a quote across routes and adapters. Integrators should render
607
672
  the returned `paths` or `routeAllocation` instead of assuming a single path.
@@ -616,17 +681,16 @@ For server integrations, contact Switch to coordinate the expected request
616
681
  rate and IP allowlisting. Do not distribute one production key across
617
682
  untrusted clients.
618
683
 
619
- ## Current limitations
620
-
621
- - Robinhood limit orders are not deployed.
622
- - Rialto DEX is not integrated.
623
- - The production router supports Uniswap V2, V3, and supported hookless
624
- static-fee V4 liquidity. V4 participates in quotes whenever adapter index
625
- `2` is advertised by `/swap/adapters`.
626
- - The first V4 phase intentionally excludes hooked and dynamic-fee pools.
627
- - A V4 allocation currently selects its best single PoolKey; intra-V4
628
- multi-pool splitting is not yet enabled. V4 can still split against V2/V3.
629
- - Contract and token addresses must be treated as chain-specific.
684
+ ## Current limitations
685
+
686
+ - Rialto liquidity is not integrated.
687
+ - Robinhood market routing is limited to the fourteen production adapters
688
+ listed above. Always use `/swap/adapters` as the runtime source of truth.
689
+ - The first V4 phase intentionally excludes hooked and dynamic-fee pools.
690
+ - A V4 allocation currently selects its best single PoolKey; intra-V4
691
+ multi-pool splitting is not yet enabled. V4 can still split against other
692
+ eligible adapters.
693
+ - Contract and token addresses must be treated as chain-specific.
630
694
 
631
695
  See the main [SDK reference](README.md) for authentication, partner fees,
632
696
  response types, error handling, and the complete swap API schema.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@switch-win/sdk",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Official integration kit for the Switch DEX Aggregator on PulseChain and Robinhood Chain",
5
5
  "author": "BuildTheTech",
6
6
  "license": "MIT",
@@ -37,7 +37,8 @@
37
37
  "src/",
38
38
  "abi/",
39
39
  "README.md",
40
- "ROBINHOOD.md"
40
+ "ROBINHOOD.md",
41
+ "LIMIT-ORDERS.md"
41
42
  ],
42
43
  "devDependencies": {
43
44
  "typescript": "^5.9.3"
package/src/index.ts CHANGED
@@ -45,8 +45,9 @@ export type {
45
45
  CancelLimitOrderResponse,
46
46
  ListLimitOrdersResponse,
47
47
  LimitOrderPair,
48
- LimitOrderStats,
49
- LimitOrderMutationResponse,
48
+ LimitOrderStats,
49
+ LimitOrderConfigResponse,
50
+ LimitOrderMutationResponse,
50
51
  } from "./types.js";
51
52
 
52
53
  export { isErrorResponse } from "./types.js";
@@ -95,31 +96,42 @@ export {
95
96
  // Limit Order helpers
96
97
  export {
97
98
  buildLimitOrder,
98
- getEIP712SigningParams,
99
+ getEIP712SigningParams,
100
+ getNetworkEIP712SigningParams,
101
+ getLimitOrderNetworkConfig,
102
+ getLimitOrderApprovalTarget,
99
103
  getApprovalTarget,
100
104
  getRouterApprovalTarget,
101
105
  shouldUnwrapOutput,
102
- getPLSFlowAddress,
103
- isNativePLS,
106
+ getPLSFlowAddress,
107
+ getNativeFlowAddress,
108
+ isNativePLS,
109
+ isNativeCurrency,
104
110
  submitLimitOrder,
105
111
  cancelLimitOrder,
106
112
  fetchLimitOrders,
107
113
  fetchLimitOrder,
108
- fetchLimitOrderPairs,
109
- fetchLimitOrderStats,
110
- } from "./limit-orders.js";
114
+ fetchLimitOrderPairs,
115
+ fetchLimitOrderConfig,
116
+ fetchLimitOrderStats,
117
+ LIMIT_ORDER_NETWORK_CONFIGS,
118
+ } from "./limit-orders.js";
111
119
 
112
120
  export type {
113
- BuildLimitOrderOptions,
114
- ListLimitOrdersOptions,
115
- } from "./limit-orders.js";
121
+ BuildLimitOrderOptions,
122
+ ListLimitOrdersOptions,
123
+ LimitOrderNetwork,
124
+ LimitOrderNetworkConfig,
125
+ LimitOrderNetworkOptions,
126
+ } from "./limit-orders.js";
116
127
 
117
128
  // Network-specific swap configuration
118
129
  export {
119
130
  ROBINHOOD_NETWORK,
120
131
  ROBINHOOD_CHAIN,
121
- ROBINHOOD_NATIVE_ETH,
122
- ROBINHOOD_SWITCH_CONTRACTS,
132
+ ROBINHOOD_NATIVE_ETH,
133
+ ROBINHOOD_LIMIT_ORDER_EIP712_DOMAIN,
134
+ ROBINHOOD_SWITCH_CONTRACTS,
123
135
  ROBINHOOD_UNISWAP_CONTRACTS,
124
136
  ROBINHOOD_TOKENS,
125
137
  ROBINHOOD_FRONTEND_TOKEN_LIST,
@@ -2,7 +2,8 @@
2
2
  * Switch Limit Orders (V2) — Helper Functions
3
3
  *
4
4
  * Provides a complete toolkit for creating, signing, submitting, querying,
5
- * and cancelling EIP-712 signed limit orders on PulseChain.
5
+ * and cancelling EIP-712 signed limit orders on PulseChain and Robinhood
6
+ * Chain.
6
7
  *
7
8
  * ## How it works
8
9
  *
@@ -10,7 +11,8 @@
10
11
  * 2. **Sign** via EIP-712 with your wallet (ethers.js `signTypedData`)
11
12
  * 3. **Submit** the signed order to the Switch backend with `submitLimitOrder()`
12
13
  * 4. The Switch filler bot monitors active orders and fills them when profitable
13
- * 5. **Cancel** an order on-chain via `invalidateNonce()` + notify backend with `cancelLimitOrder()`
14
+ * 5. **Cancel** an order on-chain via `invalidateNonce()`; the backend indexer
15
+ * observes the cancellation event
14
16
  *
15
17
  * @example
16
18
  * ```ts
@@ -26,7 +28,8 @@ import type {
26
28
  ListLimitOrdersResponse,
27
29
  LimitOrderRecord,
28
30
  LimitOrderPair,
29
- LimitOrderStats,
31
+ LimitOrderStats,
32
+ LimitOrderConfigResponse,
30
33
  LimitOrderStatus,
31
34
  ErrorResponse,
32
35
  } from "./types.js";
@@ -40,8 +43,15 @@ import {
40
43
  SWITCH_LIMIT_ORDER,
41
44
  SWITCH_ROUTER,
42
45
  SWITCH_PLS_FLOW,
43
- WPLS,
44
- } from "./constants.js";
46
+ WPLS,
47
+ NATIVE_PLS,
48
+ } from "./constants.js";
49
+ import {
50
+ ROBINHOOD_CHAIN,
51
+ ROBINHOOD_NATIVE_ETH,
52
+ ROBINHOOD_SWITCH_CONTRACTS,
53
+ ROBINHOOD_TOKENS,
54
+ } from "./networks/robinhood.js";
45
55
 
46
56
  // ── Re-export EIP-712 constants for convenience ─────────────────────────────
47
57
 
@@ -247,7 +257,7 @@ export function shouldUnwrapOutput(
247
257
  }
248
258
 
249
259
  // ═══════════════════════════════════════════════════════════════════════════════
250
- // PLSFlow (Native PLS Limit Orders)
260
+ // Native-currency flow (SwitchPLSFlow ABI: PLS on PulseChain, ETH on Robinhood)
251
261
  // ═══════════════════════════════════════════════════════════════════════════════
252
262
 
253
263
  /**
@@ -262,8 +272,83 @@ export function getPLSFlowAddress(nativeFlowContract?: string): string {
262
272
  return nativeFlowContract || SWITCH_PLS_FLOW;
263
273
  }
264
274
 
275
+ /** Networks supported by the shared Switch limit-order API. */
276
+ export type LimitOrderNetwork = "pulsechain" | "robinhood";
277
+
278
+ /** Complete deployment metadata needed to create or fill limit orders. */
279
+ export interface LimitOrderNetworkConfig {
280
+ network: LimitOrderNetwork;
281
+ chainId: number;
282
+ chainName: string;
283
+ nativeSymbol: "PLS" | "ETH";
284
+ nativeSentinel: string;
285
+ wrappedNativeToken: string;
286
+ routerContract: string;
287
+ limitOrderContract: string;
288
+ nativeFlowContract: string;
289
+ }
290
+
291
+ /** Static defaults. Prefer {@link fetchLimitOrderConfig} at application startup. */
292
+ export const LIMIT_ORDER_NETWORK_CONFIGS: Readonly<
293
+ Record<LimitOrderNetwork, LimitOrderNetworkConfig>
294
+ > = {
295
+ pulsechain: {
296
+ network: "pulsechain",
297
+ chainId: 369,
298
+ chainName: "PulseChain",
299
+ nativeSymbol: "PLS",
300
+ nativeSentinel: NATIVE_PLS,
301
+ wrappedNativeToken: WPLS,
302
+ routerContract: SWITCH_ROUTER,
303
+ limitOrderContract: SWITCH_LIMIT_ORDER,
304
+ nativeFlowContract: SWITCH_PLS_FLOW,
305
+ },
306
+ robinhood: {
307
+ network: "robinhood",
308
+ chainId: ROBINHOOD_CHAIN.id,
309
+ chainName: ROBINHOOD_CHAIN.name,
310
+ nativeSymbol: "ETH",
311
+ nativeSentinel: ROBINHOOD_NATIVE_ETH,
312
+ wrappedNativeToken: ROBINHOOD_TOKENS.WETH.address,
313
+ routerContract: ROBINHOOD_SWITCH_CONTRACTS.router,
314
+ limitOrderContract: ROBINHOOD_SWITCH_CONTRACTS.limitOrder,
315
+ nativeFlowContract: ROBINHOOD_SWITCH_CONTRACTS.nativeEthFlow,
316
+ },
317
+ } as const;
318
+
319
+ /** Return the static deployment defaults for a supported limit-order network. */
320
+ export function getLimitOrderNetworkConfig(
321
+ network: LimitOrderNetwork = "pulsechain",
322
+ ): LimitOrderNetworkConfig {
323
+ return LIMIT_ORDER_NETWORK_CONFIGS[network];
324
+ }
325
+
326
+ /** Build the correct EIP-712 signing domain for a supported network. */
327
+ export function getNetworkEIP712SigningParams(
328
+ network: LimitOrderNetwork,
329
+ limitOrderContract?: string,
330
+ ) {
331
+ const config = getLimitOrderNetworkConfig(network);
332
+ return getEIP712SigningParams(
333
+ limitOrderContract ?? config.limitOrderContract,
334
+ config.chainId,
335
+ );
336
+ }
337
+
338
+ /** Resolve the maker's ERC-20 approval target for the selected fee mode. */
339
+ export function getLimitOrderApprovalTarget(
340
+ network: LimitOrderNetwork,
341
+ feeOnOutput: boolean,
342
+ overrides: { limitOrderContract?: string; routerContract?: string } = {},
343
+ ): string {
344
+ const config = getLimitOrderNetworkConfig(network);
345
+ return feeOnOutput
346
+ ? getRouterApprovalTarget(overrides.routerContract ?? config.routerContract)
347
+ : getApprovalTarget(overrides.limitOrderContract ?? config.limitOrderContract);
348
+ }
349
+
265
350
  export interface LimitOrderNetworkOptions {
266
- network?: "pulsechain" | "robinhood";
351
+ network?: LimitOrderNetwork;
267
352
  }
268
353
 
269
354
  function endpointForNetwork(endpoint: string, network?: string): string {
@@ -282,10 +367,27 @@ function endpointForNetwork(endpoint: string, network?: string): string {
282
367
  * @param tokenIn - The input token address
283
368
  * @returns `true` if tokenIn is the native PLS sentinel address
284
369
  */
285
- export function isNativePLS(tokenIn: string): boolean {
370
+ export function isNativePLS(tokenIn: string): boolean {
286
371
  const NATIVE_SENTINEL = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
287
372
  return tokenIn.toLowerCase() === NATIVE_SENTINEL.toLowerCase();
288
- }
373
+ }
374
+
375
+ /** Network-neutral native-currency sentinel check (PLS or ETH). */
376
+ export function isNativeCurrency(tokenIn: string): boolean {
377
+ const normalized = tokenIn.toLowerCase();
378
+ return (
379
+ normalized === NATIVE_PLS.toLowerCase() ||
380
+ normalized === ROBINHOOD_NATIVE_ETH.toLowerCase()
381
+ );
382
+ }
383
+
384
+ /** Return the native-order flow contract for PulseChain or Robinhood Chain. */
385
+ export function getNativeFlowAddress(
386
+ network: LimitOrderNetwork,
387
+ nativeFlowContract?: string,
388
+ ): string {
389
+ return nativeFlowContract ?? getLimitOrderNetworkConfig(network).nativeFlowContract;
390
+ }
289
391
 
290
392
  // ═══════════════════════════════════════════════════════════════════════════════
291
393
  // API Helpers
@@ -310,7 +412,7 @@ export function isNativePLS(tokenIn: string): boolean {
310
412
  * 4. Do **not** navigate away or close the signing flow until the
311
413
  * backend confirms the order.
312
414
  *
313
- * PLSFlow (native PLS) orders are an exception — they are recorded
415
+ * Native PLS/ETH flow orders are an exception — they are recorded
314
416
  * on-chain first, so the backend can discover them via event indexing
315
417
  * even if the POST never arrives.
316
418
  *
@@ -344,16 +446,17 @@ export async function submitLimitOrder(
344
446
  }
345
447
 
346
448
  /**
347
- * Cancel a limit order on the Switch backend (marks it CANCELLED in the DB).
348
- *
349
- * **Important:** This only removes the order from the backend orderbook. To
350
- * prevent the order from being filled on-chain, you MUST also call
351
- * `invalidateNonce(nonce)` on the SwitchLimitOrder contract. See the
352
- * cancellation guide in the README.
449
+ * Legacy helper for backend deployments that implemented REST cancellation.
450
+ *
451
+ * The current hosted Switch API intentionally has no DELETE endpoint.
452
+ * Cancellation must be performed on-chain with `invalidateNonce(nonce)` on
453
+ * the contract stored in the order's `limitOrderContract` field. The indexer
454
+ * then updates the order status from the emitted event.
353
455
  *
354
456
  * @param maker - Maker address
355
457
  * @param nonce - Nonce of the order to cancel
356
- * @returns Success confirmation or error
458
+ * @returns Success confirmation or error on compatible legacy backends
459
+ * @deprecated Do not use with the hosted Switch API; cancel on-chain instead.
357
460
  */
358
461
  export async function cancelLimitOrder(
359
462
  maker: string,
@@ -372,7 +475,7 @@ export async function cancelLimitOrder(
372
475
  /** Filter options for listing limit orders */
373
476
  export interface ListLimitOrdersOptions {
374
477
  /** Backend network process to query. */
375
- network?: "pulsechain" | "robinhood";
478
+ network?: LimitOrderNetwork;
376
479
  /** Filter by order status. Default: `"ACTIVE"` */
377
480
  status?: LimitOrderStatus;
378
481
  /** Filter by maker address */
@@ -476,7 +579,20 @@ export async function fetchLimitOrderPairs(
476
579
  ): Promise<LimitOrderPair[]> {
477
580
  const res = await fetch(endpointForNetwork(LIMIT_ORDER_PAIRS_ENDPOINT, options.network));
478
581
  return res.json() as Promise<LimitOrderPair[]>;
479
- }
582
+ }
583
+
584
+ /** Fetch the active deployment and EIP-712 domain for a network. */
585
+ export async function fetchLimitOrderConfig(
586
+ options: LimitOrderNetworkOptions = {},
587
+ ): Promise<LimitOrderConfigResponse> {
588
+ const res = await fetch(
589
+ endpointForNetwork(`${LIMIT_ORDERS_ENDPOINT}/config`, options.network),
590
+ );
591
+ if (!res.ok) {
592
+ throw new Error(`Failed to fetch limit-order config (${res.status})`);
593
+ }
594
+ return res.json() as Promise<LimitOrderConfigResponse>;
595
+ }
480
596
 
481
597
  /**
482
598
  * Fetch summary statistics for all limit orders.
@@ -1,8 +1,9 @@
1
1
  export {
2
2
  ROBINHOOD_NETWORK,
3
3
  ROBINHOOD_CHAIN,
4
- ROBINHOOD_NATIVE_ETH,
5
- ROBINHOOD_SWITCH_CONTRACTS,
4
+ ROBINHOOD_NATIVE_ETH,
5
+ ROBINHOOD_LIMIT_ORDER_EIP712_DOMAIN,
6
+ ROBINHOOD_SWITCH_CONTRACTS,
6
7
  ROBINHOOD_UNISWAP_CONTRACTS,
7
8
  ROBINHOOD_TOKENS,
8
9
  ROBINHOOD_FRONTEND_TOKEN_LIST,