# Send a transaction

You send transactions through the wallet's [Ethereum provider](/docs/products/embedded-wallet/swift/wallet/ethereum-provider) by issuing an `eth_sendTransaction` JSON-RPC call. The embedded wallet signs it securely and submits it; you get back the transaction hash.

:::note
The wallet must be [`.ready`](/docs/products/embedded-wallet/swift/wallet/state) before you can send.
:::

## Send with the async `request` API

The simplest path is the provider's `async` `request(method:params:)`, which returns the transaction hash as a `String`:

```swift
let provider = try await OFSDK.shared.getEthereumProvider(
    params: OFGetEthereumProviderParams(policy: "YOUR_POLICY_ID") // omit policy if not sponsoring gas
)

let txHash = try await provider?.request(
    method: "eth_sendTransaction",
    params: [[
        "from": fromAddress,
        "to": toAddress,
        "value": "0x2386f26fc10000", // 0.01 ETH in wei (hex)
        "data": "0x",                 // ABI-encoded calldata for a contract, or "0x" for a plain transfer
    ]]
)
print("tx: \(txHash ?? "")")
```

`value` and all numeric fields are **hex strings** (prefixed with `0x`). For a plain native transfer leave `data` as `"0x"`; for a contract call set `data` to the ABI-encoded calldata.

## Gas sponsorship

To send **gasless** transactions so your users never need ETH, pass a [sponsorship policy](/docs/configuration/gas-sponsorship) when getting the provider and **omit `gas` / `gasPrice`** from the transaction. Openfort builds the user operation and the paymaster covers the fee:

```swift
let provider = try await OFSDK.shared.getEthereumProvider(
    params: OFGetEthereumProviderParams(policy: "YOUR_POLICY_ID")
)

let txHash = try await provider?.request(
    method: "eth_sendTransaction",
    params: [[
        "from": account.address,
        "to": recipient,
        "value": "0x0",
        "data": "0x",
        // no "gas" / "gasPrice" — the policy sponsors it
    ]]
)
```

:::warning
Gas sponsorship requires a **smart account** (`.smartAccount`) or **delegated account** (`.delegatedAccount`). A plain `.eoa` always pays its own gas — a policy has no effect there. See [Account types](/docs/products/embedded-wallet/account-types) and [Sponsored transactions](/docs/products/embedded-wallet/swift/wallet/eip-7702).
:::

:::warning
**EOA wallets default to Base mainnet.** If you configured an `.eoa` and want to send on a different network, switch first with [`wallet_switchEthereumChain`](/docs/products/embedded-wallet/swift/wallet/switch-chains) before calling `eth_sendTransaction`.
:::

## Transaction fields

Every field is a hex string. Provide `from` and `to`; the rest are optional.

| Field                  | Description                                                              |
| ---------------------- | ----------------------------------------------------------------------- |
| `from`                 | Sender address (the wallet address). Required.                          |
| `to`                   | Recipient address. Omit only when deploying a contract.                 |
| `value`                | Amount of wei to send, as a hex string.                                 |
| `data`                 | ABI-encoded calldata for a contract call, or `"0x"` for a plain transfer. |
| `gas`                  | Max gas units. **Omit when using a sponsorship policy.**                |
| `gasPrice`             | Legacy gas price. **Omit when using a sponsorship policy.**             |
| `maxFeePerGas`         | EIP-1559 max total fee per gas.                                         |
| `maxPriorityFeePerGas` | EIP-1559 priority fee (tip) per gas.                                    |
| `nonce`                | Transaction nonce. Omit to let the provider pick it.                    |

## Next steps

* [Sponsored (gasless) transactions](/docs/products/embedded-wallet/swift/wallet/eip-7702)
* [Switch chains](/docs/products/embedded-wallet/swift/wallet/switch-chains)
* [Sign a message](/docs/products/embedded-wallet/swift/wallet/sign-message)
