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

# prepareFlowSigning

> Prepare a quoted Flow wallet payment for signing with the JavaScript SDK and get the transaction to sign, for integrations that sign and report the transaction themselves.

Checks that a wallet payment can go ahead and returns the transaction to sign. It confirms the quote has not expired, the wallet source is not blocked, and by default that the wallet can cover the amount and the gas. The flow moves to `signing`, and `quote.signingPayload` holds the transaction.

> [!NOTE]
>
> Most integrations use [`submitFlowTransaction`](https://docs.dynamic.xyz/docs/javascript/reference/client/submit-flow-transaction), which prepares, signs, and reports the transaction in one call. Call `prepareFlowSigning` directly only when you sign and report the transaction yourself.

## When to call

Call `prepareFlowSigning` when `executionState` is `quoted` and the source is a wallet, right before the payer signs.

Once the flow is in `signing`, do not prepare it again. Sign the returned transaction and report its hash with [`broadcastFlow`](https://docs.dynamic.xyz/docs/javascript/reference/client/broadcast-flow). If the payer declines in the wallet and nothing was sent, call [`getFlowQuote`](https://docs.dynamic.xyz/docs/javascript/reference/client/get-flow-quote) to return the flow to `quoted` with a new quote.

## Usage

```javascript theme={"system"}
import { prepareFlowSigning } from '@dynamic-labs-sdk/client';

const prepared = await prepareFlowSigning({ flowId: 'your-flow-id' });

const { signingPayload } = prepared.quote;
```

## Parameters

| Parameter | Type | Description |
| - | - | - |
| `flowId` | `string` | The flow ID. |
| `assertBalanceForGasCost` | `boolean` (optional) | Reject with `insufficient_balance` when the wallet cannot cover the gas. Default `true`. |
| `assertBalanceForTransferAmount` | `boolean` (optional) | Reject with `insufficient_balance` when the wallet cannot cover the amount. Default `true`. |

## Returns

`Promise<Flow>`: the flow with `executionState: 'signing'` and `quote.signingPayload` set. The payload depends on the chain:

| Chain | Fields |
| - | - |
| EVM | `evmTransaction` (`to`, `data`, `value`, `gasLimit`), and `evmApproval` (`tokenAddress`, `spenderAddress`, `amount`) when an ERC-20 payment needs an allowance first |
| SOL, SUI | `serializedTransaction` (base64) |
| BTC | `psbt` (base64 unsigned PSBT) |
| TRON | `tronTransaction` (`rawDataHex`, `to`, `value`) |

## Examples

### Sign and report the transaction yourself

`executeSwapTransaction` signs any of these payloads with a connected wallet account. On EVM, it sends the token approval first when the payload has `evmApproval`, then the payment transaction. Report the resulting hash with `broadcastFlow`.

```javascript theme={"system"}
import {
  broadcastFlow,
  executeSwapTransaction,
  getFlowQuote,
  prepareFlowSigning,
  UserRejectedError,
} from '@dynamic-labs-sdk/client';

const prepared = await prepareFlowSigning({ flowId: 'your-flow-id' });
const { quote } = prepared;

try {
  const { transactionHash } = await executeSwapTransaction({
    walletAccount,
    signingPayload: quote.signingPayload,
  });

  await broadcastFlow({ flowId: 'your-flow-id', txHash: transactionHash });
} catch (error) {
  if (error instanceof UserRejectedError) {
    // Nothing was sent: return the flow to quoted with a new quote for the same token
    await getFlowQuote({
      flowId: 'your-flow-id',
      fromChainId: quote.fromChainId,
      fromTokenAddress: quote.fromToken,
    });
  }
  throw error;
}
```

If you sign with your own wallet code instead, an EVM payload with `evmApproval` needs two transactions: approve `spenderAddress` to spend `amount` of `tokenAddress`, then send `evmTransaction`. Without the approval, the payment transaction can fail on chain. The [Flow payments API guide](https://docs.dynamic.xyz/docs/flow/api.md#signing-the-transaction-by-chain) shows the signing steps for each chain.

## Errors

| Error | When |
| - | - |
| `FlowPrepareSigningError` | `quote_expired`: the quote expired; get a new one. `insufficient_balance`: the wallet cannot cover the amount or the gas. |
| `FlowStateConflictError` | The flow is not in `quoted`, or another request changed it first. |
| `FlowSessionTokenMissingError` | No session token for the flow is stored on this device. |
| `FlowSessionExpiredError` | The server no longer accepts the stored session token. |

A wallet source that screening blocked is rejected without a dedicated class; show `error.message` and let the payer attach another source. [Handle Flow errors](https://docs.dynamic.xyz/docs/javascript/reference/flow-errors.md) describes each error.

## React

`usePrepareFlowSigning` is a mutation hook. It takes the same parameters, and it writes the returned flow into the `useGetFlow` cache.

```tsx theme={"system"}
import { usePrepareFlowSigning } from '@dynamic-labs-sdk/react-hooks';

function PrepareButton({ flowId }) {
  const { mutate: prepareFlowSigning, data: flow, isPending } = usePrepareFlowSigning();

  return (
    <div>
      <button onClick={() => prepareFlowSigning({ flowId })} disabled={isPending}>
        {isPending ? 'Preparing...' : 'Prepare payment'}
      </button>
      {flow?.quote?.signingPayload && <p>Ready to sign</p>}
    </div>
  );
}
```

## Related

* [`submitFlowTransaction`](https://docs.dynamic.xyz/docs/javascript/reference/client/submit-flow-transaction): prepare, sign, and report in one call.
* [`broadcastFlow`](https://docs.dynamic.xyz/docs/javascript/reference/client/broadcast-flow): report the signed transaction.
* [`executeSwapTransaction`](https://docs.dynamic.xyz/docs/javascript/reference/client/execute-swap-transaction): sign a payload with a wallet account.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.