Drop pre-built financial UI directly into your dashboard. Each widget is a sandboxed iframe — your brand colors, your users, zero custody risk.
Step through mount → user action → result. Every API call and postMessage lands on the wire. Nothing real is created — this is a self-contained mock.
Add one script tag to your page. No build step, no npm install.
<!-- In your <head> or before </body> --> <script src="https://tdcoffee-b523e.web.app/fanua-widget.js"></script>
Call your backend to create a short-lived, single-use token scoped to one widget. Never expose your API key in the browser.
import { FanuaSDK } from '@fanua/sdk'; const fanua = new FanuaSDK({ apiKey: process.env.FANUA_API_KEY }); // In your API route / server action const { token } = await fanua.createEmbedToken({ scope: ['wallet_open'], }); // Return token to the browser res.json({ token });
curl -X POST \ https://us-central1-tdcoffee-b523e.cloudfunctions.net/createEmbedToken \ -H 'Content-Type: application/json' \ -H 'X-API-Key: YOUR_API_KEY' \ -d '{"data":{"scope":["wallet_open"]}}'
Pass the token from step 2 and a target element. The widget sends a fanua:account.created event when the wallet is ready.
// Fetch the token from your backend const { token } = await fetch('/api/embed-token').then(r => r.json()); const widget = window.Fanua.WalletOpen({ target: '#wallet-container', // any CSS selector or HTMLElement token, label: 'My App', onAccountCreated({ accountId, address, solanaAddress }) { console.log('Wallet ready', accountId, address); }, onError({ code, message }) { console.error(code, message); }, }); // Unmount when done // widget.destroy();
Mount the widget, fetch balances across chains, and watch the fanua:balance.updated event fire. Self-contained mock — no live account is read.
balanceOf · Aave aToken APY.Same loader as every Fanua widget — add it once and skip this step if it's already on the page.
<!-- In your <head> or before </body> --> <script src="https://tdcoffee-b523e.web.app/fanua-widget.js"></script>
Scope the token to balance_read and tie it to the account whose balances you want to show.
const { token } = await fanua.createEmbedToken({ scope: ['balance_read'], accountId: 'acc_...', });
The widget fires fanua:balance.updated on load and on every refresh.
const widget = window.Fanua.BalanceDisplay({ target: '#balance-container', token, onBalanceUpdated({ amount, available, currency }) { console.log('Balance', amount, available, currency); }, onError({ code, message }) { console.error(code, message); }, });
Mount the desk, watch customers trade against it and positions build, settle one on-chain, and watch the fanua:position.settled event fire. Self-contained mock — no real swap is broadcast.
Same loader as every Fanua widget — add it once and skip this step if it's already on the page.
<!-- In your <head> or before </body> --> <script src="https://tdcoffee-b523e.web.app/fanua-widget.js"></script>
Scope the token to venue_desk. A venueId is required for this scope.
const { token } = await fanua.createEmbedToken({ scope: ['venue_desk'], venueId: 'ven_...', });
curl -X POST \ https://us-central1-tdcoffee-b523e.cloudfunctions.net/createEmbedToken \ -H 'Content-Type: application/json' \ -H 'X-API-Key: YOUR_API_KEY' \ -d '{"data":{"scope":["venue_desk"],"venueId":"ven_..."}}'
The desk fires fanua:position.settled each time a position is settled on-chain.
// Fetch the token from your backend const { token } = await fetch('/api/embed-token').then(r => r.json()); const widget = window.Fanua.TradeDesk({ target: '#trade-desk', // any CSS selector or HTMLElement token, onPositionSettled({ pair, side, settlementId, pnl }) { console.log('Settled', pair, side, pnl); }, onError({ code, message }) { console.error(code, message); }, }); // Unmount when done // widget.destroy();