Skip to main content
Version: 0.16

Mutation hooks

Mutation hooks own the full transaction lifecycle — execute, prove, submit — and serialize under the Web SDK's concurrency lock so two components can't corrupt the WASM state.

These examples assume the provider configuration from Setup. For automatic delivery of private notes, configure its noteTransportUrl setting.

Two result-shape families show up across this page:

Transaction-producing hooks (useSend, useMultiSend, useMint, useConsume, useSwap, useTransaction):

{
[action]: (options) => Promise<Result>; // send, sendMany, mint, ...
result: Result | null;
isLoading: boolean;
stage: TransactionStage;
error: Error | null;
reset: () => void;
}

Account-creation hooks (useCreateWallet, useCreateFaucet, useImportAccount) don't go through the prove/submit pipeline, so they expose isCreating / isImporting instead of isLoading + stage:

{
createWallet: (opts?) => Promise<Account>;
wallet: Account | null;
isCreating: boolean; // or `isImporting` for useImportAccount
error: Error | null;
reset: () => void;
}

Polling helpers (useWaitForCommit, useWaitForNotes) are simpler still — they expose just the action. Per-hook exact shapes are called out below.

See setup for the TransactionStage progression.

useCreateWallet​

Creates a new wallet account. Returns the Account object.

With the 0.16.0 packages, pass the low-level authentication enum explicitly. The React hooks' default refers to an enum member missing from the high-level SDK export, causing invalid enum value passed. Obtain the numeric enum from getWasmOrThrow() as shown below for wallets, faucets, and seed imports.

import { useCreateWallet } from "@miden-sdk/react";
import { getWasmOrThrow } from "@miden-sdk/miden-sdk/lazy";

function NewWalletButton() {
const { createWallet, wallet, isCreating, error } = useCreateWallet();

const handleCreate = async () => {
const { AuthScheme } = await getWasmOrThrow();
const account = await createWallet({
storageMode: "private", // "private" | "public" (default private)
authScheme: AuthScheme.AuthRpoFalcon512,
});
console.log("Created:", account.bech32id());
};

return (
<button onClick={handleCreate} disabled={isCreating}>Create wallet</button>
);
}

CreateWalletOptions (all optional):

FieldDefaultDescription
storageMode"private""private" / "public"
authSchemePass explicitly in 0.16.0Numeric WASM signing scheme
initSeedrandom32-byte seed for deterministic account-ID derivation

useCreateFaucet​

Creates a fungible-token faucet.

import { useCreateFaucet } from "@miden-sdk/react";
import { getWasmOrThrow } from "@miden-sdk/miden-sdk/lazy";

function NewFaucetButton() {
const { createFaucet, faucet, isCreating } = useCreateFaucet();

const handleCreate = async () => {
const { AuthScheme } = await getWasmOrThrow();
const created = await createFaucet({
tokenSymbol: "TEST",
decimals: 8, // default 8
maxSupply: 10_000_000n, // number | bigint
storageMode: "public", // default "private"; public allows FPI reads
authScheme: AuthScheme.AuthRpoFalcon512,
});
console.log("Faucet:", created.bech32id());
};

return (
<button onClick={handleCreate} disabled={isCreating}>Create faucet</button>
);
}

CreateFaucetOptions:

FieldDefaultDescription
tokenSymbolrequiredDisplay symbol (e.g. "USDC")
maxSupplyrequiredbigint | number
decimals8Token decimals
storageMode"private"Public faucets are discoverable/readable onchain
authSchemePass explicitly in 0.16.0Numeric WASM signing scheme

useSend​

Sends tokens from one account to another.

import { useSend } from "@miden-sdk/react";

function SendForm({ from, to, usdcFaucetId }: Props) {
const { send, isLoading, stage, error } = useSend();

const handleSend = async () => {
const { txId, note } = await send({
from,
to,
assetId: usdcFaucetId,
amount: 100n,
noteType: "private", // default "private"
});
console.log("Transaction:", txId);
};

return (
<button onClick={handleSend} disabled={isLoading}>
{isLoading ? `${stage}…` : "Send"}
</button>
);
}

SendOptions:

FieldRequiredDescription
fromyesSender AccountRef
toyesRecipient AccountRef
assetIdyesToken faucet AccountRef
amountunless sendAllbigint | number
noteType—"private" / "public" (default "private")
recallHeight—Block height after which sender can reclaim the note
timelockHeight—Block height after which recipient can consume the note
attachment—bigint[] | Uint8Array | number[] — payload attached to the note
skipSync—Skip the pre-send auto-sync (default false)
sendAll—Drain full balance of assetId — when true, amount is ignored
returnNote—Return the Note object in the result (for out-of-band delivery, QR codes, etc.)

SendResult: { txId: string; note: Note | null }. note is non-null only when returnNote: true.

