> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pods.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# processBytecode Contract

> Host transaction bridge contract for EarnWidget and SwapWidget

`processBytecode` is the required callback for production widget integrations.

It receives bytecode transactions from Pods and must:

1. **Batch** all legs on the same `chainId` into one atomic wallet submission (never one tx per leg).
2. Ask the wallet to sign and submit the batch.
3. Wait for on-chain confirmation.
4. Emit lifecycle statuses back to the widget.

<Warning>
  Sending each item in `bytecodes[]` as a separate transaction can leave async actions stuck in
  `PENDING` with funds in escrow. See [Executing Bytecode](/getting-started/executing-bytecode).
</Warning>

## Payload Shape

```ts theme={null}
type TxIntent = {
  clientTxId: string
  bytecodes: Array<{
    chainId?: number
    to: string
    data: string
    value: string
    gasLimit?: string
  }>
  simulateError?: boolean
}
```

## Required Success Status Path

Emit, in order:

1. `HOST_ACK`
2. `SIGNATURE_PROMPTED`
3. `TX_SUBMITTED`
4. `TX_CONFIRMED`
5. `TX_FINALIZED`

`txHash` should be included on `TX_SUBMITTED` and `TX_CONFIRMED` when available.

## Required Error Statuses

* `SIGNATURE_DECLINED` for user-rejected signatures (`4001`, `ACTION_REJECTED`)
* `SIGNATURE_ERROR` for non-rejection failures before tx submission
* `TX_REVERTED` for reverted on-chain transactions
* `TX_FAILED` for unsupported failure paths where revert reason is unavailable

## Optional Advanced Statuses

* `TX_REPLACED`
* `TX_DROPPED`
* `SWAP_CROSSCHAIN_DESTINATION_CONFIRMED`

## Minimal Host Implementation

Group legs by `chainId`, then submit **one batched transaction per chain** (smart-wallet `calls`,
EIP-7702 `executeBatch`, or equivalent):

```ts theme={null}
import type { UpdateTxStatus } from 'pods-sdk'

function groupByChainId(bytecodes: TxIntent['bytecodes']) {
  const grouped = new Map<number, TxIntent['bytecodes']>()
  for (const tx of bytecodes) {
    const chainId = tx.chainId ?? 0
    const list = grouped.get(chainId) ?? []
    list.push(tx)
    grouped.set(chainId, list)
  }
  return grouped
}

export async function processBytecode(
  payload: {
    clientTxId: string
    bytecodes: Array<{ chainId?: number; to: string; data: string; value: string; gasLimit?: string }>
  },
  ctx: { updateTxStatus: UpdateTxStatus }
) {
  const { clientTxId, bytecodes } = payload

  try {
    ctx.updateTxStatus({ type: 'HOST_ACK', clientTxId })

    for (const [chainId, legs] of groupByChainId(bytecodes)) {
      ctx.updateTxStatus({ type: 'SIGNATURE_PROMPTED', clientTxId })

      // One atomic submission for all legs on this chain (e.g. smart wallet sendTransaction({ calls }))
      const txHash = await sendBatchedTransactionWithWallet({ chainId, legs })
      ctx.updateTxStatus({ type: 'TX_SUBMITTED', clientTxId, chainId, txHash })

      const receipt = await waitForReceipt(txHash)
      if (receipt.status !== 1) {
        ctx.updateTxStatus({ type: 'TX_REVERTED', clientTxId, txHash, reason: 'Execution reverted' })
        return
      }

      ctx.updateTxStatus({
        type: 'TX_CONFIRMED',
        clientTxId,
        txHash,
        blockNumber: receipt.blockNumber,
        confirmations: 1
      })
    }

    ctx.updateTxStatus({ type: 'TX_FINALIZED', clientTxId })
  } catch (error: any) {
    if (error?.code === 4001 || error?.code === 'ACTION_REJECTED') {
      ctx.updateTxStatus({ type: 'SIGNATURE_DECLINED', clientTxId })
      return
    }

    ctx.updateTxStatus({
      type: 'SIGNATURE_ERROR',
      clientTxId,
      code: String(error?.code ?? 'UNKNOWN_ERROR'),
      message: String(error?.message ?? 'Transaction failed')
    })
  }
}
```

## Compatibility Fallback

If `processBytecode` is not provided, SDK falls back to `window.parent.postMessage(...)` (`REQUEST_SIGNATURE`).

Use this only when your host already implements that message bridge. For new integrations, prefer explicit `processBytecode`.

## Operational Recommendations

1. Log `clientTxId` and wallet tx hash together in your backend.
2. **Batch** all legs per `chainId` into one atomic submission — never one `sendTransaction` per leg.
3. Enforce chain checks before requesting signatures.
4. Persist failures and rejections for support/audit trails.
