Skip to main content
Use this recipe when your app runs on Base and you want to be paid in a Base asset, but your users hold something else on another network. SODAX turns the payment into a single cross-network swap that settles at an address you control on Base. There are no new contracts and nothing for you to run; the payer signs on the network they are paying from: an approval when the allowance is short, then the swap.

What you will build

A checkout step that takes a payer’s token on a supported EVM network, quotes it against a Base asset, and settles the output at your app’s Base address.

Prerequisites

  • @sodax/sdk, plus @sodax/wallet-sdk-core (or @sodax/wallet-sdk-react in a React app) for the wallet provider.
  • A wallet on the network the payer starts from, funded with that network’s native token for gas.
  • Your app’s receiving address on Base, and a SODAX API key kept on your server. See API keys.
SODAX is mainnet only, so test with small amounts. See Is SODAX on Testnet?.

How it works

1

Key the wallet provider to the payer's network

The payer signs where they are paying from, so the provider belongs to that network, not to Base. Base is only the destination. The recipe types it as an EVM provider; a payer on another network type needs that network’s wallet provider.
2

Resolve both tokens from config

Read the payer’s token from the source network’s swap list and the settlement token from the Base list. Never hard-code addresses or decimals; the recipe throws if a network does not list the symbol.
3

Quote, approve, swap

The quote is the net output that lands on Base, so set your slippage floor from it. The intent’s destination is Base: dstChainKey is ChainKeys.BASE_MAINNET and dstAddress is your address. An ERC-20 input needs an allowance first, so approve only when isAllowanceValid says it is short, and wait for the approval to confirm before you swap. swap() then creates the intent, relays it to the hub, and hands it to a solver.
4

Wait for the fill

A successful swap() is not a fill. SolverIntentStatusCode.SOLVED means a solver filled the intent; to confirm the output was delivered to your Base address, follow it with getSolvedIntentPacket. getStatus is a one-shot read, so the recipe bounds its own poll and stops on FAILED. For what happens to an intent that fails or expires, see Swaps.

Code

Pay from an EVM network and settle at your Base address:
Then wait for the outcome:

Fees and failures

For fees, see Fees. Every call returns a Result; the failure codes are in Swaps.

Next steps