useMultiSend​

Batches multiple recipients into one transaction. All outputs must share the same sender and asset. The action function is named sendMany.

import { useMultiSend } from "@miden-sdk/react";

const { sendMany, isLoading } = useMultiSend();

await sendMany({
from: senderAccountId,
assetId: faucetId,
recipients: [
{ to: recipient1, amount: 500n, noteType: "private" },
{ to: recipient2, amount: 300n },
],
noteType: "private", // default for recipients that don't override
});

MultiSendOptions:

FieldDescription
from, assetIdSingle sender + single faucet for the whole batch
recipientsMultiSendRecipient[] — each { to, amount, noteType?, attachment? }
noteTypeDefault for recipients that don't specify one (default "private")
skipSyncSkip pre-send auto-sync

useMint​

Mints tokens from a faucet you control into a recipient account.

import { useMint } from "@miden-sdk/react";

const { mint, isLoading, stage } = useMint();

const result = await mint({
targetAccountId: recipient,
faucetId: myFaucet,
amount: 10_000n,
noteType: "private", // default "private"
});
console.log("Mint tx:", result.transactionId);

MintOptions:

FieldDescription
targetAccountIdRecipient AccountRef
faucetIdFaucet AccountRef (must be owned by the caller)
amountbigint | number
noteType"private" / "public" (default "private")

Returns TransactionResult: { transactionId: string }.

useConsume​

Claims one or more notes into an account.

import { useConsume } from "@miden-sdk/react";

const { consume, isLoading } = useConsume();

await consume({
accountId: myAccountId,
notes: [noteIdHex1, noteIdHex2], // hex IDs, NoteId objects, InputNoteRecord, or Note
});

ConsumeOptions:

FieldDescription
accountIdAccount consuming the notes
notes(string | NoteId | InputNoteRecord | Note)[] — mix-and-match accepted

useSwap​

Atomic swap between two assets.

import { useSwap } from "@miden-sdk/react";

const { swap, isLoading } = useSwap();

await swap({
accountId: myWallet,
offeredFaucetId: usdcFaucet,
offeredAmount: 100n,
requestedFaucetId: dagFaucet,
requestedAmount: 200n,
noteType: "public", // default "private"
paybackNoteType: "private", // default "private"
});

useImportAccount​

Imports an account by ID (fetches from network), by previously-exported file, or by seed.

For seed recovery with the 0.16.0 browser packages, set useWorker: false in MidenProvider's config. With the worker enabled, a subsequent transaction can reach the network but fail during local applyTransaction with account data wasn't found. The direct client path restores the account and confirms a signed transaction. If you encounter the worker error, check the account's onchain state before retrying the transaction.

import { useImportAccount } from "@miden-sdk/react";
import { getWasmOrThrow } from "@miden-sdk/miden-sdk/lazy";

const { importAccount, account, isImporting, error } = useImportAccount();

// By ID — public accounts only
const imported = await importAccount({
type: "id",
accountId: "mtst1qy35...",
});

// By seed — public accounts only
const { AuthScheme } = await getWasmOrThrow();
await importAccount({
type: "seed",
seed: initSeed, // Uint8Array
authScheme: AuthScheme.AuthRpoFalcon512,
});

// By file — works for both public and private accounts
await importAccount({
type: "file",
file: accountFileBytes, // AccountFile | Uint8Array | ArrayBuffer
});

The type discriminant is required. For private accounts, use the "file" variant — private account state isn't reconstructible from a seed alone.

useWaitForCommit / useWaitForNotes​

Polling helpers for transaction confirmation and note inbox arrivals. Both are minimal hooks — they only expose the action function.

useWaitForCommit​

Signature: waitForCommit(txId, options?) — txId is positional (hex string or TransactionId), options are merged with defaults.

import { useWaitForCommit } from "@miden-sdk/react";

const { waitForCommit } = useWaitForCommit();
await waitForCommit(result.txId, {
timeoutMs: 30_000, // default 10_000
intervalMs: 1_000, // default 1_000
});

useWaitForNotes​

Exposes waitForConsumableNotes(options) and returns the matching ConsumableNoteRecord[] when the threshold is reached.

import { useWaitForNotes } from "@miden-sdk/react";

const { waitForConsumableNotes } = useWaitForNotes();

const notes = await waitForConsumableNotes({
accountId: recipient,
minCount: 1, // default 1
timeoutMs: 30_000,
});

Both reject on timeout — wrap them in try/catch when you want a graceful fallback.

Next​

  • Advanced — custom scripts, MASM compilation, session accounts, store import/export.
  • Signers — external wallets (Para, Turnkey, MidenFi) and custom signers.
  • Recipes — realistic patterns + link-outs to Philipp's full wallet tutorial.