Reference › JavaScript SDK
/swap/sdk/btcw-swap.js — a single-file ES module with no dependencies (only fetch and BigInt),
running in the browser, Node 18+, Deno and Bun. Quotes are read straight from the contracts over RPC. The /api/v2/swap/quote API runs this same file
on the server, so both always return the same numbers.
Installation
There is no npm package. Two options, same file:
| Option | When to use |
|---|---|
| Import directly from btcw.tech | fastest — nothing to download. The file is served with CORS (Access-Control-Allow-Origin: *),
so a page on any domain can import it in the browser; cached for 5 minutes. Always the latest version. |
| Copy the file and pin the version | when you need a fixed build: serve the file yourself and decide when to upgrade (check VERSION).
Node and Bun cannot import from an https:// URL — use this option. |
// Option 1 — import directly (browser: <script type="module">; Deno)
import { getQuote } from "https://btcw.tech/swap/sdk/btcw-swap.js";
// Option 2 — copy it locally, then import the local file
// curl -sO https://btcw.tech/swap/sdk/btcw-swap.js
// grep 'export const VERSION' btcw-swap.js # currently "1.2.0"
import { getQuote } from "./btcw-swap.js";
/developers/contracts.json (addresses + ABIs) is also served with CORS — read it directly with
fetch("https://btcw.tech/developers/contracts.json") from your page.
Quick start
import { getQuote, ADD_CHAIN_PARAMS, waitForReceipt } from "https://btcw.tech/swap/sdk/btcw-swap.js";
await ethereum.request({ method: "wallet_addEthereumChain", params: [ADD_CHAIN_PARAMS] });
const q = await getQuote({ from: "native", to: "0xd8fA8202ecC699687182109084B9ECBb44025759",
amount: 10n ** 18n, sender: me, slippageBps: 100 });
if (q.error) throw new Error(q.error);
if (q.approval?.needed) await waitForReceipt(await ethereum.request({ method: "eth_sendTransaction", params: [q.approval.tx] }));
const hash = await ethereum.request({ method: "eth_sendTransaction", params: [q.tx] });
Functions
| Name | Description |
|---|---|
getQuote(p) | quote + build the transaction. p: from, to (address or "native"), amount (base units),
sender?, recipient?, slippageBps? (default 100), route? ("best" | "clp" | "amm" | "amm-eth" | "router"), rpc?.
Returns the same structure as the quote API |
getAssets({ api? }) | the list of 202 assets from /api/v2/swap/assets |
waitForReceipt(hash, { rpc?, timeoutMs? }) | waits for the receipt (default up to 120 seconds); status "0x1" means success |
decodeError(e) | maps a revert code (hex string or RPC error object) to a readable reason, or null |
normalizeAsset(a) | normalizes an asset id: returns NATIVE or a lowercase address; throws if invalid |
rpcBatch(calls, rpc?) | sends a JSON-RPC batch (counts as one request against the rate limit) |
Constants
| Name | Value |
|---|---|
VERSION | SDK version |
CHAIN | chainId, chainIdHex, name, rpc, explorer, nativeCurrency |
CONTRACTS | clp, amm, usdw, ethw, ethAmm (ETHw oracle-priced vault), router (SwapRouter) |
NATIVE | 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE — native BTCw |
DEFAULT_API | https://btcw.tech/api/v2 |
ERRORS | the selector → reason table used by decodeError |
ADD_CHAIN_PARAMS | EIP-3085 parameters for wallet_addEthereumChain |
WAD | 10n ** 18n |
Notes
- All amounts are
BigIntor integer strings in base units (18 decimals for every asset). - There is no on-chain deadline —
minAmountOutis the protection; if a quote is pastexpiresAt(30 seconds), request a new one. - Approvals are always for the exact amount of the order, never unlimited.
- With a chain fork: pass
rpc: "http://127.0.0.1:8545"— see Testing on a chain fork.