@switch-win/sdk 1.1.0 → 1.2.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.
- package/README.md +80 -41
- package/ROBINHOOD.md +530 -0
- package/package.json +7 -3
- package/src/index.ts +26 -4
- package/src/networks/index.ts +20 -0
- package/src/networks/robinhood.ts +312 -0
- package/src/types.ts +2 -2
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@switch-win/sdk)
|
|
4
4
|
[](https://www.npmjs.com/package/@switch-win/sdk)
|
|
5
5
|
|
|
6
|
-
> **Official integration kit for the Switch DEX Aggregator on PulseChain**
|
|
6
|
+
> **Official integration kit for the Switch DEX Aggregator on PulseChain and Robinhood Chain**
|
|
7
7
|
|
|
8
8
|
Everything partners need to integrate Switch swaps and limit orders — API docs, TypeScript types, ABIs, constants, and ready-to-use examples.
|
|
9
9
|
|
|
10
|
-
**Swap API:** `https://quote.switch.win` | **
|
|
10
|
+
**Swap API:** `https://quote.switch.win` | **Swap chains:** PulseChain (369), Robinhood Chain (4663) | **Limit orders:** PulseChain
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -20,7 +20,9 @@ Switch-SDK/
|
|
|
20
20
|
├── src/
|
|
21
21
|
│ ├── index.ts # Main entry — re-exports everything
|
|
22
22
|
│ ├── types.ts # TypeScript types (swap + limit orders)
|
|
23
|
-
│ ├── constants.ts #
|
|
23
|
+
│ ├── constants.ts # PulseChain addresses, ABIs, EIP-712, PLSFlow config
|
|
24
|
+
│ ├── networks/
|
|
25
|
+
│ │ └── robinhood.ts # Robinhood metadata, contracts, tokens, quote URL helper
|
|
24
26
|
│ └── limit-orders.ts # Limit order helpers (build, sign, submit, query, PLSFlow)
|
|
25
27
|
├── abi/
|
|
26
28
|
│ ├── SwitchRouterABI.json # Full SwitchRouter contract ABI
|
|
@@ -40,25 +42,26 @@ Switch-SDK/
|
|
|
40
42
|
|
|
41
43
|
0. [Installation](#installation)
|
|
42
44
|
|
|
43
|
-
### Swaps
|
|
44
|
-
|
|
45
|
-
1. [Quickstart](#quickstart)
|
|
46
|
-
2. [
|
|
47
|
-
3. [
|
|
48
|
-
4. [Swap
|
|
49
|
-
5. [
|
|
50
|
-
6. [
|
|
45
|
+
### Swaps
|
|
46
|
+
|
|
47
|
+
1. [Quickstart](#quickstart)
|
|
48
|
+
2. [Robinhood Chain](#robinhood-chain)
|
|
49
|
+
3. [Authentication](#authentication)
|
|
50
|
+
4. [Swap Integration Flow](#swap-integration-flow)
|
|
51
|
+
5. [Swap API Reference](#swap-api-reference)
|
|
52
|
+
6. [Error Handling](#error-handling)
|
|
53
|
+
7. [Partner Fee Sharing](#partner-fee-sharing)
|
|
51
54
|
|
|
52
55
|
### Limit Orders
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
8. [Limit Orders](#limit-orders) — full guide in [`LIMIT-ORDERS.md`](LIMIT-ORDERS.md)
|
|
55
58
|
|
|
56
59
|
### General
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
9. [Constants & Addresses](#constants--addresses)
|
|
62
|
+
10. [Full Integration Examples](#full-integration-examples)
|
|
63
|
+
11. [Rate Limits](#rate-limits)
|
|
64
|
+
12. [Support](#support)
|
|
62
65
|
|
|
63
66
|
---
|
|
64
67
|
|
|
@@ -83,7 +86,7 @@ Get a swap quote and execute it in **three steps**:
|
|
|
83
86
|
curl -H "x-api-key: YOUR_KEY" \
|
|
84
87
|
"https://quote.switch.win/swap/quote?network=pulsechain&from=0xA1077a294dDE1B09bB078844df40758a5D0f9a27&to=0x95B303987A60C71504D99Aa1b13B4DA07b0790ab&amount=1000000000000000000&sender=0xYOUR_WALLET&slippage=100"
|
|
85
88
|
|
|
86
|
-
# 2. Approve the SwitchRouter to spend your input token (ERC-20 only
|
|
89
|
+
# 2. Approve the SwitchRouter to spend your input token (ERC-20 only; skip for native currency)
|
|
87
90
|
|
|
88
91
|
# 3. Send the transaction using the `tx` object from the response:
|
|
89
92
|
# { to: "0x0305...", data: "0x...", value: "0" }
|
|
@@ -103,7 +106,7 @@ const res = await fetch(
|
|
|
103
106
|
);
|
|
104
107
|
const quote: BestPathResponse = await res.json();
|
|
105
108
|
|
|
106
|
-
// 2. Approve SwitchRouter (ERC-20 only — skip for native
|
|
109
|
+
// 2. Approve SwitchRouter (ERC-20 only — skip for native currency)
|
|
107
110
|
const token = new ethers.Contract(fromToken, ["function approve(address,uint256)"], signer);
|
|
108
111
|
await (await token.approve(SWITCH_ROUTER, amount)).wait();
|
|
109
112
|
|
|
@@ -113,7 +116,40 @@ await signer.sendTransaction(quote.tx);
|
|
|
113
116
|
|
|
114
117
|
> **⚠️ Always use `tx.to` from the quote response** when sending swap transactions. Do NOT hardcode the router address — the contract may be redeployed.
|
|
115
118
|
|
|
116
|
-
For a production integration with tax token handling, adapter filtering, and fee mode selection, see [Swap Integration Flow](#swap-integration-flow) and the [full examples](examples/).
|
|
119
|
+
For a production integration with tax token handling, adapter filtering, and fee mode selection, see [Swap Integration Flow](#swap-integration-flow) and the [full examples](examples/).
|
|
120
|
+
|
|
121
|
+
### Robinhood Chain
|
|
122
|
+
|
|
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.
|
|
126
|
+
|
|
127
|
+
For network configuration, deployed addresses, tax handling, execution, and
|
|
128
|
+
the complete frontend token list, see [`ROBINHOOD.md`](ROBINHOOD.md).
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import {
|
|
132
|
+
ROBINHOOD_NATIVE_ETH,
|
|
133
|
+
ROBINHOOD_TOKENS,
|
|
134
|
+
buildRobinhoodQuoteUrl,
|
|
135
|
+
} from "@switch-win/sdk/networks/robinhood";
|
|
136
|
+
|
|
137
|
+
const url = buildRobinhoodQuoteUrl({
|
|
138
|
+
from: ROBINHOOD_NATIVE_ETH,
|
|
139
|
+
to: ROBINHOOD_TOKENS.USDG.address,
|
|
140
|
+
amount: 1_000_000_000_000_000n,
|
|
141
|
+
sender: walletAddress,
|
|
142
|
+
slippage: 50,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const response = await fetch(url, {
|
|
146
|
+
headers: { "x-api-key": process.env.SWITCH_API_KEY! },
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Always approve `ROBINHOOD_SWITCH_CONTRACTS.router` for ERC-20 input, but submit
|
|
151
|
+
the transaction to `quote.tx.to` so integrations remain safe across router
|
|
152
|
+
upgrades. Limit-order helpers in this package remain PulseChain-only.
|
|
117
153
|
|
|
118
154
|
---
|
|
119
155
|
|
|
@@ -214,9 +250,8 @@ function determineFeeOnOutput(
|
|
|
214
250
|
const isSellTax = fromTax.isTaxToken && fromTax.sellTaxBps > 0;
|
|
215
251
|
const isBuyTax = toTax.isTaxToken && toTax.buyTaxBps > 0;
|
|
216
252
|
|
|
217
|
-
// Both tokens are
|
|
218
|
-
|
|
219
|
-
if (isSellTax && isBuyTax) return false;
|
|
253
|
+
// Both tokens are taxed — use fee on input to avoid extra output transfers.
|
|
254
|
+
if (isSellTax && isBuyTax) return false;
|
|
220
255
|
|
|
221
256
|
// Only output token is tax — fee on input (avoids router holding output tokens)
|
|
222
257
|
if (isBuyTax) return false;
|
|
@@ -255,15 +290,15 @@ Fee portion: Router ──transfer──▶ FeeClaimer (3rd buy tax on fee amoun
|
|
|
255
290
|
```
|
|
256
291
|
The output token is transferred **three times** through different addresses, each incurring a buy tax. The user receives significantly less than expected.
|
|
257
292
|
|
|
258
|
-
**Bottom line:** When the output token has a buy tax, always use `feeOnOutput=false` so the router routes output directly to the user in a single transfer. This applies to both regular swaps and limit orders.
|
|
259
|
-
|
|
260
|
-
### Executing the Swap
|
|
293
|
+
**Bottom line:** When the output token has a buy tax, always use `feeOnOutput=false` so the router routes output directly to the user in a single transfer. This applies to both regular swaps and limit orders.
|
|
294
|
+
|
|
295
|
+
### Executing the Swap
|
|
261
296
|
|
|
262
297
|
Once you have a quote, execute it in two steps:
|
|
263
298
|
|
|
264
299
|
#### Step 1 — Approve Token Spend (ERC-20 inputs only)
|
|
265
300
|
|
|
266
|
-
If the input token is an **ERC-20**
|
|
301
|
+
If the input token is an **ERC-20** rather than the chain's native currency, the user must approve the network's SwitchRouter contract to spend `amount` tokens before submitting the swap.
|
|
267
302
|
|
|
268
303
|
Before sending an approval transaction, check whether the user already has sufficient allowance to avoid wasting gas on a redundant approve:
|
|
269
304
|
|
|
@@ -291,7 +326,7 @@ const { tx } = quoteResponse;
|
|
|
291
326
|
const txResponse = await signer.sendTransaction({
|
|
292
327
|
to: tx.to,
|
|
293
328
|
data: tx.data,
|
|
294
|
-
value: tx.value, // "0" for ERC-20 inputs, amountIn for native
|
|
329
|
+
value: tx.value, // "0" for ERC-20 inputs, amountIn for native currency
|
|
295
330
|
});
|
|
296
331
|
|
|
297
332
|
const receipt = await txResponse.wait();
|
|
@@ -351,7 +386,7 @@ Returns all available DEX adapters with their on-chain indices and contract addr
|
|
|
351
386
|
|
|
352
387
|
| Param | Required | Type | Description |
|
|
353
388
|
|---|---|---|---|
|
|
354
|
-
| `network` | **Yes** | string | Target blockchain network
|
|
389
|
+
| `network` | **Yes** | string | Target blockchain network: `"pulsechain"` or `"robinhood"`. |
|
|
355
390
|
|
|
356
391
|
#### Authentication
|
|
357
392
|
|
|
@@ -420,7 +455,7 @@ Detects whether a token has a fee-on-transfer mechanism (tax token) and returns
|
|
|
420
455
|
| Parameter | Required | Type | Description |
|
|
421
456
|
|---|---|---|---|
|
|
422
457
|
| `token` | **Yes** | address | Token address to check (0x + 40 hex chars) |
|
|
423
|
-
| `network` | No | string | Target blockchain
|
|
458
|
+
| `network` | No | string | Target blockchain: `"pulsechain"` or `"robinhood"`. |
|
|
424
459
|
|
|
425
460
|
#### Latency
|
|
426
461
|
|
|
@@ -534,9 +569,9 @@ Returns the optimal split-route for a swap and (optionally) a ready-to-send tran
|
|
|
534
569
|
|
|
535
570
|
| Parameter | Required | Type | Default | Description |
|
|
536
571
|
|---|---|---|---|---|
|
|
537
|
-
| `network` | **Yes** | string | — | Target blockchain network
|
|
538
|
-
| `from` | **Yes** | address | — | Input token address. Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for native PLS. |
|
|
539
|
-
| `to` | **Yes** | address | — | Output token address. Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for native PLS. |
|
|
572
|
+
| `network` | **Yes** | string | — | Target blockchain network: `"pulsechain"` or `"robinhood"`. |
|
|
573
|
+
| `from` | **Yes** | address | — | Input token address. Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for the network's native currency (PLS or ETH). |
|
|
574
|
+
| `to` | **Yes** | address | — | Output token address. Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for the network's native currency (PLS or ETH). |
|
|
540
575
|
| `amount` | **Yes** | string | — | Input amount in **wei** (raw integer string, no decimals). Max: 10²⁷. |
|
|
541
576
|
| `sender` | No* | address | — | Sender wallet address. **Required to receive `tx` calldata in the response.** |
|
|
542
577
|
| `receiver` | No | address | `sender` | Custom recipient address. If omitted, output tokens are sent to `sender`. |
|
|
@@ -625,7 +660,7 @@ GET /swap/quote?network=pulsechain&from=0xA1077a294dDE1B09bB078844df40758a5D0f9a
|
|
|
625
660
|
"tx": {
|
|
626
661
|
"to": "0x0305fcb5dA680EA6fd1B01A96C1949175B99d406",
|
|
627
662
|
"data": "0x...", // ABI-encoded goSwitch() calldata with feeOnOutput = false
|
|
628
|
-
"value": "0" // "0" for ERC-20 input; amountIn for native
|
|
663
|
+
"value": "0" // "0" for ERC-20 input; amountIn for native-currency input
|
|
629
664
|
},
|
|
630
665
|
// Same swap but with fee taken from the output token instead
|
|
631
666
|
"txFeeOnOutput": {
|
|
@@ -763,7 +798,7 @@ Errors are returned as JSON with an `error` field:
|
|
|
763
798
|
| Error | Cause |
|
|
764
799
|
|---|---|
|
|
765
800
|
| `"Missing required parameter: network"` | `network` query param absent |
|
|
766
|
-
| `"This network is not supported at this time."` | `network` is not `"pulsechain"` |
|
|
801
|
+
| `"This network is not supported at this time."` | `network` is not a supported value (`"pulsechain"` or `"robinhood"`) |
|
|
767
802
|
| `"Missing required parameters: from, to, amount"` | One or more required query params absent |
|
|
768
803
|
| `"Invalid from address (must be 0x + 40 hex chars)"` | `from` is not a valid hex address |
|
|
769
804
|
| `"Invalid to address (must be 0x + 40 hex chars)"` | `to` is not a valid hex address |
|
|
@@ -793,7 +828,7 @@ If the swap transaction reverts on-chain, the SwitchRouter contract returns one
|
|
|
793
828
|
| `FinalAmountOutTooLow()` | Output after fees fell below `_minTotalAmountOut` — price moved beyond your slippage tolerance. Retry with a fresh quote or increase slippage. |
|
|
794
829
|
| `ExcessiveFee()` | `_fee` exceeds the contract maximum (100 bps / 1 %). |
|
|
795
830
|
| `InsufficientFee()` | `_fee` is below the protocol's `MIN_FEE`. Contact the Switch team if you need a lower fee. |
|
|
796
|
-
| `MsgValueMismatch()` | For native
|
|
831
|
+
| `MsgValueMismatch()` | For native-currency swaps, `msg.value` must exactly equal the route's total `amountIn`. |
|
|
797
832
|
| `ZeroInput()` | No input amount was provided. |
|
|
798
833
|
|
|
799
834
|
---
|
|
@@ -846,10 +881,11 @@ function shouldFeeOnOutput(from: string, to: string, quote?: BestPathResponse):
|
|
|
846
881
|
if (toAddr === MY_PROJECT_TOKEN) return false; // fee on input = collect input
|
|
847
882
|
|
|
848
883
|
// Priority 2: Avoid collecting tax tokens (fee revenue lost to transfer tax)
|
|
849
|
-
if (quote) {
|
|
850
|
-
const fromIsTax = quote.fromTokenTax?.isTaxToken ?? false;
|
|
851
|
-
const toIsTax = quote.toTokenTax?.isTaxToken ?? false;
|
|
852
|
-
if (fromIsTax &&
|
|
884
|
+
if (quote) {
|
|
885
|
+
const fromIsTax = quote.fromTokenTax?.isTaxToken ?? false;
|
|
886
|
+
const toIsTax = quote.toTokenTax?.isTaxToken ?? false;
|
|
887
|
+
if (fromIsTax && toIsTax) return false;
|
|
888
|
+
if (fromIsTax && !toIsTax) return true; // collect non-tax output
|
|
853
889
|
if (toIsTax && !fromIsTax) return false; // collect non-tax input
|
|
854
890
|
}
|
|
855
891
|
|
|
@@ -890,13 +926,16 @@ Covers: creating orders, approvals, `feeOnOutput` decision guide (tax tokens & o
|
|
|
890
926
|
|
|
891
927
|
## Constants & Addresses
|
|
892
928
|
|
|
893
|
-
|
|
929
|
+
PulseChain constants are importable from [`src/constants.ts`](src/constants.ts).
|
|
930
|
+
Robinhood constants are available from
|
|
931
|
+
[`src/networks/robinhood.ts`](src/networks/robinhood.ts); see the complete
|
|
932
|
+
[`ROBINHOOD.md`](ROBINHOOD.md) integration reference.
|
|
894
933
|
|
|
895
934
|
> **⚠️ Do not hardcode the SwitchRouter address.** The router contract may be redeployed from time to time. Always use the `tx.to` (or `txFeeOnOutput.to`) address returned by the `/bestPath` API response when building your transaction. This ensures your integration automatically picks up router upgrades without code changes.
|
|
896
935
|
|
|
897
936
|
| Name | Value |
|
|
898
937
|
|---|---|
|
|
899
|
-
| **Chain** | PulseChain (Chain ID `369`) |
|
|
938
|
+
| **Chain** | PulseChain (Chain ID `369`); Robinhood Chain uses ID `4663` and network-specific exports |
|
|
900
939
|
| **SwitchRouter** | `0x0305fcb5dA680EA6fd1B01A96C1949175B99d406` |
|
|
901
940
|
| **SwitchLimitOrder** (V2 — current) | `0x8e3881bdF81Fc0211383B2e576076B654F7aFD86` |
|
|
902
941
|
| **SwitchLimitOrder** (V1 — legacy) | `0x0e884072a891b406C0D814907A1E2310fE5F5Deb` |
|
package/ROBINHOOD.md
ADDED
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
# Switch SDK — Robinhood Chain
|
|
2
|
+
|
|
3
|
+
Production integration reference for Switch swaps on Robinhood Chain mainnet.
|
|
4
|
+
|
|
5
|
+
| Setting | Value |
|
|
6
|
+
|---|---|
|
|
7
|
+
| API network | `robinhood` |
|
|
8
|
+
| Chain ID | `4663` |
|
|
9
|
+
| Native currency | ETH (18 decimals) |
|
|
10
|
+
| Public RPC | `https://rpc.mainnet.chain.robinhood.com` |
|
|
11
|
+
| Explorer | `https://robinhoodchain.blockscout.com` |
|
|
12
|
+
| Quote API | `https://quote.switch.win/swap/quote` |
|
|
13
|
+
| Tax API | `https://quote.switch.win/swap/checkTax` |
|
|
14
|
+
| Supported liquidity | Uniswap V2 and Uniswap V3 |
|
|
15
|
+
| Limit orders | Not currently available |
|
|
16
|
+
|
|
17
|
+
## Contents
|
|
18
|
+
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Authentication](#authentication)
|
|
21
|
+
- [Network configuration](#network-configuration)
|
|
22
|
+
- [Contracts and native currency](#contracts-and-native-currency)
|
|
23
|
+
- [Swap integration flow](#swap-integration-flow)
|
|
24
|
+
- [Quickstart](#quickstart)
|
|
25
|
+
- [Tax-token checks](#tax-token-checks)
|
|
26
|
+
- [Selecting `feeOnOutput`](#selecting-feeonoutput)
|
|
27
|
+
- [Approving and executing](#approving-and-executing)
|
|
28
|
+
- [Swap API reference](#swap-api-reference)
|
|
29
|
+
- [Error handling](#error-handling)
|
|
30
|
+
- [Partner fee sharing](#partner-fee-sharing)
|
|
31
|
+
- [Tokens and routing](#tokens-and-routing)
|
|
32
|
+
- [Rate limits](#rate-limits)
|
|
33
|
+
- [Current limitations](#current-limitations)
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install @switch-win/sdk
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import {
|
|
43
|
+
ROBINHOOD_CHAIN,
|
|
44
|
+
ROBINHOOD_NATIVE_ETH,
|
|
45
|
+
ROBINHOOD_SWITCH_CONTRACTS,
|
|
46
|
+
ROBINHOOD_TOKENS,
|
|
47
|
+
ROBINHOOD_FEE_TOKEN_PRIORITY,
|
|
48
|
+
ROBINHOOD_FRONTEND_DEFAULT_TOKENS,
|
|
49
|
+
ROBINHOOD_FRONTEND_TOKEN_LIST,
|
|
50
|
+
buildRobinhoodQuoteUrl,
|
|
51
|
+
type BestPathResponse,
|
|
52
|
+
} from "@switch-win/sdk";
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The same exports are available from the smaller network entrypoint:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import {
|
|
59
|
+
ROBINHOOD_CHAIN,
|
|
60
|
+
ROBINHOOD_TOKENS,
|
|
61
|
+
buildRobinhoodQuoteUrl,
|
|
62
|
+
} from "@switch-win/sdk/networks/robinhood";
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Authentication
|
|
66
|
+
|
|
67
|
+
Every request to `quote.switch.win` requires a Switch API key in the
|
|
68
|
+
`x-api-key` header:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const headers = {
|
|
72
|
+
"x-api-key": process.env.SWITCH_API_KEY!,
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Do not expose a production API key in browser JavaScript. Browser applications
|
|
77
|
+
should call a same-origin server route that attaches the key before forwarding
|
|
78
|
+
the request to Switch.
|
|
79
|
+
|
|
80
|
+
## Network configuration
|
|
81
|
+
|
|
82
|
+
`ROBINHOOD_CHAIN` can be adapted directly for most wallet libraries:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const robinhoodWalletChain = {
|
|
86
|
+
chainId: `0x${ROBINHOOD_CHAIN.id.toString(16)}`,
|
|
87
|
+
chainName: ROBINHOOD_CHAIN.name,
|
|
88
|
+
nativeCurrency: ROBINHOOD_CHAIN.nativeCurrency,
|
|
89
|
+
rpcUrls: [...ROBINHOOD_CHAIN.rpcUrls],
|
|
90
|
+
blockExplorerUrls: [ROBINHOOD_CHAIN.blockExplorerUrl],
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
await window.ethereum.request({
|
|
94
|
+
method: "wallet_addEthereumChain",
|
|
95
|
+
params: [robinhoodWalletChain],
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Contracts and native currency
|
|
100
|
+
|
|
101
|
+
### Switch deployment
|
|
102
|
+
|
|
103
|
+
| Contract | Address |
|
|
104
|
+
|---|---|
|
|
105
|
+
| SwitchRouter | `0x8730C3e2cF2c8CDa8E6166837A1Ed26f46aa9E59` |
|
|
106
|
+
| SwitchRouterView | `0xFF6b56d3F444eB5b7FA1db047F57140C84810376` |
|
|
107
|
+
| Uniswap V2 adapter | `0x7a14d7A8509a66209D4332843b983b29bF5604A4` |
|
|
108
|
+
| Uniswap V3 adapter | `0xbcA08f296d9Ba0dc19Aa0E05D355365cE29A3205` |
|
|
109
|
+
|
|
110
|
+
The router constant is the ERC-20 approval target. Always submit the swap to
|
|
111
|
+
`quote.tx.to`; do not replace the API-provided transaction target with a
|
|
112
|
+
hardcoded address.
|
|
113
|
+
|
|
114
|
+
### Native ETH and WETH
|
|
115
|
+
|
|
116
|
+
Use `ROBINHOOD_NATIVE_ETH` when the user is selling or buying native ETH:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use `ROBINHOOD_TOKENS.WETH.address` for the wrapped ERC-20:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Native ETH does not require approval. WETH and every other ERC-20 input token
|
|
129
|
+
must be approved for `ROBINHOOD_SWITCH_CONTRACTS.router`.
|
|
130
|
+
|
|
131
|
+
## Swap integration flow
|
|
132
|
+
|
|
133
|
+
Use the same sequence as a PulseChain integration:
|
|
134
|
+
|
|
135
|
+
1. Check both tokens with `/swap/checkTax`.
|
|
136
|
+
2. Select `feeOnOutput` from the tax results and preferred fee-token order.
|
|
137
|
+
3. Request `/swap/quote` with `network=robinhood`, the selected fee mode, and
|
|
138
|
+
`sender` when executable calldata is required.
|
|
139
|
+
4. Approve the API-provided router target for ERC-20 input tokens.
|
|
140
|
+
5. Submit `quote.tx` for fee-on-input or `quote.txFeeOnOutput` for
|
|
141
|
+
fee-on-output.
|
|
142
|
+
6. Show `expectedOutputAmount`, `minAmountOut`, route allocation, and detected
|
|
143
|
+
taxes to the user.
|
|
144
|
+
|
|
145
|
+
Any swap involving a tax token is routed entirely through Uniswap V2. This
|
|
146
|
+
also applies when both input and output are tax tokens.
|
|
147
|
+
|
|
148
|
+
## Quickstart
|
|
149
|
+
|
|
150
|
+
`amount` is always a raw integer amount in the input token's smallest unit.
|
|
151
|
+
The following requests a quote for `0.001 ETH -> USDG`:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// This simple pair uses fee-on-input. See "Selecting feeOnOutput" below for
|
|
155
|
+
// the recommended dynamic selection when community or tax tokens are involved.
|
|
156
|
+
const feeOnOutput = false;
|
|
157
|
+
|
|
158
|
+
const url = buildRobinhoodQuoteUrl({
|
|
159
|
+
from: ROBINHOOD_NATIVE_ETH,
|
|
160
|
+
to: ROBINHOOD_TOKENS.USDG.address,
|
|
161
|
+
amount: 1_000_000_000_000_000n,
|
|
162
|
+
sender: walletAddress,
|
|
163
|
+
slippage: 50, // 0.50%, expressed in basis points
|
|
164
|
+
feeOnOutput,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const response = await fetch(url, {
|
|
168
|
+
headers: { "x-api-key": process.env.SWITCH_API_KEY! },
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
if (!response.ok) {
|
|
172
|
+
throw new Error(`Switch quote failed: ${response.status}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const quote = (await response.json()) as BestPathResponse;
|
|
176
|
+
const transaction = feeOnOutput ? quote.txFeeOnOutput : quote.tx;
|
|
177
|
+
|
|
178
|
+
if (!transaction) {
|
|
179
|
+
throw new Error("Quote did not include the selected transaction variant");
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Equivalent curl request:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
curl -H "x-api-key: YOUR_KEY" \
|
|
187
|
+
"https://quote.switch.win/swap/quote?network=robinhood&from=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&to=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&amount=1000000000000000&sender=0xYOUR_WALLET&slippage=50"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Omit `sender` for a display-only quote. Fetch again with the sender immediately
|
|
191
|
+
before execution to receive current transaction calldata.
|
|
192
|
+
|
|
193
|
+
## Tax-token checks
|
|
194
|
+
|
|
195
|
+
Robinhood tokens can apply pair-specific transfer taxes. Check both input and
|
|
196
|
+
output tokens before requesting or executing a swap:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
async function checkTax(token: string) {
|
|
200
|
+
const query = new URLSearchParams({ network: "robinhood", token });
|
|
201
|
+
const response = await fetch(
|
|
202
|
+
`https://quote.switch.win/swap/checkTax?${query}`,
|
|
203
|
+
{ headers: { "x-api-key": process.env.SWITCH_API_KEY! } },
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
if (!response.ok) throw new Error(`Tax check failed: ${response.status}`);
|
|
207
|
+
return response.json();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const [inputTax, outputTax] = await Promise.all([
|
|
211
|
+
checkTax(tokenIn),
|
|
212
|
+
checkTax(tokenOut),
|
|
213
|
+
]);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The quote response also includes `fromTokenTax`, `toTokenTax`,
|
|
217
|
+
`expectedOutputAmount`, and effective-slippage fields. Display these values to
|
|
218
|
+
the user rather than estimating taxes locally.
|
|
219
|
+
|
|
220
|
+
## Selecting `feeOnOutput`
|
|
221
|
+
|
|
222
|
+
`feeOnOutput` determines which side of the swap pays the Switch partner or
|
|
223
|
+
protocol fee:
|
|
224
|
+
|
|
225
|
+
| Value | Fee token | Transaction field |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| `false` | Input token | `quote.tx` |
|
|
228
|
+
| `true` | Output token | `quote.txFeeOnOutput` |
|
|
229
|
+
|
|
230
|
+
Choose the mode before requesting the executable quote and pass it to
|
|
231
|
+
`buildRobinhoodQuoteUrl`. This keeps `expectedOutputAmount`, routing, and the
|
|
232
|
+
transaction calldata aligned with the mode that will actually be submitted.
|
|
233
|
+
|
|
234
|
+
For Robinhood Chain, the recommended selection order is:
|
|
235
|
+
|
|
236
|
+
1. If both sides are tax tokens, use fee-on-input (`false`) to avoid the extra
|
|
237
|
+
output-token transfers required by fee-on-output.
|
|
238
|
+
2. If only the output token has buy tax, use fee-on-input (`false`) to avoid
|
|
239
|
+
routing the taxed output through additional transfers.
|
|
240
|
+
3. If only the input token has sell tax, use fee-on-output (`true`) so the fee
|
|
241
|
+
is collected in the non-tax output token.
|
|
242
|
+
4. Otherwise, prefer collecting tokens in this order: WETH (with native ETH
|
|
243
|
+
treated equivalently), USDG, WALLET, SEEDCOIN, then CASHCAT.
|
|
244
|
+
5. If neither token is preferred, default to fee-on-input (`false`).
|
|
245
|
+
|
|
246
|
+
The no-tax priority list is:
|
|
247
|
+
|
|
248
|
+
| Priority | Token | Address |
|
|
249
|
+
|---:|---|---|
|
|
250
|
+
| 1 | WETH / native ETH | `0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73` / native sentinel |
|
|
251
|
+
| 2 | USDG | `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` |
|
|
252
|
+
| 3 | WALLET | `0x0339f5459FC690aC85F1782e15782A151b4A9E1b` |
|
|
253
|
+
| 4 | SEEDCOIN | `0x58f693A30F124E59b125F7c7b837b0F6bbAF5a45` |
|
|
254
|
+
| 5 | CASHCAT | `0x020bfC650A365f8BB26819deAAbF3E21291018b4` |
|
|
255
|
+
|
|
256
|
+
The ordered ERC-20 addresses are exported as
|
|
257
|
+
`ROBINHOOD_FEE_TOKEN_PRIORITY`. When neither side is taxed, the selector takes
|
|
258
|
+
the fee from whichever side contains the higher-priority token. If neither
|
|
259
|
+
side is listed, it defaults to fee-on-input.
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import {
|
|
263
|
+
buildRobinhoodQuoteUrl,
|
|
264
|
+
selectRobinhoodFeeOnOutput,
|
|
265
|
+
type BestPathResponse,
|
|
266
|
+
} from "@switch-win/sdk";
|
|
267
|
+
|
|
268
|
+
const feeOnOutput = selectRobinhoodFeeOnOutput(
|
|
269
|
+
tokenIn,
|
|
270
|
+
tokenOut,
|
|
271
|
+
inputTax,
|
|
272
|
+
outputTax,
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const quoteUrl = buildRobinhoodQuoteUrl({
|
|
276
|
+
from: tokenIn,
|
|
277
|
+
to: tokenOut,
|
|
278
|
+
amount: amountIn,
|
|
279
|
+
sender: walletAddress,
|
|
280
|
+
slippage: 50,
|
|
281
|
+
feeOnOutput,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const quoteResponse = await fetch(quoteUrl, {
|
|
285
|
+
headers: { "x-api-key": process.env.SWITCH_API_KEY! },
|
|
286
|
+
});
|
|
287
|
+
if (!quoteResponse.ok) {
|
|
288
|
+
throw new Error(`Switch quote failed: ${quoteResponse.status}`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const quote = (await quoteResponse.json()) as BestPathResponse;
|
|
292
|
+
const transaction = feeOnOutput ? quote.txFeeOnOutput : quote.tx;
|
|
293
|
+
if (!transaction) {
|
|
294
|
+
throw new Error("Quote did not include the selected transaction variant");
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Do not request one fee mode and submit the other transaction variant. Taxed
|
|
299
|
+
output tokens are especially important: `feeOnOutput=true` makes the router
|
|
300
|
+
receive and redistribute the output, which can trigger additional transfer-tax
|
|
301
|
+
events.
|
|
302
|
+
|
|
303
|
+
## Approving and executing
|
|
304
|
+
|
|
305
|
+
For ERC-20 input:
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
const token = new ethers.Contract(
|
|
309
|
+
tokenIn,
|
|
310
|
+
["function approve(address spender, uint256 amount) returns (bool)"],
|
|
311
|
+
signer,
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
await (
|
|
315
|
+
await token.approve(ROBINHOOD_SWITCH_CONTRACTS.router, amountIn)
|
|
316
|
+
).wait();
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Then submit the transaction returned by the API:
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
await signer.sendTransaction({
|
|
323
|
+
to: transaction.to,
|
|
324
|
+
data: transaction.data,
|
|
325
|
+
value: transaction.value,
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
For native ETH input, skip approval and send the API-provided `value`.
|
|
330
|
+
|
|
331
|
+
## Swap API reference
|
|
332
|
+
|
|
333
|
+
All amounts are raw integer strings in the token's smallest unit. All token and
|
|
334
|
+
wallet values are EVM addresses.
|
|
335
|
+
|
|
336
|
+
### List adapters
|
|
337
|
+
|
|
338
|
+
```http
|
|
339
|
+
GET https://quote.switch.win/swap/adapters?network=robinhood
|
|
340
|
+
x-api-key: YOUR_KEY
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Robinhood currently returns:
|
|
344
|
+
|
|
345
|
+
| Index | Adapter |
|
|
346
|
+
|---:|---|
|
|
347
|
+
| `0` | Uniswap V2 |
|
|
348
|
+
| `1` | Uniswap V3 |
|
|
349
|
+
|
|
350
|
+
Do not permanently hard-code the available adapter list in an integration.
|
|
351
|
+
Fetch it when presenting routing-source controls. If a quote involves a tax
|
|
352
|
+
token, the backend overrides routing to tax-safe adapter `0`; an explicit
|
|
353
|
+
filter that excludes adapter `0` is rejected.
|
|
354
|
+
|
|
355
|
+
### Check token tax
|
|
356
|
+
|
|
357
|
+
```http
|
|
358
|
+
GET https://quote.switch.win/swap/checkTax?network=robinhood&token=0xTOKEN
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Example response:
|
|
362
|
+
|
|
363
|
+
```json
|
|
364
|
+
{
|
|
365
|
+
"token": "0x...",
|
|
366
|
+
"isTaxToken": true,
|
|
367
|
+
"buyTaxBps": 500,
|
|
368
|
+
"sellTaxBps": 300
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
`500` basis points is `5%`. Use the input token's `sellTaxBps` and the output
|
|
373
|
+
token's `buyTaxBps`. When both tokens are taxed, use fee-on-input.
|
|
374
|
+
|
|
375
|
+
### Get swap quote
|
|
376
|
+
|
|
377
|
+
```http
|
|
378
|
+
GET https://quote.switch.win/swap/quote
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
| Query parameter | Required | Description |
|
|
382
|
+
|---|:---:|---|
|
|
383
|
+
| `network` | Yes | Must be `robinhood`. |
|
|
384
|
+
| `from` | Yes | Input token address or `ROBINHOOD_NATIVE_ETH`. |
|
|
385
|
+
| `to` | Yes | Output token address or `ROBINHOOD_NATIVE_ETH`. |
|
|
386
|
+
| `amount` | Yes | Raw input amount. |
|
|
387
|
+
| `sender` | No | Required when transaction calldata is needed. |
|
|
388
|
+
| `receiver` | No | Output recipient; defaults to `sender`. |
|
|
389
|
+
| `slippage` | No | Basis points; default `50` (`0.5%`). |
|
|
390
|
+
| `fee` | No | Partner/protocol fee in basis points. |
|
|
391
|
+
| `partnerAddress` | No | Fee-sharing recipient. |
|
|
392
|
+
| `feeOnOutput` | No | `true` takes the fee from output; `false` takes it from input. |
|
|
393
|
+
| `adapters` | No | Comma-separated adapter indices, such as `0,1`. |
|
|
394
|
+
| `gasPrice` | No | Quote gas price in wei. |
|
|
395
|
+
|
|
396
|
+
Omitting `sender` produces a display-only quote. Request a fresh executable
|
|
397
|
+
quote with `sender` immediately before execution.
|
|
398
|
+
|
|
399
|
+
### Quote response
|
|
400
|
+
|
|
401
|
+
Important response fields:
|
|
402
|
+
|
|
403
|
+
| Field | Description |
|
|
404
|
+
|---|---|
|
|
405
|
+
| `fromToken`, `toToken` | Normalized pair addresses. |
|
|
406
|
+
| `totalAmountIn` | Gross input amount. |
|
|
407
|
+
| `totalAmountOut` | Raw pool output before taxes and Switch fees. |
|
|
408
|
+
| `expectedOutputAmount` | Expected user receipt after tax and fee, before slippage. |
|
|
409
|
+
| `minAmountOut` | Minimum output encoded into calldata. |
|
|
410
|
+
| `paths` | Human-readable route descriptions. |
|
|
411
|
+
| `routeAllocation` | Structured split, hop, adapter, and fee-tier allocation. |
|
|
412
|
+
| `fromTokenTax`, `toTokenTax` | Detected tax metadata. |
|
|
413
|
+
| `effectiveSlippageBps` | Slippage plus applicable tax buffers. |
|
|
414
|
+
| `tx` | Fee-on-input transaction; present when `sender` is supplied. |
|
|
415
|
+
| `txFeeOnOutput` | Fee-on-output transaction; present when `sender` is supplied. |
|
|
416
|
+
|
|
417
|
+
Treat the response as authoritative. Do not recalculate output taxes, route
|
|
418
|
+
splits, minimum output, or calldata in the client.
|
|
419
|
+
|
|
420
|
+
## Error handling
|
|
421
|
+
|
|
422
|
+
The API can return an `{ "error": "..." }` object for validation or routing
|
|
423
|
+
failures. Check both the HTTP status and the response body before using quote
|
|
424
|
+
fields.
|
|
425
|
+
|
|
426
|
+
Common Robinhood errors include:
|
|
427
|
+
|
|
428
|
+
- Missing or unsupported `network`.
|
|
429
|
+
- Invalid token, sender, receiver, or partner address.
|
|
430
|
+
- Invalid raw amount, slippage, fee, gas price, or adapter filter.
|
|
431
|
+
- A tax-token quote explicitly excluded the Uniswap V2 adapter.
|
|
432
|
+
- No viable Uniswap V2/V3 route or insufficient liquidity.
|
|
433
|
+
- RPC timeout or public-RPC rate limiting.
|
|
434
|
+
- Missing executable transaction because `sender` was omitted.
|
|
435
|
+
|
|
436
|
+
On-chain reverts can still occur if allowance, wallet balance, slippage,
|
|
437
|
+
liquidity, token tax, or chain state changes after quoting. Fetch a fresh quote
|
|
438
|
+
before retrying rather than resubmitting stale calldata.
|
|
439
|
+
|
|
440
|
+
## Partner fee sharing
|
|
441
|
+
|
|
442
|
+
Pass `fee` in basis points and `partnerAddress` in the quote request. The chosen
|
|
443
|
+
fee mode determines the fee token:
|
|
444
|
+
|
|
445
|
+
- `feeOnOutput=false`: collect from the input token and submit `quote.tx`.
|
|
446
|
+
- `feeOnOutput=true`: collect from the output token and submit
|
|
447
|
+
`quote.txFeeOnOutput`.
|
|
448
|
+
|
|
449
|
+
Always pass `feeOnOutput` while quoting so routing and
|
|
450
|
+
`expectedOutputAmount` match the transaction variant you will execute. Partner
|
|
451
|
+
fee eligibility and revenue share are controlled by the API-key agreement; do
|
|
452
|
+
not assume that supplying an address alone enables sharing.
|
|
453
|
+
|
|
454
|
+
## Tokens and routing
|
|
455
|
+
|
|
456
|
+
### Curated frontend token list
|
|
457
|
+
|
|
458
|
+
The token dropdown contains the following ERC-20 tokens. Native ETH is merged
|
|
459
|
+
into the UI separately from this list.
|
|
460
|
+
|
|
461
|
+
| Symbol | Name | Address | Decimals |
|
|
462
|
+
|---|---|---|---:|
|
|
463
|
+
| WETH | Wrapped Ether | `0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73` | 18 |
|
|
464
|
+
| USDG | Global Dollar | `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` | 6 |
|
|
465
|
+
| VIRTUAL | Virtuals Protocol | `0xc6911796042b15d7Fa4F6CDe69e245DdCd3d9c31` | 18 |
|
|
466
|
+
| CASHCAT | Cash Cat | `0x020bfC650A365f8BB26819deAAbF3E21291018b4` | 18 |
|
|
467
|
+
| WALLET | Robinhood Wallet | `0x0339f5459FC690aC85F1782e15782A151b4A9E1b` | 18 |
|
|
468
|
+
| seedcoin | watch it grow | `0x58f693A30F124E59b125F7c7b837b0F6bbAF5a45` | 9 |
|
|
469
|
+
| JUGGERNAUT | The Juggernaut | `0xD7321801CAae694090694Ff55A9323139F043B88` | 18 |
|
|
470
|
+
| HOODRAT | Hoodrat | `0x8e62F281f282686fCa6dCB39288069a93fC23F1c` | 18 |
|
|
471
|
+
| DIH | Dog In Hood | `0x17bb0C898254406b1Ea2e8E99B0C263e26c9E4a4` | 18 |
|
|
472
|
+
| KITSU | KITSU | `0x8d4dFaaA4198b6486E0293Fec914C2B6a821D4DC` | 18 |
|
|
473
|
+
| WEN | Wen Lambo | `0xA80eb66b3E0CF66ccB46f8b8C9e7ff5803eEb820` | 18 |
|
|
474
|
+
| REPE | Robinhood Pepe | `0x5266eeafF092D6136AB63D18B975A60a0Cc0C8f7` | 18 |
|
|
475
|
+
| TENDIES | TENDIES | `0x45242320DBB855EeA8Fd36804C6487E10E97FCF9` | 18 |
|
|
476
|
+
| GME | GameStop | `0x7e86381A763F0Ecca2bDF27C54eAC403ddD48123` | 18 |
|
|
477
|
+
| 4663 | 4663 | `0xd4052415613B34Af236024B895574c467f65b6dD` | 18 |
|
|
478
|
+
| MARIAN | Lady Marian | `0x01637b14B7378B99dE75A64d50656d98488D9a4d` | 18 |
|
|
479
|
+
|
|
480
|
+
The ordered list is exported as `ROBINHOOD_FRONTEND_TOKEN_LIST`.
|
|
481
|
+
|
|
482
|
+
These community tokens are frontend conveniences, not an endorsement or a
|
|
483
|
+
guarantee of liquidity, price stability, tax behavior, or contract safety.
|
|
484
|
+
Always identify tokens by address and obtain a fresh quote and tax check.
|
|
485
|
+
|
|
486
|
+
### Routing configuration
|
|
487
|
+
|
|
488
|
+
Switch currently evaluates:
|
|
489
|
+
|
|
490
|
+
- Uniswap V2 adapter index `0`.
|
|
491
|
+
- Uniswap V3 adapter index `1`.
|
|
492
|
+
- V3 fee tiers `100`, `500`, `3000`, and `10000`.
|
|
493
|
+
- Trusted routing hubs WETH, USDG, VIRTUAL, and CASHCAT.
|
|
494
|
+
|
|
495
|
+
If either side is detected as a transfer-tax token, the backend restricts the
|
|
496
|
+
entire route (including every split and intermediate hop) to Uniswap V2. V3 is
|
|
497
|
+
not considered for that quote.
|
|
498
|
+
|
|
499
|
+
The API may split a quote across routes and adapters. Integrators should render
|
|
500
|
+
the returned `paths` or `routeAllocation` instead of assuming a single path.
|
|
501
|
+
|
|
502
|
+
## Rate limits
|
|
503
|
+
|
|
504
|
+
Rate limits are assigned to the API key. A `429` response means the integration
|
|
505
|
+
must back off. Use request coalescing and short-lived UI caching, avoid polling
|
|
506
|
+
unchanged quotes, and debounce amount input before requesting a new route.
|
|
507
|
+
|
|
508
|
+
For server integrations, contact Switch to coordinate the expected request
|
|
509
|
+
rate and IP allowlisting. Do not distribute one production key across
|
|
510
|
+
untrusted clients.
|
|
511
|
+
|
|
512
|
+
## Current limitations
|
|
513
|
+
|
|
514
|
+
- Robinhood limit orders are not deployed.
|
|
515
|
+
- Rialto DEX is not integrated.
|
|
516
|
+
- Quotes currently use Uniswap V2 and V3 liquidity.
|
|
517
|
+
- Contract and token addresses must be treated as chain-specific.
|
|
518
|
+
|
|
519
|
+
See the main [SDK reference](README.md) for authentication, partner fees,
|
|
520
|
+
response types, error handling, and the complete swap API schema.
|
|
521
|
+
|
|
522
|
+
## Support
|
|
523
|
+
|
|
524
|
+
- Documentation: <https://docs.switch.win>
|
|
525
|
+
- Website: <https://switch.win>
|
|
526
|
+
- Quote API: <https://quote.switch.win>
|
|
527
|
+
|
|
528
|
+
## License
|
|
529
|
+
|
|
530
|
+
See [LICENSE](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@switch-win/sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Official integration kit for the Switch DEX Aggregator on PulseChain
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Official integration kit for the Switch DEX Aggregator on PulseChain and Robinhood Chain",
|
|
5
5
|
"author": "BuildTheTech",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"dex",
|
|
14
14
|
"aggregator",
|
|
15
15
|
"pulsechain",
|
|
16
|
+
"robinhood-chain",
|
|
16
17
|
"swap",
|
|
17
18
|
"limit-order",
|
|
18
19
|
"eip712",
|
|
@@ -26,6 +27,8 @@
|
|
|
26
27
|
".": "./src/index.ts",
|
|
27
28
|
"./types": "./src/types.ts",
|
|
28
29
|
"./constants": "./src/constants.ts",
|
|
30
|
+
"./networks": "./src/networks/index.ts",
|
|
31
|
+
"./networks/robinhood": "./src/networks/robinhood.ts",
|
|
29
32
|
"./limit-orders": "./src/limit-orders.ts",
|
|
30
33
|
"./abi": "./abi/SwitchRouterABI.json",
|
|
31
34
|
"./abi/limit-order": "./abi/SwitchLimitOrderABI.json"
|
|
@@ -33,7 +36,8 @@
|
|
|
33
36
|
"files": [
|
|
34
37
|
"src/",
|
|
35
38
|
"abi/",
|
|
36
|
-
"README.md"
|
|
39
|
+
"README.md",
|
|
40
|
+
"ROBINHOOD.md"
|
|
37
41
|
],
|
|
38
42
|
"devDependencies": {
|
|
39
43
|
"typescript": "^5.9.3"
|
package/src/index.ts
CHANGED
|
@@ -109,7 +109,29 @@ export {
|
|
|
109
109
|
fetchLimitOrderStats,
|
|
110
110
|
} from "./limit-orders.js";
|
|
111
111
|
|
|
112
|
-
export type {
|
|
113
|
-
BuildLimitOrderOptions,
|
|
114
|
-
ListLimitOrdersOptions,
|
|
115
|
-
} from "./limit-orders.js";
|
|
112
|
+
export type {
|
|
113
|
+
BuildLimitOrderOptions,
|
|
114
|
+
ListLimitOrdersOptions,
|
|
115
|
+
} from "./limit-orders.js";
|
|
116
|
+
|
|
117
|
+
// Network-specific swap configuration
|
|
118
|
+
export {
|
|
119
|
+
ROBINHOOD_NETWORK,
|
|
120
|
+
ROBINHOOD_CHAIN,
|
|
121
|
+
ROBINHOOD_NATIVE_ETH,
|
|
122
|
+
ROBINHOOD_SWITCH_CONTRACTS,
|
|
123
|
+
ROBINHOOD_UNISWAP_CONTRACTS,
|
|
124
|
+
ROBINHOOD_TOKENS,
|
|
125
|
+
ROBINHOOD_FRONTEND_TOKEN_LIST,
|
|
126
|
+
ROBINHOOD_FRONTEND_DEFAULT_TOKENS,
|
|
127
|
+
ROBINHOOD_TRUSTED_INTERMEDIATES,
|
|
128
|
+
ROBINHOOD_FEE_TOKEN_PRIORITY,
|
|
129
|
+
selectRobinhoodFeeOnOutput,
|
|
130
|
+
buildRobinhoodQuoteUrl,
|
|
131
|
+
} from "./networks/robinhood.js";
|
|
132
|
+
|
|
133
|
+
export type {
|
|
134
|
+
RobinhoodToken,
|
|
135
|
+
RobinhoodQuoteParams,
|
|
136
|
+
RobinhoodTaxInfo,
|
|
137
|
+
} from "./networks/robinhood.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export {
|
|
2
|
+
ROBINHOOD_NETWORK,
|
|
3
|
+
ROBINHOOD_CHAIN,
|
|
4
|
+
ROBINHOOD_NATIVE_ETH,
|
|
5
|
+
ROBINHOOD_SWITCH_CONTRACTS,
|
|
6
|
+
ROBINHOOD_UNISWAP_CONTRACTS,
|
|
7
|
+
ROBINHOOD_TOKENS,
|
|
8
|
+
ROBINHOOD_FRONTEND_TOKEN_LIST,
|
|
9
|
+
ROBINHOOD_FRONTEND_DEFAULT_TOKENS,
|
|
10
|
+
ROBINHOOD_TRUSTED_INTERMEDIATES,
|
|
11
|
+
ROBINHOOD_FEE_TOKEN_PRIORITY,
|
|
12
|
+
selectRobinhoodFeeOnOutput,
|
|
13
|
+
buildRobinhoodQuoteUrl,
|
|
14
|
+
} from "./robinhood.js";
|
|
15
|
+
|
|
16
|
+
export type {
|
|
17
|
+
RobinhoodToken,
|
|
18
|
+
RobinhoodQuoteParams,
|
|
19
|
+
RobinhoodTaxInfo,
|
|
20
|
+
} from "./robinhood.js";
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { API_BASE } from "../constants.js";
|
|
2
|
+
|
|
3
|
+
/** API network value used by Switch endpoints. */
|
|
4
|
+
export const ROBINHOOD_NETWORK = "robinhood" as const;
|
|
5
|
+
|
|
6
|
+
/** Robinhood Chain mainnet metadata. */
|
|
7
|
+
export const ROBINHOOD_CHAIN = {
|
|
8
|
+
id: 4663,
|
|
9
|
+
name: "Robinhood Chain",
|
|
10
|
+
nativeCurrency: {
|
|
11
|
+
name: "Ether",
|
|
12
|
+
symbol: "ETH",
|
|
13
|
+
decimals: 18,
|
|
14
|
+
},
|
|
15
|
+
rpcUrls: ["https://rpc.mainnet.chain.robinhood.com"],
|
|
16
|
+
blockExplorerUrl: "https://robinhoodchain.blockscout.com",
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
/** Native-ETH sentinel accepted by the Switch quote API. */
|
|
20
|
+
export const ROBINHOOD_NATIVE_ETH =
|
|
21
|
+
"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
22
|
+
|
|
23
|
+
/** Switch contracts deployed on Robinhood Chain. */
|
|
24
|
+
export const ROBINHOOD_SWITCH_CONTRACTS = {
|
|
25
|
+
/** ERC-20 approval target. Use quote.tx.to when submitting a swap. */
|
|
26
|
+
router: "0x8730C3e2cF2c8CDa8E6166837A1Ed26f46aa9E59",
|
|
27
|
+
routerView: "0xFF6b56d3F444eB5b7FA1db047F57140C84810376",
|
|
28
|
+
uniswapV2Adapter: "0x7a14d7A8509a66209D4332843b983b29bF5604A4",
|
|
29
|
+
uniswapV3Adapter: "0xbcA08f296d9Ba0dc19Aa0E05D355365cE29A3205",
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
/** Uniswap contracts used by the Robinhood Switch deployment. */
|
|
33
|
+
export const ROBINHOOD_UNISWAP_CONTRACTS = {
|
|
34
|
+
v2Factory: "0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f",
|
|
35
|
+
v3Factory: "0x1f7d7550B1b028f7571E69A784071F0205FD2EfA",
|
|
36
|
+
v3QuoterV2: "0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7",
|
|
37
|
+
v3SwapRouter02: "0xCaf681a66D020601342297493863E78C959E5cb2",
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
export interface RobinhoodToken {
|
|
41
|
+
readonly address: string;
|
|
42
|
+
readonly symbol: string;
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly decimals: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Tokens in the Switch Robinhood frontend's curated list.
|
|
49
|
+
*
|
|
50
|
+
* Community-token addresses must never be selected by symbol alone; clones
|
|
51
|
+
* can share the same symbol. The addresses, symbols, and decimals below were
|
|
52
|
+
* checked against Robinhood Chain on 2026-07-11.
|
|
53
|
+
*/
|
|
54
|
+
export const ROBINHOOD_TOKENS = {
|
|
55
|
+
WETH: {
|
|
56
|
+
address: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
|
|
57
|
+
symbol: "WETH",
|
|
58
|
+
name: "Wrapped Ether",
|
|
59
|
+
decimals: 18,
|
|
60
|
+
},
|
|
61
|
+
USDG: {
|
|
62
|
+
address: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
|
|
63
|
+
symbol: "USDG",
|
|
64
|
+
name: "Global Dollar",
|
|
65
|
+
decimals: 6,
|
|
66
|
+
},
|
|
67
|
+
VIRTUAL: {
|
|
68
|
+
address: "0xc6911796042b15d7Fa4F6CDe69e245DdCd3d9c31",
|
|
69
|
+
symbol: "VIRTUAL",
|
|
70
|
+
name: "Virtuals Protocol",
|
|
71
|
+
decimals: 18,
|
|
72
|
+
},
|
|
73
|
+
CASHCAT: {
|
|
74
|
+
address: "0x020bfC650A365f8BB26819deAAbF3E21291018b4",
|
|
75
|
+
symbol: "CASHCAT",
|
|
76
|
+
name: "Cash Cat",
|
|
77
|
+
decimals: 18,
|
|
78
|
+
},
|
|
79
|
+
WALLET: {
|
|
80
|
+
address: "0x0339f5459FC690aC85F1782e15782A151b4A9E1b",
|
|
81
|
+
symbol: "WALLET",
|
|
82
|
+
name: "Robinhood Wallet",
|
|
83
|
+
decimals: 18,
|
|
84
|
+
},
|
|
85
|
+
SEEDCOIN: {
|
|
86
|
+
address: "0x58f693A30F124E59b125F7c7b837b0F6bbAF5a45",
|
|
87
|
+
symbol: "seedcoin",
|
|
88
|
+
name: "watch it grow",
|
|
89
|
+
decimals: 9,
|
|
90
|
+
},
|
|
91
|
+
JUGGERNAUT: {
|
|
92
|
+
address: "0xD7321801CAae694090694Ff55A9323139F043B88",
|
|
93
|
+
symbol: "JUGGERNAUT",
|
|
94
|
+
name: "The Juggernaut",
|
|
95
|
+
decimals: 18,
|
|
96
|
+
},
|
|
97
|
+
HOODRAT: {
|
|
98
|
+
address: "0x8e62F281f282686fCa6dCB39288069a93fC23F1c",
|
|
99
|
+
symbol: "HOODRAT",
|
|
100
|
+
name: "Hoodrat",
|
|
101
|
+
decimals: 18,
|
|
102
|
+
},
|
|
103
|
+
DIH: {
|
|
104
|
+
address: "0x17bb0C898254406b1Ea2e8E99B0C263e26c9E4a4",
|
|
105
|
+
symbol: "DIH",
|
|
106
|
+
name: "Dog In Hood",
|
|
107
|
+
decimals: 18,
|
|
108
|
+
},
|
|
109
|
+
KITSU: {
|
|
110
|
+
address: "0x8d4dFaaA4198b6486E0293Fec914C2B6a821D4DC",
|
|
111
|
+
symbol: "KITSU",
|
|
112
|
+
name: "KITSU",
|
|
113
|
+
decimals: 18,
|
|
114
|
+
},
|
|
115
|
+
WEN: {
|
|
116
|
+
address: "0xA80eb66b3E0CF66ccB46f8b8C9e7ff5803eEb820",
|
|
117
|
+
symbol: "WEN",
|
|
118
|
+
name: "Wen Lambo",
|
|
119
|
+
decimals: 18,
|
|
120
|
+
},
|
|
121
|
+
REPE: {
|
|
122
|
+
address: "0x5266eeafF092D6136AB63D18B975A60a0Cc0C8f7",
|
|
123
|
+
symbol: "REPE",
|
|
124
|
+
name: "Robinhood Pepe",
|
|
125
|
+
decimals: 18,
|
|
126
|
+
},
|
|
127
|
+
TENDIES: {
|
|
128
|
+
address: "0x45242320DBB855EeA8Fd36804C6487E10E97FCF9",
|
|
129
|
+
symbol: "TENDIES",
|
|
130
|
+
name: "TENDIES",
|
|
131
|
+
decimals: 18,
|
|
132
|
+
},
|
|
133
|
+
GME: {
|
|
134
|
+
address: "0x7e86381A763F0Ecca2bDF27C54eAC403ddD48123",
|
|
135
|
+
symbol: "GME",
|
|
136
|
+
name: "GameStop",
|
|
137
|
+
decimals: 18,
|
|
138
|
+
},
|
|
139
|
+
TOKEN_4663: {
|
|
140
|
+
address: "0xd4052415613B34Af236024B895574c467f65b6dD",
|
|
141
|
+
symbol: "4663",
|
|
142
|
+
name: "4663",
|
|
143
|
+
decimals: 18,
|
|
144
|
+
},
|
|
145
|
+
MARIAN: {
|
|
146
|
+
address: "0x01637b14B7378B99dE75A64d50656d98488D9a4d",
|
|
147
|
+
symbol: "MARIAN",
|
|
148
|
+
name: "Lady Marian",
|
|
149
|
+
decimals: 18,
|
|
150
|
+
},
|
|
151
|
+
} as const satisfies Readonly<Record<string, RobinhoodToken>>;
|
|
152
|
+
|
|
153
|
+
/** Exact ERC-20 ordering used by the Switch Robinhood token dropdown. */
|
|
154
|
+
export const ROBINHOOD_FRONTEND_TOKEN_LIST = [
|
|
155
|
+
ROBINHOOD_TOKENS.WETH,
|
|
156
|
+
ROBINHOOD_TOKENS.USDG,
|
|
157
|
+
ROBINHOOD_TOKENS.VIRTUAL,
|
|
158
|
+
ROBINHOOD_TOKENS.CASHCAT,
|
|
159
|
+
ROBINHOOD_TOKENS.WALLET,
|
|
160
|
+
ROBINHOOD_TOKENS.SEEDCOIN,
|
|
161
|
+
ROBINHOOD_TOKENS.JUGGERNAUT,
|
|
162
|
+
ROBINHOOD_TOKENS.HOODRAT,
|
|
163
|
+
ROBINHOOD_TOKENS.DIH,
|
|
164
|
+
ROBINHOOD_TOKENS.KITSU,
|
|
165
|
+
ROBINHOOD_TOKENS.WEN,
|
|
166
|
+
ROBINHOOD_TOKENS.REPE,
|
|
167
|
+
ROBINHOOD_TOKENS.TENDIES,
|
|
168
|
+
ROBINHOOD_TOKENS.GME,
|
|
169
|
+
ROBINHOOD_TOKENS.TOKEN_4663,
|
|
170
|
+
ROBINHOOD_TOKENS.MARIAN,
|
|
171
|
+
] as const satisfies readonly RobinhoodToken[];
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Tokens used to initialize the Robinhood swap UI.
|
|
175
|
+
*
|
|
176
|
+
* The current default pair is native ETH -> USDG. WETH remains in this set so
|
|
177
|
+
* native/wrapped lookup and token selection use the canonical deployment.
|
|
178
|
+
*/
|
|
179
|
+
export const ROBINHOOD_FRONTEND_DEFAULT_TOKENS = [
|
|
180
|
+
{
|
|
181
|
+
address: ROBINHOOD_NATIVE_ETH,
|
|
182
|
+
symbol: "ETH",
|
|
183
|
+
name: "Ether",
|
|
184
|
+
decimals: 18,
|
|
185
|
+
},
|
|
186
|
+
ROBINHOOD_TOKENS.WETH,
|
|
187
|
+
ROBINHOOD_TOKENS.USDG,
|
|
188
|
+
] as const satisfies readonly RobinhoodToken[];
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Production trusted-hop addresses, ordered by routing usefulness.
|
|
192
|
+
*
|
|
193
|
+
* The 2026-07-11 audit enumerated every pool creation from the Robinhood
|
|
194
|
+
* Uniswap V2/V3 factories, then required multiple meaningful counterparties
|
|
195
|
+
* and a successful zero-tax simulation. Keep this list synchronized with the
|
|
196
|
+
* Robinhood backend routing configuration.
|
|
197
|
+
*/
|
|
198
|
+
export const ROBINHOOD_TRUSTED_INTERMEDIATES = [
|
|
199
|
+
ROBINHOOD_TOKENS.WETH.address,
|
|
200
|
+
ROBINHOOD_TOKENS.USDG.address,
|
|
201
|
+
ROBINHOOD_TOKENS.VIRTUAL.address,
|
|
202
|
+
ROBINHOOD_TOKENS.CASHCAT.address,
|
|
203
|
+
] as const;
|
|
204
|
+
|
|
205
|
+
/** Preferred Robinhood fee tokens, from highest to lowest priority. */
|
|
206
|
+
export const ROBINHOOD_FEE_TOKEN_PRIORITY = [
|
|
207
|
+
ROBINHOOD_TOKENS.WETH.address,
|
|
208
|
+
ROBINHOOD_TOKENS.USDG.address,
|
|
209
|
+
ROBINHOOD_TOKENS.WALLET.address,
|
|
210
|
+
ROBINHOOD_TOKENS.SEEDCOIN.address,
|
|
211
|
+
ROBINHOOD_TOKENS.CASHCAT.address,
|
|
212
|
+
] as const;
|
|
213
|
+
|
|
214
|
+
const ROBINHOOD_FEE_PRIORITY_BY_ADDRESS = new Map<string, number>(
|
|
215
|
+
ROBINHOOD_FEE_TOKEN_PRIORITY.map((address, index) => [
|
|
216
|
+
address.toLowerCase(),
|
|
217
|
+
index + 1,
|
|
218
|
+
]),
|
|
219
|
+
);
|
|
220
|
+
ROBINHOOD_FEE_PRIORITY_BY_ADDRESS.set(
|
|
221
|
+
ROBINHOOD_NATIVE_ETH.toLowerCase(),
|
|
222
|
+
1,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
/** Minimum directional tax data required for fee-mode selection. */
|
|
226
|
+
export interface RobinhoodTaxInfo {
|
|
227
|
+
isTaxToken: boolean;
|
|
228
|
+
buyTaxBps: number;
|
|
229
|
+
sellTaxBps: number;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Select the safer/preferred fee side for a Robinhood swap.
|
|
234
|
+
*
|
|
235
|
+
* Tax safety takes precedence over fee-token preference. Native ETH is treated
|
|
236
|
+
* as equivalent to WETH. `false` means fee on input; `true` means fee on output.
|
|
237
|
+
*/
|
|
238
|
+
export function selectRobinhoodFeeOnOutput(
|
|
239
|
+
from: string,
|
|
240
|
+
to: string,
|
|
241
|
+
fromTax: RobinhoodTaxInfo,
|
|
242
|
+
toTax: RobinhoodTaxInfo,
|
|
243
|
+
): boolean {
|
|
244
|
+
const inputHasSellTax = fromTax.isTaxToken && fromTax.sellTaxBps > 0;
|
|
245
|
+
const outputHasBuyTax = toTax.isTaxToken && toTax.buyTaxBps > 0;
|
|
246
|
+
|
|
247
|
+
if (inputHasSellTax && outputHasBuyTax) return false;
|
|
248
|
+
if (outputHasBuyTax) return false;
|
|
249
|
+
if (inputHasSellTax) return true;
|
|
250
|
+
|
|
251
|
+
const inputPriority =
|
|
252
|
+
ROBINHOOD_FEE_PRIORITY_BY_ADDRESS.get(from.toLowerCase()) ?? Infinity;
|
|
253
|
+
const outputPriority =
|
|
254
|
+
ROBINHOOD_FEE_PRIORITY_BY_ADDRESS.get(to.toLowerCase()) ?? Infinity;
|
|
255
|
+
|
|
256
|
+
if (outputPriority < inputPriority) return true;
|
|
257
|
+
if (inputPriority < outputPriority) return false;
|
|
258
|
+
if (inputPriority !== Infinity) return true;
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export interface RobinhoodQuoteParams {
|
|
263
|
+
from: string;
|
|
264
|
+
to: string;
|
|
265
|
+
/** Raw integer input amount in the input token's smallest unit. */
|
|
266
|
+
amount: string | bigint;
|
|
267
|
+
sender?: string;
|
|
268
|
+
receiver?: string;
|
|
269
|
+
/** Slippage in basis points. */
|
|
270
|
+
slippage?: number;
|
|
271
|
+
/** Partner fee in basis points. */
|
|
272
|
+
fee?: number;
|
|
273
|
+
partnerAddress?: string;
|
|
274
|
+
feeOnOutput?: boolean;
|
|
275
|
+
adapters?: string | readonly number[];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Build a Robinhood quote URL with the required network value included. */
|
|
279
|
+
export function buildRobinhoodQuoteUrl(
|
|
280
|
+
params: RobinhoodQuoteParams,
|
|
281
|
+
apiBase: string = API_BASE,
|
|
282
|
+
): string {
|
|
283
|
+
const query = new URLSearchParams({
|
|
284
|
+
network: ROBINHOOD_NETWORK,
|
|
285
|
+
from: params.from,
|
|
286
|
+
to: params.to,
|
|
287
|
+
amount: params.amount.toString(),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
if (params.sender) query.set("sender", params.sender);
|
|
291
|
+
if (params.receiver) query.set("receiver", params.receiver);
|
|
292
|
+
if (params.slippage !== undefined) {
|
|
293
|
+
query.set("slippage", params.slippage.toString());
|
|
294
|
+
}
|
|
295
|
+
if (params.fee !== undefined) query.set("fee", params.fee.toString());
|
|
296
|
+
if (params.partnerAddress) {
|
|
297
|
+
query.set("partnerAddress", params.partnerAddress);
|
|
298
|
+
}
|
|
299
|
+
if (params.feeOnOutput !== undefined) {
|
|
300
|
+
query.set("feeOnOutput", params.feeOnOutput.toString());
|
|
301
|
+
}
|
|
302
|
+
if (params.adapters !== undefined) {
|
|
303
|
+
query.set(
|
|
304
|
+
"adapters",
|
|
305
|
+
Array.isArray(params.adapters)
|
|
306
|
+
? params.adapters.join(",")
|
|
307
|
+
: String(params.adapters),
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return `${apiBase.replace(/\/$/, "")}/swap/quote?${query.toString()}`;
|
|
312
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -116,8 +116,8 @@ export interface SwapTransaction {
|
|
|
116
116
|
to: string;
|
|
117
117
|
/** ABI-encoded `goSwitch()` calldata */
|
|
118
118
|
data: string;
|
|
119
|
-
/** Native
|
|
120
|
-
value: string;
|
|
119
|
+
/** Native currency to send (wei). `"0"` for ERC-20 input tokens. */
|
|
120
|
+
value: string;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// -- Human-readable paths --
|