Skip to content

Client (Core)

Create one SwappedConnectClient with createSwappedConnectClient, then call loadSession() before any payment UI.

This SDK is browser only. createSwappedConnectClient throws BROWSER_REQUIRED on the server (Node.js, SSR, RSC). Create a sessionId on your backend — see Creating a session — then instantiate the client in the browser.

ts
import { createSwappedConnectClient } from '@swapped/connect-sdk';

const client = createSwappedConnectClient({
  sessionId: 'your-session-id',
  environment: 'staging', // omit or 'production' for live
});

await client.loadSession();

Reuse this instance for the life of the payment UI. Call restartSession() for another payment — do not create a second client unless you are running more than one session on the same page. Call destroy() on teardown.

Config

OptionDefaultNotes
sessionId''Required before loadSession() / restartSession() (SESSION_ID_REQUIRED if missing)
environment'production''production' or 'staging'. Sets default API, WebSocket, and widget-gateway hosts
apiBaseUrlenvironment defaultOverrides the API host. Allow-listed to the official production and staging hosts (INVALID_API_BASE_URL otherwise)
widgetBaseUrlenvironment defaultGateway host that serves /gateway. Localhost is allowed for widget development (INVALID_WIDGET_BASE_URL otherwise)
modulesall fourPayment modules to construct. See Modules
wallets.balancesCacheTtlMs600000 (10 min)How long wallet balances stay cached. A manual refresh always loads fresh balances

Environments

The client defaults to production. Pass environment: 'staging' to point the API, WebSocket, and widget gateway at staging. A staging sessionId will not load against production.

EnvironmentSession endpointClient
Production (default)POST https://connect-api.swapped.com/api/sessionsomit environment, or environment: 'production'
StagingPOST https://staging-api.swapped.app/api/sessionsenvironment: 'staging'

If the session was created on staging and the client stays on production, loadSession() fails — and getSessionView() still reports active because no session is loaded, so payment UI can render over a session that does not exist.

Optional apiBaseUrl / widgetBaseUrl replace that environment's defaults. If you pass a custom apiBaseUrl, the client infers environment from it when environment is omitted.

Modules

All payment modules are enabled by default (exchangePay, cashApp, coinbase, wallets). Pass modules to construct only the ones you need.

ts
const client = createSwappedConnectClient({
  sessionId: 'your-session-id',
  modules: ['exchangePay'],
});

wallets and coinbase mount a hidden /gateway iframe; exchangePay and cashApp do not. Sites with a Content-Security-Policy must allow that iframe and the API WebSocket — see Browser requirements.

Accessing a module that was not listed throws MODULE_NOT_ENABLED. paymentMethods.get() also hides methods for modules that are not enabled. Check with client.isModuleEnabled('wallets') or read client.modules.

Lifecycle

MethodPurpose
loadSession(sessionId?, options?)Load (or reload) the session. A second call with the same id uses the cache unless { forceRefetch: true }
restartSession(sessionId?)Start a new payment for the same merchant flow; clears Exchange Pay state
getSession()Last loaded SessionData, or null
getSessionView()Classified UI view — see Session
getSessionId()Active session id
getMaintenanceStatus()Latest maintenance payload, or null
getState()Snapshot: sessionId, session, isLoading, isRestarting, error, maintenance
subscribe(listener)Public state changes; returns unsubscribe
on / offLifecycle events — see Events
destroy()Tear down sockets and this client's listeners. The shared gateway iframe is removed only when the last client is destroyed

Call loadSession() once at bootstrap. You almost never need forceRefetch — sockets and payment completion already refresh the session.

ts
await client.loadSession();
await client.restartSession(); // after completion / expiry / failure
client.destroy();

getState() / subscribe are for session-level UI (loading, error, maintenance). For which screen to show, prefer getSessionView() and sessionView:changed.

Multiple clients on one page

You can create more than one client when each has its own sessionId. A second live client with the same sessionId throws SESSION_ALREADY_IN_USE. On the same page they share:

  • Wallet connections (connect / disconnect / switchChain on one client updates every client)
  • Coinbase login (the same OAuth token; each client still withdraws to its own session)
  • One hidden /gateway iframe

Accepted limits:

  • Only one WalletConnect pairing — and one QR — at a time. A second connect({ transport: 'walletconnect' }) without force: true throws WALLET_PAIRING_IN_PROGRESS. cancelPairing() or force: true aborts the in-flight pairing and clears the previous QR. The pairing expires from the URI timestamp (WALLET_PAIRING_EXPIRED).
  • Only one OAuth or wallet popup at a time (Login, swapped-wallet-popup).
  • The first client’s widgetBaseUrl / environment mounts the iframe. Do not mix staging and production gateway hosts on one page.

destroy() tears down that client. The shared iframe is removed only when the last gateway client (wallets or coinbase) is destroyed.

Errors

CodeWhenWhat to do
BROWSER_REQUIREDClient created outside the browserInstantiate in a browser-only module
SESSION_ID_REQUIREDMissing id on load / restartPass sessionId to create or to the call
SESSION_ALREADY_IN_USEAnother live client already has this sessionIdUse one client per session, or destroy() the other first
INVALID_ENVIRONMENTenvironment is not production or stagingUse one of those two values
INVALID_API_BASE_URLapiBaseUrl is not an official hostUse the production or staging API URL, or omit it
INVALID_WIDGET_BASE_URLwidgetBaseUrl is not official and not localhostUse the environment default, or a localhost widget host
INVALID_MODULESmodules is not an array of known namesPass exchangePay, cashApp, coinbase, and/or wallets
MODULE_NOT_ENABLEDCalled a module omitted from modulesInclude it, or omit modules to enable all
CLIENT_DESTROYEDMethod called after destroy()Create a new client