Skip to main content
Use sponsored swaps to build gasless trading features where users swap tokens without holding SOL for fees. A sponsor pays the transaction fee and token account creation costs on the user’s behalf. To create a sponsored swap, pass the sponsor parameter with the sponsor’s wallet address on a Trade API request. Both the user and sponsor must sign the resulting transaction.

Why Use User-Executed Sponsored Swaps

  • Smaller transactions. Eliminates the input transfer to the sponsor and output transfer back to the user, reducing overall transaction size.
  • Simpler transaction structure. The user swaps directly from their own token accounts in a single step.

Execution Modes

Execution modes determine who performs the swap. The sponsor performs the swap on the user’s behalf:
  1. User transfers input tokens to sponsor.
  2. Sponsor executes the swap using their token accounts.
  3. Sponsor transfers output tokens to user.

User Executes

The user performs the swap directly using their own token accounts. The sponsor still pays the transaction fee and token account creation costs.

Parameters

The sponsor’s wallet address. When specified, the sponsor pays the transaction fee and token account creation costs. Cannot be specified alongside predictionMarketInitPayer. Base58-encoded.

sponsoredSwap

Set to true to indicate the swap will be sponsored. This ensures the quote accounts for the correct transaction structure and fees based on the execution mode. Not needed on /order or /swap — those endpoints infer sponsorship from the sponsor parameter.

sponsorExec

Choose who executes the swap in a sponsored transaction.
ValueExecutorDescription
true (default)SponsorSponsor executes the swap using their token accounts
falseUserUser executes the swap using their own token accounts
Pass this parameter on three endpoints:
  • GET /order — query parameter, used when sponsor is specified.
  • GET /quote — query parameter, used when sponsoredSwap is true.
  • POST /swap — request body field, used when sponsor is specified.

Code Examples

const SPONSOR_ADDRESS = "SPONSOR_WALLET_ADDRESS";

const params = new URLSearchParams({
  inputMint: "So11111111111111111111111111111111111111112",
  outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  amount: "1000000000",
  userPublicKey: userKeypair.publicKey.toBase58(),
  sponsor: SPONSOR_ADDRESS,
  sponsorExec: "false", // user executes; omit or set "true" for sponsor execution
});

const headers: HeadersInit = {};
if (process.env.DFLOW_API_KEY) {
  headers["x-api-key"] = process.env.DFLOW_API_KEY;
}

const orderResponse = await fetch(
  `${API_BASE_URL}/order?${params.toString()}`,
  { headers }
).then((x) => x.json());

// Both user and sponsor must sign
const tx = VersionedTransaction.deserialize(
  Buffer.from(orderResponse.transaction, "base64")
);
tx.sign([userKeypair, sponsorKeypair]);

const signature = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(signature, "confirmed");
const params = new URLSearchParams({
  inputMint: "So11111111111111111111111111111111111111112",
  outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  amount: "1000000000",
  sponsoredSwap: "true", // required on /quote to signal sponsorship
  sponsorExec: "false",
});

const quoteResponse = await fetch(
  `${API_BASE_URL}/quote?${params.toString()}`,
  { headers }
).then((x) => x.json());
const swapResponse = await fetch(`${API_BASE_URL}/swap`, {
  method: "POST",
  headers: { "Content-Type": "application/json", ...headers },
  body: JSON.stringify({
    quoteResponse,
    userPublicKey: userKeypair.publicKey.toBase58(),
    sponsor: "SPONSOR_WALLET_ADDRESS",
    sponsorExec: false,
  }),
}).then((x) => x.json());

// Both user and sponsor must sign
const tx = VersionedTransaction.deserialize(
  Buffer.from(swapResponse.swapTransaction, "base64")
);
tx.sign([userKeypair, sponsorKeypair]);

const signature = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(signature, "confirmed");