Skip to main content
Version: 0.14

Advanced hooks

Hooks beyond the core send / mint / consume trio: custom scripts, MASM compilation, session wallets, store backup, note serialization, and sync control.

useTransaction

General-purpose transaction runner that accepts either a prebuilt TransactionRequest or a builder callback. This is the escape hatch when the higher-level hooks don't cover your flow.

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

const { execute, isLoading, stage } = useTransaction();

// Direct request
await execute({
accountId: contractAccount,
request: prebuiltRequest,
});

// Builder callback — receives the raw WebClient
await execute({
accountId: contractAccount,
request: (client) =>
new TransactionRequestBuilder()
.withCustomScript(txScript)
.build(),
});

UseTransactionResult exposes execute (not executeTransaction), plus result, isLoading, stage, error, and reset.

ExecuteTransactionOptions:

FieldDescription
accountIdAccount the transaction applies to
requestTransactionRequest or (client: WebClient) => TransactionRequest | Promise<TransactionRequest>
skipSyncSkip pre-send auto-sync (default false)
privateNoteTargetDeliver private output notes to this account after commit (any AccountRef form)

The privateNoteTarget field is the 4-step pipeline shortcut: execute the tx, commit on-chain, then auto-deliver the private note through the note transport to the target. Useful for "send private note" UIs where the recipient already has the React SDK running.

useExecuteProgram

View call — executes a transaction script locally and returns the stack output. No prove, no submit, no state change. Think of it as Miden's eth_call.

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

const { execute, isLoading, error } = useExecuteProgram();

const result = await execute({
accountId: contractAccount,
script: compiledTxScript,
foreignAccounts: [counterAccount], // optional
});

// result.stack is a bigint[] — read indices directly
const count: bigint = result.stack[0];
console.log("Count:", count);

UseExecuteProgramResult exposes execute (not executeProgram), plus result, isLoading, error, and reset. No stage — view calls don't prove or submit.

The React hook flattens the 16-element stack into a plain bigint[]. useMidenClient() exposes the underlying WASM WebClient directly — its method is client.executeProgram(...) (not namespaced under client.transactions). See the Web SDK transactions guide for the imperative MidenClient.transactions.executeProgram equivalent and the FeltArray shape.

useCompile

Compiles Miden Assembly into AccountComponent, TransactionScript, or NoteScript. Each result method is independently callable — call only what you need for the current operation.

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

const { component, txScript, noteScript, isReady } = useCompile();

// Account component
const counterComponent = await component({
code: counterContractCode,
slots: [StorageSlot.emptyValue("miden::tutorials::counter")],
});

// Transaction script (with optional libraries)
const script = await txScript({
code: `
use external_contract::counter_contract
begin
call.counter_contract::increment_count
end
`,
libraries: [
{ namespace: "external_contract::counter_contract", code: counterContractCode },
],
});

// Note script — v0.14 uses the @note_script attribute on a library proc
const attachScript = await noteScript({
code: `
use miden::protocol::active_note
use miden::core::sys

@note_script
pub proc on_consume
# body runs when the consuming account redeems this note
exec.sys::truncate_stack
end
`,
});

UseCompileResult exposes the three compile methods plus isReady. Loading and error state are tracked internally per call — catch errors at the individual await site. See the Web SDK compile guide for the full CompileComponentOptions / CompileTxScriptOptions / CompileNoteScriptOptions shapes.

useSessionAccount

Drives the "session wallet" pattern — create a throw-away wallet, wait for a funding note, consume it, then hand control back to your app. Useful for one-off interactions that shouldn't touch a long-lived account.

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

const { initialize, sessionAccountId, isReady, step, error, reset } =
useSessionAccount({
// Called with the new session wallet's bech32 ID once it's created.
// Your code is responsible for actually sending funds to it — e.g. by
// triggering a send from a main wallet elsewhere in the app.
fund: async (sessionAccountId) => {
await sendFromMainWallet(sessionAccountId);
},
assetId: usdcFaucetId, // optional
walletOptions: { storageMode: "private", mutable: true },
pollIntervalMs: 3_000, // default 3_000
maxWaitMs: 60_000, // default 60_000
});

await initialize();
// step progresses: "idle" → "creating" → "funding" → "consuming" → "ready"

UseSessionAccountReturn:

FieldDescription
initialize()Kicks off the create → fund → consume flow
sessionAccountIdbech32 ID of the session wallet once created
isReadytrue after the funding note has been consumed
stepSessionAccountStep — one of the five states above
errorNon-null if any step failed
reset()Clears session data (and any persisted state under storagePrefix)

Session state persists under the configurable storagePrefix (default "miden-session") so page reloads can resume mid-flow.

useExportStore / useImportStore

Back up and restore the entire local store as a JSON dump. Handy for wallet backup/restore UIs.

import { useExportStore, useImportStore, useMidenClient } from "@miden-sdk/react";

// Export — returns a JSON string
const { exportStore } = useExportStore();
const dump: string = await exportStore();
download(new Blob([dump]), "wallet-backup.json");

// Import (destructive — overwrites the target store)
// Positional: (storeDump, storeName, options?)
const { importStore } = useImportStore();
const client = useMidenClient();
await importStore(uploadedDump, client.storeIdentifier(), { skipSync: false });

ImportStoreOptions exposes skipSync (default false) so you can defer the post-import sync. There's no second "raw bytes" form — importStore takes the JSON dump string as its first argument and the target store name as its second.

useImportNote / useExportNote

Serialize notes to bytes for QR delivery or import notes handed over out-of-band. These complement the private-note transport layer — use the transport when the recipient is online, and QR/bytes when they aren't.

import { useExportNote, useImportNote } from "@miden-sdk/react";

const { exportNote } = useExportNote();
const noteBytes = await exportNote(noteId);
// encode noteBytes into a QR, link, email, etc.

const { importNote } = useImportNote();
await importNote(uploadedBytes);

useSyncControl

Pause and resume the auto-sync loop without dismounting MidenProvider. Useful when a long operation needs consistent local state, or during battery-sensitive background work.

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

const { pauseSync, resumeSync, isPaused } = useSyncControl();

// Before a long sequence
pauseSync();
// ... operations that need a stable snapshot ...
resumeSync();

pauseSync() stops the timer but doesn't cancel an in-flight sync — wait for isSyncing from useSyncState() to settle if you need a truly quiescent state.

Next

  • Signers — wire external wallets (Para, Turnkey, MidenFi) or build a custom signer.
  • Recipes — end-to-end patterns.