# Send transactions

> Execute a single transaction

> For the complete documentation index, see [llms.txt](/docs/llms.txt).

This guide covers how to send a single EVM transaction.

The client defaults to using [EIP-7702](/docs/wallets/transactions/using-eip-7702), so your EOA will be delegated to a smart wallet to enable gas sponsorship, batching, and more. The SDK handles delegation automatically on the first transaction.

## Prerequisites

* API key from your [dashboard](https://dashboard.alchemy.com/apps)
* A funded Smart Wallet to cover gas fees ([or a gas manager policy to sponsor gas](/docs/wallets/transactions/sponsor-gas))

## Implementation

<Tabs>
  <Tab title="JavaScript" language="typescript">
    <Info>`@alchemy/wallet-apis` (v5.x.x) is currently in beta but is the recommended replacement for `@account-kit/wallet-client` (v4.x.x). If you run into any issues, please [reach out](mailto:support@alchemy.com).</Info>

You can send transactions using the smart wallet client [`sendCalls`](/docs/wallets/reference/wallet-apis/functions/sendCalls) action.

<CodeBlocks>
  ```ts title="sendCalls.ts"
  import { client } from "./client.ts";

  // Send the transaction
  const { id } = await client.sendCalls({
    calls: [
      {
        to: "0x0000000000000000000000000000000000000000",
        value: BigInt(0),
        data: "0x",
      },
    ],
  });

  console.log({ id }); // the Call ID

  // Wait for the transaction to be confirmed
  const result = await client.waitForCallsStatus({ id });

  console.log(result);
  ```

  ```ts title="client.ts"
  import type { Hex } from "viem";
  import { arbitrumSepolia } from "viem/chains";
  import { privateKeyToAccount } from "viem/accounts";
  import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";

  export const client = createSmartWalletClient({
    transport: alchemyWalletTransport({
      apiKey: "YOUR_API_KEY",
    }),
    chain: arbitrumSepolia,
    signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
    // Optional: sponsor gas for your users (see "Sponsor gas" guide)
    // paymaster: { policyId: "YOUR_POLICY_ID" },
  });
  ```
</CodeBlocks>

    <Accordion title="Using @account-kit/wallet-client (v4.x.x)?">
The examples on this page use `@alchemy/wallet-apis` (v5.x.x). If you're using `@account-kit/wallet-client` (v4.x.x), the client setup looks like this:

```ts title="client.ts (v4.x.x)"
import { LocalAccountSigner } from "@aa-sdk/core";
import { createSmartWalletClient } from "@account-kit/wallet-client";
import { alchemy, sepolia } from "@account-kit/infra";

const signer = LocalAccountSigner.privateKeyToAccountSigner("0xYOUR_PRIVATE_KEY" as const);

export const client = createSmartWalletClient({
  transport: alchemy({ apiKey: "YOUR_API_KEY" }),
  chain: sepolia,
  signer,
  account: signer.address, // can also be passed per action as `from` or `account`
  // Optional: sponsor gas for your users (see "Sponsor gas" guide)
  policyId: "YOUR_POLICY_ID", 
});
```

Key v4.x.x differences:
* **Account address** must be specified on the client or per action (`from` or `account`). In v5.x.x, the client automatically uses the owner's address as the account address via [EIP-7702](/docs/wallets/transactions/using-eip-7702).
* **Chain imports** come directly from `@account-kit/infra` instead of `viem/chains`.
* **Numeric values** use hex strings: `value: "0x0"` instead of `value: BigInt(0)`.
* In v4.x.x, the **paymaster capability** on `prepareCalls` or `sendCalls` is called `paymasterService` instead of `paymaster`, or you can set the `policyId` directly on the client.
* **Owners** use `LocalAccountSigner` / `WalletClientSigner` from `@aa-sdk/core`. In v5.x.x, a viem `LocalAccount` or `WalletClient` is used directly.

See the [full migration guide](/docs/wallets/resources/migration-v5) for a complete cheat sheet.
</Accordion>

  </Tab>

  <Tab title="API" language="bash">
    <Info>
  The examples provided use [jq](https://jqlang.org/) to parse json and
  [foundry](https://getfoundry.sh/) to sign a raw payload.
</Info>

See the [`wallet_prepareCalls`](/docs/wallets/api-reference/smart-wallets/wallet-api-endpoints/wallet-api-endpoints/wallet-prepare-calls),
[`wallet_sendPreparedCalls`](/docs/wallets/api-reference/smart-wallets/wallet-api-endpoints/wallet-api-endpoints/wallet-send-prepared-calls),
and [`wallet_getCallsStatus`](/docs/wallets/api-reference/smart-wallets/wallet-api-endpoints/wallet-api-endpoints/wallet-get-calls-status)
API reference for full descriptions of the parameters used in the following example.

<Steps>

<Step title="Declare your secrets">

```bash twoslash
ALCHEMY_API_KEY=your-alchemy-api-key
CHAIN_ID=0x66eee # Your desired chain ID as hex
SIGNER_ADDRESS=your-signer-address
SIGNER_PRIVATE_KEY=your-signer-private-key
```

</Step>

<Step title="Prepare calls">

Prepare the calls using your signer address as the `from` field to enable [EIP-7702](/docs/wallets/transactions/using-eip-7702) by default. You can use your signer address directly without first calling `wallet_requestAccount`.

```bash twoslash
PREPARE_CALLS_RESPONSE=$(curl --request POST \
  --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
  --header 'accept: application/json' \
  --data '
{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "wallet_prepareCalls",
    "params": [
      {
        "calls": [
            {
                "to": "0x0000000000000000000000000000000000000000",
                "data": "0x",
                "value": "0x00"
            }
        ],
        "from": "'$SIGNER_ADDRESS'",
        "chainId": "'$CHAIN_ID'"
      }
    ]
}')
```

</Step>

<Step title="Sign the prepared calls">

Sign the returned signature request. How you do this will vary depending on your environment.

If the account hasn't been delegated yet, the response type will be `array` containing both an EIP-7702 authorization and a transaction that need to be signed. Once delegated (after the first successful transaction), subsequent calls will only return a transaction to sign.

```bash twoslash
# Extract values from prepare calls response
CALL_TYPE=$(echo $PREPARE_CALLS_RESPONSE | jq -r .result.type)
CALL_DATA=$(echo $PREPARE_CALLS_RESPONSE | jq -r .result.data)

if [ "$CALL_TYPE" = "array" ]; then
  # First transaction: sign both authorization and user operation
  # Sign the 7702 authorization
  AUTH_PAYLOAD=$(echo $PREPARE_CALLS_RESPONSE | jq -r '.result.data[0].signatureRequest.rawPayload')
  AUTH_SIGNATURE=$(cast wallet sign --no-hash --private-key "$SIGNER_PRIVATE_KEY" "$AUTH_PAYLOAD")

  # Sign the user operation
  UO_PAYLOAD=$(echo $PREPARE_CALLS_RESPONSE | jq -r '.result.data[1].signatureRequest.data.raw')
  UO_SIGNATURE=$(cast wallet sign --private-key "$SIGNER_PRIVATE_KEY" "$UO_PAYLOAD")

  # Build the signed array data
  SIGNED_DATA=$(echo $PREPARE_CALLS_RESPONSE | jq -c --arg auth_sig "$AUTH_SIGNATURE" --arg uo_sig "$UO_SIGNATURE" '
    .result.data | [
      { type: .[0].type, data: .[0].data, chainId: .[0].chainId, signature: { type: "secp256k1", data: $auth_sig } },
      { type: .[1].type, data: .[1].data, chainId: .[1].chainId, signature: { type: "secp256k1", data: $uo_sig } }
    ]')
else
  # Subsequent transactions: sign only the user operation
  SIGNATURE_PAYLOAD=$(echo $PREPARE_CALLS_RESPONSE | jq -r .result.signatureRequest.data.raw)
  SIGNATURE=$(cast wallet sign --private-key "$SIGNER_PRIVATE_KEY" "$SIGNATURE_PAYLOAD")
fi
```

<Warning>
  Using `cast wallet sign --no-hash` for the authorization payload is acceptable for testing but not recommended for production. See [Using EIP-7702](/docs/wallets/transactions/using-eip-7702) for production signing recommendations.
</Warning>

</Step>

<Step title="Send the prepared calls">

Send the signed calls using `wallet_sendPreparedCalls`.

```bash twoslash
if [ "$CALL_TYPE" = "array" ]; then
  # Send the array of signed calls
  SEND_CALLS_RESPONSE=$(echo '{}' | jq -n \
    --argjson signed_data "$SIGNED_DATA" \
    --arg chain_id "$CHAIN_ID" \
    '{
      "id": 1,
      "jsonrpc": "2.0",
      "method": "wallet_sendPreparedCalls",
      "params": [{
        "type": "array",
        "data": $signed_data
      }]
    }' | curl --request POST \
      --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
      --header 'accept: application/json' \
      --data @-)
else
  # Send the single user operation
  SEND_CALLS_RESPONSE=$(echo '{}' | jq -n \
    --arg call_type "$CALL_TYPE" \
    --argjson call_data "$CALL_DATA" \
    --arg chain_id "$CHAIN_ID" \
    --arg signature "$SIGNATURE" \
    '{
      "id": 1,
      "jsonrpc": "2.0",
      "method": "wallet_sendPreparedCalls",
      "params": [{
        "type": $call_type,
        "data": $call_data,
        "chainId": $chain_id,
        "signature": {
          "type": "secp256k1",
          "data": $signature
        }
      }]
    }' | curl --request POST \
      --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
      --header 'accept: application/json' \
      --data @-)
fi

CALL_ID=$(echo $SEND_CALLS_RESPONSE | jq -r '.result.id')
```

</Step>

<Step title="Check the calls status">

Finally, use `wallet_getCallsStatus` to check the status of the call. A "pending" state (1xx status codes) is expected for some time before the transition to "confirmed," so this endpoint should be polled while the status is pending. If the call does not progress, refer to the [retry guide](/docs/wallets/transactions/retry-transactions). The [API documentation](/docs/wallets/api-reference/smart-wallets/wallet-api-endpoints/wallet-api-endpoints/wallet-get-calls-status#response.body.status) provides details on each status code.

```bash twoslash
curl --request POST \
  --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
  --header 'accept: application/json' \
  --data '
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "wallet_getCallsStatus",
  "params": [
    "'$CALL_ID'"
  ]
}'
```

</Step>

</Steps>

  </Tab>
</Tabs>

## Advanced

<Accordion title="Encoding function data">
  If you need to encode function data (instead of sending value), do so using Viem or Foundry.

  <Tabs>
    <Tab title="JavaScript" language="typescript">
      In JavaScript, you can use [Viem](https://viem.sh/docs/contract/encodeFunctionData) to encode function call data.

<CodeBlocks>
  ```ts title="sendCalls.ts" focus={9-14}
  import { encodeFunctionData } from "viem";
  import { client } from "./client.ts";
  import { exampleAbi } from "./abi.ts";

  await client.sendCalls({
    calls: [
      {
        to: "0x0000000000000000000000000000000000000000",
        data: encodeFunctionData({
          abi: exampleAbi,
          functionName: "mintTo",
          args: ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"],
        }),
      },
    ],
  });
  ```

  ```ts title="abi.ts"
  export const exampleAbi = [
    {
      inputs: [{ name: "recipient", type: "address" }],
      name: "mintTo",
      outputs: [{ name: "", type: "uint256" }],
      stateMutability: "nonpayable",
      type: "function",
    },
  ] as const;
  ```

  ```ts title="client.ts"
  import type { Hex } from "viem";
  import { arbitrumSepolia } from "viem/chains";
  import { privateKeyToAccount } from "viem/accounts";
  import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";

  export const client = createSmartWalletClient({
    transport: alchemyWalletTransport({
      apiKey: "YOUR_API_KEY",
    }),
    chain: arbitrumSepolia,
    signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
  });
  ```
</CodeBlocks>

    </Tab>

    <Tab title="API" language="bash">
      You can use [foundry](https://getfoundry.sh/cast/reference/calldata#cast-calldata) to encode function call data. Use your signer address directly as the `from` field to enable [EIP-7702](/docs/wallets/transactions/using-eip-7702) by default.

```bash twoslash focus={14}
curl --request POST \
  --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
  --header 'accept: application/json' \
  --data '
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "wallet_prepareCalls",
  "params": [
    {
      "calls": [
        {
          "to": "0x0000000000000000000000000000000000000000",
          "data": "'$(cast calldata "mintTo(address)" $SIGNER_ADDRESS)'"
        }
      ],
      "from": "'$SIGNER_ADDRESS'",
      "chainId": "'$CHAIN_ID'"
    }
  ]
}'
```

    </Tab>
  </Tabs>
</Accordion>

<Accordion title="Usage with prepare calls">
  Instead of using the `sendCalls` abstraction, you can prepare and send calls using underlying methods. Usage of the capability will be the same as when using send calls. It is recommended to use `prepareCalls` if you want to inspect the prepared call prior to prompting the user for signature.

  <Tabs>
    <Tab title="JavaScript" language="typescript">
      <Info>`@alchemy/wallet-apis` (v5.x.x) is currently in beta but is the recommended replacement for `@account-kit/wallet-client` (v4.x.x). If you run into any issues, please [reach out](mailto:support@alchemy.com).</Info>

You can use smart wallet client actions to prepare, sign, and send transactions.

<CodeBlocks>
  ```ts title="sendCalls.ts" focus={4-21}
  import { client } from "./client.ts";

  // Prepare the calls
  const preparedCalls = await client.prepareCalls({
    calls: [
      {
        to: "0x0000000000000000000000000000000000000000",
        value: BigInt(0),
        data: "0x",
      },
    ],
  });

  // Inspect the prepared calls before signing
  console.log({ preparedCalls });

  // Sign the prepared calls
  const signedCalls = await client.signPreparedCalls(preparedCalls);

  // Send the signed calls
  const sentCalls = await client.sendPreparedCalls(signedCalls);

  console.log({ sentCalls });
  ```

  ```ts title="client.ts"
  import type { Hex } from "viem";
  import { arbitrumSepolia } from "viem/chains";
  import { privateKeyToAccount } from "viem/accounts";
  import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";

  export const client = createSmartWalletClient({
    transport: alchemyWalletTransport({
      apiKey: "YOUR_API_KEY",
    }),
    chain: arbitrumSepolia,
    signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
  });
  ```
</CodeBlocks>

See the [`prepareCalls`](/docs/wallets/reference/wallet-apis/functions/prepareCalls), [`signPreparedCalls`](/docs/wallets/reference/wallet-apis/functions/signPreparedCalls), and [`sendPreparedCalls`](/docs/wallets/reference/wallet-apis/functions/sendPreparedCalls) SDK references for full parameter descriptions.

    </Tab>

    <Tab title="API" language="bash">
      See the [`wallet_prepareCalls` API reference](/docs/wallets/api/smart-wallets/wallet-api-endpoints/wallet-api-endpoints/wallet-prepare-calls).
    </Tab>
  </Tabs>
</Accordion>

## Next steps

Build more:

* [Sponsor gas for users](/docs/wallets/transactions/sponsor-gas)
* [Send batch transactions](/docs/wallets/transactions/send-batch-transactions)

Troubleshooting:

* [Common errors](/docs/wallets/resources/faqs#common-errors)