Appearance
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).
| Prop | Default | Notes |
|---|---|---|
client | required | Instance from createSwappedConnectClient |
destroyOnUnmount | true | Call 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).
| Option | Default | Notes |
|---|---|---|
sessionId | '' | Required before loadSession() / restartSession() (SESSION_ID_REQUIRED if missing) |
environment | 'production' | 'production' or 'staging'. Sets default API, WebSocket, and widget-gateway hosts |
apiBaseUrl | environment default | Overrides the API host. Allow-listed to the official production and staging hosts (INVALID_API_BASE_URL otherwise) |
widgetBaseUrl | environment default | Gateway host that serves /gateway. Localhost is allowed for widget development (INVALID_WIDGET_BASE_URL otherwise) |
modules | all four | Payment modules to construct. See Modules |
wallets.balancesCacheTtlMs | 600000 (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.
| Environment | Session endpoint | Client |
|---|---|---|
| Production (default) | POST https://connect-api.swapped.com/api/sessions | omit environment, or environment: 'production' |
| Staging | POST https://staging-api.swapped.app/api/sessions | environment: '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
| Job | How |
|---|---|
| Load session | client.loadSession() once at bootstrap, outside the component tree |
| Which screen to show | useSessionView |
| Session payload / maintenance | useSession / useMaintenance |
| Another payment | useRestartSession |
| Events | Event hooks |
| Tear down | Provider unmount (default), or client.destroy() via useSwappedConnectClient |
You almost never need loadSession({ forceRefetch: true }) — sockets and payment completion already refresh the session.
Errors
| Code | When | What to do |
|---|---|---|
BROWSER_REQUIRED | Client created outside the browser | Instantiate in a client component / browser-only module |
REACT_CONTEXT_PROVIDER_REQUIRED | Hook used outside SwappedConnectProvider | Wrap the tree with the provider |
REACT_CLIENT_ALREADY_PROVIDED | Same client instance passed to two providers | Use one provider per client |
SESSION_ID_REQUIRED | Missing id on load / restart | Pass sessionId to create or to the call |
SESSION_ALREADY_IN_USE | Another live client already has this sessionId | Use one client per session, or destroy() the other first |
INVALID_ENVIRONMENT | environment is not production or staging | Use one of those two values |
INVALID_API_BASE_URL | apiBaseUrl is not an official host | Use the production or staging API URL, or omit it |
INVALID_WIDGET_BASE_URL | widgetBaseUrl is not official and not localhost | Use the environment default, or a localhost widget host |
INVALID_MODULES | modules is not an array of known names | Pass exchangePay, cashApp, coinbase, and/or wallets |
MODULE_NOT_ENABLED | Called a module omitted from modules | Include it, or omit modules to enable all |
CLIENT_DESTROYED | Method called after destroy() | Create a new client |