Swaps (Alpha)

Swap any token across networks. Integrate in minutes. Built natively into Smart Wallets.

  • 1-click Swap + Action (ex: send, deposit, borrow, pay)
  • Gasless swaps
  • [Coming soon] Cross-chain swaps

Swaps are in early access. The service is production ready, however there may be changes in the future to simplify the endpoint. We will let you know if/when that happens.

Request early access!

The Swap flow

Flow

  1. Request a swap quote
  2. Sign the prepared calls (swap + post swap action)
  3. Send prepared calls (swap + post swap action)
  4. Poll for confirmation

Swap options

1// Mode 1: Swap exact input amount
2{
3 fromAmount: "0x2710";
4} // Swap exactly 0.01 USDC (10000 in hex, 6 decimals)
5
6// Mode 2: Get minimum output amount
7{
8 minimumToAmount: "0x5AF3107A4000";
9} // Get at least 0.0001 ETH (18 decimals). We calculate how much USDC you need to spend to get at least your desired ETH amount!

Prerequisites

Before you begin, ensure you have:

  • An Alchemy API Key
  • A Gas Manager policy
  • A small amount of USDC for testing (~$1 worth is enough!)
    • Important: You’ll need to send these tokens to your smart wallet address in Step 3 of the Implementation!
  • A signer to own the account and sign messages

Note that Swaps are currently only supported via direct APIs. React and other JS options are coming (very) soon!

You will need to fill in values wrapped in curly braces like {SIGNER_ADDRESS}.

1

Request an account

$curl -X POST https://api.g.alchemy.com/v2/{apiKey} \
> -H "Content-Type: application/json" \
> -d '{
> "jsonrpc": "2.0",
> "id": 1,
> "method": "wallet_requestAccount",
> "params": [
> {
> "signerAddress": "{SIGNER_ADDRESS}"
> }
> ]
> }'

This returns:

1{
2 "jsonrpc": "2.0",
3 "id": 1,
4 "result": {
5 "accountAddress": "ACCOUNT_ADDRESS",
6 "id": "ACCOUNT_ID"
7 }
8}

For other potential responses, check out the API reference!

2

Request a swap quote

Note that postCalls are optional and allow you to batch an array of calls after the swap.

$curl -X POST https://api.g.alchemy.com/v2/{API_KEY} \
> -H "Content-Type: application/json" \
> -d '{
> "jsonrpc": "2.0",
> "id": 1,
> "method": "wallet_requestQuote_v0",
> "params": [
> {
> "from": "{ACCOUNT_ADDRESS_FROM_STEP_1}",
> "chainId": "{CHAIN_ID}",
> "fromToken": "{FROM_TOKEN}",
> "toToken": "{TO_TOKEN}",
> "fromAmount": "{FROM_AMOUNT_HEXADECIMAL}",
> "postCalls": [{
> "to:" "{POSTCALL_TO_ADDRESS}",
> "data": "{POSTCALL_DATA}",
> "value": "{POSTCALL_VALUE}"
> }],
> "capabilities": {
> "paymasterService": {
> "policyId": "{PAYMASTER_POLICY_ID}"
> }
> }
> }
> ]
> }'

This returns:

1{
2 "jsonrpc": "2.0",
3 "id": 0,
4 "result": {
5 "rawCalls": false,
6 "chainId": "...",
7 "quote": {
8 "expiry": "EXPIRY",
9 "minimumToAmount": "MINIMUM_TO_AMOUNT",
10 "fromAmount": "FROM_AMOUNT"
11 },
12 "type": "user-operation-v070",
13 "data": "USER_OPERATION_DATA",
14 "signatureRequest": {
15 "type": "personal_sign",
16 "data": {
17 "raw": "..."
18 },
19 "rawPayload": "..."
20 },
21 "feePayment": {
22 "sponsored": true,
23 "tokenAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
24 "maxAmount": "..."
25 }
26 }
27}

Note the signatureRequest! This is what you now have to sign, and the returned data field is what you will need to send the transaction!

3

Sign the signature request

To sign the signature request, you should sign the raw field (note, this is not a string! You need to pass it to your signer as raw bytes, generally like so: { raw: "0x..." }) with your signer of choice.

This should use the personal_sign RPC method, as noted by the type in the signatureRequest.

Alternatively, you can sign the raw payload with a simple eth_sign but this RPC method is not favored due to security concerns.

4

Send the prepared call

$curl -X POST https://api.g.alchemy.com/v2/{apiKey} \
> -H "Content-Type: application/json" \
> -d '{
> "jsonrpc": "2.0",
> "method": "wallet_sendPreparedCalls",
> "params": [
> {
> "type": "user-operation-v070",
> "data": "{DATA_FROM_STEP_2}",
> "chainId": "{CHAIN_ID}",
> "signature": {
> "type": "secp256k1",
> "data": "{SIGNATURE_FROM_STEP_3}"
> }
> }
> ],
> "id": 1
> }'

This returns:

1{
2 "jsonrpc": "2.0",
3 "id": "1",
4 "result": {
5 "preparedCallIds": ["PREPARED_CALL_ID"]
6 }
7}

Note the PREPARED_CALL_ID! You need this to track call status in the next step.

For other potential responses, check out the API reference!

5

Track the prepared call

You can use the wallet_getCallsStatus endpoint to check up on the transaction’s status.

$curl -X POST https://api.g.alchemy.com/v2/{apiKey} \
> -H "Content-Type: application/json" \
> -d '{
> "jsonrpc": "2.0",
> "method": "wallet_getCallsStatus",
> "params": [
> [
> "{PREPARED_CALL_ID_FROM_STEP_4}"
> ]
> ],
> "id": 1
> }'

This returns:

1{
2 "id": "1",
3 "jsonrpc": "2.0",
4 "result": {
5 "id": "PREPARED_CALL_ID",
6 "chainId": "CHAIN_ID",
7 "atomic": true,
8 "status": 200,
9 "receipts": [...]
10 }
11}

Note that the status codes match the following:

CodeTitle
100Pending
200Confirmed
400Offchain Failure
500Onchain Failure
600Partial Onchain Failure

To get your transaction hash, you can access result.receipts[0].transactionHash.

For more details, check out the API reference!

FAQs

What chains are supported?

Chains supported (for now) are: Ethereum, Arbitrum, Base, Berachain, BSC/BNB, Ink, Monad, Optimism, Polygon, Unichain and World Chain mainnets.

Does the Swap API support cross-chain swaps?

Currently, the Swap API supports only single-chain swaps. Cross-chain swaps are coming soon!

How do you encode values?

Values are simply passed as hexadecimal strings. The Swap API doesn’t add complexity to consider decimals, so 0x01 is always the smallest amount of a given asset. 1 ETH, or DAI (18 decimals) is 0xDE0B6B3A7640000 1 USDC (6 decimals) is 0xF4240 This removes any ambiguity— if it’s numerical, it’s a hex.

What is the expiry?

The expiry is an informational indicator of when you can expect to be able to process the swap request. If you’re at/near the expiry, it might be a good time to request a new quote.

What if I’m using React?

Use the @account-kit/react package to access a smartWalletClient. This package automatically uses the Signer for user authentication & signing. Check out the docs for getting started with React to learn more.