Skip to main content
Use this guide when you want your own UI — asset selector, amount input, buttons, status — and the SDK only as the execution engine. This is the pattern our live production integrations use. The prebuilt modals (SpiceSupply, SpiceDeposit) package this same pipeline; use them instead if you want less code. The pattern, per market:
  1. Describe the market’s token as a destinationToken.
  2. Write one buildActionCalls function returning the market’s on chain calls (approve + supply).
  3. useSupplyAssets lists every asset the user can fund it with, across all supported chains.
  4. useSupplyQuote resolves routing (swap needed or direct) for the selected source asset.
  5. estimateFeePreview produces the fee quote — surface it before enabling the submit button.
  6. executeSupply runs the whole flow: funding, routing, delegation signing, solver execution.
The user never bridges and never needs gas on the source chain — the Spicenet solver executes via EIP 7702 and covers gas on the routing legs, accounted for in the fee quote. If your app already sponsors gas on the destination chain (e.g. Privy gas sponsorship on Base), keep it: it applies to your app’s own transactions and needs no SDK configuration.

Provider Setup

SpiceFlowProvider does not mount Privy, wagmi, or react-query — it reads wallet state from those contexts. Your app mounts all four, in this order:
One chains array feeds wagmi, Privy, and the SDK, so the three stay consistent by construction. If you restrict to specific chains instead, keep all three in sync — a chain missing from the PrivyProvider config fails at wallet-client creation with “Chain X is not configured in PrivyProvider”. If you already run Privy, reuse your existing PrivyProvider — just add the source chains you enable. For production, put your own RPC URLs in the wagmi transports — the bare http() falls back to each chain’s public endpoint, which rate-limits under real traffic.
The styles.css import is required even with a fully custom UI — the Privy login modal renders unstyled (invisible) without it. On Vite, also polyfill Node’s Buffer global before the SDK loads; cross-chain swap quoting references it at runtime.

Complete Example

A supply panel for one market. Verified against @spicenet-io/spiceflow-ui@4.7.9.
Everything above the JSX is wiring; the JSX is yours to replace entirely.

Scaling to All Markets

Only two things vary per market: destinationToken and buildActionCalls. Wrap the panel in a component that takes those as props (or a market config object) and every market gets any-asset, any-chain funding with the same code path.

Withdrawals

SpiceWithdraw handles withdrawing Spice balances back to a wallet on any supported chain. To build your own withdraw UI instead, use useSpiceAssets for balances and useSpiceExecution for execution — see Hooks.

Testing

Set network="testnet" on SpiceFlowProvider (and swap the wagmi/Privy chain set to the testnet chains) to run the identical flow against testnet infrastructure. Testnet funds for supported tokens come from the airdrop endpoint. Move to network="mainnet" only after the full supply → withdraw loop passes on testnet.

Notes

  • feeExecutionMode: "backend-transfer" lets the backend collect fees from the funded amount; the fee quote’s netAmount is what reaches the market.
  • executeSupply drives your state through the ui setters — render step, statusMsg, and error however you like. Steps: idle → signing-delegation → signing-intent → submitting → executing → success | error.
  • Supported chains come from the SDK per network — see Configuration. Restrict with supportedChainIds or sourceChains on useSupplyAssets.