Skip to content

Client (React)

Create a core client with createSwappedConnectClient, call loadSession() once at bootstrap, then wrap your tree with SwappedConnectProvider. Hooks read that client from context.

This SDK is browser only. createSwappedConnectClient throws BROWSER_REQUIRED on the server (Node.js, SSR, RSC). In Next.js and similar frameworks, instantiate the client in a client component ('use client') or a module that only runs in the browser. Session creation stays on your backend — see Creating a session.

tsx
import { createSwappedConnectClient } from '@swapped/connect-sdk'
import { SwappedConnectProvider } from '@swapped/connect-sdk/react'

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

// Provider does not load the session — do it once at bootstrap
void client.loadSession()

function App() {
  return (
    <SwappedConnectProvider client={client}>
      {/* payment UI */}
    </SwappedConnectProvider>
  )
}

Create the client once and pass it into the provider. Reuse that instance for the life of the payment UI. Call restartSession() for another payment — do not create a second client unless each tree is a separate session (SESSION_ALREADY_IN_USE). Call destroy() on teardown.

Multiple clients on one page share wallet connections and Coinbase login. See Multiple clients on one page.

SwappedConnectProvider

Provides the client to every hook under @swapped/connect-sdk/react. Hooks throw REACT_CONTEXT_PROVIDER_REQUIRED outside this tree. One client instance may be passed to only one provider at a time (REACT_CLIENT_ALREADY_PROVIDED).

The provider does not call loadSession() or restartSession() — do those on the client instance (or via useSwappedConnectClient / useRestartSession).

PropDefaultNotes
clientrequiredInstance from createSwappedConnectClient
destroyOnUnmounttrueCall client.destroy() when this provider unmounts. Pass false if you reuse the same client after this tree unmounts. Destroy is deferred by a macrotask so React Strict Mode remounts do not tear down a reused client.

Do not wrap the tree with a module provider (WalletsProvider, ExchangePayContextProvider, CashAppProvider, CoinbaseProvider) for a module that was omitted from modules (MODULE_NOT_ENABLED).

useSwappedConnectClient

Returns the same SwappedConnectClient you passed to the provider. Use it for methods that do not have a dedicated hook (destroy, isModuleEnabled, module calls).

tsx
import { useSwappedConnectClient } from '@swapped/connect-sdk/react'

function TeardownButton() {
  const client = useSwappedConnectClient()

  return (
    <button type="button" onClick={() => client.destroy()}>
      Tear down
    </button>
  )
}

For another payment after completion, prefer useRestartSession so the button can show isRestarting / error.

Config

Same options as Client (Core).

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 useSessionView() 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 — 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.

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

Payment method lists hide methods for modules that were left out. Accessing a disabled module throws MODULE_NOT_ENABLED.

Lifecycle

JobHow
Load sessionclient.loadSession() once at bootstrap, outside the component tree
Which screen to showuseSessionView
Session payload / maintenanceuseSession / useMaintenance
Another paymentuseRestartSession
EventsEvent hooks
Tear downProvider unmount (default), or client.destroy() via useSwappedConnectClient

You almost never need loadSession({ forceRefetch: true }) — sockets and payment completion already refresh the session.

Errors

CodeWhenWhat to do
BROWSER_REQUIREDClient created outside the browserInstantiate in a client component / browser-only module
REACT_CONTEXT_PROVIDER_REQUIREDHook used outside SwappedConnectProviderWrap the tree with the provider
REACT_CLIENT_ALREADY_PROVIDEDSame client instance passed to two providersUse one provider per client
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