@miden-sdk/react 0.13.3 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -17,24 +17,33 @@ var initialSyncState = {
17
17
  lastSyncTime: null,
18
18
  error: null
19
19
  };
20
- var initialState = {
21
- client: null,
22
- isReady: false,
23
- isInitializing: false,
24
- initError: null,
25
- config: {},
26
- sync: initialSyncState,
27
- accounts: [],
28
- accountDetails: /* @__PURE__ */ new Map(),
29
- notes: [],
30
- consumableNotes: [],
31
- assetMetadata: /* @__PURE__ */ new Map(),
32
- noteFirstSeen: /* @__PURE__ */ new Map(),
33
- isLoadingAccounts: false,
34
- isLoadingNotes: false
35
- };
20
+ function freshCachedState() {
21
+ return {
22
+ sync: { ...initialSyncState },
23
+ syncPaused: false,
24
+ accounts: [],
25
+ accountDetails: /* @__PURE__ */ new Map(),
26
+ notes: [],
27
+ consumableNotes: [],
28
+ assetMetadata: /* @__PURE__ */ new Map(),
29
+ noteFirstSeen: /* @__PURE__ */ new Map(),
30
+ isLoadingAccounts: false,
31
+ isLoadingNotes: false
32
+ };
33
+ }
34
+ function freshState() {
35
+ return {
36
+ client: null,
37
+ isReady: false,
38
+ isInitializing: false,
39
+ initError: null,
40
+ config: {},
41
+ signerConnected: null,
42
+ ...freshCachedState()
43
+ };
44
+ }
36
45
  var useMidenStore = create()((set) => ({
37
- ...initialState,
46
+ ...freshState(),
38
47
  setClient: (client) => set({
39
48
  client,
40
49
  isReady: client !== null,
@@ -48,9 +57,11 @@ var useMidenStore = create()((set) => ({
48
57
  isReady: false
49
58
  }),
50
59
  setConfig: (config) => set({ config }),
60
+ setSignerConnected: (signerConnected) => set({ signerConnected }),
51
61
  setSyncState: (sync) => set((state) => ({
52
62
  sync: { ...state.sync, ...sync }
53
63
  })),
64
+ setSyncPaused: (syncPaused) => set({ syncPaused }),
54
65
  setAccounts: (accounts) => set({ accounts }),
55
66
  setAccountDetails: (accountId, account) => set((state) => {
56
67
  const newMap = new Map(state.accountDetails);
@@ -132,7 +143,8 @@ var useMidenStore = create()((set) => ({
132
143
  }),
133
144
  setLoadingAccounts: (isLoadingAccounts) => set({ isLoadingAccounts }),
134
145
  setLoadingNotes: (isLoadingNotes) => set({ isLoadingNotes }),
135
- reset: () => set(initialState)
146
+ resetInMemoryState: () => set(freshCachedState()),
147
+ reset: () => set(freshState())
136
148
  }));
137
149
  var useSyncStateStore = () => useMidenStore((state) => state.sync);
138
150
  var useAccountsStore = () => useMidenStore((state) => state.accounts);
@@ -157,11 +169,13 @@ var parseAccountIdFromString = (value) => {
157
169
  return AccountId.fromHex(normalizeHexInput(value));
158
170
  };
159
171
  var parseAccountId = (value) => {
160
- if (typeof value !== "string") {
161
- return value;
172
+ if (typeof value === "string") {
173
+ return parseAccountIdFromString(normalizeAccountIdInput(value));
162
174
  }
163
- const normalized = normalizeAccountIdInput(value);
164
- return parseAccountIdFromString(normalized);
175
+ if (typeof value.id === "function") {
176
+ return value.id();
177
+ }
178
+ return value;
165
179
  };
166
180
  function isFaucetId(accountId) {
167
181
  try {
@@ -177,6 +191,10 @@ function isFaucetId(accountId) {
177
191
  }
178
192
  }
179
193
  var parseAddress = (value, accountId) => {
194
+ if (typeof value !== "string") {
195
+ const resolvedId = accountId ?? parseAccountId(value);
196
+ return Address.fromAccountId(resolvedId, "BasicWallet");
197
+ }
180
198
  const normalized = normalizeAccountIdInput(value);
181
199
  if (isBech32Input(normalized)) {
182
200
  try {
@@ -288,16 +306,17 @@ import {
288
306
  useMemo,
289
307
  useState
290
308
  } from "react";
291
- import { WebClient } from "@miden-sdk/miden-sdk";
309
+ import { WasmWebClient as WebClient } from "@miden-sdk/miden-sdk";
292
310
 
293
311
  // src/types/index.ts
312
+ import { AuthScheme } from "@miden-sdk/miden-sdk";
294
313
  var DEFAULTS = {
295
314
  RPC_URL: void 0,
296
315
  // Will use SDK's testnet default
297
316
  AUTO_SYNC_INTERVAL: 15e3,
298
317
  STORAGE_MODE: "private",
299
318
  WALLET_MUTABLE: true,
300
- AUTH_SCHEME: 0,
319
+ AUTH_SCHEME: AuthScheme.AuthRpoFalcon512,
301
320
  NOTE_TYPE: "private",
302
321
  FAUCET_DECIMALS: 8
303
322
  };
@@ -351,9 +370,35 @@ function resolveTransactionProver(config) {
351
370
  if (!prover) {
352
371
  return null;
353
372
  }
354
- if (typeof prover === "string") {
355
- const normalized = prover.trim().toLowerCase();
356
- if (normalized === "local") {
373
+ if (isFallbackConfig(prover)) {
374
+ return resolveProverTarget(prover.primary, config);
375
+ }
376
+ return resolveProverTarget(prover, config);
377
+ }
378
+ async function proveWithFallback(proveFn, config) {
379
+ const primaryProver = resolveTransactionProver(config);
380
+ try {
381
+ return await proveFn(primaryProver ?? void 0);
382
+ } catch (primaryError) {
383
+ const { prover } = config;
384
+ if (!prover || !isFallbackConfig(prover) || !prover.fallback) {
385
+ throw primaryError;
386
+ }
387
+ if (prover.disableFallback?.()) {
388
+ throw primaryError;
389
+ }
390
+ const fallbackProver = resolveProverTarget(prover.fallback, config);
391
+ prover.onFallback?.();
392
+ return await proveFn(fallbackProver ?? void 0);
393
+ }
394
+ }
395
+ function isFallbackConfig(prover) {
396
+ return typeof prover === "object" && "primary" in prover;
397
+ }
398
+ function resolveProverTarget(target, config) {
399
+ if (typeof target === "string") {
400
+ const normalized = target.trim().toLowerCase();
401
+ if (normalized === "local" || normalized === "localhost") {
357
402
  return TransactionProver.newLocalProver();
358
403
  }
359
404
  if (normalized === "devnet" || normalized === "testnet") {
@@ -367,11 +412,11 @@ function resolveTransactionProver(config) {
367
412
  );
368
413
  }
369
414
  return TransactionProver.newRemoteProver(
370
- prover,
415
+ target,
371
416
  normalizeTimeout(config.proverTimeoutMs)
372
417
  );
373
418
  }
374
- return createRemoteProver(prover, config.proverTimeoutMs);
419
+ return createRemoteProver(target, config.proverTimeoutMs);
375
420
  }
376
421
  function createRemoteProver(config, fallbackTimeout) {
377
422
  const { url, timeoutMs } = config;
@@ -401,35 +446,41 @@ function useSigner() {
401
446
  }
402
447
 
403
448
  // src/utils/signerAccount.ts
404
- async function getAccountType(accountType) {
405
- const { AccountType } = await import("@miden-sdk/miden-sdk");
406
- switch (accountType) {
407
- case "RegularAccountImmutableCode":
408
- return AccountType.RegularAccountImmutableCode;
409
- case "RegularAccountUpdatableCode":
410
- return AccountType.RegularAccountUpdatableCode;
411
- case "FungibleFaucet":
412
- return AccountType.FungibleFaucet;
413
- case "NonFungibleFaucet":
414
- return AccountType.NonFungibleFaucet;
415
- default:
416
- return AccountType.RegularAccountImmutableCode;
417
- }
449
+ var WASM_ACCOUNT_TYPE = {
450
+ FungibleFaucet: 0,
451
+ NonFungibleFaucet: 1,
452
+ RegularAccountImmutableCode: 2,
453
+ RegularAccountUpdatableCode: 3
454
+ };
455
+ function getAccountType(accountType) {
456
+ return WASM_ACCOUNT_TYPE[accountType] ?? WASM_ACCOUNT_TYPE.RegularAccountImmutableCode;
418
457
  }
419
458
  function isPrivateStorageMode(storageMode) {
420
459
  return storageMode.toString() === "private";
421
460
  }
422
461
  async function initializeSignerAccount(client, config) {
423
- const { AccountBuilder, AccountComponent, Word: Word2 } = await import("@miden-sdk/miden-sdk");
462
+ const { AccountBuilder, AccountComponent, AuthScheme: AuthScheme2, Word: Word2 } = await import("@miden-sdk/miden-sdk");
424
463
  await client.syncState();
464
+ if (config.importAccountId) {
465
+ const accountId2 = parseAccountId(config.importAccountId);
466
+ try {
467
+ await client.importAccountById(accountId2);
468
+ } catch (e) {
469
+ const msg = e instanceof Error ? e.message : String(e);
470
+ if (!msg.includes("already being tracked")) {
471
+ throw e;
472
+ }
473
+ }
474
+ await client.syncState();
475
+ return config.importAccountId;
476
+ }
425
477
  const commitmentWord = Word2.deserialize(config.publicKeyCommitment);
426
478
  const seed = config.accountSeed ?? crypto.getRandomValues(new Uint8Array(32));
427
- const accountType = await getAccountType(config.accountType);
479
+ const accountType = getAccountType(config.accountType);
428
480
  let builder = new AccountBuilder(seed).withAuthComponent(
429
481
  AccountComponent.createAuthComponentFromCommitment(
430
482
  commitmentWord,
431
- 1
432
- // ECDSA auth scheme (K256/Keccak)
483
+ AuthScheme2.AuthEcdsaK256Keccak
433
484
  )
434
485
  ).accountType(accountType).storageMode(config.storageMode).withBasicWalletComponent();
435
486
  if (config.customComponents?.length) {
@@ -480,15 +531,19 @@ function MidenProvider({
480
531
  isReady,
481
532
  isInitializing,
482
533
  initError,
534
+ signerConnected,
483
535
  setClient,
484
536
  setInitializing,
485
537
  setInitError,
486
538
  setConfig,
487
- setSyncState
539
+ setSyncState,
540
+ setSignerConnected
488
541
  } = useMidenStore();
489
542
  const syncIntervalRef = useRef(null);
490
543
  const isInitializedRef = useRef(false);
491
544
  const clientLockRef = useRef(new AsyncLock());
545
+ const currentStoreNameRef = useRef(null);
546
+ const signCbRef = useRef(null);
492
547
  const signerContext = useSigner();
493
548
  const [signerAccountId, setSignerAccountId] = useState(null);
494
549
  const resolvedConfig = useMemo(
@@ -516,35 +571,62 @@ function MidenProvider({
516
571
  const store = useMidenStore.getState();
517
572
  if (store.sync.isSyncing) return;
518
573
  setSyncState({ isSyncing: true, error: null });
519
- await runExclusive(async () => {
520
- try {
521
- const summary = await client.syncState();
522
- const syncHeight = summary.blockNum();
523
- setSyncState({
524
- syncHeight,
525
- isSyncing: false,
526
- lastSyncTime: Date.now(),
527
- error: null
528
- });
529
- const accounts = await client.getAccounts();
530
- useMidenStore.getState().setAccounts(accounts);
531
- } catch (error) {
532
- setSyncState({
533
- isSyncing: false,
534
- error: error instanceof Error ? error : new Error(String(error))
535
- });
574
+ try {
575
+ const summary = await client.syncState();
576
+ const syncHeight = summary.blockNum();
577
+ setSyncState({
578
+ syncHeight,
579
+ isSyncing: false,
580
+ lastSyncTime: Date.now(),
581
+ error: null
582
+ });
583
+ const accounts = await client.getAccounts();
584
+ useMidenStore.getState().setAccounts(accounts);
585
+ } catch (error) {
586
+ setSyncState({
587
+ isSyncing: false,
588
+ error: error instanceof Error ? error : new Error(String(error))
589
+ });
590
+ }
591
+ }, [client, isReady, setSyncState]);
592
+ const signerIsConnected = signerContext?.isConnected ?? null;
593
+ const signerStoreName = signerContext?.storeName ?? null;
594
+ const signerAccountType = signerContext?.accountConfig?.accountType ?? null;
595
+ const signerStorageMode = signerContext?.accountConfig?.storageMode?.toString() ?? null;
596
+ useEffect(() => {
597
+ signCbRef.current = signerContext?.signCb ?? null;
598
+ }, [signerContext?.signCb]);
599
+ const wrappedSignCb = useCallback(
600
+ async (pubKey, signingInputs) => {
601
+ const cb = signCbRef.current;
602
+ if (!cb) {
603
+ throw new Error("Signer is disconnected. Cannot sign.");
536
604
  }
537
- });
538
- }, [client, isReady, runExclusive, setSyncState]);
605
+ return cb(pubKey, signingInputs);
606
+ },
607
+ []
608
+ );
539
609
  useEffect(() => {
540
- if (!signerContext && isInitializedRef.current) return;
541
- if (signerContext && !signerContext.isConnected) {
542
- if (useMidenStore.getState().client) {
543
- useMidenStore.getState().reset();
610
+ if (signerIsConnected === null && isInitializedRef.current) return;
611
+ if (signerIsConnected === false) {
612
+ const store = useMidenStore.getState();
613
+ if (store.signerConnected !== false) {
614
+ setSignerConnected(false);
615
+ }
616
+ return;
617
+ }
618
+ if (signerIsConnected === true && signerStoreName !== null) {
619
+ const store = useMidenStore.getState();
620
+ if (currentStoreNameRef.current === signerStoreName && store.client !== null) {
621
+ store.client.setSignCb(wrappedSignCb);
622
+ setSignerConnected(true);
623
+ return;
624
+ }
625
+ if (currentStoreNameRef.current !== null && currentStoreNameRef.current !== signerStoreName) {
626
+ store.resetInMemoryState();
544
627
  setClient(null);
545
628
  setSignerAccountId(null);
546
629
  }
547
- return;
548
630
  }
549
631
  let cancelled = false;
550
632
  const initClient = async () => {
@@ -555,18 +637,17 @@ function MidenProvider({
555
637
  try {
556
638
  let webClient;
557
639
  let didSignerInit = false;
558
- if (signerContext && signerContext.isConnected) {
640
+ if (signerContext && signerIsConnected === true) {
559
641
  const storeName = `MidenClientDB_${signerContext.storeName}`;
642
+ signCbRef.current = signerContext.signCb;
560
643
  webClient = await WebClient.createClientWithExternalKeystore(
561
644
  resolvedConfig.rpcUrl,
562
645
  resolvedConfig.noteTransportUrl,
563
646
  resolvedConfig.seed,
564
647
  storeName,
565
- void 0,
566
- // getKeyCb - not needed for public accounts
567
- void 0,
568
- // insertKeyCb - not needed for public accounts
569
- signerContext.signCb
648
+ signerContext.getKeyCb,
649
+ signerContext.insertKeyCb,
650
+ wrappedSignCb
570
651
  );
571
652
  if (cancelled) return;
572
653
  const accountId = await initializeSignerAccount(
@@ -576,6 +657,7 @@ function MidenProvider({
576
657
  if (cancelled) return;
577
658
  setSignerAccountId(accountId);
578
659
  didSignerInit = true;
660
+ currentStoreNameRef.current = signerContext.storeName;
579
661
  } else {
580
662
  const seed = resolvedConfig.seed;
581
663
  webClient = await WebClient.createClient(
@@ -609,6 +691,9 @@ function MidenProvider({
609
691
  isInitializedRef.current = true;
610
692
  }
611
693
  setClient(webClient);
694
+ if (signerIsConnected === true) {
695
+ setSignerConnected(true);
696
+ }
612
697
  }
613
698
  } catch (error) {
614
699
  if (!cancelled) {
@@ -632,14 +717,26 @@ function MidenProvider({
632
717
  setInitError,
633
718
  setInitializing,
634
719
  setSyncState,
635
- signerContext
720
+ setSignerConnected,
721
+ signerIsConnected,
722
+ signerStoreName,
723
+ signerAccountType,
724
+ signerStorageMode,
725
+ wrappedSignCb
726
+ // Note: signerContext is intentionally NOT a dep — we use stable primitives
727
+ // (signerIsConnected, signerStoreName, signerAccountType, signerStorageMode)
728
+ // to avoid re-running when the signer provider creates a new object ref.
729
+ // signCb changes are handled by the dedicated useEffect + signCbRef above,
730
+ // not by this effect.
636
731
  ]);
637
732
  useEffect(() => {
638
733
  if (!isReady || !client) return;
639
734
  const interval = config.autoSyncInterval ?? DEFAULTS.AUTO_SYNC_INTERVAL;
640
735
  if (interval <= 0) return;
641
736
  syncIntervalRef.current = setInterval(() => {
642
- sync();
737
+ if (!useMidenStore.getState().syncPaused) {
738
+ sync();
739
+ }
643
740
  }, interval);
644
741
  return () => {
645
742
  if (syncIntervalRef.current) {
@@ -648,6 +745,20 @@ function MidenProvider({
648
745
  }
649
746
  };
650
747
  }, [isReady, client, config.autoSyncInterval, sync]);
748
+ useEffect(() => {
749
+ if (!isReady || !client) return;
750
+ const unsubscribe = client.onStateChanged?.(async () => {
751
+ try {
752
+ const accounts = await client.getAccounts();
753
+ useMidenStore.getState().setAccounts(accounts);
754
+ setSyncState({ lastSyncTime: Date.now() });
755
+ } catch {
756
+ }
757
+ });
758
+ return () => {
759
+ unsubscribe?.();
760
+ };
761
+ }, [isReady, client, setSyncState]);
651
762
  if (isInitializing && loadingComponent) {
652
763
  return /* @__PURE__ */ jsx(Fragment, { children: loadingComponent });
653
764
  }
@@ -665,7 +776,8 @@ function MidenProvider({
665
776
  sync,
666
777
  runExclusive,
667
778
  prover: defaultProver,
668
- signerAccountId
779
+ signerAccountId,
780
+ signerConnected
669
781
  };
670
782
  return /* @__PURE__ */ jsx(MidenContext.Provider, { value: contextValue, children });
671
783
  }
@@ -686,35 +798,191 @@ function useMidenClient() {
686
798
  return client;
687
799
  }
688
800
 
689
- // src/hooks/useAccounts.ts
690
- import { useCallback as useCallback2, useEffect as useEffect2 } from "react";
691
-
692
- // src/utils/runExclusive.ts
693
- var runExclusiveDirect = async (fn) => fn();
801
+ // src/context/MultiSignerProvider.tsx
802
+ import {
803
+ createContext as createContext3,
804
+ useContext as useContext3,
805
+ useEffect as useEffect2,
806
+ useRef as useRef2,
807
+ useState as useState2,
808
+ useCallback as useCallback2,
809
+ useMemo as useMemo2
810
+ } from "react";
811
+ import { jsx as jsx2 } from "react/jsx-runtime";
812
+ var MultiSignerRegistryContext = createContext3(null);
813
+ var MultiSignerContext = createContext3(null);
814
+ function MultiSignerProvider({ children }) {
815
+ const signersRef = useRef2(/* @__PURE__ */ new Map());
816
+ const [signersSnapshot, setSignersSnapshot] = useState2(
817
+ []
818
+ );
819
+ const [activeSignerName, setActiveSignerName] = useState2(null);
820
+ const activeSignerNameRef = useRef2(null);
821
+ const generationRef = useRef2(0);
822
+ const updateSnapshot = useCallback2(() => {
823
+ setSignersSnapshot(Array.from(signersRef.current.values()));
824
+ }, []);
825
+ const register = useCallback2(
826
+ (value) => {
827
+ const prev = signersRef.current.get(value.name);
828
+ signersRef.current.set(value.name, value);
829
+ if (!prev || prev.name !== value.name || prev.isConnected !== value.isConnected || prev.storeName !== value.storeName || prev.accountConfig !== value.accountConfig) {
830
+ updateSnapshot();
831
+ }
832
+ },
833
+ [updateSnapshot]
834
+ );
835
+ const unregister = useCallback2(
836
+ (name) => {
837
+ signersRef.current.delete(name);
838
+ setActiveSignerName((current) => current === name ? null : current);
839
+ updateSnapshot();
840
+ },
841
+ [updateSnapshot]
842
+ );
843
+ const registry = useMemo2(
844
+ () => ({ register, unregister }),
845
+ [register, unregister]
846
+ );
847
+ const activeSigner = activeSignerName ? signersSnapshot.find((s) => s.name === activeSignerName) ?? null : null;
848
+ const stableSignCb = useCallback2(
849
+ async (pubKey, signingInputs) => {
850
+ const name = activeSignerName;
851
+ if (!name) throw new Error("No active signer (signer was disconnected)");
852
+ const signer = signersRef.current.get(name);
853
+ if (!signer) throw new Error(`Signer "${name}" not found in registry`);
854
+ return signer.signCb(pubKey, signingInputs);
855
+ },
856
+ [activeSignerName]
857
+ );
858
+ const stableConnect = useCallback2(async () => {
859
+ const name = activeSignerName;
860
+ if (!name) throw new Error("No active signer (signer was disconnected)");
861
+ const signer = signersRef.current.get(name);
862
+ if (!signer) throw new Error(`Signer "${name}" not found in registry`);
863
+ return signer.connect();
864
+ }, [activeSignerName]);
865
+ const stableDisconnect = useCallback2(async () => {
866
+ const name = activeSignerName;
867
+ if (!name) throw new Error("No active signer (signer was disconnected)");
868
+ const signer = signersRef.current.get(name);
869
+ if (!signer) throw new Error(`Signer "${name}" not found in registry`);
870
+ return signer.disconnect();
871
+ }, [activeSignerName]);
872
+ const forwardedValue = useMemo2(() => {
873
+ if (!activeSigner) return null;
874
+ return {
875
+ name: activeSigner.name,
876
+ isConnected: activeSigner.isConnected,
877
+ storeName: activeSigner.storeName,
878
+ accountConfig: activeSigner.accountConfig,
879
+ signCb: stableSignCb,
880
+ connect: stableConnect,
881
+ disconnect: stableDisconnect
882
+ };
883
+ }, [
884
+ activeSigner?.name,
885
+ activeSigner?.isConnected,
886
+ activeSigner?.storeName,
887
+ activeSigner?.accountConfig,
888
+ stableSignCb,
889
+ stableConnect,
890
+ stableDisconnect
891
+ ]);
892
+ const setActiveName = useCallback2((name) => {
893
+ activeSignerNameRef.current = name;
894
+ setActiveSignerName(name);
895
+ }, []);
896
+ const connectSigner = useCallback2(
897
+ async (name) => {
898
+ const currentName = activeSignerNameRef.current;
899
+ const currentSigner = currentName ? signersRef.current.get(currentName) : null;
900
+ if (currentName === name && currentSigner?.isConnected) return;
901
+ const newSigner = signersRef.current.get(name);
902
+ if (!newSigner) throw new Error(`Signer "${name}" not found`);
903
+ const generation = ++generationRef.current;
904
+ setActiveName(name);
905
+ if (currentSigner?.isConnected) {
906
+ currentSigner.disconnect().catch((err) => {
907
+ console.warn("Failed to disconnect previous signer:", err);
908
+ });
909
+ }
910
+ try {
911
+ await newSigner.connect();
912
+ if (generation !== generationRef.current) return;
913
+ } catch (err) {
914
+ if (generation !== generationRef.current) return;
915
+ setActiveName(null);
916
+ throw err;
917
+ }
918
+ },
919
+ [setActiveName]
920
+ );
921
+ const disconnectSigner = useCallback2(async () => {
922
+ ++generationRef.current;
923
+ const currentName = activeSignerNameRef.current;
924
+ const signer = currentName ? signersRef.current.get(currentName) : null;
925
+ setActiveName(null);
926
+ if (signer?.isConnected) {
927
+ signer.disconnect().catch((err) => {
928
+ console.warn("Failed to disconnect signer:", err);
929
+ });
930
+ }
931
+ }, [setActiveName]);
932
+ const multiSignerValue = useMemo2(
933
+ () => ({
934
+ signers: signersSnapshot,
935
+ activeSigner,
936
+ connectSigner,
937
+ disconnectSigner
938
+ }),
939
+ [signersSnapshot, activeSigner, connectSigner, disconnectSigner]
940
+ );
941
+ return /* @__PURE__ */ jsx2(SignerContext.Provider, { value: forwardedValue, children: /* @__PURE__ */ jsx2(MultiSignerRegistryContext.Provider, { value: registry, children: /* @__PURE__ */ jsx2(MultiSignerContext.Provider, { value: multiSignerValue, children }) }) });
942
+ }
943
+ function SignerSlot() {
944
+ const signerValue = useSigner();
945
+ const registry = useContext3(MultiSignerRegistryContext);
946
+ const nameRef = useRef2();
947
+ useEffect2(() => {
948
+ if (!signerValue || !registry) return;
949
+ nameRef.current = signerValue.name;
950
+ registry.register(signerValue);
951
+ }, [signerValue, registry]);
952
+ useEffect2(() => {
953
+ return () => {
954
+ if (nameRef.current && registry) {
955
+ registry.unregister(nameRef.current);
956
+ }
957
+ };
958
+ }, [registry]);
959
+ return null;
960
+ }
961
+ function useMultiSigner() {
962
+ return useContext3(MultiSignerContext);
963
+ }
694
964
 
695
965
  // src/hooks/useAccounts.ts
966
+ import { useCallback as useCallback3, useEffect as useEffect3 } from "react";
696
967
  function useAccounts() {
697
- const { client, isReady, runExclusive } = useMiden();
698
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
968
+ const { client, isReady } = useMiden();
699
969
  const accounts = useAccountsStore();
700
970
  const isLoadingAccounts = useMidenStore((state) => state.isLoadingAccounts);
701
971
  const setLoadingAccounts = useMidenStore((state) => state.setLoadingAccounts);
702
972
  const setAccounts = useMidenStore((state) => state.setAccounts);
703
- const refetch = useCallback2(async () => {
973
+ const refetch = useCallback3(async () => {
704
974
  if (!client || !isReady) return;
705
975
  setLoadingAccounts(true);
706
976
  try {
707
- const fetchedAccounts = await runExclusiveSafe(
708
- () => client.getAccounts()
709
- );
977
+ const fetchedAccounts = await client.getAccounts();
710
978
  setAccounts(fetchedAccounts);
711
979
  } catch (error) {
712
980
  console.error("Failed to fetch accounts:", error);
713
981
  } finally {
714
982
  setLoadingAccounts(false);
715
983
  }
716
- }, [client, isReady, runExclusive, setAccounts, setLoadingAccounts]);
717
- useEffect2(() => {
984
+ }, [client, isReady, setAccounts, setLoadingAccounts]);
985
+ useEffect3(() => {
718
986
  if (isReady && accounts.length === 0) {
719
987
  refetch();
720
988
  }
@@ -740,10 +1008,10 @@ function useAccounts() {
740
1008
  }
741
1009
 
742
1010
  // src/hooks/useAccount.ts
743
- import { useCallback as useCallback3, useEffect as useEffect4, useState as useState2, useMemo as useMemo3 } from "react";
1011
+ import { useCallback as useCallback4, useEffect as useEffect5, useState as useState3, useMemo as useMemo4 } from "react";
744
1012
 
745
1013
  // src/hooks/useAssetMetadata.ts
746
- import { useEffect as useEffect3, useMemo as useMemo2 } from "react";
1014
+ import { useEffect as useEffect4, useMemo as useMemo3 } from "react";
747
1015
  import {
748
1016
  BasicFungibleFaucetComponent,
749
1017
  Endpoint,
@@ -783,12 +1051,12 @@ function useAssetMetadata(assetIds = []) {
783
1051
  const assetMetadata = useAssetMetadataStore();
784
1052
  const setAssetMetadata = useMidenStore((state) => state.setAssetMetadata);
785
1053
  const rpcUrl = useMidenStore((state) => state.config.rpcUrl);
786
- const rpcClient = useMemo2(() => getRpcClient(rpcUrl), [rpcUrl]);
787
- const uniqueAssetIds = useMemo2(
1054
+ const rpcClient = useMemo3(() => getRpcClient(rpcUrl), [rpcUrl]);
1055
+ const uniqueAssetIds = useMemo3(
788
1056
  () => Array.from(new Set(assetIds.filter(Boolean))),
789
1057
  [assetIds]
790
1058
  );
791
- useEffect3(() => {
1059
+ useEffect4(() => {
792
1060
  if (!rpcClient || uniqueAssetIds.length === 0) return;
793
1061
  uniqueAssetIds.forEach((assetId) => {
794
1062
  const existing = assetMetadata.get(assetId);
@@ -807,31 +1075,25 @@ function useAssetMetadata(assetIds = []) {
807
1075
 
808
1076
  // src/hooks/useAccount.ts
809
1077
  function useAccount(accountId) {
810
- const { client, isReady, runExclusive } = useMiden();
811
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1078
+ const { client, isReady } = useMiden();
812
1079
  const accountDetails = useMidenStore((state) => state.accountDetails);
813
1080
  const setAccountDetails = useMidenStore((state) => state.setAccountDetails);
814
1081
  const { lastSyncTime } = useSyncStateStore();
815
- const [isLoading, setIsLoading] = useState2(false);
816
- const [error, setError] = useState2(null);
817
- const accountIdStr = useMemo3(() => {
1082
+ const [isLoading, setIsLoading] = useState3(false);
1083
+ const [error, setError] = useState3(null);
1084
+ const accountIdStr = useMemo4(() => {
818
1085
  if (!accountId) return void 0;
819
1086
  if (typeof accountId === "string") return accountId;
820
- if (typeof accountId.toString === "function") {
821
- return accountId.toString();
822
- }
823
- return String(accountId);
1087
+ return parseAccountId(accountId).toString();
824
1088
  }, [accountId]);
825
1089
  const account = accountIdStr ? accountDetails.get(accountIdStr) ?? null : null;
826
- const refetch = useCallback3(async () => {
1090
+ const refetch = useCallback4(async () => {
827
1091
  if (!client || !isReady || !accountIdStr) return;
828
1092
  setIsLoading(true);
829
1093
  setError(null);
830
1094
  try {
831
1095
  const accountIdObj = parseAccountId(accountIdStr);
832
- const fetchedAccount = await runExclusiveSafe(
833
- () => client.getAccount(accountIdObj)
834
- );
1096
+ const fetchedAccount = await client.getAccount(accountIdObj);
835
1097
  if (fetchedAccount) {
836
1098
  ensureAccountBech32(fetchedAccount);
837
1099
  setAccountDetails(accountIdStr, fetchedAccount);
@@ -841,17 +1103,17 @@ function useAccount(accountId) {
841
1103
  } finally {
842
1104
  setIsLoading(false);
843
1105
  }
844
- }, [client, isReady, runExclusive, accountIdStr, setAccountDetails]);
845
- useEffect4(() => {
1106
+ }, [client, isReady, accountIdStr, setAccountDetails]);
1107
+ useEffect5(() => {
846
1108
  if (isReady && accountIdStr && !account) {
847
1109
  refetch();
848
1110
  }
849
1111
  }, [isReady, accountIdStr, account, refetch]);
850
- useEffect4(() => {
1112
+ useEffect5(() => {
851
1113
  if (!isReady || !accountIdStr || !lastSyncTime) return;
852
1114
  refetch();
853
1115
  }, [isReady, accountIdStr, lastSyncTime, refetch]);
854
- const rawAssets = useMemo3(() => {
1116
+ const rawAssets = useMemo4(() => {
855
1117
  if (!account) return [];
856
1118
  try {
857
1119
  const vault = account.vault();
@@ -868,12 +1130,12 @@ function useAccount(accountId) {
868
1130
  return [];
869
1131
  }
870
1132
  }, [account]);
871
- const assetIds = useMemo3(
1133
+ const assetIds = useMemo4(
872
1134
  () => rawAssets.map((asset) => asset.assetId),
873
1135
  [rawAssets]
874
1136
  );
875
1137
  const { assetMetadata } = useAssetMetadata(assetIds);
876
- const assets = useMemo3(
1138
+ const assets = useMemo4(
877
1139
  () => rawAssets.map((asset) => {
878
1140
  const metadata = assetMetadata.get(asset.assetId);
879
1141
  return {
@@ -884,7 +1146,7 @@ function useAccount(accountId) {
884
1146
  }),
885
1147
  [rawAssets, assetMetadata]
886
1148
  );
887
- const getBalance = useCallback3(
1149
+ const getBalance = useCallback4(
888
1150
  (assetId) => {
889
1151
  const asset = assets.find((a) => a.assetId === assetId);
890
1152
  return asset?.amount ?? 0n;
@@ -902,17 +1164,18 @@ function useAccount(accountId) {
902
1164
  }
903
1165
 
904
1166
  // src/hooks/useNotes.ts
905
- import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo4, useState as useState3 } from "react";
1167
+ import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useState as useState4 } from "react";
906
1168
  import { NoteFilter } from "@miden-sdk/miden-sdk";
907
1169
 
908
1170
  // src/utils/amounts.ts
909
1171
  var formatAssetAmount = (amount, decimals) => {
1172
+ const amt = BigInt(amount);
910
1173
  if (!decimals || decimals <= 0) {
911
- return amount.toString();
1174
+ return amt.toString();
912
1175
  }
913
1176
  const factor = 10n ** BigInt(decimals);
914
- const whole = amount / factor;
915
- const fraction = amount % factor;
1177
+ const whole = amt / factor;
1178
+ const fraction = amt % factor;
916
1179
  if (fraction === 0n) {
917
1180
  return whole.toString();
918
1181
  }
@@ -1069,8 +1332,7 @@ function normalizeHex(value) {
1069
1332
 
1070
1333
  // src/hooks/useNotes.ts
1071
1334
  function useNotes(options) {
1072
- const { client, isReady, runExclusive } = useMiden();
1073
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1335
+ const { client, isReady } = useMiden();
1074
1336
  const notes = useNotesStore();
1075
1337
  const consumableNotes = useConsumableNotesStore();
1076
1338
  const isLoadingNotes = useMidenStore((state) => state.isLoadingNotes);
@@ -1080,30 +1342,22 @@ function useNotes(options) {
1080
1342
  (state) => state.setConsumableNotesIfChanged
1081
1343
  );
1082
1344
  const { lastSyncTime } = useSyncStateStore();
1083
- const [error, setError] = useState3(null);
1084
- const refetch = useCallback4(async () => {
1345
+ const [error, setError] = useState4(null);
1346
+ const refetch = useCallback5(async () => {
1085
1347
  if (!client || !isReady) return;
1086
1348
  setLoadingNotes(true);
1087
1349
  setError(null);
1088
1350
  try {
1089
- const { fetchedNotes, fetchedConsumable } = await runExclusiveSafe(
1090
- async () => {
1091
- const filterType = getNoteFilterType(options?.status);
1092
- const filter = new NoteFilter(filterType);
1093
- const notesResult = await client.getInputNotes(filter);
1094
- let consumableResult;
1095
- if (options?.accountId) {
1096
- const accountIdObj = parseAccountId(options.accountId);
1097
- consumableResult = await client.getConsumableNotes(accountIdObj);
1098
- } else {
1099
- consumableResult = await client.getConsumableNotes();
1100
- }
1101
- return {
1102
- fetchedNotes: notesResult,
1103
- fetchedConsumable: consumableResult
1104
- };
1105
- }
1106
- );
1351
+ const filterType = getNoteFilterType(options?.status);
1352
+ const filter = new NoteFilter(filterType);
1353
+ const fetchedNotes = await client.getInputNotes(filter);
1354
+ let fetchedConsumable;
1355
+ if (options?.accountId) {
1356
+ const accountIdObj = parseAccountId(options.accountId);
1357
+ fetchedConsumable = await client.getConsumableNotes(accountIdObj);
1358
+ } else {
1359
+ fetchedConsumable = await client.getConsumableNotes();
1360
+ }
1107
1361
  setNotesIfChanged(fetchedNotes);
1108
1362
  setConsumableNotesIfChanged(fetchedConsumable);
1109
1363
  } catch (err) {
@@ -1114,23 +1368,22 @@ function useNotes(options) {
1114
1368
  }, [
1115
1369
  client,
1116
1370
  isReady,
1117
- runExclusive,
1118
1371
  options?.status,
1119
1372
  options?.accountId,
1120
1373
  setLoadingNotes,
1121
1374
  setNotesIfChanged,
1122
1375
  setConsumableNotesIfChanged
1123
1376
  ]);
1124
- useEffect5(() => {
1377
+ useEffect6(() => {
1125
1378
  if (isReady && notes.length === 0) {
1126
1379
  refetch();
1127
1380
  }
1128
1381
  }, [isReady, notes.length, refetch]);
1129
- useEffect5(() => {
1382
+ useEffect6(() => {
1130
1383
  if (!isReady || !lastSyncTime) return;
1131
1384
  refetch();
1132
1385
  }, [isReady, lastSyncTime, refetch]);
1133
- const noteAssetIds = useMemo4(() => {
1386
+ const noteAssetIds = useMemo5(() => {
1134
1387
  const ids = /* @__PURE__ */ new Set();
1135
1388
  const collect = (note) => {
1136
1389
  const summary = getNoteSummary(note);
@@ -1142,11 +1395,11 @@ function useNotes(options) {
1142
1395
  return Array.from(ids);
1143
1396
  }, [notes, consumableNotes]);
1144
1397
  const { assetMetadata } = useAssetMetadata(noteAssetIds);
1145
- const getMetadata = useCallback4(
1398
+ const getMetadata = useCallback5(
1146
1399
  (assetId) => assetMetadata.get(assetId),
1147
1400
  [assetMetadata]
1148
1401
  );
1149
- const normalizedSender = useMemo4(() => {
1402
+ const normalizedSender = useMemo5(() => {
1150
1403
  if (!options?.sender) return null;
1151
1404
  try {
1152
1405
  return normalizeAccountId(options.sender);
@@ -1154,11 +1407,11 @@ function useNotes(options) {
1154
1407
  return options.sender;
1155
1408
  }
1156
1409
  }, [options?.sender]);
1157
- const excludeIdsKey = useMemo4(() => {
1410
+ const excludeIdsKey = useMemo5(() => {
1158
1411
  if (!options?.excludeIds || options.excludeIds.length === 0) return "";
1159
1412
  return [...options.excludeIds].sort().join("\0");
1160
1413
  }, [options?.excludeIds]);
1161
- const filterBySender = useCallback4(
1414
+ const filterBySender = useCallback5(
1162
1415
  (summaries, target) => {
1163
1416
  const cache = /* @__PURE__ */ new Map();
1164
1417
  return summaries.filter((s) => {
@@ -1177,7 +1430,7 @@ function useNotes(options) {
1177
1430
  },
1178
1431
  []
1179
1432
  );
1180
- const noteSummaries = useMemo4(() => {
1433
+ const noteSummaries = useMemo5(() => {
1181
1434
  let summaries = notes.map((note) => getNoteSummary(note, getMetadata)).filter(Boolean);
1182
1435
  if (normalizedSender) {
1183
1436
  summaries = filterBySender(summaries, normalizedSender);
@@ -1188,7 +1441,7 @@ function useNotes(options) {
1188
1441
  }
1189
1442
  return summaries;
1190
1443
  }, [notes, getMetadata, normalizedSender, excludeIdsKey, filterBySender]);
1191
- const consumableNoteSummaries = useMemo4(() => {
1444
+ const consumableNoteSummaries = useMemo5(() => {
1192
1445
  let summaries = consumableNotes.map((note) => getNoteSummary(note, getMetadata)).filter(Boolean);
1193
1446
  if (normalizedSender) {
1194
1447
  summaries = filterBySender(summaries, normalizedSender);
@@ -1217,7 +1470,7 @@ function useNotes(options) {
1217
1470
  }
1218
1471
 
1219
1472
  // src/hooks/useNoteStream.ts
1220
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef2, useState as useState4 } from "react";
1473
+ import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef3, useState as useState5 } from "react";
1221
1474
  import { NoteFilter as NoteFilter2 } from "@miden-sdk/miden-sdk";
1222
1475
 
1223
1476
  // src/utils/noteAttachment.ts
@@ -1293,54 +1546,51 @@ function createNoteAttachment(values) {
1293
1546
 
1294
1547
  // src/hooks/useNoteStream.ts
1295
1548
  function useNoteStream(options = {}) {
1296
- const { client, isReady, runExclusive } = useMiden();
1297
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1549
+ const { client, isReady } = useMiden();
1298
1550
  const allNotes = useNotesStore();
1299
1551
  const noteFirstSeen = useNoteFirstSeenStore();
1300
1552
  const { lastSyncTime } = useSyncStateStore();
1301
1553
  const setNotesIfChanged = useMidenStore((state) => state.setNotesIfChanged);
1302
- const [isLoading, setIsLoading] = useState4(false);
1303
- const [error, setError] = useState4(null);
1304
- const handledIdsRef = useRef2(/* @__PURE__ */ new Set());
1305
- const [handledVersion, setHandledVersion] = useState4(0);
1554
+ const [isLoading, setIsLoading] = useState5(false);
1555
+ const [error, setError] = useState5(null);
1556
+ const handledIdsRef = useRef3(/* @__PURE__ */ new Set());
1557
+ const [handledVersion, setHandledVersion] = useState5(0);
1306
1558
  const status = options.status ?? "committed";
1307
1559
  const sender = options.sender ?? null;
1308
1560
  const since = options.since;
1309
- const amountFilterRef = useRef2(options.amountFilter);
1561
+ const amountFilterRef = useRef3(options.amountFilter);
1310
1562
  amountFilterRef.current = options.amountFilter;
1311
- const excludeIdsKey = useMemo5(() => {
1563
+ const excludeIdsKey = useMemo6(() => {
1312
1564
  if (!options.excludeIds) return "";
1313
1565
  if (options.excludeIds instanceof Set)
1314
1566
  return Array.from(options.excludeIds).sort().join("\0");
1315
1567
  return [...options.excludeIds].sort().join("\0");
1316
1568
  }, [options.excludeIds]);
1317
- const excludeIdSet = useMemo5(() => {
1569
+ const excludeIdSet = useMemo6(() => {
1318
1570
  if (!excludeIdsKey) return null;
1319
1571
  return new Set(excludeIdsKey.split("\0"));
1320
1572
  }, [excludeIdsKey]);
1321
- const refetch = useCallback5(async () => {
1573
+ const refetch = useCallback6(async () => {
1322
1574
  if (!client || !isReady) return;
1323
1575
  setIsLoading(true);
1324
1576
  setError(null);
1325
1577
  try {
1326
1578
  const filterType = getNoteFilterType(status);
1327
1579
  const filter = new NoteFilter2(filterType);
1328
- const fetched = await runExclusiveSafe(
1329
- () => client.getInputNotes(filter)
1330
- );
1580
+ const fetched = await client.getInputNotes(filter);
1331
1581
  setNotesIfChanged(fetched);
1332
1582
  } catch (err) {
1333
1583
  setError(err instanceof Error ? err : new Error(String(err)));
1334
1584
  } finally {
1335
1585
  setIsLoading(false);
1336
1586
  }
1337
- }, [client, isReady, runExclusiveSafe, status, setNotesIfChanged]);
1338
- useEffect6(() => {
1587
+ }, [client, isReady, status, setNotesIfChanged]);
1588
+ useEffect7(() => {
1339
1589
  if (isReady) {
1340
1590
  refetch();
1341
1591
  }
1342
1592
  }, [isReady, lastSyncTime, refetch]);
1343
- const streamedNotes = useMemo5(() => {
1593
+ const streamedNotes = useMemo6(() => {
1344
1594
  void handledVersion;
1345
1595
  const result = [];
1346
1596
  let normalizedSender = null;
@@ -1365,15 +1615,15 @@ function useNoteStream(options = {}) {
1365
1615
  result.sort((a, b) => a.firstSeenAt - b.firstSeenAt);
1366
1616
  return result;
1367
1617
  }, [allNotes, noteFirstSeen, excludeIdSet, sender, since, handledVersion]);
1368
- const latest = useMemo5(
1618
+ const latest = useMemo6(
1369
1619
  () => streamedNotes.length > 0 ? streamedNotes[streamedNotes.length - 1] : null,
1370
1620
  [streamedNotes]
1371
1621
  );
1372
- const markHandled = useCallback5((noteId) => {
1622
+ const markHandled = useCallback6((noteId) => {
1373
1623
  handledIdsRef.current = new Set(handledIdsRef.current).add(noteId);
1374
1624
  setHandledVersion((v) => v + 1);
1375
1625
  }, []);
1376
- const markAllHandled = useCallback5(() => {
1626
+ const markAllHandled = useCallback6(() => {
1377
1627
  const newSet = new Set(handledIdsRef.current);
1378
1628
  for (const note of streamedNotes) {
1379
1629
  newSet.add(note.id);
@@ -1381,7 +1631,7 @@ function useNoteStream(options = {}) {
1381
1631
  handledIdsRef.current = newSet;
1382
1632
  setHandledVersion((v) => v + 1);
1383
1633
  }, [streamedNotes]);
1384
- const snapshot = useCallback5(() => {
1634
+ const snapshot = useCallback6(() => {
1385
1635
  const ids = /* @__PURE__ */ new Set();
1386
1636
  for (const note of streamedNotes) {
1387
1637
  ids.add(note.id);
@@ -1437,21 +1687,20 @@ function buildStreamedNote(record, noteFirstSeen) {
1437
1687
  }
1438
1688
 
1439
1689
  // src/hooks/useTransactionHistory.ts
1440
- import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo6, useState as useState5 } from "react";
1690
+ import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo7, useState as useState6 } from "react";
1441
1691
  import { TransactionFilter as TransactionFilter2 } from "@miden-sdk/miden-sdk";
1442
1692
  function useTransactionHistory(options = {}) {
1443
- const { client, isReady, runExclusive } = useMiden();
1444
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1693
+ const { client, isReady } = useMiden();
1445
1694
  const { lastSyncTime } = useSyncStateStore();
1446
- const [records, setRecords] = useState5([]);
1447
- const [isLoading, setIsLoading] = useState5(false);
1448
- const [error, setError] = useState5(null);
1449
- const rawIds = useMemo6(() => {
1695
+ const [records, setRecords] = useState6([]);
1696
+ const [isLoading, setIsLoading] = useState6(false);
1697
+ const [error, setError] = useState6(null);
1698
+ const rawIds = useMemo7(() => {
1450
1699
  if (options.id) return [options.id];
1451
1700
  if (options.ids && options.ids.length > 0) return options.ids;
1452
1701
  return null;
1453
1702
  }, [options.id, options.ids]);
1454
- const idsHex = useMemo6(() => {
1703
+ const idsHex = useMemo7(() => {
1455
1704
  if (!rawIds) return null;
1456
1705
  return rawIds.map(
1457
1706
  (id) => normalizeHex2(typeof id === "string" ? id : id.toHex())
@@ -1459,7 +1708,7 @@ function useTransactionHistory(options = {}) {
1459
1708
  }, [rawIds]);
1460
1709
  const filter = options.filter;
1461
1710
  const refreshOnSync = options.refreshOnSync !== false;
1462
- const refetch = useCallback6(async () => {
1711
+ const refetch = useCallback7(async () => {
1463
1712
  if (!client || !isReady) return;
1464
1713
  setIsLoading(true);
1465
1714
  setError(null);
@@ -1469,9 +1718,7 @@ function useTransactionHistory(options = {}) {
1469
1718
  rawIds,
1470
1719
  idsHex
1471
1720
  );
1472
- const fetched = await runExclusiveSafe(
1473
- () => client.getTransactions(resolvedFilter)
1474
- );
1721
+ const fetched = await client.getTransactions(resolvedFilter);
1475
1722
  const filtered = localFilterHexes ? fetched.filter(
1476
1723
  (record2) => localFilterHexes.includes(normalizeHex2(record2.id().toHex()))
1477
1724
  ) : fetched;
@@ -1481,20 +1728,20 @@ function useTransactionHistory(options = {}) {
1481
1728
  } finally {
1482
1729
  setIsLoading(false);
1483
1730
  }
1484
- }, [client, isReady, runExclusiveSafe, filter, rawIds, idsHex]);
1485
- useEffect7(() => {
1731
+ }, [client, isReady, filter, rawIds, idsHex]);
1732
+ useEffect8(() => {
1486
1733
  if (!isReady) return;
1487
1734
  refetch();
1488
1735
  }, [isReady, refetch]);
1489
- useEffect7(() => {
1736
+ useEffect8(() => {
1490
1737
  if (!isReady || !refreshOnSync || !lastSyncTime) return;
1491
1738
  refetch();
1492
1739
  }, [isReady, lastSyncTime, refreshOnSync, refetch]);
1493
- const record = useMemo6(() => {
1740
+ const record = useMemo7(() => {
1494
1741
  if (!idsHex || idsHex.length !== 1) return null;
1495
1742
  return records.find((item) => normalizeHex2(item.id().toHex()) === idsHex[0]) ?? null;
1496
1743
  }, [records, idsHex]);
1497
- const status = useMemo6(() => {
1744
+ const status = useMemo7(() => {
1498
1745
  if (!record) return null;
1499
1746
  const current = record.transactionStatus();
1500
1747
  if (current.isCommitted()) return "committed";
@@ -1534,11 +1781,11 @@ function normalizeHex2(value) {
1534
1781
  }
1535
1782
 
1536
1783
  // src/hooks/useSyncState.ts
1537
- import { useCallback as useCallback7 } from "react";
1784
+ import { useCallback as useCallback8 } from "react";
1538
1785
  function useSyncState() {
1539
1786
  const { sync: triggerSync } = useMiden();
1540
1787
  const syncState = useSyncStateStore();
1541
- const sync = useCallback7(async () => {
1788
+ const sync = useCallback8(async () => {
1542
1789
  await triggerSync();
1543
1790
  }, [triggerSync]);
1544
1791
  return {
@@ -1548,21 +1795,25 @@ function useSyncState() {
1548
1795
  }
1549
1796
 
1550
1797
  // src/hooks/useCreateWallet.ts
1551
- import { useCallback as useCallback8, useState as useState6 } from "react";
1798
+ import { useCallback as useCallback9, useState as useState7 } from "react";
1552
1799
  import { AccountStorageMode } from "@miden-sdk/miden-sdk";
1800
+
1801
+ // src/utils/runExclusive.ts
1802
+ var runExclusiveDirect = async (fn) => fn();
1803
+
1804
+ // src/hooks/useCreateWallet.ts
1553
1805
  function useCreateWallet() {
1554
- const { client, isReady, sync, runExclusive } = useMiden();
1806
+ const { client, isReady, runExclusive } = useMiden();
1555
1807
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1556
1808
  const setAccounts = useMidenStore((state) => state.setAccounts);
1557
- const [wallet, setWallet] = useState6(null);
1558
- const [isCreating, setIsCreating] = useState6(false);
1559
- const [error, setError] = useState6(null);
1560
- const createWallet = useCallback8(
1809
+ const [wallet, setWallet] = useState7(null);
1810
+ const [isCreating, setIsCreating] = useState7(false);
1811
+ const [error, setError] = useState7(null);
1812
+ const createWallet = useCallback9(
1561
1813
  async (options = {}) => {
1562
1814
  if (!client || !isReady) {
1563
1815
  throw new Error("Miden client is not ready");
1564
1816
  }
1565
- await sync();
1566
1817
  setIsCreating(true);
1567
1818
  setError(null);
1568
1819
  try {
@@ -1595,7 +1846,7 @@ function useCreateWallet() {
1595
1846
  },
1596
1847
  [client, isReady, runExclusive, setAccounts]
1597
1848
  );
1598
- const reset = useCallback8(() => {
1849
+ const reset = useCallback9(() => {
1599
1850
  setWallet(null);
1600
1851
  setIsCreating(false);
1601
1852
  setError(null);
@@ -1622,16 +1873,16 @@ function getStorageMode(mode) {
1622
1873
  }
1623
1874
 
1624
1875
  // src/hooks/useCreateFaucet.ts
1625
- import { useCallback as useCallback9, useState as useState7 } from "react";
1876
+ import { useCallback as useCallback10, useState as useState8 } from "react";
1626
1877
  import { AccountStorageMode as AccountStorageMode2 } from "@miden-sdk/miden-sdk";
1627
1878
  function useCreateFaucet() {
1628
1879
  const { client, isReady, runExclusive } = useMiden();
1629
1880
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1630
1881
  const setAccounts = useMidenStore((state) => state.setAccounts);
1631
- const [faucet, setFaucet] = useState7(null);
1632
- const [isCreating, setIsCreating] = useState7(false);
1633
- const [error, setError] = useState7(null);
1634
- const createFaucet = useCallback9(
1882
+ const [faucet, setFaucet] = useState8(null);
1883
+ const [isCreating, setIsCreating] = useState8(false);
1884
+ const [error, setError] = useState8(null);
1885
+ const createFaucet = useCallback10(
1635
1886
  async (options) => {
1636
1887
  if (!client || !isReady) {
1637
1888
  throw new Error("Miden client is not ready");
@@ -1651,7 +1902,7 @@ function useCreateFaucet() {
1651
1902
  // nonFungible - currently only fungible faucets supported
1652
1903
  options.tokenSymbol,
1653
1904
  decimals,
1654
- options.maxSupply,
1905
+ BigInt(options.maxSupply),
1655
1906
  authScheme
1656
1907
  );
1657
1908
  const accounts = await client.getAccounts();
@@ -1670,7 +1921,7 @@ function useCreateFaucet() {
1670
1921
  },
1671
1922
  [client, isReady, runExclusive, setAccounts]
1672
1923
  );
1673
- const reset = useCallback9(() => {
1924
+ const reset = useCallback10(() => {
1674
1925
  setFaucet(null);
1675
1926
  setIsCreating(false);
1676
1927
  setError(null);
@@ -1697,25 +1948,79 @@ function getStorageMode2(mode) {
1697
1948
  }
1698
1949
 
1699
1950
  // src/hooks/useImportAccount.ts
1700
- import { useCallback as useCallback10, useState as useState8 } from "react";
1951
+ import { useCallback as useCallback11, useState as useState9 } from "react";
1701
1952
  import { AccountFile } from "@miden-sdk/miden-sdk";
1953
+
1954
+ // src/utils/errors.ts
1955
+ var MidenError = class extends Error {
1956
+ constructor(message, options) {
1957
+ super(message);
1958
+ this.name = "MidenError";
1959
+ this.code = options?.code ?? "UNKNOWN";
1960
+ if (options?.cause !== void 0) {
1961
+ this.cause = options.cause;
1962
+ }
1963
+ }
1964
+ };
1965
+ var ERROR_PATTERNS = [
1966
+ {
1967
+ test: (msg) => msg.includes("_assertClass") || msg.includes("expected instance of"),
1968
+ code: "WASM_CLASS_MISMATCH",
1969
+ message: "WASM class identity mismatch. This usually means multiple copies of @miden-sdk/miden-sdk are bundled. Ensure your bundler deduplicates the package. For Vite: add resolve.dedupe and optimizeDeps.exclude for @miden-sdk/miden-sdk."
1970
+ },
1971
+ {
1972
+ test: (msg) => msg.includes("null pointer") || msg.includes("already been freed") || msg.includes("dereferencing a null"),
1973
+ code: "WASM_POINTER_CONSUMED",
1974
+ message: "WASM object was already consumed. Some WASM-bound objects can only be passed once \u2014 if you need to reuse a value, create a fresh instance before each call."
1975
+ },
1976
+ {
1977
+ test: (msg) => msg.includes("not initialized") || msg.includes("Cannot read properties of null"),
1978
+ code: "WASM_NOT_INITIALIZED",
1979
+ message: "Miden client is not initialized. Ensure you are inside a <MidenProvider> and the client is ready before calling SDK methods."
1980
+ },
1981
+ {
1982
+ test: (msg) => msg.includes("state commitment mismatch") || msg.includes("stale state"),
1983
+ code: "WASM_SYNC_REQUIRED",
1984
+ message: "Account state is stale. Call sync() before executing transactions, or ensure no concurrent transactions are running against the same account."
1985
+ }
1986
+ ];
1987
+ function assertSignerConnected(signerConnected) {
1988
+ if (signerConnected === false) {
1989
+ throw new Error(
1990
+ "Signer is disconnected. Reconnect your wallet to perform transactions."
1991
+ );
1992
+ }
1993
+ }
1994
+ function wrapWasmError(e) {
1995
+ if (e instanceof MidenError) return e;
1996
+ const msg = e instanceof Error ? e.message : String(e);
1997
+ for (const pattern of ERROR_PATTERNS) {
1998
+ if (pattern.test(msg)) {
1999
+ return new MidenError(pattern.message, { cause: e, code: pattern.code });
2000
+ }
2001
+ }
2002
+ if (e instanceof Error) return e;
2003
+ return new Error(msg);
2004
+ }
2005
+
2006
+ // src/hooks/useImportAccount.ts
1702
2007
  function useImportAccount() {
1703
- const { client, isReady, runExclusive } = useMiden();
1704
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2008
+ const { client, isReady, signerConnected } = useMiden();
1705
2009
  const setAccounts = useMidenStore((state) => state.setAccounts);
1706
- const [account, setAccount] = useState8(null);
1707
- const [isImporting, setIsImporting] = useState8(false);
1708
- const [error, setError] = useState8(null);
1709
- const importAccount = useCallback10(
2010
+ const [account, setAccount] = useState9(null);
2011
+ const [isImporting, setIsImporting] = useState9(false);
2012
+ const [error, setError] = useState9(null);
2013
+ const importAccount = useCallback11(
1710
2014
  async (options) => {
1711
2015
  if (!client || !isReady) {
1712
2016
  throw new Error("Miden client is not ready");
1713
2017
  }
2018
+ assertSignerConnected(signerConnected);
1714
2019
  setIsImporting(true);
1715
2020
  setError(null);
1716
2021
  try {
1717
2022
  let accountsAfter = null;
1718
- const imported = await runExclusiveSafe(async () => {
2023
+ const imported = await (async () => {
1719
2024
  switch (options.type) {
1720
2025
  case "file": {
1721
2026
  const accountsBefore = await client.getAccounts();
@@ -1767,7 +2072,7 @@ function useImportAccount() {
1767
2072
  throw new Error("Account not found after import");
1768
2073
  }
1769
2074
  case "id": {
1770
- const accountId = resolveAccountId(options.accountId);
2075
+ const accountId = parseAccountId(options.accountId);
1771
2076
  await client.importAccountById(accountId);
1772
2077
  const fetchedAccount = await client.getAccount(accountId);
1773
2078
  if (!fetchedAccount) {
@@ -1785,7 +2090,7 @@ function useImportAccount() {
1785
2090
  );
1786
2091
  }
1787
2092
  }
1788
- });
2093
+ })();
1789
2094
  ensureAccountBech32(imported);
1790
2095
  const accounts = accountsAfter ?? await client.getAccounts();
1791
2096
  setAccounts(accounts);
@@ -1799,9 +2104,9 @@ function useImportAccount() {
1799
2104
  setIsImporting(false);
1800
2105
  }
1801
2106
  },
1802
- [client, isReady, runExclusive, setAccounts]
2107
+ [client, isReady, setAccounts, signerConnected]
1803
2108
  );
1804
- const reset = useCallback10(() => {
2109
+ const reset = useCallback11(() => {
1805
2110
  setAccount(null);
1806
2111
  setIsImporting(false);
1807
2112
  setError(null);
@@ -1814,9 +2119,6 @@ function useImportAccount() {
1814
2119
  reset
1815
2120
  };
1816
2121
  }
1817
- function resolveAccountId(accountId) {
1818
- return parseAccountId(accountId);
1819
- }
1820
2122
  async function resolveAccountFile(file) {
1821
2123
  if (file instanceof Uint8Array) {
1822
2124
  return AccountFile.deserialize(file);
@@ -1851,72 +2153,25 @@ function bytesEqual(left, right) {
1851
2153
  }
1852
2154
 
1853
2155
  // src/hooks/useSend.ts
1854
- import { useCallback as useCallback11, useRef as useRef3, useState as useState9 } from "react";
2156
+ import { useCallback as useCallback12, useRef as useRef4, useState as useState10 } from "react";
1855
2157
  import {
1856
2158
  FungibleAsset,
1857
2159
  Note,
1858
2160
  NoteAssets,
2161
+ NoteAttachment as NoteAttachment2,
1859
2162
  NoteType as NoteType2,
1860
- OutputNote,
1861
- OutputNoteArray,
2163
+ NoteArray,
1862
2164
  TransactionRequestBuilder
1863
2165
  } from "@miden-sdk/miden-sdk";
1864
-
1865
- // src/utils/errors.ts
1866
- var MidenError = class extends Error {
1867
- constructor(message, options) {
1868
- super(message);
1869
- this.name = "MidenError";
1870
- this.code = options?.code ?? "UNKNOWN";
1871
- if (options?.cause !== void 0) {
1872
- this.cause = options.cause;
1873
- }
1874
- }
1875
- };
1876
- var ERROR_PATTERNS = [
1877
- {
1878
- test: (msg) => msg.includes("_assertClass") || msg.includes("expected instance of"),
1879
- code: "WASM_CLASS_MISMATCH",
1880
- message: "WASM class identity mismatch. This usually means multiple copies of @miden-sdk/miden-sdk are bundled. Ensure your bundler deduplicates the package. For Vite: add resolve.dedupe and optimizeDeps.exclude for @miden-sdk/miden-sdk."
1881
- },
1882
- {
1883
- test: (msg) => msg.includes("null pointer") || msg.includes("already been freed") || msg.includes("dereferencing a null"),
1884
- code: "WASM_POINTER_CONSUMED",
1885
- message: "WASM object was already consumed. Some WASM-bound objects can only be passed once \u2014 if you need to reuse a value, create a fresh instance before each call."
1886
- },
1887
- {
1888
- test: (msg) => msg.includes("not initialized") || msg.includes("Cannot read properties of null"),
1889
- code: "WASM_NOT_INITIALIZED",
1890
- message: "Miden client is not initialized. Ensure you are inside a <MidenProvider> and the client is ready before calling SDK methods."
1891
- },
1892
- {
1893
- test: (msg) => msg.includes("state commitment mismatch") || msg.includes("stale state"),
1894
- code: "WASM_SYNC_REQUIRED",
1895
- message: "Account state is stale. Call sync() before executing transactions, or ensure no concurrent transactions are running against the same account."
1896
- }
1897
- ];
1898
- function wrapWasmError(e) {
1899
- if (e instanceof MidenError) return e;
1900
- const msg = e instanceof Error ? e.message : String(e);
1901
- for (const pattern of ERROR_PATTERNS) {
1902
- if (pattern.test(msg)) {
1903
- return new MidenError(pattern.message, { cause: e, code: pattern.code });
1904
- }
1905
- }
1906
- if (e instanceof Error) return e;
1907
- return new Error(msg);
1908
- }
1909
-
1910
- // src/hooks/useSend.ts
1911
2166
  function useSend() {
1912
2167
  const { client, isReady, sync, runExclusive, prover } = useMiden();
1913
2168
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1914
- const isBusyRef = useRef3(false);
1915
- const [result, setResult] = useState9(null);
1916
- const [isLoading, setIsLoading] = useState9(false);
1917
- const [stage, setStage] = useState9("idle");
1918
- const [error, setError] = useState9(null);
1919
- const send = useCallback11(
2169
+ const isBusyRef = useRef4(false);
2170
+ const [result, setResult] = useState10(null);
2171
+ const [isLoading, setIsLoading] = useState10(false);
2172
+ const [stage, setStage] = useState10("idle");
2173
+ const [error, setError] = useState10(null);
2174
+ const send = useCallback12(
1920
2175
  async (options) => {
1921
2176
  if (!client || !isReady) {
1922
2177
  throw new Error("Miden client is not ready");
@@ -1958,6 +2213,7 @@ function useSend() {
1958
2213
  if (amount === void 0 || amount === null) {
1959
2214
  throw new Error("Amount is required (provide amount or sendAll)");
1960
2215
  }
2216
+ amount = BigInt(amount);
1961
2217
  const assetId = options.assetId ?? options.faucetId ?? null;
1962
2218
  if (!assetId) {
1963
2219
  throw new Error("Asset ID is required");
@@ -1968,6 +2224,35 @@ function useSend() {
1968
2224
  "recallHeight and timelockHeight are not supported when attachment is provided"
1969
2225
  );
1970
2226
  }
2227
+ if (options.returnNote === true) {
2228
+ const returnResult = await runExclusiveSafe(async () => {
2229
+ const fromId = parseAccountId(options.from);
2230
+ const toId = parseAccountId(options.to);
2231
+ const assetObj = parseAccountId(assetId);
2232
+ const assets = new NoteAssets([
2233
+ new FungibleAsset(assetObj, BigInt(amount))
2234
+ ]);
2235
+ const p2idNote = Note.createP2IDNote(
2236
+ fromId,
2237
+ toId,
2238
+ assets,
2239
+ noteType,
2240
+ new NoteAttachment2()
2241
+ );
2242
+ const txRequest = new TransactionRequestBuilder().withOwnOutputNotes(new NoteArray([p2idNote])).build();
2243
+ const execFromId = parseAccountId(options.from);
2244
+ const txId = prover ? await client.submitNewTransactionWithProver(
2245
+ execFromId,
2246
+ txRequest,
2247
+ prover
2248
+ ) : await client.submitNewTransaction(execFromId, txRequest);
2249
+ return { txId: txId.toString(), note: p2idNote };
2250
+ });
2251
+ setStage("complete");
2252
+ setResult(returnResult);
2253
+ await sync();
2254
+ return returnResult;
2255
+ }
1971
2256
  const txResult = await runExclusiveSafe(async () => {
1972
2257
  const fromAccountId = parseAccountId(options.from);
1973
2258
  const toAccountId = parseAccountId(options.to);
@@ -1985,7 +2270,7 @@ function useSend() {
1985
2270
  noteType,
1986
2271
  attachment
1987
2272
  );
1988
- txRequest = new TransactionRequestBuilder().withOwnOutputNotes(new OutputNoteArray([OutputNote.full(note)])).build();
2273
+ txRequest = new TransactionRequestBuilder().withOwnOutputNotes(new NoteArray([note])).build();
1989
2274
  } else {
1990
2275
  txRequest = client.newSendTransactionRequest(
1991
2276
  fromAccountId,
@@ -2001,8 +2286,12 @@ function useSend() {
2001
2286
  return await client.executeTransaction(execAccountId, txRequest);
2002
2287
  });
2003
2288
  setStage("proving");
2004
- const provenTransaction = await runExclusiveSafe(
2005
- () => client.proveTransaction(txResult, prover ?? void 0)
2289
+ const proverConfig = useMidenStore.getState().config;
2290
+ const provenTransaction = await proveWithFallback(
2291
+ (resolvedProver) => runExclusiveSafe(
2292
+ () => client.proveTransaction(txResult, resolvedProver)
2293
+ ),
2294
+ proverConfig
2006
2295
  );
2007
2296
  setStage("submitting");
2008
2297
  const submissionHeight = await runExclusiveSafe(
@@ -2032,11 +2321,14 @@ function useSend() {
2032
2321
  () => client.sendPrivateNote(fullNote, recipientAddress)
2033
2322
  );
2034
2323
  }
2035
- const txSummary = { transactionId: txIdString };
2324
+ const sendResult = {
2325
+ txId: txIdString,
2326
+ note: null
2327
+ };
2036
2328
  setStage("complete");
2037
- setResult(txSummary);
2329
+ setResult(sendResult);
2038
2330
  await sync();
2039
- return txSummary;
2331
+ return sendResult;
2040
2332
  } catch (err) {
2041
2333
  const error2 = err instanceof Error ? err : new Error(String(err));
2042
2334
  setError(error2);
@@ -2049,7 +2341,7 @@ function useSend() {
2049
2341
  },
2050
2342
  [client, isReady, prover, runExclusive, sync]
2051
2343
  );
2052
- const reset = useCallback11(() => {
2344
+ const reset = useCallback12(() => {
2053
2345
  setResult(null);
2054
2346
  setIsLoading(false);
2055
2347
  setStage("idle");
@@ -2076,30 +2368,29 @@ function extractFullNote(txResult) {
2076
2368
  }
2077
2369
 
2078
2370
  // src/hooks/useMultiSend.ts
2079
- import { useCallback as useCallback12, useRef as useRef4, useState as useState10 } from "react";
2371
+ import { useCallback as useCallback13, useRef as useRef5, useState as useState11 } from "react";
2080
2372
  import {
2081
2373
  FungibleAsset as FungibleAsset2,
2082
2374
  Note as Note2,
2083
2375
  NoteAssets as NoteAssets2,
2084
- NoteAttachment as NoteAttachment2,
2376
+ NoteAttachment as NoteAttachment3,
2085
2377
  NoteType as NoteType3,
2086
- OutputNote as OutputNote2,
2087
- OutputNoteArray as OutputNoteArray2,
2378
+ NoteArray as NoteArray2,
2088
2379
  TransactionRequestBuilder as TransactionRequestBuilder2
2089
2380
  } from "@miden-sdk/miden-sdk";
2090
2381
  function useMultiSend() {
2091
- const { client, isReady, sync, runExclusive, prover } = useMiden();
2092
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2093
- const isBusyRef = useRef4(false);
2094
- const [result, setResult] = useState10(null);
2095
- const [isLoading, setIsLoading] = useState10(false);
2096
- const [stage, setStage] = useState10("idle");
2097
- const [error, setError] = useState10(null);
2098
- const sendMany = useCallback12(
2382
+ const { client, isReady, sync, prover, signerConnected } = useMiden();
2383
+ const isBusyRef = useRef5(false);
2384
+ const [result, setResult] = useState11(null);
2385
+ const [isLoading, setIsLoading] = useState11(false);
2386
+ const [stage, setStage] = useState11("idle");
2387
+ const [error, setError] = useState11(null);
2388
+ const sendMany = useCallback13(
2099
2389
  async (options) => {
2100
2390
  if (!client || !isReady) {
2101
2391
  throw new Error("Miden client is not ready");
2102
2392
  }
2393
+ assertSignerConnected(signerConnected);
2103
2394
  if (options.recipients.length === 0) {
2104
2395
  throw new Error("No recipients provided");
2105
2396
  }
@@ -2124,10 +2415,10 @@ function useMultiSend() {
2124
2415
  const iterAssetId = parseAccountId(options.assetId);
2125
2416
  const receiverId = parseAccountId(to);
2126
2417
  const assets = new NoteAssets2([
2127
- new FungibleAsset2(iterAssetId, amount)
2418
+ new FungibleAsset2(iterAssetId, BigInt(amount))
2128
2419
  ]);
2129
2420
  const resolvedNoteType = recipientNoteType ? getNoteType(recipientNoteType) : noteType;
2130
- const noteAttachment = attachment !== void 0 && attachment !== null ? createNoteAttachment(attachment) : new NoteAttachment2();
2421
+ const noteAttachment = attachment !== void 0 && attachment !== null ? createNoteAttachment(attachment) : new NoteAttachment3();
2131
2422
  const note = Note2.createP2IDNote(
2132
2423
  iterSenderId,
2133
2424
  receiverId,
@@ -2137,44 +2428,43 @@ function useMultiSend() {
2137
2428
  );
2138
2429
  const recipientAddress = parseAddress(to, receiverId);
2139
2430
  return {
2140
- outputNote: OutputNote2.full(note),
2141
2431
  note,
2142
2432
  recipientAddress,
2143
2433
  noteType: resolvedNoteType
2144
2434
  };
2145
2435
  }
2146
2436
  );
2147
- const txRequest = new TransactionRequestBuilder2().withOwnOutputNotes(
2148
- new OutputNoteArray2(outputs.map((o) => o.outputNote))
2149
- ).build();
2437
+ const txRequest = new TransactionRequestBuilder2().withOwnOutputNotes(new NoteArray2(outputs.map((o) => o.note))).build();
2150
2438
  const txSenderId = parseAccountId(options.from);
2151
- const txResult = await runExclusiveSafe(
2152
- () => client.executeTransaction(txSenderId, txRequest)
2153
- );
2439
+ const txResult = await client.executeTransaction(txSenderId, txRequest);
2154
2440
  setStage("proving");
2155
- const provenTransaction = await runExclusiveSafe(
2156
- () => client.proveTransaction(txResult, prover ?? void 0)
2441
+ const proverConfig = useMidenStore.getState().config;
2442
+ const provenTransaction = await proveWithFallback(
2443
+ (resolvedProver) => runExclusiveDirect(
2444
+ () => client.proveTransaction(txResult, resolvedProver)
2445
+ ),
2446
+ proverConfig
2157
2447
  );
2158
2448
  setStage("submitting");
2159
- const submissionHeight = await runExclusiveSafe(
2160
- () => client.submitProvenTransaction(provenTransaction, txResult)
2449
+ const submissionHeight = await client.submitProvenTransaction(
2450
+ provenTransaction,
2451
+ txResult
2161
2452
  );
2162
2453
  const txIdHex = txResult.id().toHex();
2163
2454
  const txIdString = txResult.id().toString();
2164
- await runExclusiveSafe(
2165
- () => client.applyTransaction(txResult, submissionHeight)
2166
- );
2455
+ await client.applyTransaction(txResult, submissionHeight);
2167
2456
  const hasPrivate = outputs.some((o) => o.noteType === NoteType3.Private);
2168
2457
  if (hasPrivate) {
2169
2458
  await waitForTransactionCommit(
2170
2459
  client,
2171
- runExclusiveSafe,
2460
+ runExclusiveDirect,
2172
2461
  txIdHex
2173
2462
  );
2174
2463
  for (const output of outputs) {
2175
2464
  if (output.noteType === NoteType3.Private) {
2176
- await runExclusiveSafe(
2177
- () => client.sendPrivateNote(output.note, output.recipientAddress)
2465
+ await client.sendPrivateNote(
2466
+ output.note,
2467
+ output.recipientAddress
2178
2468
  );
2179
2469
  }
2180
2470
  }
@@ -2194,154 +2484,7 @@ function useMultiSend() {
2194
2484
  isBusyRef.current = false;
2195
2485
  }
2196
2486
  },
2197
- [client, isReady, prover, runExclusive, sync]
2198
- );
2199
- const reset = useCallback12(() => {
2200
- setResult(null);
2201
- setIsLoading(false);
2202
- setStage("idle");
2203
- setError(null);
2204
- }, []);
2205
- return {
2206
- sendMany,
2207
- result,
2208
- isLoading,
2209
- stage,
2210
- error,
2211
- reset
2212
- };
2213
- }
2214
-
2215
- // src/hooks/useInternalTransfer.ts
2216
- import { useCallback as useCallback13, useState as useState11 } from "react";
2217
- import {
2218
- FungibleAsset as FungibleAsset3,
2219
- Note as Note3,
2220
- NoteAndArgs,
2221
- NoteAndArgsArray,
2222
- NoteAssets as NoteAssets3,
2223
- NoteAttachment as NoteAttachment3,
2224
- OutputNote as OutputNote3,
2225
- OutputNoteArray as OutputNoteArray3,
2226
- TransactionRequestBuilder as TransactionRequestBuilder3
2227
- } from "@miden-sdk/miden-sdk";
2228
- function useInternalTransfer() {
2229
- const { client, isReady, sync, runExclusive, prover } = useMiden();
2230
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2231
- const [result, setResult] = useState11(null);
2232
- const [isLoading, setIsLoading] = useState11(false);
2233
- const [stage, setStage] = useState11("idle");
2234
- const [error, setError] = useState11(null);
2235
- const transferOnce = useCallback13(
2236
- async (options) => {
2237
- if (!client || !isReady) {
2238
- throw new Error("Miden client is not ready");
2239
- }
2240
- const noteType = getNoteType(options.noteType ?? DEFAULTS.NOTE_TYPE);
2241
- const senderId = parseAccountId(options.from);
2242
- const receiverId = parseAccountId(options.to);
2243
- const assetId = parseAccountId(options.assetId);
2244
- const assets = new NoteAssets3([
2245
- new FungibleAsset3(assetId, options.amount)
2246
- ]);
2247
- const note = Note3.createP2IDNote(
2248
- senderId,
2249
- receiverId,
2250
- assets,
2251
- noteType,
2252
- new NoteAttachment3()
2253
- );
2254
- const noteId = note.id().toString();
2255
- const createRequest = new TransactionRequestBuilder3().withOwnOutputNotes(new OutputNoteArray3([OutputNote3.full(note)])).build();
2256
- const createTxId = await runExclusiveSafe(
2257
- () => prover ? client.submitNewTransactionWithProver(
2258
- senderId,
2259
- createRequest,
2260
- prover
2261
- ) : client.submitNewTransaction(senderId, createRequest)
2262
- );
2263
- const consumeRequest = new TransactionRequestBuilder3().withInputNotes(new NoteAndArgsArray([new NoteAndArgs(note, null)])).build();
2264
- const consumeTxId = await runExclusiveSafe(
2265
- () => prover ? client.submitNewTransactionWithProver(
2266
- receiverId,
2267
- consumeRequest,
2268
- prover
2269
- ) : client.submitNewTransaction(receiverId, consumeRequest)
2270
- );
2271
- return {
2272
- createTransactionId: createTxId.toString(),
2273
- consumeTransactionId: consumeTxId.toString(),
2274
- noteId
2275
- };
2276
- },
2277
- [client, isReady, prover, runExclusiveSafe]
2278
- );
2279
- const transfer = useCallback13(
2280
- async (options) => {
2281
- if (!client || !isReady) {
2282
- throw new Error("Miden client is not ready");
2283
- }
2284
- setIsLoading(true);
2285
- setStage("executing");
2286
- setError(null);
2287
- try {
2288
- setStage("proving");
2289
- const txResult = await transferOnce(options);
2290
- setStage("complete");
2291
- setResult(txResult);
2292
- await sync();
2293
- return txResult;
2294
- } catch (err) {
2295
- const error2 = err instanceof Error ? err : new Error(String(err));
2296
- setError(error2);
2297
- setStage("idle");
2298
- throw error2;
2299
- } finally {
2300
- setIsLoading(false);
2301
- }
2302
- },
2303
- [client, isReady, sync, transferOnce]
2304
- );
2305
- const transferChain = useCallback13(
2306
- async (options) => {
2307
- if (!client || !isReady) {
2308
- throw new Error("Miden client is not ready");
2309
- }
2310
- if (options.recipients.length === 0) {
2311
- throw new Error("No recipients provided");
2312
- }
2313
- setIsLoading(true);
2314
- setStage("executing");
2315
- setError(null);
2316
- try {
2317
- const results = [];
2318
- let currentSender = options.from;
2319
- for (const recipient of options.recipients) {
2320
- setStage("proving");
2321
- const txResult = await transferOnce({
2322
- from: currentSender,
2323
- to: recipient,
2324
- assetId: options.assetId,
2325
- amount: options.amount,
2326
- noteType: options.noteType
2327
- });
2328
- results.push(txResult);
2329
- currentSender = recipient;
2330
- }
2331
- setStage("complete");
2332
- setResult(results);
2333
- await sync();
2334
- return results;
2335
- } catch (err) {
2336
- const error2 = err instanceof Error ? err : new Error(String(err));
2337
- setError(error2);
2338
- setStage("idle");
2339
- throw error2;
2340
- } finally {
2341
- setIsLoading(false);
2342
- }
2343
- },
2344
- [client, isReady, sync, transferOnce]
2487
+ [client, isReady, prover, signerConnected, sync]
2345
2488
  );
2346
2489
  const reset = useCallback13(() => {
2347
2490
  setResult(null);
@@ -2350,8 +2493,7 @@ function useInternalTransfer() {
2350
2493
  setError(null);
2351
2494
  }, []);
2352
2495
  return {
2353
- transfer,
2354
- transferChain,
2496
+ sendMany,
2355
2497
  result,
2356
2498
  isLoading,
2357
2499
  stage,
@@ -2364,8 +2506,7 @@ function useInternalTransfer() {
2364
2506
  import { useCallback as useCallback14 } from "react";
2365
2507
  import { TransactionFilter as TransactionFilter3 } from "@miden-sdk/miden-sdk";
2366
2508
  function useWaitForCommit() {
2367
- const { client, isReady, runExclusive } = useMiden();
2368
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2509
+ const { client, isReady } = useMiden();
2369
2510
  const waitForCommit = useCallback14(
2370
2511
  async (txId, options) => {
2371
2512
  if (!client || !isReady) {
@@ -2378,13 +2519,9 @@ function useWaitForCommit() {
2378
2519
  );
2379
2520
  const deadline = Date.now() + timeoutMs;
2380
2521
  while (Date.now() < deadline) {
2381
- await runExclusiveSafe(
2382
- () => client.syncState()
2383
- );
2384
- const records = await runExclusiveSafe(
2385
- () => client.getTransactions(
2386
- typeof txId === "string" ? TransactionFilter3.all() : TransactionFilter3.ids([txId])
2387
- )
2522
+ await client.syncState();
2523
+ const records = await client.getTransactions(
2524
+ typeof txId === "string" ? TransactionFilter3.all() : TransactionFilter3.ids([txId])
2388
2525
  );
2389
2526
  const record = records.find(
2390
2527
  (item) => normalizeHex3(item.id().toHex()) === targetHex
@@ -2402,7 +2539,7 @@ function useWaitForCommit() {
2402
2539
  }
2403
2540
  throw new Error("Timeout waiting for transaction commit");
2404
2541
  },
2405
- [client, isReady, runExclusiveSafe]
2542
+ [client, isReady]
2406
2543
  );
2407
2544
  return { waitForCommit };
2408
2545
  }
@@ -2431,11 +2568,11 @@ function useWaitForNotes() {
2431
2568
  await runExclusiveSafe(
2432
2569
  () => client.syncState()
2433
2570
  );
2434
- const notes = await runExclusiveSafe(
2571
+ const consumable = await runExclusiveSafe(
2435
2572
  () => client.getConsumableNotes(accountId)
2436
2573
  );
2437
- if (notes.length >= minCount) {
2438
- return notes;
2574
+ if (consumable.length >= minCount) {
2575
+ return consumable;
2439
2576
  }
2440
2577
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
2441
2578
  waited += intervalMs;
@@ -2474,7 +2611,7 @@ function useMint() {
2474
2611
  targetAccountIdObj,
2475
2612
  faucetIdObj,
2476
2613
  noteType,
2477
- options.amount
2614
+ BigInt(options.amount)
2478
2615
  );
2479
2616
  const txId = prover ? await client.submitNewTransactionWithProver(
2480
2617
  faucetIdObj,
@@ -2529,8 +2666,8 @@ function useConsume() {
2529
2666
  if (!client || !isReady) {
2530
2667
  throw new Error("Miden client is not ready");
2531
2668
  }
2532
- if (options.noteIds.length === 0) {
2533
- throw new Error("No note IDs provided");
2669
+ if (options.notes.length === 0) {
2670
+ throw new Error("No notes provided");
2534
2671
  }
2535
2672
  setIsLoading(true);
2536
2673
  setStage("executing");
@@ -2539,16 +2676,47 @@ function useConsume() {
2539
2676
  const accountIdObj = parseAccountId(options.accountId);
2540
2677
  setStage("proving");
2541
2678
  const txResult = await runExclusiveSafe(async () => {
2542
- const noteIds = options.noteIds.map(
2543
- (noteId) => NoteId.fromHex(noteId)
2544
- );
2545
- const filter = new NoteFilter3(NoteFilterTypes2.List, noteIds);
2546
- const noteRecords = await client.getInputNotes(filter);
2547
- const notes = noteRecords.map((record) => record.toNote());
2679
+ const resolved = new Array(options.notes.length);
2680
+ const lookupIndices = [];
2681
+ const lookupIds = [];
2682
+ for (let i = 0; i < options.notes.length; i++) {
2683
+ const item = options.notes[i];
2684
+ if (typeof item === "string") {
2685
+ lookupIndices.push(i);
2686
+ lookupIds.push(NoteId.fromHex(item));
2687
+ } else if (item !== null && typeof item === "object" && typeof item.toNote === "function") {
2688
+ resolved[i] = item.toNote();
2689
+ } else if (item !== null && typeof item === "object" && typeof item.id === "function") {
2690
+ resolved[i] = item;
2691
+ } else {
2692
+ lookupIndices.push(i);
2693
+ lookupIds.push(item);
2694
+ }
2695
+ }
2696
+ if (lookupIds.length > 0) {
2697
+ const filter = new NoteFilter3(NoteFilterTypes2.List, lookupIds);
2698
+ const noteRecords = await client.getInputNotes(filter);
2699
+ if (noteRecords.length !== lookupIds.length) {
2700
+ throw new Error("Some notes could not be found for provided IDs");
2701
+ }
2702
+ const recordById = new Map(
2703
+ noteRecords.map((r) => [r.id().toString(), r])
2704
+ );
2705
+ for (let j = 0; j < lookupIndices.length; j++) {
2706
+ const record = recordById.get(lookupIds[j].toString());
2707
+ if (!record) {
2708
+ throw new Error(
2709
+ "Some notes could not be found for provided IDs"
2710
+ );
2711
+ }
2712
+ resolved[lookupIndices[j]] = record.toNote();
2713
+ }
2714
+ }
2715
+ const notes = resolved;
2548
2716
  if (notes.length === 0) {
2549
2717
  throw new Error("No notes found for provided IDs");
2550
2718
  }
2551
- if (notes.length !== options.noteIds.length) {
2719
+ if (notes.length !== options.notes.length) {
2552
2720
  throw new Error("Some notes could not be found for provided IDs");
2553
2721
  }
2554
2722
  const txRequest = client.newConsumeTransactionRequest(notes);
@@ -2620,9 +2788,9 @@ function useSwap() {
2620
2788
  const txRequest = client.newSwapTransactionRequest(
2621
2789
  accountIdObj,
2622
2790
  offeredFaucetIdObj,
2623
- options.offeredAmount,
2791
+ BigInt(options.offeredAmount),
2624
2792
  requestedFaucetIdObj,
2625
- options.requestedAmount,
2793
+ BigInt(options.requestedAmount),
2626
2794
  noteType,
2627
2795
  paybackNoteType
2628
2796
  );
@@ -2665,11 +2833,53 @@ function useSwap() {
2665
2833
  }
2666
2834
 
2667
2835
  // src/hooks/useTransaction.ts
2668
- import { useCallback as useCallback19, useRef as useRef5, useState as useState15 } from "react";
2836
+ import { useCallback as useCallback19, useRef as useRef6, useState as useState15 } from "react";
2837
+
2838
+ // src/utils/transactions.ts
2839
+ import { NoteType as NoteType4, TransactionFilter as TransactionFilter4 } from "@miden-sdk/miden-sdk";
2840
+ async function waitForTransactionCommit2(client, runExclusiveSafe, txId, maxWaitMs = 1e4, delayMs = 1e3) {
2841
+ let waited = 0;
2842
+ while (waited < maxWaitMs) {
2843
+ await runExclusiveSafe(() => client.syncState());
2844
+ const [record] = await runExclusiveSafe(
2845
+ () => client.getTransactions(TransactionFilter4.ids([txId]))
2846
+ );
2847
+ if (record) {
2848
+ const status = record.transactionStatus();
2849
+ if (status.isCommitted()) {
2850
+ return;
2851
+ }
2852
+ if (status.isDiscarded()) {
2853
+ throw new Error("Transaction was discarded before commit");
2854
+ }
2855
+ }
2856
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
2857
+ waited += delayMs;
2858
+ }
2859
+ throw new Error("Timeout waiting for transaction commit");
2860
+ }
2861
+ function extractFullNotes(txResult) {
2862
+ try {
2863
+ const executedTx = txResult.executedTransaction?.();
2864
+ const notes = executedTx?.outputNotes?.().notes?.() ?? [];
2865
+ const result = [];
2866
+ for (const note of notes) {
2867
+ if (note.noteType?.() === NoteType4.Private) {
2868
+ const full = note.intoFull?.();
2869
+ if (full) result.push(full);
2870
+ }
2871
+ }
2872
+ return result;
2873
+ } catch {
2874
+ return [];
2875
+ }
2876
+ }
2877
+
2878
+ // src/hooks/useTransaction.ts
2669
2879
  function useTransaction() {
2670
- const { client, isReady, sync, runExclusive, prover } = useMiden();
2880
+ const { client, isReady, sync, runExclusive } = useMiden();
2671
2881
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2672
- const isBusyRef = useRef5(false);
2882
+ const isBusyRef = useRef6(false);
2673
2883
  const [result, setResult] = useState15(null);
2674
2884
  const [isLoading, setIsLoading] = useState15(false);
2675
2885
  const [stage, setStage] = useState15("idle");
@@ -2694,20 +2904,41 @@ function useTransaction() {
2694
2904
  await sync();
2695
2905
  }
2696
2906
  const txRequest = await resolveRequest(options.request, client);
2697
- setStage("proving");
2698
- const txResult = await runExclusiveSafe(async () => {
2699
- const accountIdObj = resolveAccountId2(options.accountId);
2700
- const txId = prover ? await client.submitNewTransactionWithProver(
2701
- accountIdObj,
2702
- txRequest,
2703
- prover
2704
- ) : await client.submitNewTransaction(accountIdObj, txRequest);
2705
- return { transactionId: txId.toString() };
2907
+ const txResult = await runExclusiveSafe(() => {
2908
+ const accountIdObj = parseAccountId(options.accountId);
2909
+ return client.executeTransaction(accountIdObj, txRequest);
2706
2910
  });
2911
+ setStage("proving");
2912
+ const proverConfig = useMidenStore.getState().config;
2913
+ const provenTransaction = await proveWithFallback(
2914
+ (resolvedProver) => runExclusiveSafe(
2915
+ () => client.proveTransaction(txResult, resolvedProver)
2916
+ ),
2917
+ proverConfig
2918
+ );
2919
+ setStage("submitting");
2920
+ const submissionHeight = await runExclusiveSafe(
2921
+ () => client.submitProvenTransaction(provenTransaction, txResult)
2922
+ );
2923
+ await runExclusiveSafe(
2924
+ () => client.applyTransaction(txResult, submissionHeight)
2925
+ );
2926
+ const txId = txResult.id();
2927
+ if (options.privateNoteTarget != null) {
2928
+ await waitForTransactionCommit2(client, runExclusiveSafe, txId);
2929
+ const targetAddress = parseAddress(options.privateNoteTarget);
2930
+ const fullNotes = extractFullNotes(txResult);
2931
+ for (const note of fullNotes) {
2932
+ await runExclusiveSafe(
2933
+ () => client.sendPrivateNote(note, targetAddress)
2934
+ );
2935
+ }
2936
+ }
2937
+ const txSummary = { transactionId: txId.toString() };
2707
2938
  setStage("complete");
2708
- setResult(txResult);
2939
+ setResult(txSummary);
2709
2940
  await sync();
2710
- return txResult;
2941
+ return txSummary;
2711
2942
  } catch (err) {
2712
2943
  const error2 = err instanceof Error ? err : new Error(String(err));
2713
2944
  setError(error2);
@@ -2718,7 +2949,7 @@ function useTransaction() {
2718
2949
  isBusyRef.current = false;
2719
2950
  }
2720
2951
  },
2721
- [client, isReady, prover, runExclusive, sync]
2952
+ [client, isReady, runExclusive, sync]
2722
2953
  );
2723
2954
  const reset = useCallback19(() => {
2724
2955
  setResult(null);
@@ -2735,9 +2966,6 @@ function useTransaction() {
2735
2966
  reset
2736
2967
  };
2737
2968
  }
2738
- function resolveAccountId2(accountId) {
2739
- return parseAccountId(accountId);
2740
- }
2741
2969
  async function resolveRequest(request, client) {
2742
2970
  if (typeof request === "function") {
2743
2971
  return await request(client);
@@ -2745,27 +2973,117 @@ async function resolveRequest(request, client) {
2745
2973
  return request;
2746
2974
  }
2747
2975
 
2976
+ // src/hooks/useExecuteProgram.ts
2977
+ import { useCallback as useCallback20, useRef as useRef7, useState as useState16 } from "react";
2978
+ import {
2979
+ AdviceInputs,
2980
+ ForeignAccount,
2981
+ ForeignAccountArray,
2982
+ AccountStorageRequirements
2983
+ } from "@miden-sdk/miden-sdk";
2984
+ function isForeignAccountWrapper(fa) {
2985
+ return fa !== null && typeof fa === "object" && "id" in fa && typeof fa.id !== "function";
2986
+ }
2987
+ function useExecuteProgram() {
2988
+ const { client, isReady, sync, runExclusive } = useMiden();
2989
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2990
+ const isBusyRef = useRef7(false);
2991
+ const [result, setResult] = useState16(null);
2992
+ const [isLoading, setIsLoading] = useState16(false);
2993
+ const [error, setError] = useState16(null);
2994
+ const execute = useCallback20(
2995
+ async (options) => {
2996
+ if (!client || !isReady) {
2997
+ throw new Error("Miden client is not ready");
2998
+ }
2999
+ if (isBusyRef.current) {
3000
+ throw new MidenError(
3001
+ "A program execution is already in progress. Await the previous call before starting another.",
3002
+ { code: "OPERATION_BUSY" }
3003
+ );
3004
+ }
3005
+ isBusyRef.current = true;
3006
+ setIsLoading(true);
3007
+ setError(null);
3008
+ try {
3009
+ if (!options.skipSync) {
3010
+ await sync();
3011
+ }
3012
+ const programResult = await runExclusiveSafe(async () => {
3013
+ const accountIdObj = parseAccountId(options.accountId);
3014
+ const adviceInputs = options.adviceInputs ?? new AdviceInputs();
3015
+ let foreignAccountsArray;
3016
+ if (options.foreignAccounts?.length) {
3017
+ const accounts = options.foreignAccounts.map((fa) => {
3018
+ const wrapper = isForeignAccountWrapper(fa);
3019
+ const id = parseAccountId(wrapper ? fa.id : fa);
3020
+ const storage = wrapper && fa.storage ? fa.storage : new AccountStorageRequirements();
3021
+ return ForeignAccount.public(id, storage);
3022
+ });
3023
+ foreignAccountsArray = new ForeignAccountArray(accounts);
3024
+ } else {
3025
+ foreignAccountsArray = new ForeignAccountArray();
3026
+ }
3027
+ const feltArray = await client.executeProgram(
3028
+ accountIdObj,
3029
+ options.script,
3030
+ adviceInputs,
3031
+ foreignAccountsArray
3032
+ );
3033
+ const stack = [];
3034
+ const len = feltArray.length();
3035
+ for (let i = 0; i < len; i++) {
3036
+ stack.push(feltArray.get(i).asInt());
3037
+ }
3038
+ return { stack };
3039
+ });
3040
+ setResult(programResult);
3041
+ return programResult;
3042
+ } catch (err) {
3043
+ const error2 = err instanceof Error ? err : new Error(String(err));
3044
+ setError(error2);
3045
+ throw error2;
3046
+ } finally {
3047
+ setIsLoading(false);
3048
+ isBusyRef.current = false;
3049
+ }
3050
+ },
3051
+ [client, isReady, runExclusive, sync]
3052
+ );
3053
+ const reset = useCallback20(() => {
3054
+ setResult(null);
3055
+ setIsLoading(false);
3056
+ setError(null);
3057
+ }, []);
3058
+ return {
3059
+ execute,
3060
+ result,
3061
+ isLoading,
3062
+ error,
3063
+ reset
3064
+ };
3065
+ }
3066
+
2748
3067
  // src/hooks/useSessionAccount.ts
2749
- import { useCallback as useCallback20, useEffect as useEffect8, useRef as useRef6, useState as useState16 } from "react";
3068
+ import { useCallback as useCallback21, useEffect as useEffect9, useRef as useRef8, useState as useState17 } from "react";
2750
3069
  import { AccountStorageMode as AccountStorageMode3 } from "@miden-sdk/miden-sdk";
2751
3070
  function useSessionAccount(options) {
2752
- const { client, isReady, sync, runExclusive } = useMiden();
2753
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
3071
+ const { client, isReady, sync } = useMiden();
2754
3072
  const setAccounts = useMidenStore((state) => state.setAccounts);
2755
- const [sessionAccountId, setSessionAccountId] = useState16(null);
2756
- const [step, setStep] = useState16("idle");
2757
- const [error, setError] = useState16(null);
2758
- const cancelledRef = useRef6(false);
2759
- const isBusyRef = useRef6(false);
3073
+ const [sessionAccountId, setSessionAccountId] = useState17(null);
3074
+ const [step, setStep] = useState17("idle");
3075
+ const [error, setError] = useState17(null);
3076
+ const cancelledRef = useRef8(false);
3077
+ const isBusyRef = useRef8(false);
2760
3078
  const storagePrefix = options.storagePrefix ?? "miden-session";
2761
3079
  const pollIntervalMs = options.pollIntervalMs ?? 3e3;
2762
3080
  const maxWaitMs = options.maxWaitMs ?? 6e4;
2763
3081
  const storageMode = options.walletOptions?.storageMode ?? "public";
2764
3082
  const mutable = options.walletOptions?.mutable ?? DEFAULTS.WALLET_MUTABLE;
2765
3083
  const authScheme = options.walletOptions?.authScheme ?? DEFAULTS.AUTH_SCHEME;
2766
- const fundRef = useRef6(options.fund);
3084
+ const fundRef = useRef8(options.fund);
2767
3085
  fundRef.current = options.fund;
2768
- useEffect8(() => {
3086
+ useEffect9(() => {
2769
3087
  try {
2770
3088
  const stored = localStorage.getItem(`${storagePrefix}:accountId`);
2771
3089
  const storedReady = localStorage.getItem(`${storagePrefix}:ready`);
@@ -2782,7 +3100,7 @@ function useSessionAccount(options) {
2782
3100
  localStorage.removeItem(`${storagePrefix}:ready`);
2783
3101
  }
2784
3102
  }, [storagePrefix]);
2785
- const initialize = useCallback20(async () => {
3103
+ const initialize = useCallback21(async () => {
2786
3104
  if (!client || !isReady) {
2787
3105
  throw new Error("Miden client is not ready");
2788
3106
  }
@@ -2800,17 +3118,14 @@ function useSessionAccount(options) {
2800
3118
  if (!walletId) {
2801
3119
  setStep("creating");
2802
3120
  const resolvedStorageMode = getStorageMode3(storageMode);
2803
- const wallet = await runExclusiveSafe(async () => {
2804
- const w = await client.newWallet(
2805
- resolvedStorageMode,
2806
- mutable,
2807
- authScheme
2808
- );
2809
- ensureAccountBech32(w);
2810
- const accounts = await client.getAccounts();
2811
- setAccounts(accounts);
2812
- return w;
2813
- });
3121
+ const wallet = await client.newWallet(
3122
+ resolvedStorageMode,
3123
+ mutable,
3124
+ authScheme
3125
+ );
3126
+ ensureAccountBech32(wallet);
3127
+ const accounts = await client.getAccounts();
3128
+ setAccounts(accounts);
2814
3129
  if (cancelledRef.current) return;
2815
3130
  walletId = wallet.id().toString();
2816
3131
  setSessionAccountId(walletId);
@@ -2822,7 +3137,6 @@ function useSessionAccount(options) {
2822
3137
  setStep("consuming");
2823
3138
  await waitAndConsume(
2824
3139
  client,
2825
- runExclusiveSafe,
2826
3140
  walletId,
2827
3141
  pollIntervalMs,
2828
3142
  maxWaitMs,
@@ -2846,7 +3160,6 @@ function useSessionAccount(options) {
2846
3160
  client,
2847
3161
  isReady,
2848
3162
  sync,
2849
- runExclusiveSafe,
2850
3163
  sessionAccountId,
2851
3164
  storageMode,
2852
3165
  mutable,
@@ -2856,7 +3169,7 @@ function useSessionAccount(options) {
2856
3169
  maxWaitMs,
2857
3170
  setAccounts
2858
3171
  ]);
2859
- const reset = useCallback20(() => {
3172
+ const reset = useCallback21(() => {
2860
3173
  cancelledRef.current = true;
2861
3174
  isBusyRef.current = false;
2862
3175
  setSessionAccountId(null);
@@ -2884,30 +3197,202 @@ function getStorageMode3(mode) {
2884
3197
  return AccountStorageMode3.public();
2885
3198
  }
2886
3199
  }
2887
- async function waitAndConsume(client, runExclusiveSafe, walletId, pollIntervalMs, maxWaitMs, cancelledRef) {
3200
+ async function waitAndConsume(client, walletId, pollIntervalMs, maxWaitMs, cancelledRef) {
2888
3201
  const deadline = Date.now() + maxWaitMs;
2889
3202
  while (Date.now() < deadline) {
2890
3203
  if (cancelledRef.current) return;
2891
- await runExclusiveSafe(
2892
- () => client.syncState()
2893
- );
3204
+ await client.syncState();
2894
3205
  if (cancelledRef.current) return;
2895
- const consumed = await runExclusiveSafe(async () => {
2896
- const accountIdObj = parseAccountId(walletId);
2897
- const consumable = await client.getConsumableNotes(accountIdObj);
2898
- if (consumable.length === 0) return false;
3206
+ const accountIdObj = parseAccountId(walletId);
3207
+ const consumable = await client.getConsumableNotes(accountIdObj);
3208
+ if (consumable.length > 0) {
2899
3209
  const notes = consumable.map((c) => c.inputNoteRecord().toNote());
2900
3210
  const txRequest = client.newConsumeTransactionRequest(notes);
2901
3211
  const freshAccountId = parseAccountId(walletId);
2902
3212
  await client.submitNewTransaction(freshAccountId, txRequest);
2903
- return true;
2904
- });
2905
- if (consumed) return;
3213
+ return;
3214
+ }
2906
3215
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
2907
3216
  }
2908
3217
  throw new Error("Timeout waiting for session wallet funding");
2909
3218
  }
2910
3219
 
3220
+ // src/hooks/useExportStore.ts
3221
+ import { useCallback as useCallback22, useState as useState18 } from "react";
3222
+ import { exportStore as sdkExportStore } from "@miden-sdk/miden-sdk";
3223
+ function useExportStore() {
3224
+ const { client, isReady, runExclusive } = useMiden();
3225
+ const [isExporting, setIsExporting] = useState18(false);
3226
+ const [error, setError] = useState18(null);
3227
+ const exportStore = useCallback22(async () => {
3228
+ if (!client || !isReady) {
3229
+ throw new Error("Miden client is not ready");
3230
+ }
3231
+ setIsExporting(true);
3232
+ setError(null);
3233
+ try {
3234
+ const storeName = client.storeIdentifier();
3235
+ const snapshot = await runExclusive(() => sdkExportStore(storeName));
3236
+ return snapshot;
3237
+ } catch (err) {
3238
+ const error2 = err instanceof Error ? err : new Error(String(err));
3239
+ setError(error2);
3240
+ throw error2;
3241
+ } finally {
3242
+ setIsExporting(false);
3243
+ }
3244
+ }, [client, isReady, runExclusive]);
3245
+ const reset = useCallback22(() => {
3246
+ setIsExporting(false);
3247
+ setError(null);
3248
+ }, []);
3249
+ return {
3250
+ exportStore,
3251
+ isExporting,
3252
+ error,
3253
+ reset
3254
+ };
3255
+ }
3256
+
3257
+ // src/hooks/useImportStore.ts
3258
+ import { useCallback as useCallback23, useState as useState19 } from "react";
3259
+ import { importStore as sdkImportStore } from "@miden-sdk/miden-sdk";
3260
+ function useImportStore() {
3261
+ const { client, isReady, runExclusive, sync } = useMiden();
3262
+ const [isImporting, setIsImporting] = useState19(false);
3263
+ const [error, setError] = useState19(null);
3264
+ const importStore = useCallback23(
3265
+ async (storeDump, storeName, options) => {
3266
+ if (!client || !isReady) {
3267
+ throw new Error("Miden client is not ready");
3268
+ }
3269
+ setIsImporting(true);
3270
+ setError(null);
3271
+ try {
3272
+ await runExclusive(() => sdkImportStore(storeName, storeDump));
3273
+ if (!options?.skipSync) {
3274
+ await sync();
3275
+ }
3276
+ } catch (err) {
3277
+ const error2 = err instanceof Error ? err : new Error(String(err));
3278
+ setError(error2);
3279
+ throw error2;
3280
+ } finally {
3281
+ setIsImporting(false);
3282
+ }
3283
+ },
3284
+ [client, isReady, runExclusive, sync]
3285
+ );
3286
+ const reset = useCallback23(() => {
3287
+ setIsImporting(false);
3288
+ setError(null);
3289
+ }, []);
3290
+ return {
3291
+ importStore,
3292
+ isImporting,
3293
+ error,
3294
+ reset
3295
+ };
3296
+ }
3297
+
3298
+ // src/hooks/useImportNote.ts
3299
+ import { useCallback as useCallback24, useState as useState20 } from "react";
3300
+ import { NoteFile } from "@miden-sdk/miden-sdk";
3301
+ function useImportNote() {
3302
+ const { client, isReady, runExclusive, sync } = useMiden();
3303
+ const [isImporting, setIsImporting] = useState20(false);
3304
+ const [error, setError] = useState20(null);
3305
+ const importNote = useCallback24(
3306
+ async (noteBytes) => {
3307
+ if (!client || !isReady) {
3308
+ throw new Error("Miden client is not ready");
3309
+ }
3310
+ setIsImporting(true);
3311
+ setError(null);
3312
+ try {
3313
+ const noteFile = NoteFile.deserialize(noteBytes);
3314
+ const noteId = await runExclusive(
3315
+ () => client.importNoteFile(noteFile)
3316
+ );
3317
+ await sync();
3318
+ return noteId.toString();
3319
+ } catch (err) {
3320
+ const error2 = err instanceof Error ? err : new Error(String(err));
3321
+ setError(error2);
3322
+ throw error2;
3323
+ } finally {
3324
+ setIsImporting(false);
3325
+ }
3326
+ },
3327
+ [client, isReady, runExclusive, sync]
3328
+ );
3329
+ const reset = useCallback24(() => {
3330
+ setIsImporting(false);
3331
+ setError(null);
3332
+ }, []);
3333
+ return {
3334
+ importNote,
3335
+ isImporting,
3336
+ error,
3337
+ reset
3338
+ };
3339
+ }
3340
+
3341
+ // src/hooks/useExportNote.ts
3342
+ import { useCallback as useCallback25, useState as useState21 } from "react";
3343
+ import { NoteExportFormat } from "@miden-sdk/miden-sdk";
3344
+ function useExportNote() {
3345
+ const { client, isReady, runExclusive } = useMiden();
3346
+ const [isExporting, setIsExporting] = useState21(false);
3347
+ const [error, setError] = useState21(null);
3348
+ const exportNote = useCallback25(
3349
+ async (noteId) => {
3350
+ if (!client || !isReady) {
3351
+ throw new Error("Miden client is not ready");
3352
+ }
3353
+ setIsExporting(true);
3354
+ setError(null);
3355
+ try {
3356
+ const noteFile = await runExclusive(
3357
+ () => client.exportNoteFile(noteId, NoteExportFormat.Full)
3358
+ );
3359
+ return noteFile.serialize();
3360
+ } catch (err) {
3361
+ const error2 = err instanceof Error ? err : new Error(String(err));
3362
+ setError(error2);
3363
+ throw error2;
3364
+ } finally {
3365
+ setIsExporting(false);
3366
+ }
3367
+ },
3368
+ [client, isReady, runExclusive]
3369
+ );
3370
+ const reset = useCallback25(() => {
3371
+ setIsExporting(false);
3372
+ setError(null);
3373
+ }, []);
3374
+ return {
3375
+ exportNote,
3376
+ isExporting,
3377
+ error,
3378
+ reset
3379
+ };
3380
+ }
3381
+
3382
+ // src/hooks/useSyncControl.ts
3383
+ import { useCallback as useCallback26 } from "react";
3384
+ function useSyncControl() {
3385
+ const isPaused = useMidenStore((state) => state.syncPaused);
3386
+ const setSyncPaused = useMidenStore((state) => state.setSyncPaused);
3387
+ const pauseSync = useCallback26(() => setSyncPaused(true), [setSyncPaused]);
3388
+ const resumeSync = useCallback26(() => setSyncPaused(false), [setSyncPaused]);
3389
+ return {
3390
+ pauseSync,
3391
+ resumeSync,
3392
+ isPaused
3393
+ };
3394
+ }
3395
+
2911
3396
  // src/utils/bytes.ts
2912
3397
  function bytesToBigInt(bytes) {
2913
3398
  let result = 0n;
@@ -3058,10 +3543,13 @@ function createMidenStorage(prefix) {
3058
3543
  // src/index.ts
3059
3544
  installAccountBech32();
3060
3545
  export {
3546
+ AuthScheme,
3061
3547
  DEFAULTS,
3062
3548
  MidenError,
3063
3549
  MidenProvider,
3550
+ MultiSignerProvider,
3064
3551
  SignerContext,
3552
+ SignerSlot,
3065
3553
  accountIdsEqual,
3066
3554
  bigIntToBytes,
3067
3555
  bytesToBigInt,
@@ -3083,18 +3571,24 @@ export {
3083
3571
  useConsume,
3084
3572
  useCreateFaucet,
3085
3573
  useCreateWallet,
3574
+ useExecuteProgram,
3575
+ useExportNote,
3576
+ useExportStore,
3086
3577
  useImportAccount,
3087
- useInternalTransfer,
3578
+ useImportNote,
3579
+ useImportStore,
3088
3580
  useMiden,
3089
3581
  useMidenClient,
3090
3582
  useMint,
3091
3583
  useMultiSend,
3584
+ useMultiSigner,
3092
3585
  useNoteStream,
3093
3586
  useNotes,
3094
3587
  useSend,
3095
3588
  useSessionAccount,
3096
3589
  useSigner,
3097
3590
  useSwap,
3591
+ useSyncControl,
3098
3592
  useSyncState,
3099
3593
  useTransaction,
3100
3594
  useTransactionHistory,