Integrate the fan-out widget
Drop cross-chain disperse into your product: your users send to many wallets, across Ethereum, Arbitrum, Optimism, Base, Polygon and BNB Chain, in one signature — and you earn on every swap. Paying from TON, Solana, Bitcoin, XRP and the rest of the 25+ networks lives in the Cherum app the card links to. Non-custodial, no KYB, no forms: your wallet address is the whole registration.
Quick start — iframe¶
The simplest path: copy, replace integrator with your wallet, done. The listener auto-sizes the frame as the widget grows.
<iframe id="cherum-widget"
src="https://app.cherum.io/en/embed?integrator=0xYourWalletAddress&integratorBps=20&theme=dark&accent=%238B6FE6"
style="width:100%;max-width:460px;height:600px;border:0;border-radius:18px"
allow="clipboard-write" loading="lazy"></iframe>
<script>
window.addEventListener('message', function (e) {
if (e.origin !== 'https://app.cherum.io') return;
if (e.data && e.data.type === 'cherum-embed:height') {
document.getElementById('cherum-widget').style.height = e.data.height + 'px';
}
});
</script>Try configurations live in the playground — it generates this snippet for you.
Quick start — script tag¶
One tag, auto-height included. The loader mounts the same secure iframe under the hood and wires the resize listener for you.
<script src="https://cdn.cherum.io/widget.js" async></script>
<div id="cherum-widget"></div>
<script>
window.addEventListener('load', function () {
Cherum.mount('#cherum-widget', {
integrator: '0xYourWalletAddress', // your wallet — receives your fee
integratorBps: 20, // your cut · default 20 (0.2%) · cap 500
theme: 'dark',
accent: '#8B6FE6' // any hex — your brand color
});
});
</script>Quick start — React¶
The typed component wraps the same embed. Config maps 1:1 to the script loader.
// npm install @cherum/widget-react
import { CherumWidget } from '@cherum/widget-react';
export default function Pay() {
return (
<CherumWidget
integrator="0xYourWalletAddress"
integratorBps={20}
theme="dark"
accent="#8B6FE6"
source={{ chain: 'arbitrum', token: 'USDC', amount: '1000' }}
recipients={[
{ chain: 'base', token: 'USDC' },
{ chain: 'optimism', token: 'USDC' },
]}
/>
);
}Parameters¶
Same fields in all three forms (URL query for the raw iframe, config object for the loader and React). Everything is optional except integrator — required to earn.
| Field | Type | Default | Notes |
|---|---|---|---|
mode | 'payouts' | — | Switches the card from swap/fan-out to mass payouts (one token on one network to a list of address + amount rows). See Payouts widget. |
integrator | address | — | Your EVM wallet. Receives your fee on-chain (Model A) and identifies you for off-chain accrual (Model B). |
integratorBps | number | 20 | Your EVM markup in basis points. Cap 500 (5%). Baked into your snippet — nothing stored server-side. |
theme | 'dark' | 'light' | 'dark' | Fixes the card theme regardless of the host page. |
accent | string | — | Brand accent as free HEX (#RRGGBB, #RGB or #RRGGBBAA); hover and text shades derive automatically. Invalid values are ignored. Iframe query: accent=%238B6FE6 (URL-encode the #). |
branding | boolean | true | Reserved: the flag is accepted but not applied yet — the “Powered by” footer always shows today. |
lockSource | boolean | false | Locks the pre-set source chain/token (checkout-style flows). |
source | object | — | { chain, token, amount? } — prefill of the pay side. Iframe query: src=arbitrum.USDC&amt=1000 (dot between chain and token). |
recipients | array | — | Pre-set fan-out destinations, see below. Iframe query: to=base.USDC,optimism.USDC. Destinations are EVM only and capped at 12 per swap; anything else is dropped and named in the card. |
radius | number | 18 | Corner radius in px, 0–40 — applies inside the card and works in all three forms (iframe query: radius=12). |
maxWidth | number | 460 | Frame width cap (loader/React only; for the raw iframe set your own CSS). |
fullpage | 1 | — | Hosted checkout page: open the embed URL directly (no iframe needed) — the card centers on a full page. Combine with bg (page background, HEX like accent) and title (your brand line above the card, ≤64 chars). Example: /en/embed?integrator=0x…&fullpage=1&bg=%23081018&title=Acme%20Pay. |
Source & recipients¶
Pre-set destinations are chain × token pairs — the user fills addresses and split percentages inside the widget (they must confirm where their money goes; that stays in their hands).
source: { chain: 'arbitrum', token: 'USDC', amount: '1000' },
recipients: [
{ chain: 'base', token: 'USDC' },
{ chain: 'optimism', token: 'USDC' },
{ chain: 'polygon', token: 'USDT' },
]Pre-set destinations are EVM only. chain is one of ethereum, arbitrum, optimism, base, polygon, bsc; token is USDC or USDT where that pair exists on the chain (no USDT on Base or Optimism). Non-EVM destinations — TON, Tron, Solana, Bitcoin — are a source feature today: your users pay from them in the app, and the embedded card cannot send to them. A pair the card cannot execute is dropped rather than substituted, and the card says which one. At most 12 recipients travel in one swap.
Gas on arrival. On supported routes every recipient lands with a little native coin, ready to transact — no separate top-up.
Payouts widget¶
The same card, switched to mass payouts: your users send one token on one network to a list of address + amount rows — typed in, or pasted as CSV straight from a spreadsheet. Large lists are split into batches automatically — the batch size is whatever fits one transaction on that chain, so it runs from 60 recipients on HyperEVM to 900 on Polygon, and the token path fits more than the native one (546 recipients per transaction for a token on Base) — with pause and resume between batches. Safe multisigs work as senders out of the box: the card detects a contract wallet, queues the batch for co-signers and picks the result up from the chain.
<iframe id="cherum-payouts"
src="https://app.cherum.io/en/embed?mode=payouts&integrator=0xYourWalletAddress&integratorBps=30&theme=dark"
style="width:100%;max-width:460px;height:520px;border:0;border-radius:18px"
allow="clipboard-write" loading="lazy"></iframe>
<script>
window.addEventListener('message', function (e) {
if (e.origin !== 'https://app.cherum.io') return;
if (e.data && e.data.type === 'cherum-embed:height') {
document.getElementById('cherum-payouts').style.height = e.data.height + 'px';
}
});
</script>Pricing is flat and public — no tiers, no calls, no forms:
- Cherum fee: 0.10% of the batch total. That’s it. A $10,000 payroll batch costs $10 — compare that to per-batch flat fees elsewhere that run into hundreds of dollars.
- Your markup: 100% yours. Set
integratorBpsup to300(3%) — the contract pays it to your wallet in the same transaction as the payout. Verify every settlement in the block explorer; you never have to trust our reports. - The payer sees both lines before signing: our fee, your fee, and the exact total to pay. No surprises after the fact.
- Use
src=base.USDCto pre-select the network and token,lockSource=1to pin them.
Recipients stay in the payer’s hands. The embed config cannot pre-fill recipient addresses — the person signing types or pastes the list themselves and confirms the totals. Your page styles the card; it never controls where the money goes.
Fees & integrator¶
Two models, two rails — they never blend, and your earnings never come out of Cherum’s fee (or vice versa):
- Through the Cherum contract (Model A): your
integratorBpsmarkup is collected by the contract and routed to yourintegratorwallet on-chain, in the same transaction as the swap. Settled the moment the swap settles — nothing to withdraw. - Everywhere else (Model B): some swaps run entirely inside a provider, with no Cherum contract in the execution path — every non-EVM source (TON, Solana, Bitcoin, XRP, Cardano…) and direct aggregator swaps on EVM chains. There is no contract to split on, so the provider withholds your markup together with our share and your part accrues off-chain — set your rate in the dashboard (default 0.2%, up to 1%) and withdraw in USDC on Base. One rate, one balance, whatever the route.
Same wallet everywhere. Sign in to the dashboard with the wallet you set as integrator — attribution keys on it.
Dashboard & payouts¶
- Sign in at dashboard.cherum.io with your integrator wallet — signature only, no email or password.
- Dashboard: your revshare ledger (accrued, pending, paid out, balance), your rate setting, and embed snippets with your wallet baked in.
- Markup paid by the contract is not in the dashboard, by design: it goes to your wallet in the same transaction as the swap, so the block explorer is the receipt — there is nothing for us to report and nothing to trust us on.
- Payouts: request a withdrawal once that balance reaches $50 — paid in USDC on Base to your integrator wallet.
CSP & embedding¶
- The widget runs in an isolated iframe on
app.cherum.io— no styles or scripts leak into your page, and your page cannot touch user funds. - Allow framing: nothing needed on your side — the embed sends
frame-ancestors *. Your CSP needsframe-src https://app.cherum.io(andscript-src https://cdn.cherum.ioif you use the loader). - Auto-height is one-way: the card posts
{type:'cherum-embed:height'}to your page, and the listener in the snippet checkse.originbefore resizing. The card itself listens to nothing, so no page it sits on can drive it. - No trackers, no external fonts — everything is served from Cherum domains.
Next
Playground
Configure the card live and copy the snippet it generates.