Embeddable Solana payment widget for FluxPay. Drop one script tag on your site and get a full crypto checkout flow — wallet connect, QR code, and real-time payment status.
Built for Colosseum Hackathon 2026.
Video.Project.1.mp4
[Link To FlowChart](https://app.eraser.io/workspace/z35BCDaVw5haoEzWbcEY?origin=share)
No page redirects. No wallet SDK required on the merchant's side. Works on any website regardless of framework.
- Wallet Connect — supports any Solana wallet (Phantom, Solflare, Backpack, etc.) via Wallet Standard
- One-click payment — user connects wallet, clicks Pay, approves in Phantom. Done.
- QR Code fallback — users can also scan and pay from a mobile wallet
- Real-time status — polls backend every 3 seconds, updates UI automatically
- Status transitions — Pending → Detected → Converting → Confirmed with live UI
- Countdown timer — shows payment expiry window
- Self-contained — React + wallet adapter bundled inside, no dependencies for merchant
- Works anywhere — plain HTML, React, Vue, Shopify, WordPress, anything
<script src="https://cdn.fluxpay.io/fluxpay.js"></script>
<script>
FluxPay.init({
apiUrl: 'https://api.fluxpay.io',
apiKey: 'fp_live_...',
onSuccess: (payment) => {
console.log('Payment confirmed!', payment.payment_id)
// redirect, show success page, etc.
},
onExpired: () => console.log('Payment expired'),
onError: (err) => console.log('Error:', err.message),
})
</script>
<button onclick="FluxPay.open('PAYMENT_ID')">
Pay with Crypto
</button>npm install @fluxpay/widgetimport FluxPay from '@fluxpay/widget'
FluxPay.init({
apiUrl: 'https://api.fluxpay.io',
apiKey: 'fp_live_...',
onSuccess: (payment) => console.log('done', payment),
})
FluxPay.open('PAYMENT_ID')Call once on page load.
| Option | Type | Required | Description |
|---|---|---|---|
apiUrl |
string | ✅ | Your FluxPay backend URL |
apiKey |
string | ✅ | Merchant API key (fp_live_...) |
onSuccess |
function | ❌ | Called when payment completes |
onExpired |
function | ❌ | Called when payment expires |
onError |
function | ❌ | Called on error |
Opens the checkout modal for a given payment ID. Get the payment ID by calling POST /api/payments/create on your backend first.
Programmatically closes the modal.
Your backend creates the payment, your frontend opens the widget:
// 1. Create payment on your backend (server-side or via API call)
const res = await fetch('https://api.fluxpay.io/api/payments/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'fp_live_...',
},
body: JSON.stringify({
order_id: 'order_123',
amount_usdc: 25.00,
}),
})
const { payment_id } = await res.json()
// 2. Open the widget with the payment ID
FluxPay.open(payment_id)pending → detected → swapping → completed ✅
→ failed ❌
pending → expired ⏱️
The widget handles all status transitions automatically.
fluxpay-widget/
├── src/
│ ├── index.tsx ← entry point, exposes FluxPay.init() + FluxPay.open()
│ ├── CheckoutModal.tsx ← main modal UI (wallet connect + QR code + status)
│ ├── usePaymentStatus.ts ← polls backend every 3s for payment status
│ ├── useCountdown.ts ← countdown timer hook
│ └── types.ts ← shared TypeScript types
├── dist/
│ ├── fluxpay.js ← IIFE bundle (script tag usage)
│ └── fluxpay.esm.js ← ESM bundle (npm/bundler usage)
├── rollup.config.js
├── tsconfig.json
└── package.json
git clone https://github.com/Cypher-CP0/fluxpay-widget.git
cd fluxpay-widget
npm install
npm run build # builds dist/fluxpay.jsTo test locally, serve the folder and open test.html:
npx serve .
# open http://localhost:8080/test.htmlMake sure your FluxPay backend is running.
| Layer | Choice |
|---|---|
| UI | React 18 |
| Wallet | @solana/wallet-adapter (Wallet Standard) |
| Bundler | Rollup |
| Language | TypeScript |
| Output | IIFE (script tag) + ESM (npm) |
- fluxpay — backend API, Helius webhooks, Jupiter swap