Fanua.

Embeddable Widgets

Drop pre-built financial UI directly into your dashboard. Each widget is a sandboxed iframe — your brand colors, your users, zero custody risk.

Available widgets
Live
Balance Display
Shows live wallet balances across EVM and Solana chains. Fires an event on load and on each refresh.
fanua:balance.updated fanua:error
Try simulator Integrate
Live
Trade Desk
An embeddable OTC settlement desk for a trade venue — shows open positions and blended rates, settles them via an on-chain swap, and reports PnL.
fanua:position.settled fanua:error
Try simulator Integrate

Simulator — Balance Display

Mount the widget, fetch balances across chains, and watch the fanua:balance.updated event fire. Self-contained mock — no live account is read.

HOST PAGE
Your site. Mints a token scoped to one account, drops one script tag.
FANUA WIDGET
Sandboxed iframe. Auto-fetches balances on mount.
FANUA API
Validates the token, aggregates balances per instrument.
PROVIDER
Chain RPC — wallet balanceOf · Aave aToken APY.
Host page — your chrome, Fanua's widget
https://yourapp.com/wallet
YOUR APP
// host page — your own code & nav
Fanua.BalanceDisplay
The wire — every request, response & event, in order
Nothing on the wire yetRun step 1 to mint a token and mount the widget.
Quick-start — Balance Display
1

Load the snippet

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>
2

Mint an embed token (server-side)

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_...',
});
3

Mount the widget

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);
  },
});

Simulator — Trade Desk

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.

HOST PAGE
Your venue console. Mints a token scoped to one venue, drops one script tag.
FANUA WIDGET
Sandboxed iframe. Renders positions, drives settlement.
FANUA API
Validates the token, computes positions, settles.
PROVIDER
Uniswap swap · pro-rata payouts to customer wallets.
Venue console — your chrome, Fanua's desk
https://venue.example.com/otc
VENUE CONSOLE
// host page — your own code & nav
Fanua.TradeDesk
The wire — every request, response & event, in order
Nothing on the wire yetRun step 1 to mint a token and mount the desk.
Quick-start — Trade Desk
1

Load the snippet

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>
2

Mint an embed token (server-side)

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/api/createEmbedToken \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -d '{"data":{"scope":["venue_desk"],"venueId":"ven_..."}}'
3

Mount the widget

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();