---
name: silentswap-integration
description: Integrate or migrate @silentswap/sdk 2.x using its unified RFQ client. Use when quoting, placing, tracking, or refunding private SilentSwap and Simple Bridge orders; wiring EVM/Solana/Bitcoin/TON/TRON wallet adapters; adding integrator fees; migrating from SilentSwap V2; or verifying an integration against production.
---

# Integrate SilentSwap

Use `@silentswap/sdk` as the protocol boundary. Do not reproduce quote serialization,
allowance logic, wallet-payload validation, Bitcoin PSBT audits, or status normalization in
application code. Read [references/complete-example.ts](references/complete-example.ts) for a
compiling EVM example.

## Install and configure

1. Install `@silentswap/sdk@^2.3.0` and its `viem` peer dependency. Private order reads need
   2.2.0 or later; older releases do not send the order access token and receive HTTP 401.
2. Create one client with `createSilentSwapClient({ walletClient, walletAdapters, integratorId })`.
   Omit `integratorId` for a direct, non-integrator application. Registered integrators use the
   ID issued by SilentSwap; never synthesize one.
3. Omit `baseUrl` in production; it defaults to `https://api.silentswap.com`. Override it only
   for tests or self-hosted deployments.
4. Run local browser testing on `http://localhost:3000` or `http://127.0.0.1:3000`; both are
   enabled by default, and the issued integrator ID selects the correct local configuration.
   Register every exact HTTPS browser origin before production rollout. Node and server calls do
   not need CORS registration, but still need the issued integrator ID for managed fees.
5. Supply capability adapters only for wallet families the application already selected.
   Never discover injected wallets or merge addresses across brands inside an integration.

## Use the RFQ lifecycle

Use the same sequence in both modes:

1. Call `quote({ privacy, ... })`.
2. Display the input, every output, assets, fees, and expiration in trusted application UI.
3. Call `placeOrder(quote)` directly. There is no authorization-signing or confirmation API.
4. Persist `order.reference`; it is serializable and contains the privacy discriminator. A
   private reference also carries `accessToken`, the only read credential for that order.
   Store it as private application data, never in a URL, log, analytics payload, share link,
   or calldata. Alternatively pass `orderAccessTokenStore: { get, set }` to
   `createSilentSwapClient`. A missing or wrong token returns HTTP 401 `order_access_required`.
5. Call `trackOrderViaWebSocket(order.reference, onState, onError)` and retain its unsubscribe
   function.
6. For private refunds only, call `executeRefund(privateReference)`.

`trackOrderViaWebSocket` is a compatibility name. Private orders use SSE with polling fallback;
Simple Bridge uses polling. `DROPPED` is not terminal: a late deposit can resurrect it to
`OPEN`. Terminal private statuses are `COMPLETED`, `FAILED`, and `ABORTED`.

## Build quote requests

- Private wallet-funded: `privacy: true`, `inputAddress`, and 1–20 `outputs` with
  `address`, `chainId`, `amount`, and optional `dest`.
- `outputs[].amount` is in gateway-chain USDC units. Always build it with `parseUsdc(value)`;
  never hardcode a decimal precision.
- Private BTC/LTC/TON/TRON/USDT-TRC20 exact-input: add top-level `amount` and exactly one output.
  The SDK sends the backend's internal zero-payout placeholder. Integrator fees are unsupported.
- Simple Bridge: `privacy: false`, top-level `amount`, and exactly one output. `inputAddress`
  may default to the active configured adapter. Integrator fees are unsupported.
- Use `sourceAsset` for registry assets or `sourceToken` for an arbitrary token, never both.
- Never pass `integratorFee` or `integratorAddress`. SilentSwap controls the additive total
  percentage, integrator/SilentSwap split, and payout address for the configured `integratorId`;
  display the calculated service and integrator fee fields.

## Wire wallet capabilities

- EVM uses the configured viem `WalletClient` and performs approvals inside `placeOrder`.
- Solana supplies the active address and `signAndSendTransaction(transaction)`. The transaction
  is either a serialized private-route transaction or an audited bridge instruction payload.
- Bitcoin supplies the active address/public key and `signAndSendPsbt(audit)`. The SDK audits
  outputs, refund address, inputs, absolute fee, and fee rate before invoking it.
