Polkadot Apps
    Preparing search index...

    Module @polkadot-apps/tx

    @polkadot-apps/tx

    Transaction submission, lifecycle watching, and dev signers for Polkadot chains.

    pnpm add @polkadot-apps/tx
    

    Peer dependency: polkadot-api must be installed in your project.

    pnpm add polkadot-api
    
    import { submitAndWatch, createDevSigner } from "@polkadot-apps/tx";

    const signer = createDevSigner("Alice");

    const result = await submitAndWatch(tx, signer, {
    waitFor: "finalized",
    onStatus: (status) => console.log(status),
    });

    console.log(result.txHash, result.ok);

    Submit multiple transactions as a single atomic batch. Uses Substrate's Utility.batch_all by default (all-or-nothing).

    import { batchSubmitAndWatch } from "@polkadot-apps/tx";

    const tx1 = api.tx.Balances.transfer_keep_alive({ dest: addr1, value: 1_000n });
    const tx2 = api.tx.Balances.transfer_keep_alive({ dest: addr2, value: 2_000n });
    const tx3 = api.tx.System.remark({ remark: Binary.fromText("hello") });

    const result = await batchSubmitAndWatch([tx1, tx2, tx3], api, signer, {
    onStatus: (status) => console.log(status),
    });

    Three batch modes are available:

    Mode Behavior
    "batch_all" (default) Atomic. Reverts all calls if any single call fails.
    "batch" Best-effort. Stops at first failure but earlier successful calls are not reverted.
    "force_batch" Like batch but continues after failures (never aborts early).
    // Non-atomic: some calls may fail while others succeed
    const result = await batchSubmitAndWatch(calls, api, signer, { mode: "batch" });

    WARNING: In "batch" and "force_batch" modes, result.ok is true even when individual calls fail. Inspect result.events for Utility.ItemFailed events to detect individual failures. Only "batch_all" guarantees that result.ok === false when any call fails.

    Calls can be PAPI transactions (.decodedCall extracted automatically), Ink SDK AsyncTransaction wrappers (.waited resolved automatically), or raw decoded calls.

    // Mix of raw decoded calls and transactions
    const calls = [
    api.tx.Balances.transfer_keep_alive({ dest, value: 1_000n }), // PAPI tx
    extractTransaction(await contract.query("mint", { origin, data })), // Ink SDK
    someDecodedCallObject, // raw
    ];
    const result = await batchSubmitAndWatch(calls, api, signer);

    submitAndWatch drives a transaction through its full lifecycle: signing, broadcasting, block inclusion, and optional finalization. You choose when to resolve the returned promise with the waitFor option.

    import { submitAndWatch } from "@polkadot-apps/tx";

    const result = await submitAndWatch(tx, signer, {
    waitFor: "best-block", // resolve at best-block inclusion (default)
    timeoutMs: 300_000, // 5-minute timeout (default)
    mortalityPeriod: 256, // ~43 minutes on Polkadot (default)
    onStatus: (status) => {
    // "signing" -> "broadcasting" -> "in-block" -> "finalized"
    updateUI(status);
    },
    });

    if (!result.ok) {
    console.error("Dispatch failed:", result.dispatchError);
    }

    The function accepts both raw PAPI transactions and Ink SDK AsyncTransaction wrappers. Ink SDK wrappers are resolved automatically via the .waited promise.

    Create signers from the well-known Substrate dev mnemonic for local testing. All keys derive at //Name using sr25519.

    import { createDevSigner, getDevPublicKey } from "@polkadot-apps/tx";

    const alice = createDevSigner("Alice");
    const bobPubKey = getDevPublicKey("Bob"); // Uint8Array (32 bytes)

    Available names: "Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie".

    Extract a submittable transaction from an Ink SDK dry-run result and apply a safety buffer to weight estimates before submission.

    import { extractTransaction, applyWeightBuffer } from "@polkadot-apps/tx";

    const dryRunResult = await contract.query.myMethod(args);
    const tx = extractTransaction(dryRunResult);

    const buffered = applyWeightBuffer(dryRunResult.weight_required, {
    percent: 25, // default: 25%
    });

    Map an SS58 address to an H160 address on Asset Hub. The operation is idempotent -- it returns null when the account is already mapped.

    import { ensureAccountMapped, isAccountMapped } from "@polkadot-apps/tx";

    const mapped = await isAccountMapped(address, checker);

    if (!mapped) {
    const result = await ensureAccountMapped(address, signer, checker, api);
    // result is TxResult or null (if already mapped)
    }

    withRetry wraps any async function with exponential backoff and jitter. It does not retry TxDispatchError, TxBatchError, TxSigningRejectedError, or TxTimeoutError -- these represent terminal conditions that retrying cannot fix.

    import { withRetry, calculateDelay } from "@polkadot-apps/tx";

    const result = await withRetry(() => submitAndWatch(tx, signer), {
    maxAttempts: 3, // total attempts including the first (default)
    baseDelayMs: 1_000, // initial backoff (default)
    maxDelayMs: 15_000, // backoff cap (default)
    });

    // Calculate delay directly for custom retry strategies
    const delay = calculateDelay(2, 1_000, 15_000);

    All errors extend a common TxError base class. Use the specific error types and utility functions to handle failures precisely.

    import {
    TxTimeoutError,
    TxDispatchError,
    TxSigningRejectedError,
    TxDryRunError,
    TxAccountMappingError,
    formatDispatchError,
    formatDryRunError,
    isSigningRejection,
    } from "@polkadot-apps/tx";

    try {
    await submitAndWatch(tx, signer);
    } catch (error) {
    if (isSigningRejection(error)) {
    console.log("User cancelled signing");
    } else if (error instanceof TxDispatchError) {
    console.error(error.formatted, error.dispatchError);
    } else if (error instanceof TxTimeoutError) {
    console.error(`Timed out after ${error.timeoutMs}ms`);
    } else if (error instanceof TxDryRunError) {
    console.error(error.formatted, error.revertReason);
    }
    }

    Submit a transaction and watch its lifecycle through to inclusion or finalization.

    Parameter Type Description
    tx SubmittableTransaction Transaction with signSubmitAndWatch. Raw PAPI or Ink SDK.
    signer PolkadotSigner Signer from a wallet, Host API, or createDevSigner.
    options SubmitOptions Optional. See below.

    Throws: TxTimeoutError, TxDispatchError, TxSigningRejectedError.

    Batch multiple transactions into a single Substrate Utility batch and submit with lifecycle tracking.

    Parameter Type Description
    calls BatchableCall[] Transactions, AsyncTransactions, or raw decoded calls.
    api BatchApi Typed API with tx.Utility.batch_all/batch/force_batch.
    signer PolkadotSigner Signer from a wallet, Host API, or createDevSigner.
    options BatchSubmitOptions Optional. Extends SubmitOptions with mode.

    Throws: TxBatchError (empty calls), TxTimeoutError, TxDispatchError, TxSigningRejectedError.

    Create a signer from the well-known dev mnemonic at //Name (sr25519).

    Parameter Type Description
    name DevAccountName One of "Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie".

    Return the 32-byte public key for a dev account.

    Retry an async function with exponential backoff and jitter. Does not retry TxBatchError, TxDispatchError, TxSigningRejectedError, or TxTimeoutError.

    Parameter Type Description
    fn () => Promise<T> Async function to retry.
    options RetryOptions Optional retry configuration.

    Compute the backoff delay for a given attempt number, with jitter.

    Extract a submittable transaction from an Ink SDK dry-run result.

    Apply a percentage safety buffer to a weight estimate. Default buffer is 25%.

    Map an SS58 address to H160 on Asset Hub. Returns null if the account is already mapped.

    Check whether an SS58 address is already mapped to an H160 address.

    Function Signature Description
    formatDispatchError (result) => string Format a dispatch error into a readable string.
    formatDryRunError (result) => string Format a dry-run error into a readable string.
    isSigningRejection (error) => boolean Check if an error is a signing rejection.
    type TxStatus = "signing" | "broadcasting" | "in-block" | "finalized" | "error";

    type WaitFor = "best-block" | "finalized";

    interface TxResult {
    txHash: string;
    ok: boolean;
    block: { hash: string; number: number; index: number };
    events: unknown[];
    dispatchError?: unknown;
    }

    interface SubmitOptions {
    waitFor?: WaitFor; // default: "best-block"
    timeoutMs?: number; // default: 300_000
    mortalityPeriod?: number; // default: 256
    onStatus?: (status: TxStatus) => void;
    }

    interface RetryOptions {
    maxAttempts?: number; // default: 3
    baseDelayMs?: number; // default: 1_000
    maxDelayMs?: number; // default: 15_000
    }

    type DevAccountName = "Alice" | "Bob" | "Charlie" | "Dave" | "Eve" | "Ferdie";

    interface Weight {
    ref_time: bigint;
    proof_size: bigint;
    }

    type BatchMode = "batch_all" | "batch" | "force_batch";

    interface BatchSubmitOptions extends SubmitOptions {
    mode?: BatchMode; // default: "batch_all"
    }

    interface BatchApi {
    tx: {
    Utility: {
    batch(args: { calls: unknown[] }): SubmittableTransaction;
    batch_all(args: { calls: unknown[] }): SubmittableTransaction;
    force_batch(args: { calls: unknown[] }): SubmittableTransaction;
    };
    };
    }
    Class Extends Key properties
    TxError Error Base class for all tx errors.
    TxTimeoutError TxError timeoutMs: number
    TxDispatchError TxError dispatchError: unknown, formatted: string
    TxSigningRejectedError TxError User rejected signing.
    TxDryRunError TxError raw: unknown, formatted: string, revertReason?: string
    TxBatchError TxError Batch construction failed (e.g., empty calls).
    TxAccountMappingError TxError Account mapping failed.

    Apache-2.0

    Classes

    TxAccountMappingError
    TxBatchError
    TxDispatchError
    TxDryRunError
    TxError
    TxSigningRejectedError
    TxTimeoutError

    Interfaces

    BatchApi
    BatchSubmitOptions
    EnsureAccountMappedOptions
    MappingChecker
    RetryOptions
    ReviveApi
    SubmitOptions
    SubmittableTransaction
    TxResult
    Weight

    Type Aliases

    BatchableCall
    BatchMode
    DevAccountName
    TxEvent
    TxStatus
    WaitFor

    Functions

    applyWeightBuffer
    batchSubmitAndWatch
    calculateDelay
    createDevSigner
    ensureAccountMapped
    extractTransaction
    formatDispatchError
    formatDryRunError
    getDevPublicKey
    isAccountMapped
    isSigningRejection
    submitAndWatch
    withRetry