Reference
Integrate the checkout widget, wire Solana wallet adapters, and optionally proxy Jupiter and RPC from your own origin so keys and CORS behave like production infrastructure.
Overview
FlexPay packages a Jupiter Swap API v2 flow (quote via /order, submit via /execute) with the Tokens and Price APIs for surface-level UX: token metadata, slippage safety, and optional volatility checks before the user signs.
Cluster: Jupiter's swap routes are mainnet. Point rpcEndpoint at a mainnet RPC. The demo can use /api/solana-rpc to avoid public-RPC 403s in the browser.
Install
Start with the SDK only, then add wallet adapter packages used by the React widget.
pnpm add @flexpay/sdknpm i @flexpay/sdkAdd wallet adapters (required for connect/sign in widget mode):
pnpm add @solana/wallet-adapter-react @solana/wallet-adapter-react-uinpm i @solana/wallet-adapter-react @solana/wallet-adapter-react-uiWhat each URL is for
In proxy mode the widget calls your origin instead of Jupiter or a raw RPC directly. Your server attaches secrets, avoids CORS issues, and can rate-limit.
- rpcEndpoint: Solana JSON-RPC transport (balances, blockhash, tx confirmation context).
- quoteApiUrl: route discovery + quote/order.
- swapApiUrl: execute/broadcast of signed swap transaction.
- tokensApiUrl: token metadata/list for the selector UX.
| Config | Role | Typical path (this demo) |
|---|---|---|
rpcEndpoint | Solana JSON-RPC: balances, blockhash, and other chain reads the widget needs before and after the swap. Not Jupiter—use your provider or a same-origin proxy. | /api/solana-rpc (browser) with SSR fallback to a public or private HTTPS RPC |
quoteApiUrl | Base URL for Jupiter Swap API v2 quote / order requests. | /api/flexpay/quote |
swapApiUrl | Base URL for execute (signed transaction submit) and related swap execution calls. | /api/flexpay/swap |
tokensApiUrl | Base for token metadata and list endpoints the UI uses for labels, icons, and input selection. | /api/flexpay/tokens |
Environment
In direct mode the widget calls Jupiter with jupiterApiKey from the client. For production, prefer server routes that inject the key so it is not exposed in the bundle.
# Browser-safe keys only where intended
NEXT_PUBLIC_FLEXPAY_MERCHANT_WALLET=<merchant_pubkey>
NEXT_PUBLIC_JUPITER_API_KEY=<jupiter_browser_key>
NEXT_PUBLIC_SOLANA_RPC_URL=<https_rpc_or_omit_for_demo_proxy>Widget (direct API key)
Wrap your app (or subtree) with the same wallet provider you use for any Solana dApp.
import { FlexPayWidget } from "@flexpay/react";
export function Checkout() {
return (
<FlexPayWidget
merchantWallet={process.env.NEXT_PUBLIC_FLEXPAY_MERCHANT_WALLET!}
amount={29.99}
rpcEndpoint="https://api.mainnet-beta.solana.com"
jupiterApiKey={process.env.NEXT_PUBLIC_JUPITER_API_KEY}
onSuccess={(p) => console.log(p.signature)}
/>
);
}Proxy mode (recommended)
Point quoteApiUrl, swapApiUrl, and tokensApiUrl at your Next.js API routes. Implementations in this repo forward to Jupiter and attach the API key on the server.
<FlexPayWidget
merchantWallet={process.env.NEXT_PUBLIC_FLEXPAY_MERCHANT_WALLET!}
amount={29.99}
rpcEndpoint={typeof window !== "undefined"
? new URL("/api/solana-rpc", window.location.origin).toString()
: "https://api.mainnet-beta.solana.com"}
quoteApiUrl="/api/flexpay/quote"
swapApiUrl="/api/flexpay/swap"
tokensApiUrl="/api/flexpay/tokens"
/>FlexPayWidget — fields
| Prop | Type | Notes |
|---|---|---|
amount | number | USDC-equivalent target amount for the swap route. |
merchantWallet | string | Receiver pubkey (USDC destination). |
rpcEndpoint | string | Mainnet HTTP RPC; use your provider or the demo proxy URL. |
jupiterApiKey | string? | Direct-to-Jupiter mode; omit when using proxy routes. |
quoteApiUrl | string? | Jupiter quote/order base; omit if using jupiterApiKey on the client. |
swapApiUrl | string? | Swap execute base; pairs with quoteApiUrl in proxy mode. |
tokensApiUrl | string? | Token list/metadata base for picker and display. |
slippageBps | number? | Basis points passed through to Jupiter order requests. |
onSuccess / onError / onCancel | callbacks | Payment lifecycle hooks. |
onTelemetry / onVolatility | callbacks | Latency stages and optional Price API volatility verdict. |
theme | object? | CSS variable overrides for widget chrome. |
Operations
- Insufficient funds / SOL for fees: Ensure the payer wallet has enough of the input token and reserved SOL for transaction fees on mainnet.
- 403 on public RPC: Use an authenticated RPC provider or the demo
/api/solana-rpcproxy pattern. - Devnet RPC + mainnet Jupiter: Not supported; configs guard against mixed clusters.