- TON supplies the active address and message submission.
- TRON supplies the active address and smart-contract transaction submission.

The SDK verifies each active adapter address against `inputAddress`, validates the Solana payer,
and throws `WalletAdapterRequiredError` when a capability is absent. Preserve
`awaiting-external-deposit` instructions for exchange or manual deposits.

## Refund safely

Pass only a private `reference` to `executeRefund`. The SDK refreshes state and rejects a refund
when the source is not EVM, the state is not `OPEN` or `FAILED`, expiration has not passed, any
recipient is paid/in flight, the order is fulfilled/refunded, or the connected wallet is not
the depositor. Handle `RefundNotAllowedError` without another wallet prompt and surface
`RefundRevertedError.refundTxHash` for an included revert.

## Migrate from V2

When asked to migrate an existing 0.x consumer:

1. Inventory every `@silentswap/sdk` import, client construction, quote/order/tracking/refund
   call, stored credential, environment variable, and pending order. Remove legacy imports and
   configuration for the V2 API URL, nonce/auth endpoints, SIWE credentials, facilitator groups,
   viewing authorization, and signed order authorizations after the pinned-order path is isolated.
2. Pin the old 0.x runtime for pending V2 orders. They cannot be converted to V3 references.
3. Remove nonce requests, SIWE authentication, facilitator groups/derivation, authorization
   signing, and persistence for those values.
4. Keep familiar names where possible:
   - `createSilentSwapClient` stays.
   - `quote({ outputs, pro })` becomes `quote({ privacy, inputAddress, outputs })`.
     If the application is an approved integrator, configure the new ID once with
     `createSilentSwapClient({ integratorId })`. Do not reuse the old `pro` value.
   - `order()` becomes `placeOrder(quote)`.
   - `trackOrderViaWebSocket` stays but takes `order.reference`.
   - `executeRefund` stays but takes a private reference.
   - Simple Bridge uses the same client with `privacy: false`.
5. Rewrite each old V2 output explicitly:
   - `recipient` becomes `address`.
   - For a USDC output, decimal-string `value` becomes `amount: parseUsdc(value)` in
     gateway-chain USDC units.
   - For a non-USDC output, do not copy destination-native `value` into `amount`: obtain or
     recompute the V3 USDC payout budget from the application's intent/quote logic, then encode
     the desired destination asset under `dest`.
   - The old CAIP-19 `asset` describes the destination only. Derive output `chainId` and `dest`
     from it; derive top-level `sourceAsset` or `sourceToken` independently from the old
     application's source selection/deposit flow.
   - delete `method` and `facilitatorPublicKeys`.
   - inspect `extra.swap`; when it represents an arbitrary destination asset, translate it to
     `dest` and leave an application TODO if its chain/token metadata is ambiguous.
6. Rewrite control flow, not only names:
   - Old `await trackOrderViaWebSocket(orderId, viewingAuth, options)` resolved to a final status.
     New `client.trackOrderViaWebSocket(reference, onState, onError)` returns an unsubscribe
     function immediately; persist the reference, update state from callbacks, and call the
     function during teardown.
   - Old `executeRefund(walletClient, orderId, gateway)` returned a hash. New
     `client.executeRefund(privateReference)` refreshes state and returns `{ refundTxHash }`.
7. Replace tuple-error handling with typed thrown errors.
8. Add narrow adapters around the application's existing wallet selection. Leave explicit TODOs
   only when the application owner must decide wallet-specific signing or broadcasting.
9. Run the consumer's real typecheck against the installed package and search again for old
   nonce, SIWE, facilitator, authorization, `order()`, positional tracking calls, and stale V2
   environment configuration.

## Verify

1. Typecheck against the installed/packed SDK rather than copied source types.
2. Test private and Simple Bridge serialization without changing backend request formats.
3. Exercise missing-adapter, address-mismatch, user-rejection, EVM approval, and revert paths.
4. Exercise any configured non-EVM adapter without cross-brand fallback.
5. Verify private SSE, polling fallback, Simple Bridge normalization, unsubscribe behavior, and
   `DROPPED → OPEN` resurrection.
6. Reload mid-order and confirm tracking resumes from the persisted reference or token store
   without a 401.
7. Request small production private and public quotes without broadcasting.
8. Keep real-funds tests behind an explicit operator-controlled sentinel.
