Wallet Provider
Spice Flow uses Privy for wallet connections and embedded wallets.Privy
Best for embedded wallets and social logins.PrivyProvider (which the SDK reads through Privy’s hooks), not on SpiceFlowProvider:
privyAppId and embeddedWalletConfig props on SpiceFlowProvider exist for compatibility but
have no effect in the current release.
Get Your Privy App ID:
- Sign up at privy.io
- Create a new app
- Copy your App ID from the dashboard
Execution Modes
mode="7702" selects the embedded account (default). mode="ondemand" selects the external
account; "presign" is an alias of "ondemand". These account modes do not mean that all
external-mode actions are implemented through host callbacks.
- A positive-amount external action using its matching destination token on the destination chain executes directly from that wallet, with its native gas. Fee-only and proceeds-funded actions are excluded.
- Other supported sources use the routed path through the embedded wallet. The host defines destination
calls and any separate beneficiary; it does not send the transaction through
onPayExecuteoronLockExecute. - Same-wallet, same-chain embedded actions that need no routing execute without an unnecessary Spice funding leg.
SpiceDeposit / SpiceWithdraw retain their own non-7702 callbacks (onDepositExecute,
onWithdrawExecute). They are account funding/withdrawal flows, not the Supply/Lock override contract.
Use useSpiceAccount() to render mode and owner. Omit a fixed provider mode when the SDK account
toggle should control it. Funding from both connected wallets is enabled by default; mode chooses the
account owner and is not a source-wallet filter. See Migration.
Card and Exchange Deposits
Available from@spicenet-io/spiceflow-ui@4.7.11. When enabled, SpiceDeposit opens with a source
chooser in front of the existing flow: Wallet, Card, or Exchange. Card and exchange deposits
run through the Swapper Finance widget, and the SDK verifies on chain that the USDC arrived before handing
off. Users can fund with a debit card or from an exchange account instead of only from a connected wallet.
It is off by default. Nothing changes for your integration until you opt in:
enabled: true is the only required field. The integrator id defaults to Spicenet’s; pass
integratorId only if Swapper has issued you your own.
Where the funds land
Swapper delivers USDC to the wallet the user is operating with, and the wallet mode decides what happens next.
Swapper currently delivers to Base and Arbitrum. An embedded deposit always lands on Arbitrum
because escrow abstracts the chain downstream. An external deposit lands on your app’s chain when Swapper
covers it, and on Arbitrum when it does not. The app’s chain is read from
destinationChainId on
SpiceDeposit, falling back to nativeChainId on the provider.
If your app runs on a chain Swapper does not deliver to, an external-wallet user’s card or exchange deposit
ends up on Arbitrum, in their own wallet. Consider enabling this only for embedded-wallet users on those
chains, or make sure your flow can handle funds arriving there.
Telling the two outcomes apart
onDepositSuccess on SpiceDeposit reports which path completed through detail.type:
"deposit" keeps working and will not treat a wallet funding as a spice
credit.
The source chooser only appears on network="mainnet"; testnets skip it and go straight to the wallet
flow.
Network Configuration
Set the network to control which chains are available:Default Chains by Network
The SDK derives the chain set from the installed core package: Mainnet: Ethereum (1), Base (8453), Arbitrum (42161), Citrea (4114), Robinhood (4663), BSC (56), Polygon (137), Monad (143) Testnet: Sepolia (11155111), Arbitrum Sepolia (421614), Base Sepolia (84532), Citrea Testnet (5115), Base Camp (123420001114), Pharos (688688), Pharos Atlantic (688689), Robinhood Testnet (46630), Monad Testnet (10143), BSC Testnet (97), Avalanche Fuji (43113), Polygon Amoy (80002), Optimism Sepolia (11155420) The list grows with releases — read it from your installed version withgetChainIdsByNetwork("mainnet") (exported from the SDK) rather than hardcoding.
Custom Chain IDs
Override the defaults withsupportedChainIds:
RPC provider and token discovery
Wallet token discovery and USD prices use the Alchemy API of the RPC endpoint in use for a chain. On an endpoint that is not Alchemy’s, or on a chain where Alchemy has no token API, the SDK lists only the tokens configured for that chain, and balances show without provider prices. Pass your own endpoint per chain withrpcOverrides; a chain without an entry uses the SDK’s built-in endpoint. Production integrations should supply their own endpoints for the chains they exercise. Wagmi transports alone do not configure SDK reads. Rollup price lookups require a host-configured RPC.
Liquidity Venues
Available from@spicenet-io/spiceflow-ui@4.8.0. When a flow has to swap on the destination chain,
the SDK quotes every liquidity venue that covers that chain and takes the best fill: the most output
for an exact input, the least input for an exact output. Routing is decided in the SDK, on your RPC.
The solver only executes the calls the winning quote produced.
Leave liquidityVenues off and you get the built-in venues:
Every built-in serves both swap directions, so a venue is never reachable for an exact-input swap
but missing for an exact-output one.
A supported chain still needs a configured venue and liquidity for the requested swap pair. The SDK
has no keyless 1inch fallback in its default venue list. For deployments outside the built-ins,
declare a venue explicitly; both exact-input and exact-output routing use the declaration.
Adding your own venue
Declare it once on the provider and every component picks it up. This is the whole change needed to route through a deployment the SDK does not ship — here, the SushiSwap v3 deployment on Robinhood:Turning the built-ins off
SetincludeDefaults: false to drop every built-in venue, and route only through
what you declared:
includeDefaults off (or true) to keep the built-ins and
add yours alongside them.
Venue fields
Supply the deployment’s addresses, not a pool address. A v3-style pool calls back intomsg.sender, so swaps go through the router and quotes through the quoter; the SDK finds the pools
itself from the fee tiers (or tick spacings) and hub currencies.
Each entry names exactly one chain. Declare the same deployment twice if it runs on two chains.
nameis shown to the user asvia <name>once an exact-output swap is quoted. It defaults to the protocol.hubCurrenciesare the intermediate tokens tried for two-hop routes, usually wrapped native and the chain’s main stablecoin.feeTiers/tickSpacingsare the pool tiers to search. Include any non-standard tier your venue uses, such as PancakeSwap’s 2500.
Every venue covering a chain is quoted on every keystroke, and each one costs several quoter calls
against your RPC (roughly
feeTiers x (1 + hubCurrencies) per venue). Adding venues improves
fill and increases RPC load. Scope chainId tightly and keep hubCurrencies to the tokens that
actually carry liquidity.Venues from another protocol family
Most DEXs are forks of one of the three families above, so adding one is addresses only. A venue built on a different family — a Uniswap v2 pair, Curve, Balancer — needs an adapter inside the SDK, because the SDK owns the calldata rather than asking you to encode swaps yourself. Send us the chain, router, quoter and one funded pool and it becomes aprotocol every integration can name.
Theming
Set your app’s visual identity through thetheme prop. All SDK components inherit these values.
API URL Override
By default, the SDK connects to the Spicenet relayer. Override this if you’re proxying requests or using a custom deployment:Complete Provider Reference
Next Steps
Styling
Customize component appearance
Components
Explore available components
Examples
See complete examples
Best Practices
Security and integration patterns
