Skip to main content
Turnkey works well for backend EIP-7702 flows. This is the minimal Supertransaction API flow: request a quote, sign the 7702 authorization if required, sign the payload from the API response, then execute.
Signing the payload is the critical step. The API returns payloadToSign, and you must sign it with Turnkey before calling /v1/execute.

Minimal EIP-7702 flow

import { Turnkey } from "@turnkey/sdk-server";
import { createAccount } from "@turnkey/viem";
import { createWalletClient, http } from "viem";
import { base } from "viem/chains";

const turnkey = new Turnkey({
  apiBaseUrl: process.env.BASE_URL, // https://api.turnkey.com
  apiPrivateKey: process.env.API_PRIVATE_KEY,
  apiPublicKey: process.env.API_PUBLIC_KEY,
  defaultOrganizationId: process.env.ORGANIZATION_ID,
});

const account = await createAccount({
  client: turnkey.apiClient(),
  organizationId: process.env.ORGANIZATION_ID,
  signWith: process.env.SIGN_WITH,
});

const walletClient = createWalletClient({
  account,
  chain: base,
  transport: http(),
});

const ownerAddress = account.address;

let quoteResponse = await fetch("https://api.biconomy.io/v1/quote", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    mode: "eoa-7702",
    ownerAddress,
    composeFlows: [...],
  }),
});

if (quoteResponse.status === 412) {
  const { authorizations } = await quoteResponse.json();
  const signedAuths = await Promise.all(
    authorizations.map(async (authItem) => {
      const authorization = await walletClient.signAuthorization({
        account,
        ...authItem,
      });

      return {
        ...authorization,
        yParity: authorization.yParity,
        v: authorization.v?.toString(),
      };
    })
  );

  quoteResponse = await fetch("https://api.biconomy.io/v1/quote", {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      mode: "eoa-7702",
      ownerAddress,
      composeFlows: [...],
      authorizations: signedAuths,
    }),
  });
}

const quote = await quoteResponse.json();
const payload = quote.payloadToSign[0];
const signablePayload = payload.signablePayload ?? payload;

const signature = await walletClient.signMessage({
  account,
  message: signablePayload.message,
});

await fetch("https://api.biconomy.io/v1/execute", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    ...quote,
    payloadToSign: [{ ...payload, signature }],
  }),
});