> For the complete documentation index, see [llms.txt](https://onchainlabs-tech-documentation.gitbook.io/wallettwo-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://onchainlabs-tech-documentation.gitbook.io/wallettwo-documentation/actions/transaction.md).

# Transaction

## Action: `transaction`

**Endpoint:** `/action/transaction`

Allows a third-party host page to trigger one or more sponsored on-chain transactions on behalf of the logged-in WalletTwo user. The user sees a confirmation screen and can approve or cancel. The result is communicated back via `postMessage` and/or redirect.

***

### Required user state

| Check             | Middleware                | Redirects to if missing |
| ----------------- | ------------------------- | ----------------------- |
| User is logged in | `LoggedMiddleware`        | `/auth/login`           |
| Email is verified | `EmailVerifiedMiddleware` | `/auth/email/verify`    |
| Wallet is created | `WalletMiddleware`        | `/auth/wallet/register` |

***

### Iframe URL

```
https://<WALLETTWO_ORIGIN>/action/transaction?iframe=true&network=<CHAIN_ID>&transactions=<JSON_STRING>
```

URL parameters:

| Param          | Required            | Type                    | Description                                                                     |
| -------------- | ------------------- | ----------------------- | ------------------------------------------------------------------------------- |
| `transactions` | Yes                 | JSON string             | Array of transaction objects (see format below)                                 |
| `network`      | Yes                 | `string`                | Chain ID of the network to execute on. Also accepted as `chain_id` or `chainId` |
| `redirect_uri` | No                  | `string` (absolute URL) | Where to redirect after success or cancellation                                 |
| `iframe`       | Yes (for embedding) | `"true"`                | Activates bare rendering mode                                                   |
| `auto_forward` | No                  | `"true"` \| `"false"`   | Auto-navigate to `redirect_uri` after success. Defaults to `false`              |

The network param is resolved in priority order: `network` → `chain_id` → `chainId`. Pass the numeric chain ID as a string (e.g. `"137"` for Polygon).

***

### Transaction object format

`transactions` must be a JSON-encoded array. Each object:

```json
[
  {
    "method": "transfer",
    "params": ["0xRecipientAddress", "1000000000000000000"],
    "address": "0xContractAddress",
    "abi": [{ "name": "transfer", "type": "function", "inputs": [...] }],
    "wait_tx": true
  }
]
```

| Field     | Required | Description                                                                                        |
| --------- | -------- | -------------------------------------------------------------------------------------------------- |
| `method`  | Yes      | Contract method name to call                                                                       |
| `params`  | Yes      | Array of arguments for the method (must be an array)                                               |
| `address` | Yes      | Target contract address                                                                            |
| `abi`     | No       | ABI fragment for the method. Required if the contract is not already known by WalletTwo            |
| `wait_tx` | No       | Whether to wait for on-chain confirmation for this transaction. Defaults to `true`. See note below |

**`wait_tx` behavior:** if *any* transaction in the array has `wait_tx: false`, the entire batch is submitted without waiting for confirmation.

A transaction is considered invalid if `method`, `address`, or `params` is missing, or if `params` is not an array. Any invalid transaction in the array blocks execution and shows the parameter error screen.

***

### What happens when the action runs

1. URL params are parsed and the network is resolved from `network` / `chain_id` / `chainId`.
2. If the resolved network differs from the currently selected network, it switches automatically.
3. The user sees a confirmation screen with a "Confirm" and "Not now" button.
4. On confirm, `execute()` runs:
   * Calls `generateSponsoredTransaction` with all transactions.
   * Sends `transactions_executing` postMessage immediately.
   * On completion, sends `transaction_complete` postMessage.
   * If `redirect_uri` is set, builds the redirect URL and navigates to it (or waits for `auto_forward`).
5. On cancel, sends `transaction_cancelled` postMessage (if no `redirect_uri` and in iframe mode) or navigates to `redirect_uri` with `status=cancelled`.

***

### UI states

| State           | Component                   | When shown                                            |
| --------------- | --------------------------- | ----------------------------------------------------- |
| Confirmation    | Default view                | Network is valid, params are valid, not yet confirmed |
| Network error   | `TransactionNetworkError`   | The `network` param doesn't match any known network   |
| Parameter error | `TransactionParameterError` | Any transaction fails validation                      |
| Executing       | `TransactionExecuting`      | User confirmed, transaction is being submitted        |
| Done            | `TransactionDone`           | Transaction submitted successfully                    |

#### `TransactionExecuting`

Animated gradient progress bar + spinner using the operator's `primaryColor` and `secondaryColor` from `useCustomization`.

#### `TransactionDone`

Success screen with a 2-second countdown. When the countdown hits zero and `autoForward` is `true`, the iframe navigates to `redirect_uri` (if set) or to `/wallet/dashboard`.

#### `TransactionNetworkError`

Warning icon with an explanation that the network in the URL is unrecognized or unsupported.

#### `TransactionParameterError`

Error screen with a "Go back" button that calls `window.history.back()`.

***

### postMessage events

#### On execution start

Sent immediately after the user confirms:

```js
{
  type: "transactions_executing",
  tx: "<transaction-id>",
  status: "executing"
}
```

#### On success

Sent when the transaction is complete:

```js
{
  type: "transaction_complete",
  tx: "<transaction-id>",
  status: "done"
}
```

#### On cancellation (iframe mode, no redirect\_uri)

```js
{
  type: "transaction_cancelled"
}
```

Note: when `redirect_uri` is set and the user cancels, the iframe navigates to the redirect URL instead of sending a `transaction_cancelled` message.

***

### redirect\_uri callbacks

#### On success

```
<redirect_uri>?status=success&txId=<tx-id>&hashes=<tx-hash>
```

| Param    | Description                       |
| -------- | --------------------------------- |
| `status` | Always `"success"`                |
| `txId`   | Internal WalletTwo transaction ID |
| `hashes` | On-chain transaction hash         |

#### On cancellation

```
<redirect_uri>?status=cancelled
```

***

### Host page integration

```html
<iframe
  id="w2-transaction"
  src="https://<WALLETTWO_ORIGIN>/action/transaction?iframe=true&network=137&transactions=%5B%7B%22method%22%3A%22transfer%22%2C%22params%22%3A%5B%220xRecipient%22%2C%221000000000000000000%22%5D%2C%22address%22%3A%220xContract%22%7D%5D"
  style="width:420px;height:700px;border:0;"
></iframe>

<script>
  const WALLET_TWO_ORIGIN = "https://<WALLETTWO_ORIGIN>";

  window.addEventListener("message", (event) => {
    if (event.origin !== WALLET_TWO_ORIGIN) return;

    switch (event.data?.type) {
      case "transaction_complete":
        console.log("Transaction done, id:", event.data.tx);
        break;
      case "transaction_cancelled":
        console.log("User cancelled");
        break;
    }
  });
</script>
```

***

### URL building helper

```js
function buildTransactionUrl(origin, chainId, transactions, options = {}) {
  const url = new URL(`/action/transaction`, origin);
  url.searchParams.set("iframe", "true");
  url.searchParams.set("network", String(chainId));
  url.searchParams.set("transactions", JSON.stringify(transactions));

  if (options.redirectUri) url.searchParams.set("redirect_uri", options.redirectUri);
  if (options.autoForward !== undefined) url.searchParams.set("auto_forward", String(options.autoForward));

  return url.toString();
}

// Example
const src = buildTransactionUrl(
  "https://<WALLETTWO_ORIGIN>",
  137,
  [
    {
      method: "transfer",
      params: ["0xRecipient", "1000000000000000000"],
      address: "0xTokenContract"
    }
  ],
  { redirectUri: "https://example.com/tx-done", autoForward: true }
);
```
