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

# Submitting Transactions and Handling Network Fees with Walley

> Submit Daml commands through Walley with prepareExecute and prepareExecuteAndWait, and learn how Walley's prepaid traffic-fee model keeps fee handling off your dApp.

Walley submits transactions on the user's behalf after they review and sign them inside the wallet popup. Your dApp describes *what* to do as a list of Daml commands; the user approves, and Walley prepares, signs, and submits.

## Choosing a method

<CardGroup cols={2}>
  <Card title="prepareExecute" icon="paper-plane">
    Fire-and-forget. Resolves to `null` as soon as the transaction is submitted. Use when you don't need the committed result inline.
  </Card>

  <Card title="prepareExecuteAndWait" icon="hourglass-half">
    Waits for the transaction to commit and returns the result. Use when your UI needs to react to the committed outcome.
  </Card>
</CardGroup>

Both take the same `params` — a `commands` array — and both open a popup for the user to review and sign.

## Submitting commands

```ts theme={null}
await provider.request({
  method: "prepareExecuteAndWait",
  params: {
    commands: [
      {
        type: "create",
        templateId: "<package-id>:<module>:<entity>",
        argument: {
          // template fields
        },
      },
    ],
  },
});
```

The `commands` array can contain more than one command; Walley submits them together in a single transaction, so they commit atomically — either all succeed or none do.

<Note>
  Always call `prepareExecute` / `prepareExecuteAndWait` from a user gesture. The submission opens a popup, and browsers block popups that aren't triggered by user interaction.
</Note>

## Waiting for the result

`prepareExecuteAndWait` resolves once the transaction is committed, so you can update your UI directly off the returned result:

```ts theme={null}
try {
  const result = await provider.request({
    method: "prepareExecuteAndWait",
    params: { commands },
  });
  // transaction committed — update UI from `result`
} catch (err) {
  // user rejected, popup blocked, or submission failed
}
```

If the user closes the popup without signing, the request rejects with `providerErrors.userRejectedRequest`. Handle it as a normal cancellation rather than an error state.

## Network fees

The Canton Network charges traffic for transactions. **Walley handles this for you** — your dApp never calculates, quotes, or pays a network fee.

Walley charges Canton traffic against the user's **prepaid traffic balance**. The user buys traffic ahead of time (with Canton Coin) inside the Walley app, and each chargeable transaction's fee is drawn from that balance automatically — there's no per-transaction payment step. Your dApp submits commands exactly as above; the fee is invisible to your integration.

<Tip>
  There is no fee handling on the dApp side. You don't estimate costs, attach fee parameters, or surface fee UI — the user's prepaid traffic balance covers it, and Walley owns that flow end to end.
</Tip>

### When a transaction is refused

Walley will front a single transaction even when the traffic balance can't cover its fee — the balance simply goes negative by that one transaction. While the balance is negative, new transactions are refused until the user tops it back up.

If `prepareExecute` / `prepareExecuteAndWait` rejects and the popup indicated an empty traffic balance, that's the cause. Traffic isn't purchased from your dApp — direct the user to [walley.cc](https://walley.cc) to top up their traffic balance, then have them retry the transaction.

## Reading state instead of writing

If you only need to *read* ledger state — query active contracts, look up a contract by id — use the [Ledger API](/build/ledger-api) proxy instead. It's a read path that doesn't open a popup or incur a fee.
