Skip to main content

Wallet Provider

Spice Flow uses Privy for wallet connections and embedded wallets.

Privy

Best for embedded wallets and social logins.
Configuration: your Privy app ID and embedded-wallet policy are configured on your own PrivyProvider (which the SDK reads through Privy’s hooks), not on SpiceFlowProvider:
The privyAppId and embeddedWalletConfig props on SpiceFlowProvider exist for compatibility but have no effect in the current release. Get Your Privy App ID:
  1. Sign up at privy.io
  2. Create a new app
  3. Copy your App ID from the dashboard

Execution Modes

Spice Flow supports three execution modes.

7702 Mode (Default)

Uses EIP 7702 with embedded wallets. The solver executes transactions on behalf of the user via delegate contracts. This is the default and recommended mode for most chains.

Presign Mode

Users sign all transactions upfront using their external wallet. Used for chains that don’t support EIP 7702.

Ondemand Mode

Each transaction is signed on demand during execution. The app handles execution via onDepositExecute / onWithdrawExecute callbacks.
In presign and ondemand modes, the embedded wallet flow is skipped. Components use callback props (like onDepositExecute) instead of the solver execution path.

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:
Code that already checks for "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

As of @spicenet-io/spiceflow-ui@4.7.9: 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 with getChainIdsByNetwork("mainnet") (exported from the SDK) rather than hardcoding.

Custom Chain IDs

Override the defaults with supportedChainIds:

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.
The SDK also registers a 1inch venue, but it carries no API key and 1inch rejects keyless requests, so it never returns a quote, and there is no way to supply a key through this prop. On chains where 1inch is the only thing covering you — the last row above — declare your own venue, or a swap on that chain has nothing to route through.

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:
Your venue races the built-ins on price. It does not override them, and it is used in both swap directions.

Turning the built-ins off

Set includeDefaults: false to drop every built-in venue, including 1inch, and route only through what you declared:
On a chain with no venue at all, quoting then fails naming that chain rather than falling back to something you did not configure. Leave 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 into msg.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.
  • name is shown to the user as via <name> once an exact-output swap is quoted. It defaults to the protocol.
  • hubCurrencies are the intermediate tokens tried for two-hop routes, usually wrapped native and the chain’s main stablecoin.
  • feeTiers / tickSpacings are the pool tiers to search. Include any non-standard tier your venue uses, such as PancakeSwap’s 2500.
Set routerHasDeadline: true when the deployment forked the original Uniswap SwapRouter, whose exact-output structs carry a deadline. SwapRouter02 forks do not, and this is the default.Getting it wrong is invisible until execution: quoting goes through the quoter, which does not care, so the quote looks correct either way and only the transaction reverts. If your exact-output swaps quote cleanly but revert on chain, this flag is the first thing to check.
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 a protocol every integration can name.

Theming

Set your app’s visual identity through the theme prop. All SDK components inherit these values.
See Styling for the full theming reference.

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