Widget
The orda Widget is a comprehensive, embeddable React component that enables multi-chain cryptocurrency payments in your application — swap, on-ramp, and off-ramp flows with built-in wallet connection, all wrapped around the orda TypeScript SDK.
Replaces the old /developers/widget-beta page. The widget moved out of @ordanetwork/sdk/react (deleted in the SDK v2 release) into its own package @ordanetwork/[email protected]. If you were on the beta, see Migrating from @ordanetwork/sdk/react at the bottom.Try the widget →
What it does
Multi-chain support — EVM (Ethereum, Polygon, Arbitrum, Base, Optimism, plus plasma / stable / megaeth) and Solana
Three transaction flows — Swap, Off-ramp (crypto → BRL via PIX), On-ramp (BRL → crypto via PIX)
Wallet integration — WalletConnect / Reown AppKit modal mounted for you
Lifecycle callbacks — 10 typed events for quote / transaction / wallet / error, plus a firehose for analytics
Recipient management — save and manage payment recipients
Token prices & balances — real-time USD prices and multi-chain balance fetching
Responsive UI — desktop and mobile
Customizable theming — CSS variables
Prerequisites
WalletConnect / Reown project id — cloud.reown.com
orda API credentials —
clientIdandclientSecretReact 18 or React 19
Node.js 18+
Installation
Version compatibility
@ordanetwork/widget
^1.0.0
@ordanetwork/sdk
^1.3.0 || ^2.0.0
react
^18.0.0 || ^19.0.0
react-dom
^18.0.0 || ^19.0.0
@tanstack/react-query
^5.0.0
wagmi
^2.0.0
viem
^2.0.0
@solana/web3.js, @reown/appkit*, and the radix-ui primitives are direct dependencies of @ordanetwork/widget — you don't need to install them yourself.
Quick start
Step 1 — Set environment variables (.env.local)
.env.local)Step 2 — Create the JWT auth route (app/api/auth/jwt/route.ts)
app/api/auth/jwt/route.ts)The widget calls config.getToken() to obtain a JWT; you handle credential exchange server-side so the secret never reaches the browser.
Step 3 — Create the provider (app/providers.tsx)
app/providers.tsx)Step 4 — Mount the provider + styles in your root layout (app/layout.tsx)
app/layout.tsx)Step 5 — Drop in the Widget (app/page.tsx)
app/page.tsx)Step 6 — Run
Lifecycle callbacks
All optional props on <Widget />. Every event fires alongside onAnalyticsEvent — dedupe by event.id if you wire both (see Analytics firehose below).
onQuoteRequested
The widget asked the SDK for a quote (before network round-trip).
onQuoteAccepted
A quote returned successfully (or was served from the 30 s cache — payload.cached: true).
onQuoteFailed
Quote request failed (network / validation / SDK error).
onTransactionInitiated
User confirmed; the wallet was asked to sign / submit.
onTransactionSettled
Transaction confirmed on-chain or settled by the backend.
onTransactionFailed
Transaction reverted, was rejected, or failed before settling.
onWalletConnected
An EVM or Solana wallet just connected.
onWalletDisconnected
A wallet just disconnected.
onError
Any user-visible error (fires alongside the specific *_failed callback when applicable).
onAnalyticsEvent
Firehose — every event in order.
Every event payload shares the same envelope:
Analytics firehose
onAnalyticsEvent fires for every event, alongside the specific callback. Dedupe by event.id when you wire both:
Payload redaction (PII)
Event payloads are deliberately redacted so they are safe to forward verbatim to a third-party analytics sink (Segment / GA / PostHog / Mixpanel).
quote_acceptedcarries only a serializable summary —transactionId,provider,fromSymbol/toSymbol,fromAmount/toAmount,fromChainId/toChainId,estimatedDuration, andcached. It does not include PIX key / QR code, deposit address, reference id, rawtransactionRequest/approvalTxParams(signed calldata), or wallet addresses.quote_failed,transaction_failed, anderrorexpose a human-readablemessageplus an optionalcauseMessagestring. The underlying error object is never forwarded — viem / RPC errors embed tx params and request payloads, so only a message string crosses the callback boundary.
If you need the full, unredacted quote (e.g. to render PIX deposit instructions yourself), read it from the hook return values (useOnRamp().quote, etc.) rather than from events.
Configuration flags
All optional on the config object passed to <OrdaProvider>:
getToken
— (required)
Returns { jwt, expiresAt }. Called on mount and ~5 min before expiry.
appKitConfig
— (required)
From createAppKitConfig({ projectId, metadata }).
debug
false
Verbose console logs for SDK init / refresh.
notifications
true
When true, mounts a Sonner <Toaster />. When false, in-progress states render as inline <Alert /> banners and success / error states surface only through lifecycle callbacks.
disableOnRamp
false
Hide on-ramp (fiat → crypto) flows.
disableOffRamp
false
Hide off-ramp (crypto → fiat) flows.
enableOfframpSolana
false
Allow Solana as a source chain for off-ramp.
Apps controlling these via env (e.g. NEXT_PUBLIC_ON_RAMP_DISABLED) should map the env value to the config field when constructing the provider — the widget does not read process.env.* directly.
SSR / RSC
@ordanetwork/widget is a client component. The bundle starts with 'use client'; so importing it from a React Server Component is safe — you get the 'use client' boundary automatically. You do not need to wrap it.
createAppKitConfig() must be called at module scope (outside components) for SSR safety — see Step 3 above.
Wallet mode
@ordanetwork/[email protected] ships one wallet mode: appkit (the default). The widget mounts Wagmi + the Reown AppKit modal internally; you supply a projectId via createAppKitConfig.
BYOW (wallet: 'external') is coming in 1.1.0 — for hosts that already own a <WagmiProvider> and want the widget to consume it. The plumbing exists internally; a few downstream call sites are still being migrated. Tracked as COR-963.
TypeScript
All types ship with the package; no @types/... install needed.
The full event union is discriminated by type, so narrowing in a callback works without casts.
Security note
Never expose ORDA_CLIENT_SECRET to the browser. Always exchange credentials for a JWT on a server-side route (Step 2) and let the widget call that route via config.getToken.
Migrating from @ordanetwork/sdk/react
@ordanetwork/sdk/reactIf you integrated against the beta (when the widget lived inside the core SDK), here's the migration:
Before (@ordanetwork/sdk/react)
After (@ordanetwork/widget)
npm install @ordanetwork/sdk
npm install @ordanetwork/widget @ordanetwork/sdk
import { OrdaProvider, Widget, createAppKitConfig } from '@ordanetwork/sdk/react'
import { OrdaProvider, Widget, createAppKitConfig } from '@ordanetwork/widget'
import '@ordanetwork/sdk/react/styles.css'
import '@ordanetwork/widget/styles.css'
No runtime behavior changes — the same components, the same OrdaProvider config shape, the same Widget props. The split is purely about packaging: the React UI now ships independently of the core SDK so it can version on its own cadence.
The @ordanetwork/sdk itself remains a peer dependency (the widget uses it internally for quote / transaction / recipient API calls).
Last updated