@miden-sdk/react 0.14.0-alpha → 0.14.1

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.js CHANGED
@@ -34,7 +34,9 @@ __export(index_exports, {
34
34
  DEFAULTS: () => DEFAULTS,
35
35
  MidenError: () => MidenError,
36
36
  MidenProvider: () => MidenProvider,
37
+ MultiSignerProvider: () => MultiSignerProvider,
37
38
  SignerContext: () => SignerContext,
39
+ SignerSlot: () => SignerSlot,
38
40
  accountIdsEqual: () => accountIdsEqual,
39
41
  bigIntToBytes: () => bigIntToBytes,
40
42
  bytesToBigInt: () => bytesToBigInt,
@@ -56,18 +58,24 @@ __export(index_exports, {
56
58
  useConsume: () => useConsume,
57
59
  useCreateFaucet: () => useCreateFaucet,
58
60
  useCreateWallet: () => useCreateWallet,
61
+ useExecuteProgram: () => useExecuteProgram,
62
+ useExportNote: () => useExportNote,
63
+ useExportStore: () => useExportStore,
59
64
  useImportAccount: () => useImportAccount,
60
- useInternalTransfer: () => useInternalTransfer,
65
+ useImportNote: () => useImportNote,
66
+ useImportStore: () => useImportStore,
61
67
  useMiden: () => useMiden,
62
68
  useMidenClient: () => useMidenClient,
63
69
  useMint: () => useMint,
64
70
  useMultiSend: () => useMultiSend,
71
+ useMultiSigner: () => useMultiSigner,
65
72
  useNoteStream: () => useNoteStream,
66
73
  useNotes: () => useNotes,
67
74
  useSend: () => useSend,
68
75
  useSessionAccount: () => useSessionAccount,
69
76
  useSigner: () => useSigner,
70
77
  useSwap: () => useSwap,
78
+ useSyncControl: () => useSyncControl,
71
79
  useSyncState: () => useSyncState,
72
80
  useTransaction: () => useTransaction,
73
81
  useTransactionHistory: () => useTransactionHistory,
@@ -92,24 +100,33 @@ var initialSyncState = {
92
100
  lastSyncTime: null,
93
101
  error: null
94
102
  };
95
- var initialState = {
96
- client: null,
97
- isReady: false,
98
- isInitializing: false,
99
- initError: null,
100
- config: {},
101
- sync: initialSyncState,
102
- accounts: [],
103
- accountDetails: /* @__PURE__ */ new Map(),
104
- notes: [],
105
- consumableNotes: [],
106
- assetMetadata: /* @__PURE__ */ new Map(),
107
- noteFirstSeen: /* @__PURE__ */ new Map(),
108
- isLoadingAccounts: false,
109
- isLoadingNotes: false
110
- };
103
+ function freshCachedState() {
104
+ return {
105
+ sync: { ...initialSyncState },
106
+ syncPaused: false,
107
+ accounts: [],
108
+ accountDetails: /* @__PURE__ */ new Map(),
109
+ notes: [],
110
+ consumableNotes: [],
111
+ assetMetadata: /* @__PURE__ */ new Map(),
112
+ noteFirstSeen: /* @__PURE__ */ new Map(),
113
+ isLoadingAccounts: false,
114
+ isLoadingNotes: false
115
+ };
116
+ }
117
+ function freshState() {
118
+ return {
119
+ client: null,
120
+ isReady: false,
121
+ isInitializing: false,
122
+ initError: null,
123
+ config: {},
124
+ signerConnected: null,
125
+ ...freshCachedState()
126
+ };
127
+ }
111
128
  var useMidenStore = (0, import_zustand.create)()((set) => ({
112
- ...initialState,
129
+ ...freshState(),
113
130
  setClient: (client) => set({
114
131
  client,
115
132
  isReady: client !== null,
@@ -123,9 +140,11 @@ var useMidenStore = (0, import_zustand.create)()((set) => ({
123
140
  isReady: false
124
141
  }),
125
142
  setConfig: (config) => set({ config }),
143
+ setSignerConnected: (signerConnected) => set({ signerConnected }),
126
144
  setSyncState: (sync) => set((state) => ({
127
145
  sync: { ...state.sync, ...sync }
128
146
  })),
147
+ setSyncPaused: (syncPaused) => set({ syncPaused }),
129
148
  setAccounts: (accounts) => set({ accounts }),
130
149
  setAccountDetails: (accountId, account) => set((state) => {
131
150
  const newMap = new Map(state.accountDetails);
@@ -207,7 +226,8 @@ var useMidenStore = (0, import_zustand.create)()((set) => ({
207
226
  }),
208
227
  setLoadingAccounts: (isLoadingAccounts) => set({ isLoadingAccounts }),
209
228
  setLoadingNotes: (isLoadingNotes) => set({ isLoadingNotes }),
210
- reset: () => set(initialState)
229
+ resetInMemoryState: () => set(freshCachedState()),
230
+ reset: () => set(freshState())
211
231
  }));
212
232
  var useSyncStateStore = () => useMidenStore((state) => state.sync);
213
233
  var useAccountsStore = () => useMidenStore((state) => state.accounts);
@@ -232,11 +252,13 @@ var parseAccountIdFromString = (value) => {
232
252
  return import_miden_sdk2.AccountId.fromHex(normalizeHexInput(value));
233
253
  };
234
254
  var parseAccountId = (value) => {
235
- if (typeof value !== "string") {
236
- return value;
255
+ if (typeof value === "string") {
256
+ return parseAccountIdFromString(normalizeAccountIdInput(value));
237
257
  }
238
- const normalized = normalizeAccountIdInput(value);
239
- return parseAccountIdFromString(normalized);
258
+ if (typeof value.id === "function") {
259
+ return value.id();
260
+ }
261
+ return value;
240
262
  };
241
263
  function isFaucetId(accountId) {
242
264
  try {
@@ -252,6 +274,10 @@ function isFaucetId(accountId) {
252
274
  }
253
275
  }
254
276
  var parseAddress = (value, accountId) => {
277
+ if (typeof value !== "string") {
278
+ const resolvedId = accountId ?? parseAccountId(value);
279
+ return import_miden_sdk2.Address.fromAccountId(resolvedId, "BasicWallet");
280
+ }
255
281
  const normalized = normalizeAccountIdInput(value);
256
282
  if (isBech32Input(normalized)) {
257
283
  try {
@@ -419,9 +445,35 @@ function resolveTransactionProver(config) {
419
445
  if (!prover) {
420
446
  return null;
421
447
  }
422
- if (typeof prover === "string") {
423
- const normalized = prover.trim().toLowerCase();
424
- if (normalized === "local") {
448
+ if (isFallbackConfig(prover)) {
449
+ return resolveProverTarget(prover.primary, config);
450
+ }
451
+ return resolveProverTarget(prover, config);
452
+ }
453
+ async function proveWithFallback(proveFn, config) {
454
+ const primaryProver = resolveTransactionProver(config);
455
+ try {
456
+ return await proveFn(primaryProver ?? void 0);
457
+ } catch (primaryError) {
458
+ const { prover } = config;
459
+ if (!prover || !isFallbackConfig(prover) || !prover.fallback) {
460
+ throw primaryError;
461
+ }
462
+ if (prover.disableFallback?.()) {
463
+ throw primaryError;
464
+ }
465
+ const fallbackProver = resolveProverTarget(prover.fallback, config);
466
+ prover.onFallback?.();
467
+ return await proveFn(fallbackProver ?? void 0);
468
+ }
469
+ }
470
+ function isFallbackConfig(prover) {
471
+ return typeof prover === "object" && "primary" in prover;
472
+ }
473
+ function resolveProverTarget(target, config) {
474
+ if (typeof target === "string") {
475
+ const normalized = target.trim().toLowerCase();
476
+ if (normalized === "local" || normalized === "localhost") {
425
477
  return import_miden_sdk5.TransactionProver.newLocalProver();
426
478
  }
427
479
  if (normalized === "devnet" || normalized === "testnet") {
@@ -435,11 +487,11 @@ function resolveTransactionProver(config) {
435
487
  );
436
488
  }
437
489
  return import_miden_sdk5.TransactionProver.newRemoteProver(
438
- prover,
490
+ target,
439
491
  normalizeTimeout(config.proverTimeoutMs)
440
492
  );
441
493
  }
442
- return createRemoteProver(prover, config.proverTimeoutMs);
494
+ return createRemoteProver(target, config.proverTimeoutMs);
443
495
  }
444
496
  function createRemoteProver(config, fallbackTimeout) {
445
497
  const { url, timeoutMs } = config;
@@ -484,6 +536,19 @@ function isPrivateStorageMode(storageMode) {
484
536
  async function initializeSignerAccount(client, config) {
485
537
  const { AccountBuilder, AccountComponent, AuthScheme: AuthScheme2, Word: Word2 } = await import("@miden-sdk/miden-sdk");
486
538
  await client.syncState();
539
+ if (config.importAccountId) {
540
+ const accountId2 = parseAccountId(config.importAccountId);
541
+ try {
542
+ await client.importAccountById(accountId2);
543
+ } catch (e) {
544
+ const msg = e instanceof Error ? e.message : String(e);
545
+ if (!msg.includes("already being tracked")) {
546
+ throw e;
547
+ }
548
+ }
549
+ await client.syncState();
550
+ return config.importAccountId;
551
+ }
487
552
  const commitmentWord = Word2.deserialize(config.publicKeyCommitment);
488
553
  const seed = config.accountSeed ?? crypto.getRandomValues(new Uint8Array(32));
489
554
  const accountType = getAccountType(config.accountType);
@@ -541,15 +606,19 @@ function MidenProvider({
541
606
  isReady,
542
607
  isInitializing,
543
608
  initError,
609
+ signerConnected,
544
610
  setClient,
545
611
  setInitializing,
546
612
  setInitError,
547
613
  setConfig,
548
- setSyncState
614
+ setSyncState,
615
+ setSignerConnected
549
616
  } = useMidenStore();
550
617
  const syncIntervalRef = (0, import_react2.useRef)(null);
551
618
  const isInitializedRef = (0, import_react2.useRef)(false);
552
619
  const clientLockRef = (0, import_react2.useRef)(new AsyncLock());
620
+ const currentStoreNameRef = (0, import_react2.useRef)(null);
621
+ const signCbRef = (0, import_react2.useRef)(null);
553
622
  const signerContext = useSigner();
554
623
  const [signerAccountId, setSignerAccountId] = (0, import_react2.useState)(null);
555
624
  const resolvedConfig = (0, import_react2.useMemo)(
@@ -577,35 +646,62 @@ function MidenProvider({
577
646
  const store = useMidenStore.getState();
578
647
  if (store.sync.isSyncing) return;
579
648
  setSyncState({ isSyncing: true, error: null });
580
- await runExclusive(async () => {
581
- try {
582
- const summary = await client.syncState();
583
- const syncHeight = summary.blockNum();
584
- setSyncState({
585
- syncHeight,
586
- isSyncing: false,
587
- lastSyncTime: Date.now(),
588
- error: null
589
- });
590
- const accounts = await client.getAccounts();
591
- useMidenStore.getState().setAccounts(accounts);
592
- } catch (error) {
593
- setSyncState({
594
- isSyncing: false,
595
- error: error instanceof Error ? error : new Error(String(error))
596
- });
649
+ try {
650
+ const summary = await client.syncState();
651
+ const syncHeight = summary.blockNum();
652
+ setSyncState({
653
+ syncHeight,
654
+ isSyncing: false,
655
+ lastSyncTime: Date.now(),
656
+ error: null
657
+ });
658
+ const accounts = await client.getAccounts();
659
+ useMidenStore.getState().setAccounts(accounts);
660
+ } catch (error) {
661
+ setSyncState({
662
+ isSyncing: false,
663
+ error: error instanceof Error ? error : new Error(String(error))
664
+ });
665
+ }
666
+ }, [client, isReady, setSyncState]);
667
+ const signerIsConnected = signerContext?.isConnected ?? null;
668
+ const signerStoreName = signerContext?.storeName ?? null;
669
+ const signerAccountType = signerContext?.accountConfig?.accountType ?? null;
670
+ const signerStorageMode = signerContext?.accountConfig?.storageMode?.toString() ?? null;
671
+ (0, import_react2.useEffect)(() => {
672
+ signCbRef.current = signerContext?.signCb ?? null;
673
+ }, [signerContext?.signCb]);
674
+ const wrappedSignCb = (0, import_react2.useCallback)(
675
+ async (pubKey, signingInputs) => {
676
+ const cb = signCbRef.current;
677
+ if (!cb) {
678
+ throw new Error("Signer is disconnected. Cannot sign.");
597
679
  }
598
- });
599
- }, [client, isReady, runExclusive, setSyncState]);
680
+ return cb(pubKey, signingInputs);
681
+ },
682
+ []
683
+ );
600
684
  (0, import_react2.useEffect)(() => {
601
- if (!signerContext && isInitializedRef.current) return;
602
- if (signerContext && !signerContext.isConnected) {
603
- if (useMidenStore.getState().client) {
604
- useMidenStore.getState().reset();
685
+ if (signerIsConnected === null && isInitializedRef.current) return;
686
+ if (signerIsConnected === false) {
687
+ const store = useMidenStore.getState();
688
+ if (store.signerConnected !== false) {
689
+ setSignerConnected(false);
690
+ }
691
+ return;
692
+ }
693
+ if (signerIsConnected === true && signerStoreName !== null) {
694
+ const store = useMidenStore.getState();
695
+ if (currentStoreNameRef.current === signerStoreName && store.client !== null) {
696
+ store.client.setSignCb(wrappedSignCb);
697
+ setSignerConnected(true);
698
+ return;
699
+ }
700
+ if (currentStoreNameRef.current !== null && currentStoreNameRef.current !== signerStoreName) {
701
+ store.resetInMemoryState();
605
702
  setClient(null);
606
703
  setSignerAccountId(null);
607
704
  }
608
- return;
609
705
  }
610
706
  let cancelled = false;
611
707
  const initClient = async () => {
@@ -616,18 +712,17 @@ function MidenProvider({
616
712
  try {
617
713
  let webClient;
618
714
  let didSignerInit = false;
619
- if (signerContext && signerContext.isConnected) {
715
+ if (signerContext && signerIsConnected === true) {
620
716
  const storeName = `MidenClientDB_${signerContext.storeName}`;
717
+ signCbRef.current = signerContext.signCb;
621
718
  webClient = await import_miden_sdk6.WasmWebClient.createClientWithExternalKeystore(
622
719
  resolvedConfig.rpcUrl,
623
720
  resolvedConfig.noteTransportUrl,
624
721
  resolvedConfig.seed,
625
722
  storeName,
626
- void 0,
627
- // getKeyCb - not needed for public accounts
628
- void 0,
629
- // insertKeyCb - not needed for public accounts
630
- signerContext.signCb
723
+ signerContext.getKeyCb,
724
+ signerContext.insertKeyCb,
725
+ wrappedSignCb
631
726
  );
632
727
  if (cancelled) return;
633
728
  const accountId = await initializeSignerAccount(
@@ -637,6 +732,7 @@ function MidenProvider({
637
732
  if (cancelled) return;
638
733
  setSignerAccountId(accountId);
639
734
  didSignerInit = true;
735
+ currentStoreNameRef.current = signerContext.storeName;
640
736
  } else {
641
737
  const seed = resolvedConfig.seed;
642
738
  webClient = await import_miden_sdk6.WasmWebClient.createClient(
@@ -670,6 +766,9 @@ function MidenProvider({
670
766
  isInitializedRef.current = true;
671
767
  }
672
768
  setClient(webClient);
769
+ if (signerIsConnected === true) {
770
+ setSignerConnected(true);
771
+ }
673
772
  }
674
773
  } catch (error) {
675
774
  if (!cancelled) {
@@ -693,14 +792,26 @@ function MidenProvider({
693
792
  setInitError,
694
793
  setInitializing,
695
794
  setSyncState,
696
- signerContext
795
+ setSignerConnected,
796
+ signerIsConnected,
797
+ signerStoreName,
798
+ signerAccountType,
799
+ signerStorageMode,
800
+ wrappedSignCb
801
+ // Note: signerContext is intentionally NOT a dep — we use stable primitives
802
+ // (signerIsConnected, signerStoreName, signerAccountType, signerStorageMode)
803
+ // to avoid re-running when the signer provider creates a new object ref.
804
+ // signCb changes are handled by the dedicated useEffect + signCbRef above,
805
+ // not by this effect.
697
806
  ]);
698
807
  (0, import_react2.useEffect)(() => {
699
808
  if (!isReady || !client) return;
700
809
  const interval = config.autoSyncInterval ?? DEFAULTS.AUTO_SYNC_INTERVAL;
701
810
  if (interval <= 0) return;
702
811
  syncIntervalRef.current = setInterval(() => {
703
- sync();
812
+ if (!useMidenStore.getState().syncPaused) {
813
+ sync();
814
+ }
704
815
  }, interval);
705
816
  return () => {
706
817
  if (syncIntervalRef.current) {
@@ -709,6 +820,20 @@ function MidenProvider({
709
820
  }
710
821
  };
711
822
  }, [isReady, client, config.autoSyncInterval, sync]);
823
+ (0, import_react2.useEffect)(() => {
824
+ if (!isReady || !client) return;
825
+ const unsubscribe = client.onStateChanged?.(async () => {
826
+ try {
827
+ const accounts = await client.getAccounts();
828
+ useMidenStore.getState().setAccounts(accounts);
829
+ setSyncState({ lastSyncTime: Date.now() });
830
+ } catch {
831
+ }
832
+ });
833
+ return () => {
834
+ unsubscribe?.();
835
+ };
836
+ }, [isReady, client, setSyncState]);
712
837
  if (isInitializing && loadingComponent) {
713
838
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: loadingComponent });
714
839
  }
@@ -726,7 +851,8 @@ function MidenProvider({
726
851
  sync,
727
852
  runExclusive,
728
853
  prover: defaultProver,
729
- signerAccountId
854
+ signerAccountId,
855
+ signerConnected
730
856
  };
731
857
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MidenContext.Provider, { value: contextValue, children });
732
858
  }
@@ -747,35 +873,183 @@ function useMidenClient() {
747
873
  return client;
748
874
  }
749
875
 
750
- // src/hooks/useAccounts.ts
876
+ // src/context/MultiSignerProvider.tsx
751
877
  var import_react3 = require("react");
752
-
753
- // src/utils/runExclusive.ts
754
- var runExclusiveDirect = async (fn) => fn();
878
+ var import_jsx_runtime2 = require("react/jsx-runtime");
879
+ var MultiSignerRegistryContext = (0, import_react3.createContext)(null);
880
+ var MultiSignerContext = (0, import_react3.createContext)(null);
881
+ function MultiSignerProvider({ children }) {
882
+ const signersRef = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
883
+ const [signersSnapshot, setSignersSnapshot] = (0, import_react3.useState)(
884
+ []
885
+ );
886
+ const [activeSignerName, setActiveSignerName] = (0, import_react3.useState)(null);
887
+ const activeSignerNameRef = (0, import_react3.useRef)(null);
888
+ const generationRef = (0, import_react3.useRef)(0);
889
+ const updateSnapshot = (0, import_react3.useCallback)(() => {
890
+ setSignersSnapshot(Array.from(signersRef.current.values()));
891
+ }, []);
892
+ const register = (0, import_react3.useCallback)(
893
+ (value) => {
894
+ const prev = signersRef.current.get(value.name);
895
+ signersRef.current.set(value.name, value);
896
+ if (!prev || prev.name !== value.name || prev.isConnected !== value.isConnected || prev.storeName !== value.storeName || prev.accountConfig !== value.accountConfig) {
897
+ updateSnapshot();
898
+ }
899
+ },
900
+ [updateSnapshot]
901
+ );
902
+ const unregister = (0, import_react3.useCallback)(
903
+ (name) => {
904
+ signersRef.current.delete(name);
905
+ setActiveSignerName((current) => current === name ? null : current);
906
+ updateSnapshot();
907
+ },
908
+ [updateSnapshot]
909
+ );
910
+ const registry = (0, import_react3.useMemo)(
911
+ () => ({ register, unregister }),
912
+ [register, unregister]
913
+ );
914
+ const activeSigner = activeSignerName ? signersSnapshot.find((s) => s.name === activeSignerName) ?? null : null;
915
+ const stableSignCb = (0, import_react3.useCallback)(
916
+ async (pubKey, signingInputs) => {
917
+ const name = activeSignerName;
918
+ if (!name) throw new Error("No active signer (signer was disconnected)");
919
+ const signer = signersRef.current.get(name);
920
+ if (!signer) throw new Error(`Signer "${name}" not found in registry`);
921
+ return signer.signCb(pubKey, signingInputs);
922
+ },
923
+ [activeSignerName]
924
+ );
925
+ const stableConnect = (0, import_react3.useCallback)(async () => {
926
+ const name = activeSignerName;
927
+ if (!name) throw new Error("No active signer (signer was disconnected)");
928
+ const signer = signersRef.current.get(name);
929
+ if (!signer) throw new Error(`Signer "${name}" not found in registry`);
930
+ return signer.connect();
931
+ }, [activeSignerName]);
932
+ const stableDisconnect = (0, import_react3.useCallback)(async () => {
933
+ const name = activeSignerName;
934
+ if (!name) throw new Error("No active signer (signer was disconnected)");
935
+ const signer = signersRef.current.get(name);
936
+ if (!signer) throw new Error(`Signer "${name}" not found in registry`);
937
+ return signer.disconnect();
938
+ }, [activeSignerName]);
939
+ const forwardedValue = (0, import_react3.useMemo)(() => {
940
+ if (!activeSigner) return null;
941
+ return {
942
+ name: activeSigner.name,
943
+ isConnected: activeSigner.isConnected,
944
+ storeName: activeSigner.storeName,
945
+ accountConfig: activeSigner.accountConfig,
946
+ signCb: stableSignCb,
947
+ connect: stableConnect,
948
+ disconnect: stableDisconnect
949
+ };
950
+ }, [
951
+ activeSigner?.name,
952
+ activeSigner?.isConnected,
953
+ activeSigner?.storeName,
954
+ activeSigner?.accountConfig,
955
+ stableSignCb,
956
+ stableConnect,
957
+ stableDisconnect
958
+ ]);
959
+ const setActiveName = (0, import_react3.useCallback)((name) => {
960
+ activeSignerNameRef.current = name;
961
+ setActiveSignerName(name);
962
+ }, []);
963
+ const connectSigner = (0, import_react3.useCallback)(
964
+ async (name) => {
965
+ const currentName = activeSignerNameRef.current;
966
+ const currentSigner = currentName ? signersRef.current.get(currentName) : null;
967
+ if (currentName === name && currentSigner?.isConnected) return;
968
+ const newSigner = signersRef.current.get(name);
969
+ if (!newSigner) throw new Error(`Signer "${name}" not found`);
970
+ const generation = ++generationRef.current;
971
+ setActiveName(name);
972
+ if (currentSigner?.isConnected) {
973
+ currentSigner.disconnect().catch((err) => {
974
+ console.warn("Failed to disconnect previous signer:", err);
975
+ });
976
+ }
977
+ try {
978
+ await newSigner.connect();
979
+ if (generation !== generationRef.current) return;
980
+ } catch (err) {
981
+ if (generation !== generationRef.current) return;
982
+ setActiveName(null);
983
+ throw err;
984
+ }
985
+ },
986
+ [setActiveName]
987
+ );
988
+ const disconnectSigner = (0, import_react3.useCallback)(async () => {
989
+ ++generationRef.current;
990
+ const currentName = activeSignerNameRef.current;
991
+ const signer = currentName ? signersRef.current.get(currentName) : null;
992
+ setActiveName(null);
993
+ if (signer?.isConnected) {
994
+ signer.disconnect().catch((err) => {
995
+ console.warn("Failed to disconnect signer:", err);
996
+ });
997
+ }
998
+ }, [setActiveName]);
999
+ const multiSignerValue = (0, import_react3.useMemo)(
1000
+ () => ({
1001
+ signers: signersSnapshot,
1002
+ activeSigner,
1003
+ connectSigner,
1004
+ disconnectSigner
1005
+ }),
1006
+ [signersSnapshot, activeSigner, connectSigner, disconnectSigner]
1007
+ );
1008
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SignerContext.Provider, { value: forwardedValue, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MultiSignerRegistryContext.Provider, { value: registry, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MultiSignerContext.Provider, { value: multiSignerValue, children }) }) });
1009
+ }
1010
+ function SignerSlot() {
1011
+ const signerValue = useSigner();
1012
+ const registry = (0, import_react3.useContext)(MultiSignerRegistryContext);
1013
+ const nameRef = (0, import_react3.useRef)();
1014
+ (0, import_react3.useEffect)(() => {
1015
+ if (!signerValue || !registry) return;
1016
+ nameRef.current = signerValue.name;
1017
+ registry.register(signerValue);
1018
+ }, [signerValue, registry]);
1019
+ (0, import_react3.useEffect)(() => {
1020
+ return () => {
1021
+ if (nameRef.current && registry) {
1022
+ registry.unregister(nameRef.current);
1023
+ }
1024
+ };
1025
+ }, [registry]);
1026
+ return null;
1027
+ }
1028
+ function useMultiSigner() {
1029
+ return (0, import_react3.useContext)(MultiSignerContext);
1030
+ }
755
1031
 
756
1032
  // src/hooks/useAccounts.ts
1033
+ var import_react4 = require("react");
757
1034
  function useAccounts() {
758
- const { client, isReady, runExclusive } = useMiden();
759
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1035
+ const { client, isReady } = useMiden();
760
1036
  const accounts = useAccountsStore();
761
1037
  const isLoadingAccounts = useMidenStore((state) => state.isLoadingAccounts);
762
1038
  const setLoadingAccounts = useMidenStore((state) => state.setLoadingAccounts);
763
1039
  const setAccounts = useMidenStore((state) => state.setAccounts);
764
- const refetch = (0, import_react3.useCallback)(async () => {
1040
+ const refetch = (0, import_react4.useCallback)(async () => {
765
1041
  if (!client || !isReady) return;
766
1042
  setLoadingAccounts(true);
767
1043
  try {
768
- const fetchedAccounts = await runExclusiveSafe(
769
- () => client.getAccounts()
770
- );
1044
+ const fetchedAccounts = await client.getAccounts();
771
1045
  setAccounts(fetchedAccounts);
772
1046
  } catch (error) {
773
1047
  console.error("Failed to fetch accounts:", error);
774
1048
  } finally {
775
1049
  setLoadingAccounts(false);
776
1050
  }
777
- }, [client, isReady, runExclusive, setAccounts, setLoadingAccounts]);
778
- (0, import_react3.useEffect)(() => {
1051
+ }, [client, isReady, setAccounts, setLoadingAccounts]);
1052
+ (0, import_react4.useEffect)(() => {
779
1053
  if (isReady && accounts.length === 0) {
780
1054
  refetch();
781
1055
  }
@@ -801,10 +1075,10 @@ function useAccounts() {
801
1075
  }
802
1076
 
803
1077
  // src/hooks/useAccount.ts
804
- var import_react5 = require("react");
1078
+ var import_react6 = require("react");
805
1079
 
806
1080
  // src/hooks/useAssetMetadata.ts
807
- var import_react4 = require("react");
1081
+ var import_react5 = require("react");
808
1082
  var import_miden_sdk7 = require("@miden-sdk/miden-sdk");
809
1083
  var inflight = /* @__PURE__ */ new Map();
810
1084
  var rpcClients = /* @__PURE__ */ new Map();
@@ -840,12 +1114,12 @@ function useAssetMetadata(assetIds = []) {
840
1114
  const assetMetadata = useAssetMetadataStore();
841
1115
  const setAssetMetadata = useMidenStore((state) => state.setAssetMetadata);
842
1116
  const rpcUrl = useMidenStore((state) => state.config.rpcUrl);
843
- const rpcClient = (0, import_react4.useMemo)(() => getRpcClient(rpcUrl), [rpcUrl]);
844
- const uniqueAssetIds = (0, import_react4.useMemo)(
1117
+ const rpcClient = (0, import_react5.useMemo)(() => getRpcClient(rpcUrl), [rpcUrl]);
1118
+ const uniqueAssetIds = (0, import_react5.useMemo)(
845
1119
  () => Array.from(new Set(assetIds.filter(Boolean))),
846
1120
  [assetIds]
847
1121
  );
848
- (0, import_react4.useEffect)(() => {
1122
+ (0, import_react5.useEffect)(() => {
849
1123
  if (!rpcClient || uniqueAssetIds.length === 0) return;
850
1124
  uniqueAssetIds.forEach((assetId) => {
851
1125
  const existing = assetMetadata.get(assetId);
@@ -864,31 +1138,25 @@ function useAssetMetadata(assetIds = []) {
864
1138
 
865
1139
  // src/hooks/useAccount.ts
866
1140
  function useAccount(accountId) {
867
- const { client, isReady, runExclusive } = useMiden();
868
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1141
+ const { client, isReady } = useMiden();
869
1142
  const accountDetails = useMidenStore((state) => state.accountDetails);
870
1143
  const setAccountDetails = useMidenStore((state) => state.setAccountDetails);
871
1144
  const { lastSyncTime } = useSyncStateStore();
872
- const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
873
- const [error, setError] = (0, import_react5.useState)(null);
874
- const accountIdStr = (0, import_react5.useMemo)(() => {
1145
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
1146
+ const [error, setError] = (0, import_react6.useState)(null);
1147
+ const accountIdStr = (0, import_react6.useMemo)(() => {
875
1148
  if (!accountId) return void 0;
876
1149
  if (typeof accountId === "string") return accountId;
877
- if (typeof accountId.toString === "function") {
878
- return accountId.toString();
879
- }
880
- return String(accountId);
1150
+ return parseAccountId(accountId).toString();
881
1151
  }, [accountId]);
882
1152
  const account = accountIdStr ? accountDetails.get(accountIdStr) ?? null : null;
883
- const refetch = (0, import_react5.useCallback)(async () => {
1153
+ const refetch = (0, import_react6.useCallback)(async () => {
884
1154
  if (!client || !isReady || !accountIdStr) return;
885
1155
  setIsLoading(true);
886
1156
  setError(null);
887
1157
  try {
888
1158
  const accountIdObj = parseAccountId(accountIdStr);
889
- const fetchedAccount = await runExclusiveSafe(
890
- () => client.getAccount(accountIdObj)
891
- );
1159
+ const fetchedAccount = await client.getAccount(accountIdObj);
892
1160
  if (fetchedAccount) {
893
1161
  ensureAccountBech32(fetchedAccount);
894
1162
  setAccountDetails(accountIdStr, fetchedAccount);
@@ -898,17 +1166,17 @@ function useAccount(accountId) {
898
1166
  } finally {
899
1167
  setIsLoading(false);
900
1168
  }
901
- }, [client, isReady, runExclusive, accountIdStr, setAccountDetails]);
902
- (0, import_react5.useEffect)(() => {
1169
+ }, [client, isReady, accountIdStr, setAccountDetails]);
1170
+ (0, import_react6.useEffect)(() => {
903
1171
  if (isReady && accountIdStr && !account) {
904
1172
  refetch();
905
1173
  }
906
1174
  }, [isReady, accountIdStr, account, refetch]);
907
- (0, import_react5.useEffect)(() => {
1175
+ (0, import_react6.useEffect)(() => {
908
1176
  if (!isReady || !accountIdStr || !lastSyncTime) return;
909
1177
  refetch();
910
1178
  }, [isReady, accountIdStr, lastSyncTime, refetch]);
911
- const rawAssets = (0, import_react5.useMemo)(() => {
1179
+ const rawAssets = (0, import_react6.useMemo)(() => {
912
1180
  if (!account) return [];
913
1181
  try {
914
1182
  const vault = account.vault();
@@ -925,12 +1193,12 @@ function useAccount(accountId) {
925
1193
  return [];
926
1194
  }
927
1195
  }, [account]);
928
- const assetIds = (0, import_react5.useMemo)(
1196
+ const assetIds = (0, import_react6.useMemo)(
929
1197
  () => rawAssets.map((asset) => asset.assetId),
930
1198
  [rawAssets]
931
1199
  );
932
1200
  const { assetMetadata } = useAssetMetadata(assetIds);
933
- const assets = (0, import_react5.useMemo)(
1201
+ const assets = (0, import_react6.useMemo)(
934
1202
  () => rawAssets.map((asset) => {
935
1203
  const metadata = assetMetadata.get(asset.assetId);
936
1204
  return {
@@ -941,7 +1209,7 @@ function useAccount(accountId) {
941
1209
  }),
942
1210
  [rawAssets, assetMetadata]
943
1211
  );
944
- const getBalance = (0, import_react5.useCallback)(
1212
+ const getBalance = (0, import_react6.useCallback)(
945
1213
  (assetId) => {
946
1214
  const asset = assets.find((a) => a.assetId === assetId);
947
1215
  return asset?.amount ?? 0n;
@@ -959,17 +1227,18 @@ function useAccount(accountId) {
959
1227
  }
960
1228
 
961
1229
  // src/hooks/useNotes.ts
962
- var import_react6 = require("react");
1230
+ var import_react7 = require("react");
963
1231
  var import_miden_sdk9 = require("@miden-sdk/miden-sdk");
964
1232
 
965
1233
  // src/utils/amounts.ts
966
1234
  var formatAssetAmount = (amount, decimals) => {
1235
+ const amt = BigInt(amount);
967
1236
  if (!decimals || decimals <= 0) {
968
- return amount.toString();
1237
+ return amt.toString();
969
1238
  }
970
1239
  const factor = 10n ** BigInt(decimals);
971
- const whole = amount / factor;
972
- const fraction = amount % factor;
1240
+ const whole = amt / factor;
1241
+ const fraction = amt % factor;
973
1242
  if (fraction === 0n) {
974
1243
  return whole.toString();
975
1244
  }
@@ -1122,8 +1391,7 @@ function normalizeHex(value) {
1122
1391
 
1123
1392
  // src/hooks/useNotes.ts
1124
1393
  function useNotes(options) {
1125
- const { client, isReady, runExclusive } = useMiden();
1126
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1394
+ const { client, isReady } = useMiden();
1127
1395
  const notes = useNotesStore();
1128
1396
  const consumableNotes = useConsumableNotesStore();
1129
1397
  const isLoadingNotes = useMidenStore((state) => state.isLoadingNotes);
@@ -1133,30 +1401,22 @@ function useNotes(options) {
1133
1401
  (state) => state.setConsumableNotesIfChanged
1134
1402
  );
1135
1403
  const { lastSyncTime } = useSyncStateStore();
1136
- const [error, setError] = (0, import_react6.useState)(null);
1137
- const refetch = (0, import_react6.useCallback)(async () => {
1404
+ const [error, setError] = (0, import_react7.useState)(null);
1405
+ const refetch = (0, import_react7.useCallback)(async () => {
1138
1406
  if (!client || !isReady) return;
1139
1407
  setLoadingNotes(true);
1140
1408
  setError(null);
1141
1409
  try {
1142
- const { fetchedNotes, fetchedConsumable } = await runExclusiveSafe(
1143
- async () => {
1144
- const filterType = getNoteFilterType(options?.status);
1145
- const filter = new import_miden_sdk9.NoteFilter(filterType);
1146
- const notesResult = await client.getInputNotes(filter);
1147
- let consumableResult;
1148
- if (options?.accountId) {
1149
- const accountIdObj = parseAccountId(options.accountId);
1150
- consumableResult = await client.getConsumableNotes(accountIdObj);
1151
- } else {
1152
- consumableResult = await client.getConsumableNotes();
1153
- }
1154
- return {
1155
- fetchedNotes: notesResult,
1156
- fetchedConsumable: consumableResult
1157
- };
1158
- }
1159
- );
1410
+ const filterType = getNoteFilterType(options?.status);
1411
+ const filter = new import_miden_sdk9.NoteFilter(filterType);
1412
+ const fetchedNotes = await client.getInputNotes(filter);
1413
+ let fetchedConsumable;
1414
+ if (options?.accountId) {
1415
+ const accountIdObj = parseAccountId(options.accountId);
1416
+ fetchedConsumable = await client.getConsumableNotes(accountIdObj);
1417
+ } else {
1418
+ fetchedConsumable = await client.getConsumableNotes();
1419
+ }
1160
1420
  setNotesIfChanged(fetchedNotes);
1161
1421
  setConsumableNotesIfChanged(fetchedConsumable);
1162
1422
  } catch (err) {
@@ -1167,23 +1427,22 @@ function useNotes(options) {
1167
1427
  }, [
1168
1428
  client,
1169
1429
  isReady,
1170
- runExclusive,
1171
1430
  options?.status,
1172
1431
  options?.accountId,
1173
1432
  setLoadingNotes,
1174
1433
  setNotesIfChanged,
1175
1434
  setConsumableNotesIfChanged
1176
1435
  ]);
1177
- (0, import_react6.useEffect)(() => {
1436
+ (0, import_react7.useEffect)(() => {
1178
1437
  if (isReady && notes.length === 0) {
1179
1438
  refetch();
1180
1439
  }
1181
1440
  }, [isReady, notes.length, refetch]);
1182
- (0, import_react6.useEffect)(() => {
1441
+ (0, import_react7.useEffect)(() => {
1183
1442
  if (!isReady || !lastSyncTime) return;
1184
1443
  refetch();
1185
1444
  }, [isReady, lastSyncTime, refetch]);
1186
- const noteAssetIds = (0, import_react6.useMemo)(() => {
1445
+ const noteAssetIds = (0, import_react7.useMemo)(() => {
1187
1446
  const ids = /* @__PURE__ */ new Set();
1188
1447
  const collect = (note) => {
1189
1448
  const summary = getNoteSummary(note);
@@ -1195,11 +1454,11 @@ function useNotes(options) {
1195
1454
  return Array.from(ids);
1196
1455
  }, [notes, consumableNotes]);
1197
1456
  const { assetMetadata } = useAssetMetadata(noteAssetIds);
1198
- const getMetadata = (0, import_react6.useCallback)(
1457
+ const getMetadata = (0, import_react7.useCallback)(
1199
1458
  (assetId) => assetMetadata.get(assetId),
1200
1459
  [assetMetadata]
1201
1460
  );
1202
- const normalizedSender = (0, import_react6.useMemo)(() => {
1461
+ const normalizedSender = (0, import_react7.useMemo)(() => {
1203
1462
  if (!options?.sender) return null;
1204
1463
  try {
1205
1464
  return normalizeAccountId(options.sender);
@@ -1207,11 +1466,11 @@ function useNotes(options) {
1207
1466
  return options.sender;
1208
1467
  }
1209
1468
  }, [options?.sender]);
1210
- const excludeIdsKey = (0, import_react6.useMemo)(() => {
1469
+ const excludeIdsKey = (0, import_react7.useMemo)(() => {
1211
1470
  if (!options?.excludeIds || options.excludeIds.length === 0) return "";
1212
1471
  return [...options.excludeIds].sort().join("\0");
1213
1472
  }, [options?.excludeIds]);
1214
- const filterBySender = (0, import_react6.useCallback)(
1473
+ const filterBySender = (0, import_react7.useCallback)(
1215
1474
  (summaries, target) => {
1216
1475
  const cache = /* @__PURE__ */ new Map();
1217
1476
  return summaries.filter((s) => {
@@ -1230,7 +1489,7 @@ function useNotes(options) {
1230
1489
  },
1231
1490
  []
1232
1491
  );
1233
- const noteSummaries = (0, import_react6.useMemo)(() => {
1492
+ const noteSummaries = (0, import_react7.useMemo)(() => {
1234
1493
  let summaries = notes.map((note) => getNoteSummary(note, getMetadata)).filter(Boolean);
1235
1494
  if (normalizedSender) {
1236
1495
  summaries = filterBySender(summaries, normalizedSender);
@@ -1241,7 +1500,7 @@ function useNotes(options) {
1241
1500
  }
1242
1501
  return summaries;
1243
1502
  }, [notes, getMetadata, normalizedSender, excludeIdsKey, filterBySender]);
1244
- const consumableNoteSummaries = (0, import_react6.useMemo)(() => {
1503
+ const consumableNoteSummaries = (0, import_react7.useMemo)(() => {
1245
1504
  let summaries = consumableNotes.map((note) => getNoteSummary(note, getMetadata)).filter(Boolean);
1246
1505
  if (normalizedSender) {
1247
1506
  summaries = filterBySender(summaries, normalizedSender);
@@ -1270,7 +1529,7 @@ function useNotes(options) {
1270
1529
  }
1271
1530
 
1272
1531
  // src/hooks/useNoteStream.ts
1273
- var import_react7 = require("react");
1532
+ var import_react8 = require("react");
1274
1533
  var import_miden_sdk11 = require("@miden-sdk/miden-sdk");
1275
1534
 
1276
1535
  // src/utils/noteAttachment.ts
@@ -1341,54 +1600,51 @@ function createNoteAttachment(values) {
1341
1600
 
1342
1601
  // src/hooks/useNoteStream.ts
1343
1602
  function useNoteStream(options = {}) {
1344
- const { client, isReady, runExclusive } = useMiden();
1345
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1603
+ const { client, isReady } = useMiden();
1346
1604
  const allNotes = useNotesStore();
1347
1605
  const noteFirstSeen = useNoteFirstSeenStore();
1348
1606
  const { lastSyncTime } = useSyncStateStore();
1349
1607
  const setNotesIfChanged = useMidenStore((state) => state.setNotesIfChanged);
1350
- const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
1351
- const [error, setError] = (0, import_react7.useState)(null);
1352
- const handledIdsRef = (0, import_react7.useRef)(/* @__PURE__ */ new Set());
1353
- const [handledVersion, setHandledVersion] = (0, import_react7.useState)(0);
1608
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1609
+ const [error, setError] = (0, import_react8.useState)(null);
1610
+ const handledIdsRef = (0, import_react8.useRef)(/* @__PURE__ */ new Set());
1611
+ const [handledVersion, setHandledVersion] = (0, import_react8.useState)(0);
1354
1612
  const status = options.status ?? "committed";
1355
1613
  const sender = options.sender ?? null;
1356
1614
  const since = options.since;
1357
- const amountFilterRef = (0, import_react7.useRef)(options.amountFilter);
1615
+ const amountFilterRef = (0, import_react8.useRef)(options.amountFilter);
1358
1616
  amountFilterRef.current = options.amountFilter;
1359
- const excludeIdsKey = (0, import_react7.useMemo)(() => {
1617
+ const excludeIdsKey = (0, import_react8.useMemo)(() => {
1360
1618
  if (!options.excludeIds) return "";
1361
1619
  if (options.excludeIds instanceof Set)
1362
1620
  return Array.from(options.excludeIds).sort().join("\0");
1363
1621
  return [...options.excludeIds].sort().join("\0");
1364
1622
  }, [options.excludeIds]);
1365
- const excludeIdSet = (0, import_react7.useMemo)(() => {
1623
+ const excludeIdSet = (0, import_react8.useMemo)(() => {
1366
1624
  if (!excludeIdsKey) return null;
1367
1625
  return new Set(excludeIdsKey.split("\0"));
1368
1626
  }, [excludeIdsKey]);
1369
- const refetch = (0, import_react7.useCallback)(async () => {
1627
+ const refetch = (0, import_react8.useCallback)(async () => {
1370
1628
  if (!client || !isReady) return;
1371
1629
  setIsLoading(true);
1372
1630
  setError(null);
1373
1631
  try {
1374
1632
  const filterType = getNoteFilterType(status);
1375
1633
  const filter = new import_miden_sdk11.NoteFilter(filterType);
1376
- const fetched = await runExclusiveSafe(
1377
- () => client.getInputNotes(filter)
1378
- );
1634
+ const fetched = await client.getInputNotes(filter);
1379
1635
  setNotesIfChanged(fetched);
1380
1636
  } catch (err) {
1381
1637
  setError(err instanceof Error ? err : new Error(String(err)));
1382
1638
  } finally {
1383
1639
  setIsLoading(false);
1384
1640
  }
1385
- }, [client, isReady, runExclusiveSafe, status, setNotesIfChanged]);
1386
- (0, import_react7.useEffect)(() => {
1641
+ }, [client, isReady, status, setNotesIfChanged]);
1642
+ (0, import_react8.useEffect)(() => {
1387
1643
  if (isReady) {
1388
1644
  refetch();
1389
1645
  }
1390
1646
  }, [isReady, lastSyncTime, refetch]);
1391
- const streamedNotes = (0, import_react7.useMemo)(() => {
1647
+ const streamedNotes = (0, import_react8.useMemo)(() => {
1392
1648
  void handledVersion;
1393
1649
  const result = [];
1394
1650
  let normalizedSender = null;
@@ -1413,15 +1669,15 @@ function useNoteStream(options = {}) {
1413
1669
  result.sort((a, b) => a.firstSeenAt - b.firstSeenAt);
1414
1670
  return result;
1415
1671
  }, [allNotes, noteFirstSeen, excludeIdSet, sender, since, handledVersion]);
1416
- const latest = (0, import_react7.useMemo)(
1672
+ const latest = (0, import_react8.useMemo)(
1417
1673
  () => streamedNotes.length > 0 ? streamedNotes[streamedNotes.length - 1] : null,
1418
1674
  [streamedNotes]
1419
1675
  );
1420
- const markHandled = (0, import_react7.useCallback)((noteId) => {
1676
+ const markHandled = (0, import_react8.useCallback)((noteId) => {
1421
1677
  handledIdsRef.current = new Set(handledIdsRef.current).add(noteId);
1422
1678
  setHandledVersion((v) => v + 1);
1423
1679
  }, []);
1424
- const markAllHandled = (0, import_react7.useCallback)(() => {
1680
+ const markAllHandled = (0, import_react8.useCallback)(() => {
1425
1681
  const newSet = new Set(handledIdsRef.current);
1426
1682
  for (const note of streamedNotes) {
1427
1683
  newSet.add(note.id);
@@ -1429,7 +1685,7 @@ function useNoteStream(options = {}) {
1429
1685
  handledIdsRef.current = newSet;
1430
1686
  setHandledVersion((v) => v + 1);
1431
1687
  }, [streamedNotes]);
1432
- const snapshot = (0, import_react7.useCallback)(() => {
1688
+ const snapshot = (0, import_react8.useCallback)(() => {
1433
1689
  const ids = /* @__PURE__ */ new Set();
1434
1690
  for (const note of streamedNotes) {
1435
1691
  ids.add(note.id);
@@ -1485,21 +1741,20 @@ function buildStreamedNote(record, noteFirstSeen) {
1485
1741
  }
1486
1742
 
1487
1743
  // src/hooks/useTransactionHistory.ts
1488
- var import_react8 = require("react");
1744
+ var import_react9 = require("react");
1489
1745
  var import_miden_sdk12 = require("@miden-sdk/miden-sdk");
1490
1746
  function useTransactionHistory(options = {}) {
1491
- const { client, isReady, runExclusive } = useMiden();
1492
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1747
+ const { client, isReady } = useMiden();
1493
1748
  const { lastSyncTime } = useSyncStateStore();
1494
- const [records, setRecords] = (0, import_react8.useState)([]);
1495
- const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1496
- const [error, setError] = (0, import_react8.useState)(null);
1497
- const rawIds = (0, import_react8.useMemo)(() => {
1749
+ const [records, setRecords] = (0, import_react9.useState)([]);
1750
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
1751
+ const [error, setError] = (0, import_react9.useState)(null);
1752
+ const rawIds = (0, import_react9.useMemo)(() => {
1498
1753
  if (options.id) return [options.id];
1499
1754
  if (options.ids && options.ids.length > 0) return options.ids;
1500
1755
  return null;
1501
1756
  }, [options.id, options.ids]);
1502
- const idsHex = (0, import_react8.useMemo)(() => {
1757
+ const idsHex = (0, import_react9.useMemo)(() => {
1503
1758
  if (!rawIds) return null;
1504
1759
  return rawIds.map(
1505
1760
  (id) => normalizeHex2(typeof id === "string" ? id : id.toHex())
@@ -1507,7 +1762,7 @@ function useTransactionHistory(options = {}) {
1507
1762
  }, [rawIds]);
1508
1763
  const filter = options.filter;
1509
1764
  const refreshOnSync = options.refreshOnSync !== false;
1510
- const refetch = (0, import_react8.useCallback)(async () => {
1765
+ const refetch = (0, import_react9.useCallback)(async () => {
1511
1766
  if (!client || !isReady) return;
1512
1767
  setIsLoading(true);
1513
1768
  setError(null);
@@ -1517,9 +1772,7 @@ function useTransactionHistory(options = {}) {
1517
1772
  rawIds,
1518
1773
  idsHex
1519
1774
  );
1520
- const fetched = await runExclusiveSafe(
1521
- () => client.getTransactions(resolvedFilter)
1522
- );
1775
+ const fetched = await client.getTransactions(resolvedFilter);
1523
1776
  const filtered = localFilterHexes ? fetched.filter(
1524
1777
  (record2) => localFilterHexes.includes(normalizeHex2(record2.id().toHex()))
1525
1778
  ) : fetched;
@@ -1529,20 +1782,20 @@ function useTransactionHistory(options = {}) {
1529
1782
  } finally {
1530
1783
  setIsLoading(false);
1531
1784
  }
1532
- }, [client, isReady, runExclusiveSafe, filter, rawIds, idsHex]);
1533
- (0, import_react8.useEffect)(() => {
1785
+ }, [client, isReady, filter, rawIds, idsHex]);
1786
+ (0, import_react9.useEffect)(() => {
1534
1787
  if (!isReady) return;
1535
1788
  refetch();
1536
1789
  }, [isReady, refetch]);
1537
- (0, import_react8.useEffect)(() => {
1790
+ (0, import_react9.useEffect)(() => {
1538
1791
  if (!isReady || !refreshOnSync || !lastSyncTime) return;
1539
1792
  refetch();
1540
1793
  }, [isReady, lastSyncTime, refreshOnSync, refetch]);
1541
- const record = (0, import_react8.useMemo)(() => {
1794
+ const record = (0, import_react9.useMemo)(() => {
1542
1795
  if (!idsHex || idsHex.length !== 1) return null;
1543
1796
  return records.find((item) => normalizeHex2(item.id().toHex()) === idsHex[0]) ?? null;
1544
1797
  }, [records, idsHex]);
1545
- const status = (0, import_react8.useMemo)(() => {
1798
+ const status = (0, import_react9.useMemo)(() => {
1546
1799
  if (!record) return null;
1547
1800
  const current = record.transactionStatus();
1548
1801
  if (current.isCommitted()) return "committed";
@@ -1582,11 +1835,11 @@ function normalizeHex2(value) {
1582
1835
  }
1583
1836
 
1584
1837
  // src/hooks/useSyncState.ts
1585
- var import_react9 = require("react");
1838
+ var import_react10 = require("react");
1586
1839
  function useSyncState() {
1587
1840
  const { sync: triggerSync } = useMiden();
1588
1841
  const syncState = useSyncStateStore();
1589
- const sync = (0, import_react9.useCallback)(async () => {
1842
+ const sync = (0, import_react10.useCallback)(async () => {
1590
1843
  await triggerSync();
1591
1844
  }, [triggerSync]);
1592
1845
  return {
@@ -1596,16 +1849,21 @@ function useSyncState() {
1596
1849
  }
1597
1850
 
1598
1851
  // src/hooks/useCreateWallet.ts
1599
- var import_react10 = require("react");
1852
+ var import_react11 = require("react");
1600
1853
  var import_miden_sdk13 = require("@miden-sdk/miden-sdk");
1854
+
1855
+ // src/utils/runExclusive.ts
1856
+ var runExclusiveDirect = async (fn) => fn();
1857
+
1858
+ // src/hooks/useCreateWallet.ts
1601
1859
  function useCreateWallet() {
1602
1860
  const { client, isReady, runExclusive } = useMiden();
1603
1861
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1604
1862
  const setAccounts = useMidenStore((state) => state.setAccounts);
1605
- const [wallet, setWallet] = (0, import_react10.useState)(null);
1606
- const [isCreating, setIsCreating] = (0, import_react10.useState)(false);
1607
- const [error, setError] = (0, import_react10.useState)(null);
1608
- const createWallet = (0, import_react10.useCallback)(
1863
+ const [wallet, setWallet] = (0, import_react11.useState)(null);
1864
+ const [isCreating, setIsCreating] = (0, import_react11.useState)(false);
1865
+ const [error, setError] = (0, import_react11.useState)(null);
1866
+ const createWallet = (0, import_react11.useCallback)(
1609
1867
  async (options = {}) => {
1610
1868
  if (!client || !isReady) {
1611
1869
  throw new Error("Miden client is not ready");
@@ -1642,7 +1900,7 @@ function useCreateWallet() {
1642
1900
  },
1643
1901
  [client, isReady, runExclusive, setAccounts]
1644
1902
  );
1645
- const reset = (0, import_react10.useCallback)(() => {
1903
+ const reset = (0, import_react11.useCallback)(() => {
1646
1904
  setWallet(null);
1647
1905
  setIsCreating(false);
1648
1906
  setError(null);
@@ -1669,16 +1927,16 @@ function getStorageMode(mode) {
1669
1927
  }
1670
1928
 
1671
1929
  // src/hooks/useCreateFaucet.ts
1672
- var import_react11 = require("react");
1930
+ var import_react12 = require("react");
1673
1931
  var import_miden_sdk14 = require("@miden-sdk/miden-sdk");
1674
1932
  function useCreateFaucet() {
1675
1933
  const { client, isReady, runExclusive } = useMiden();
1676
1934
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1677
1935
  const setAccounts = useMidenStore((state) => state.setAccounts);
1678
- const [faucet, setFaucet] = (0, import_react11.useState)(null);
1679
- const [isCreating, setIsCreating] = (0, import_react11.useState)(false);
1680
- const [error, setError] = (0, import_react11.useState)(null);
1681
- const createFaucet = (0, import_react11.useCallback)(
1936
+ const [faucet, setFaucet] = (0, import_react12.useState)(null);
1937
+ const [isCreating, setIsCreating] = (0, import_react12.useState)(false);
1938
+ const [error, setError] = (0, import_react12.useState)(null);
1939
+ const createFaucet = (0, import_react12.useCallback)(
1682
1940
  async (options) => {
1683
1941
  if (!client || !isReady) {
1684
1942
  throw new Error("Miden client is not ready");
@@ -1698,7 +1956,7 @@ function useCreateFaucet() {
1698
1956
  // nonFungible - currently only fungible faucets supported
1699
1957
  options.tokenSymbol,
1700
1958
  decimals,
1701
- options.maxSupply,
1959
+ BigInt(options.maxSupply),
1702
1960
  authScheme
1703
1961
  );
1704
1962
  const accounts = await client.getAccounts();
@@ -1717,7 +1975,7 @@ function useCreateFaucet() {
1717
1975
  },
1718
1976
  [client, isReady, runExclusive, setAccounts]
1719
1977
  );
1720
- const reset = (0, import_react11.useCallback)(() => {
1978
+ const reset = (0, import_react12.useCallback)(() => {
1721
1979
  setFaucet(null);
1722
1980
  setIsCreating(false);
1723
1981
  setError(null);
@@ -1744,25 +2002,79 @@ function getStorageMode2(mode) {
1744
2002
  }
1745
2003
 
1746
2004
  // src/hooks/useImportAccount.ts
1747
- var import_react12 = require("react");
2005
+ var import_react13 = require("react");
1748
2006
  var import_miden_sdk15 = require("@miden-sdk/miden-sdk");
2007
+
2008
+ // src/utils/errors.ts
2009
+ var MidenError = class extends Error {
2010
+ constructor(message, options) {
2011
+ super(message);
2012
+ this.name = "MidenError";
2013
+ this.code = options?.code ?? "UNKNOWN";
2014
+ if (options?.cause !== void 0) {
2015
+ this.cause = options.cause;
2016
+ }
2017
+ }
2018
+ };
2019
+ var ERROR_PATTERNS = [
2020
+ {
2021
+ test: (msg) => msg.includes("_assertClass") || msg.includes("expected instance of"),
2022
+ code: "WASM_CLASS_MISMATCH",
2023
+ 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."
2024
+ },
2025
+ {
2026
+ test: (msg) => msg.includes("null pointer") || msg.includes("already been freed") || msg.includes("dereferencing a null"),
2027
+ code: "WASM_POINTER_CONSUMED",
2028
+ 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."
2029
+ },
2030
+ {
2031
+ test: (msg) => msg.includes("not initialized") || msg.includes("Cannot read properties of null"),
2032
+ code: "WASM_NOT_INITIALIZED",
2033
+ message: "Miden client is not initialized. Ensure you are inside a <MidenProvider> and the client is ready before calling SDK methods."
2034
+ },
2035
+ {
2036
+ test: (msg) => msg.includes("state commitment mismatch") || msg.includes("stale state"),
2037
+ code: "WASM_SYNC_REQUIRED",
2038
+ message: "Account state is stale. Call sync() before executing transactions, or ensure no concurrent transactions are running against the same account."
2039
+ }
2040
+ ];
2041
+ function assertSignerConnected(signerConnected) {
2042
+ if (signerConnected === false) {
2043
+ throw new Error(
2044
+ "Signer is disconnected. Reconnect your wallet to perform transactions."
2045
+ );
2046
+ }
2047
+ }
2048
+ function wrapWasmError(e) {
2049
+ if (e instanceof MidenError) return e;
2050
+ const msg = e instanceof Error ? e.message : String(e);
2051
+ for (const pattern of ERROR_PATTERNS) {
2052
+ if (pattern.test(msg)) {
2053
+ return new MidenError(pattern.message, { cause: e, code: pattern.code });
2054
+ }
2055
+ }
2056
+ if (e instanceof Error) return e;
2057
+ return new Error(msg);
2058
+ }
2059
+
2060
+ // src/hooks/useImportAccount.ts
1749
2061
  function useImportAccount() {
1750
- const { client, isReady, runExclusive } = useMiden();
1751
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2062
+ const { client, isReady, signerConnected } = useMiden();
1752
2063
  const setAccounts = useMidenStore((state) => state.setAccounts);
1753
- const [account, setAccount] = (0, import_react12.useState)(null);
1754
- const [isImporting, setIsImporting] = (0, import_react12.useState)(false);
1755
- const [error, setError] = (0, import_react12.useState)(null);
1756
- const importAccount = (0, import_react12.useCallback)(
2064
+ const [account, setAccount] = (0, import_react13.useState)(null);
2065
+ const [isImporting, setIsImporting] = (0, import_react13.useState)(false);
2066
+ const [error, setError] = (0, import_react13.useState)(null);
2067
+ const importAccount = (0, import_react13.useCallback)(
1757
2068
  async (options) => {
1758
2069
  if (!client || !isReady) {
1759
2070
  throw new Error("Miden client is not ready");
1760
2071
  }
2072
+ assertSignerConnected(signerConnected);
1761
2073
  setIsImporting(true);
1762
2074
  setError(null);
1763
2075
  try {
1764
2076
  let accountsAfter = null;
1765
- const imported = await runExclusiveSafe(async () => {
2077
+ const imported = await (async () => {
1766
2078
  switch (options.type) {
1767
2079
  case "file": {
1768
2080
  const accountsBefore = await client.getAccounts();
@@ -1814,7 +2126,7 @@ function useImportAccount() {
1814
2126
  throw new Error("Account not found after import");
1815
2127
  }
1816
2128
  case "id": {
1817
- const accountId = resolveAccountId(options.accountId);
2129
+ const accountId = parseAccountId(options.accountId);
1818
2130
  await client.importAccountById(accountId);
1819
2131
  const fetchedAccount = await client.getAccount(accountId);
1820
2132
  if (!fetchedAccount) {
@@ -1832,7 +2144,7 @@ function useImportAccount() {
1832
2144
  );
1833
2145
  }
1834
2146
  }
1835
- });
2147
+ })();
1836
2148
  ensureAccountBech32(imported);
1837
2149
  const accounts = accountsAfter ?? await client.getAccounts();
1838
2150
  setAccounts(accounts);
@@ -1846,9 +2158,9 @@ function useImportAccount() {
1846
2158
  setIsImporting(false);
1847
2159
  }
1848
2160
  },
1849
- [client, isReady, runExclusive, setAccounts]
2161
+ [client, isReady, setAccounts, signerConnected]
1850
2162
  );
1851
- const reset = (0, import_react12.useCallback)(() => {
2163
+ const reset = (0, import_react13.useCallback)(() => {
1852
2164
  setAccount(null);
1853
2165
  setIsImporting(false);
1854
2166
  setError(null);
@@ -1861,9 +2173,6 @@ function useImportAccount() {
1861
2173
  reset
1862
2174
  };
1863
2175
  }
1864
- function resolveAccountId(accountId) {
1865
- return parseAccountId(accountId);
1866
- }
1867
2176
  async function resolveAccountFile(file) {
1868
2177
  if (file instanceof Uint8Array) {
1869
2178
  return import_miden_sdk15.AccountFile.deserialize(file);
@@ -1898,64 +2207,17 @@ function bytesEqual(left, right) {
1898
2207
  }
1899
2208
 
1900
2209
  // src/hooks/useSend.ts
1901
- var import_react13 = require("react");
2210
+ var import_react14 = require("react");
1902
2211
  var import_miden_sdk16 = require("@miden-sdk/miden-sdk");
1903
-
1904
- // src/utils/errors.ts
1905
- var MidenError = class extends Error {
1906
- constructor(message, options) {
1907
- super(message);
1908
- this.name = "MidenError";
1909
- this.code = options?.code ?? "UNKNOWN";
1910
- if (options?.cause !== void 0) {
1911
- this.cause = options.cause;
1912
- }
1913
- }
1914
- };
1915
- var ERROR_PATTERNS = [
1916
- {
1917
- test: (msg) => msg.includes("_assertClass") || msg.includes("expected instance of"),
1918
- code: "WASM_CLASS_MISMATCH",
1919
- 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."
1920
- },
1921
- {
1922
- test: (msg) => msg.includes("null pointer") || msg.includes("already been freed") || msg.includes("dereferencing a null"),
1923
- code: "WASM_POINTER_CONSUMED",
1924
- 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."
1925
- },
1926
- {
1927
- test: (msg) => msg.includes("not initialized") || msg.includes("Cannot read properties of null"),
1928
- code: "WASM_NOT_INITIALIZED",
1929
- message: "Miden client is not initialized. Ensure you are inside a <MidenProvider> and the client is ready before calling SDK methods."
1930
- },
1931
- {
1932
- test: (msg) => msg.includes("state commitment mismatch") || msg.includes("stale state"),
1933
- code: "WASM_SYNC_REQUIRED",
1934
- message: "Account state is stale. Call sync() before executing transactions, or ensure no concurrent transactions are running against the same account."
1935
- }
1936
- ];
1937
- function wrapWasmError(e) {
1938
- if (e instanceof MidenError) return e;
1939
- const msg = e instanceof Error ? e.message : String(e);
1940
- for (const pattern of ERROR_PATTERNS) {
1941
- if (pattern.test(msg)) {
1942
- return new MidenError(pattern.message, { cause: e, code: pattern.code });
1943
- }
1944
- }
1945
- if (e instanceof Error) return e;
1946
- return new Error(msg);
1947
- }
1948
-
1949
- // src/hooks/useSend.ts
1950
2212
  function useSend() {
1951
2213
  const { client, isReady, sync, runExclusive, prover } = useMiden();
1952
2214
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1953
- const isBusyRef = (0, import_react13.useRef)(false);
1954
- const [result, setResult] = (0, import_react13.useState)(null);
1955
- const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
1956
- const [stage, setStage] = (0, import_react13.useState)("idle");
1957
- const [error, setError] = (0, import_react13.useState)(null);
1958
- const send = (0, import_react13.useCallback)(
2215
+ const isBusyRef = (0, import_react14.useRef)(false);
2216
+ const [result, setResult] = (0, import_react14.useState)(null);
2217
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
2218
+ const [stage, setStage] = (0, import_react14.useState)("idle");
2219
+ const [error, setError] = (0, import_react14.useState)(null);
2220
+ const send = (0, import_react14.useCallback)(
1959
2221
  async (options) => {
1960
2222
  if (!client || !isReady) {
1961
2223
  throw new Error("Miden client is not ready");
@@ -1997,6 +2259,7 @@ function useSend() {
1997
2259
  if (amount === void 0 || amount === null) {
1998
2260
  throw new Error("Amount is required (provide amount or sendAll)");
1999
2261
  }
2262
+ amount = BigInt(amount);
2000
2263
  const assetId = options.assetId ?? options.faucetId ?? null;
2001
2264
  if (!assetId) {
2002
2265
  throw new Error("Asset ID is required");
@@ -2007,6 +2270,37 @@ function useSend() {
2007
2270
  "recallHeight and timelockHeight are not supported when attachment is provided"
2008
2271
  );
2009
2272
  }
2273
+ if (options.returnNote === true) {
2274
+ const returnResult = await runExclusiveSafe(async () => {
2275
+ const fromId = parseAccountId(options.from);
2276
+ const toId = parseAccountId(options.to);
2277
+ const assetObj = parseAccountId(assetId);
2278
+ const assets = new import_miden_sdk16.NoteAssets([
2279
+ new import_miden_sdk16.FungibleAsset(assetObj, BigInt(amount))
2280
+ ]);
2281
+ const p2idNote = import_miden_sdk16.Note.createP2IDNote(
2282
+ fromId,
2283
+ toId,
2284
+ assets,
2285
+ noteType,
2286
+ new import_miden_sdk16.NoteAttachment()
2287
+ );
2288
+ const ownOutputs = new import_miden_sdk16.NoteArray();
2289
+ ownOutputs.push(p2idNote);
2290
+ const txRequest = new import_miden_sdk16.TransactionRequestBuilder().withOwnOutputNotes(ownOutputs).build();
2291
+ const execFromId = parseAccountId(options.from);
2292
+ const txId = prover ? await client.submitNewTransactionWithProver(
2293
+ execFromId,
2294
+ txRequest,
2295
+ prover
2296
+ ) : await client.submitNewTransaction(execFromId, txRequest);
2297
+ return { txId: txId.toString(), note: p2idNote };
2298
+ });
2299
+ setStage("complete");
2300
+ setResult(returnResult);
2301
+ await sync();
2302
+ return returnResult;
2303
+ }
2010
2304
  const txResult = await runExclusiveSafe(async () => {
2011
2305
  const fromAccountId = parseAccountId(options.from);
2012
2306
  const toAccountId = parseAccountId(options.to);
@@ -2024,7 +2318,7 @@ function useSend() {
2024
2318
  noteType,
2025
2319
  attachment
2026
2320
  );
2027
- txRequest = new import_miden_sdk16.TransactionRequestBuilder().withOwnOutputNotes(new import_miden_sdk16.OutputNoteArray([import_miden_sdk16.OutputNote.full(note)])).build();
2321
+ txRequest = new import_miden_sdk16.TransactionRequestBuilder().withOwnOutputNotes(new import_miden_sdk16.NoteArray([note])).build();
2028
2322
  } else {
2029
2323
  txRequest = client.newSendTransactionRequest(
2030
2324
  fromAccountId,
@@ -2040,8 +2334,12 @@ function useSend() {
2040
2334
  return await client.executeTransaction(execAccountId, txRequest);
2041
2335
  });
2042
2336
  setStage("proving");
2043
- const provenTransaction = await runExclusiveSafe(
2044
- () => client.proveTransaction(txResult, prover ?? void 0)
2337
+ const proverConfig = useMidenStore.getState().config;
2338
+ const provenTransaction = await proveWithFallback(
2339
+ (resolvedProver) => runExclusiveSafe(
2340
+ () => client.proveTransaction(txResult, resolvedProver)
2341
+ ),
2342
+ proverConfig
2045
2343
  );
2046
2344
  setStage("submitting");
2047
2345
  const submissionHeight = await runExclusiveSafe(
@@ -2071,11 +2369,14 @@ function useSend() {
2071
2369
  () => client.sendPrivateNote(fullNote, recipientAddress)
2072
2370
  );
2073
2371
  }
2074
- const txSummary = { transactionId: txIdString };
2372
+ const sendResult = {
2373
+ txId: txIdString,
2374
+ note: null
2375
+ };
2075
2376
  setStage("complete");
2076
- setResult(txSummary);
2377
+ setResult(sendResult);
2077
2378
  await sync();
2078
- return txSummary;
2379
+ return sendResult;
2079
2380
  } catch (err) {
2080
2381
  const error2 = err instanceof Error ? err : new Error(String(err));
2081
2382
  setError(error2);
@@ -2088,7 +2389,7 @@ function useSend() {
2088
2389
  },
2089
2390
  [client, isReady, prover, runExclusive, sync]
2090
2391
  );
2091
- const reset = (0, import_react13.useCallback)(() => {
2392
+ const reset = (0, import_react14.useCallback)(() => {
2092
2393
  setResult(null);
2093
2394
  setIsLoading(false);
2094
2395
  setStage("idle");
@@ -2115,21 +2416,21 @@ function extractFullNote(txResult) {
2115
2416
  }
2116
2417
 
2117
2418
  // src/hooks/useMultiSend.ts
2118
- var import_react14 = require("react");
2419
+ var import_react15 = require("react");
2119
2420
  var import_miden_sdk17 = require("@miden-sdk/miden-sdk");
2120
2421
  function useMultiSend() {
2121
- const { client, isReady, sync, runExclusive, prover } = useMiden();
2122
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2123
- const isBusyRef = (0, import_react14.useRef)(false);
2124
- const [result, setResult] = (0, import_react14.useState)(null);
2125
- const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
2126
- const [stage, setStage] = (0, import_react14.useState)("idle");
2127
- const [error, setError] = (0, import_react14.useState)(null);
2128
- const sendMany = (0, import_react14.useCallback)(
2422
+ const { client, isReady, sync, prover, signerConnected } = useMiden();
2423
+ const isBusyRef = (0, import_react15.useRef)(false);
2424
+ const [result, setResult] = (0, import_react15.useState)(null);
2425
+ const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
2426
+ const [stage, setStage] = (0, import_react15.useState)("idle");
2427
+ const [error, setError] = (0, import_react15.useState)(null);
2428
+ const sendMany = (0, import_react15.useCallback)(
2129
2429
  async (options) => {
2130
2430
  if (!client || !isReady) {
2131
2431
  throw new Error("Miden client is not ready");
2132
2432
  }
2433
+ assertSignerConnected(signerConnected);
2133
2434
  if (options.recipients.length === 0) {
2134
2435
  throw new Error("No recipients provided");
2135
2436
  }
@@ -2154,7 +2455,7 @@ function useMultiSend() {
2154
2455
  const iterAssetId = parseAccountId(options.assetId);
2155
2456
  const receiverId = parseAccountId(to);
2156
2457
  const assets = new import_miden_sdk17.NoteAssets([
2157
- new import_miden_sdk17.FungibleAsset(iterAssetId, amount)
2458
+ new import_miden_sdk17.FungibleAsset(iterAssetId, BigInt(amount))
2158
2459
  ]);
2159
2460
  const resolvedNoteType = recipientNoteType ? getNoteType(recipientNoteType) : noteType;
2160
2461
  const noteAttachment = attachment !== void 0 && attachment !== null ? createNoteAttachment(attachment) : new import_miden_sdk17.NoteAttachment();
@@ -2167,44 +2468,43 @@ function useMultiSend() {
2167
2468
  );
2168
2469
  const recipientAddress = parseAddress(to, receiverId);
2169
2470
  return {
2170
- outputNote: import_miden_sdk17.OutputNote.full(note),
2171
2471
  note,
2172
2472
  recipientAddress,
2173
2473
  noteType: resolvedNoteType
2174
2474
  };
2175
2475
  }
2176
2476
  );
2177
- const txRequest = new import_miden_sdk17.TransactionRequestBuilder().withOwnOutputNotes(
2178
- new import_miden_sdk17.OutputNoteArray(outputs.map((o) => o.outputNote))
2179
- ).build();
2477
+ const txRequest = new import_miden_sdk17.TransactionRequestBuilder().withOwnOutputNotes(new import_miden_sdk17.NoteArray(outputs.map((o) => o.note))).build();
2180
2478
  const txSenderId = parseAccountId(options.from);
2181
- const txResult = await runExclusiveSafe(
2182
- () => client.executeTransaction(txSenderId, txRequest)
2183
- );
2479
+ const txResult = await client.executeTransaction(txSenderId, txRequest);
2184
2480
  setStage("proving");
2185
- const provenTransaction = await runExclusiveSafe(
2186
- () => client.proveTransaction(txResult, prover ?? void 0)
2481
+ const proverConfig = useMidenStore.getState().config;
2482
+ const provenTransaction = await proveWithFallback(
2483
+ (resolvedProver) => runExclusiveDirect(
2484
+ () => client.proveTransaction(txResult, resolvedProver)
2485
+ ),
2486
+ proverConfig
2187
2487
  );
2188
2488
  setStage("submitting");
2189
- const submissionHeight = await runExclusiveSafe(
2190
- () => client.submitProvenTransaction(provenTransaction, txResult)
2489
+ const submissionHeight = await client.submitProvenTransaction(
2490
+ provenTransaction,
2491
+ txResult
2191
2492
  );
2192
2493
  const txIdHex = txResult.id().toHex();
2193
2494
  const txIdString = txResult.id().toString();
2194
- await runExclusiveSafe(
2195
- () => client.applyTransaction(txResult, submissionHeight)
2196
- );
2495
+ await client.applyTransaction(txResult, submissionHeight);
2197
2496
  const hasPrivate = outputs.some((o) => o.noteType === import_miden_sdk17.NoteType.Private);
2198
2497
  if (hasPrivate) {
2199
2498
  await waitForTransactionCommit(
2200
2499
  client,
2201
- runExclusiveSafe,
2500
+ runExclusiveDirect,
2202
2501
  txIdHex
2203
2502
  );
2204
2503
  for (const output of outputs) {
2205
2504
  if (output.noteType === import_miden_sdk17.NoteType.Private) {
2206
- await runExclusiveSafe(
2207
- () => client.sendPrivateNote(output.note, output.recipientAddress)
2505
+ await client.sendPrivateNote(
2506
+ output.note,
2507
+ output.recipientAddress
2208
2508
  );
2209
2509
  }
2210
2510
  }
@@ -2224,144 +2524,7 @@ function useMultiSend() {
2224
2524
  isBusyRef.current = false;
2225
2525
  }
2226
2526
  },
2227
- [client, isReady, prover, runExclusive, sync]
2228
- );
2229
- const reset = (0, import_react14.useCallback)(() => {
2230
- setResult(null);
2231
- setIsLoading(false);
2232
- setStage("idle");
2233
- setError(null);
2234
- }, []);
2235
- return {
2236
- sendMany,
2237
- result,
2238
- isLoading,
2239
- stage,
2240
- error,
2241
- reset
2242
- };
2243
- }
2244
-
2245
- // src/hooks/useInternalTransfer.ts
2246
- var import_react15 = require("react");
2247
- var import_miden_sdk18 = require("@miden-sdk/miden-sdk");
2248
- function useInternalTransfer() {
2249
- const { client, isReady, sync, runExclusive, prover } = useMiden();
2250
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2251
- const [result, setResult] = (0, import_react15.useState)(null);
2252
- const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
2253
- const [stage, setStage] = (0, import_react15.useState)("idle");
2254
- const [error, setError] = (0, import_react15.useState)(null);
2255
- const transferOnce = (0, import_react15.useCallback)(
2256
- async (options) => {
2257
- if (!client || !isReady) {
2258
- throw new Error("Miden client is not ready");
2259
- }
2260
- const noteType = getNoteType(options.noteType ?? DEFAULTS.NOTE_TYPE);
2261
- const senderId = parseAccountId(options.from);
2262
- const receiverId = parseAccountId(options.to);
2263
- const assetId = parseAccountId(options.assetId);
2264
- const assets = new import_miden_sdk18.NoteAssets([
2265
- new import_miden_sdk18.FungibleAsset(assetId, options.amount)
2266
- ]);
2267
- const note = import_miden_sdk18.Note.createP2IDNote(
2268
- senderId,
2269
- receiverId,
2270
- assets,
2271
- noteType,
2272
- new import_miden_sdk18.NoteAttachment()
2273
- );
2274
- const noteId = note.id().toString();
2275
- const createRequest = new import_miden_sdk18.TransactionRequestBuilder().withOwnOutputNotes(new import_miden_sdk18.OutputNoteArray([import_miden_sdk18.OutputNote.full(note)])).build();
2276
- const createTxId = await runExclusiveSafe(
2277
- () => prover ? client.submitNewTransactionWithProver(
2278
- senderId,
2279
- createRequest,
2280
- prover
2281
- ) : client.submitNewTransaction(senderId, createRequest)
2282
- );
2283
- const consumeRequest = new import_miden_sdk18.TransactionRequestBuilder().withInputNotes(new import_miden_sdk18.NoteAndArgsArray([new import_miden_sdk18.NoteAndArgs(note, null)])).build();
2284
- const consumeTxId = await runExclusiveSafe(
2285
- () => prover ? client.submitNewTransactionWithProver(
2286
- receiverId,
2287
- consumeRequest,
2288
- prover
2289
- ) : client.submitNewTransaction(receiverId, consumeRequest)
2290
- );
2291
- return {
2292
- createTransactionId: createTxId.toString(),
2293
- consumeTransactionId: consumeTxId.toString(),
2294
- noteId
2295
- };
2296
- },
2297
- [client, isReady, prover, runExclusiveSafe]
2298
- );
2299
- const transfer = (0, import_react15.useCallback)(
2300
- async (options) => {
2301
- if (!client || !isReady) {
2302
- throw new Error("Miden client is not ready");
2303
- }
2304
- setIsLoading(true);
2305
- setStage("executing");
2306
- setError(null);
2307
- try {
2308
- setStage("proving");
2309
- const txResult = await transferOnce(options);
2310
- setStage("complete");
2311
- setResult(txResult);
2312
- await sync();
2313
- return txResult;
2314
- } catch (err) {
2315
- const error2 = err instanceof Error ? err : new Error(String(err));
2316
- setError(error2);
2317
- setStage("idle");
2318
- throw error2;
2319
- } finally {
2320
- setIsLoading(false);
2321
- }
2322
- },
2323
- [client, isReady, sync, transferOnce]
2324
- );
2325
- const transferChain = (0, import_react15.useCallback)(
2326
- async (options) => {
2327
- if (!client || !isReady) {
2328
- throw new Error("Miden client is not ready");
2329
- }
2330
- if (options.recipients.length === 0) {
2331
- throw new Error("No recipients provided");
2332
- }
2333
- setIsLoading(true);
2334
- setStage("executing");
2335
- setError(null);
2336
- try {
2337
- const results = [];
2338
- let currentSender = options.from;
2339
- for (const recipient of options.recipients) {
2340
- setStage("proving");
2341
- const txResult = await transferOnce({
2342
- from: currentSender,
2343
- to: recipient,
2344
- assetId: options.assetId,
2345
- amount: options.amount,
2346
- noteType: options.noteType
2347
- });
2348
- results.push(txResult);
2349
- currentSender = recipient;
2350
- }
2351
- setStage("complete");
2352
- setResult(results);
2353
- await sync();
2354
- return results;
2355
- } catch (err) {
2356
- const error2 = err instanceof Error ? err : new Error(String(err));
2357
- setError(error2);
2358
- setStage("idle");
2359
- throw error2;
2360
- } finally {
2361
- setIsLoading(false);
2362
- }
2363
- },
2364
- [client, isReady, sync, transferOnce]
2527
+ [client, isReady, prover, signerConnected, sync]
2365
2528
  );
2366
2529
  const reset = (0, import_react15.useCallback)(() => {
2367
2530
  setResult(null);
@@ -2370,8 +2533,7 @@ function useInternalTransfer() {
2370
2533
  setError(null);
2371
2534
  }, []);
2372
2535
  return {
2373
- transfer,
2374
- transferChain,
2536
+ sendMany,
2375
2537
  result,
2376
2538
  isLoading,
2377
2539
  stage,
@@ -2382,10 +2544,9 @@ function useInternalTransfer() {
2382
2544
 
2383
2545
  // src/hooks/useWaitForCommit.ts
2384
2546
  var import_react16 = require("react");
2385
- var import_miden_sdk19 = require("@miden-sdk/miden-sdk");
2547
+ var import_miden_sdk18 = require("@miden-sdk/miden-sdk");
2386
2548
  function useWaitForCommit() {
2387
- const { client, isReady, runExclusive } = useMiden();
2388
- const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2549
+ const { client, isReady } = useMiden();
2389
2550
  const waitForCommit = (0, import_react16.useCallback)(
2390
2551
  async (txId, options) => {
2391
2552
  if (!client || !isReady) {
@@ -2398,13 +2559,9 @@ function useWaitForCommit() {
2398
2559
  );
2399
2560
  const deadline = Date.now() + timeoutMs;
2400
2561
  while (Date.now() < deadline) {
2401
- await runExclusiveSafe(
2402
- () => client.syncState()
2403
- );
2404
- const records = await runExclusiveSafe(
2405
- () => client.getTransactions(
2406
- typeof txId === "string" ? import_miden_sdk19.TransactionFilter.all() : import_miden_sdk19.TransactionFilter.ids([txId])
2407
- )
2562
+ await client.syncState();
2563
+ const records = await client.getTransactions(
2564
+ typeof txId === "string" ? import_miden_sdk18.TransactionFilter.all() : import_miden_sdk18.TransactionFilter.ids([txId])
2408
2565
  );
2409
2566
  const record = records.find(
2410
2567
  (item) => normalizeHex3(item.id().toHex()) === targetHex
@@ -2422,7 +2579,7 @@ function useWaitForCommit() {
2422
2579
  }
2423
2580
  throw new Error("Timeout waiting for transaction commit");
2424
2581
  },
2425
- [client, isReady, runExclusiveSafe]
2582
+ [client, isReady]
2426
2583
  );
2427
2584
  return { waitForCommit };
2428
2585
  }
@@ -2451,11 +2608,11 @@ function useWaitForNotes() {
2451
2608
  await runExclusiveSafe(
2452
2609
  () => client.syncState()
2453
2610
  );
2454
- const notes = await runExclusiveSafe(
2611
+ const consumable = await runExclusiveSafe(
2455
2612
  () => client.getConsumableNotes(accountId)
2456
2613
  );
2457
- if (notes.length >= minCount) {
2458
- return notes;
2614
+ if (consumable.length >= minCount) {
2615
+ return consumable;
2459
2616
  }
2460
2617
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
2461
2618
  waited += intervalMs;
@@ -2494,7 +2651,7 @@ function useMint() {
2494
2651
  targetAccountIdObj,
2495
2652
  faucetIdObj,
2496
2653
  noteType,
2497
- options.amount
2654
+ BigInt(options.amount)
2498
2655
  );
2499
2656
  const txId = prover ? await client.submitNewTransactionWithProver(
2500
2657
  faucetIdObj,
@@ -2536,7 +2693,7 @@ function useMint() {
2536
2693
 
2537
2694
  // src/hooks/useConsume.ts
2538
2695
  var import_react19 = require("react");
2539
- var import_miden_sdk20 = require("@miden-sdk/miden-sdk");
2696
+ var import_miden_sdk19 = require("@miden-sdk/miden-sdk");
2540
2697
  function useConsume() {
2541
2698
  const { client, isReady, sync, runExclusive, prover } = useMiden();
2542
2699
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
@@ -2549,8 +2706,8 @@ function useConsume() {
2549
2706
  if (!client || !isReady) {
2550
2707
  throw new Error("Miden client is not ready");
2551
2708
  }
2552
- if (options.noteIds.length === 0) {
2553
- throw new Error("No note IDs provided");
2709
+ if (options.notes.length === 0) {
2710
+ throw new Error("No notes provided");
2554
2711
  }
2555
2712
  setIsLoading(true);
2556
2713
  setStage("executing");
@@ -2559,16 +2716,47 @@ function useConsume() {
2559
2716
  const accountIdObj = parseAccountId(options.accountId);
2560
2717
  setStage("proving");
2561
2718
  const txResult = await runExclusiveSafe(async () => {
2562
- const noteIds = options.noteIds.map(
2563
- (noteId) => import_miden_sdk20.NoteId.fromHex(noteId)
2564
- );
2565
- const filter = new import_miden_sdk20.NoteFilter(import_miden_sdk20.NoteFilterTypes.List, noteIds);
2566
- const noteRecords = await client.getInputNotes(filter);
2567
- const notes = noteRecords.map((record) => record.toNote());
2719
+ const resolved = new Array(options.notes.length);
2720
+ const lookupIndices = [];
2721
+ const lookupIds = [];
2722
+ for (let i = 0; i < options.notes.length; i++) {
2723
+ const item = options.notes[i];
2724
+ if (typeof item === "string") {
2725
+ lookupIndices.push(i);
2726
+ lookupIds.push(import_miden_sdk19.NoteId.fromHex(item));
2727
+ } else if (item !== null && typeof item === "object" && typeof item.toNote === "function") {
2728
+ resolved[i] = item.toNote();
2729
+ } else if (item !== null && typeof item === "object" && typeof item.id === "function") {
2730
+ resolved[i] = item;
2731
+ } else {
2732
+ lookupIndices.push(i);
2733
+ lookupIds.push(item);
2734
+ }
2735
+ }
2736
+ if (lookupIds.length > 0) {
2737
+ const filter = new import_miden_sdk19.NoteFilter(import_miden_sdk19.NoteFilterTypes.List, lookupIds);
2738
+ const noteRecords = await client.getInputNotes(filter);
2739
+ if (noteRecords.length !== lookupIds.length) {
2740
+ throw new Error("Some notes could not be found for provided IDs");
2741
+ }
2742
+ const recordById = new Map(
2743
+ noteRecords.map((r) => [r.id().toString(), r])
2744
+ );
2745
+ for (let j = 0; j < lookupIndices.length; j++) {
2746
+ const record = recordById.get(lookupIds[j].toString());
2747
+ if (!record) {
2748
+ throw new Error(
2749
+ "Some notes could not be found for provided IDs"
2750
+ );
2751
+ }
2752
+ resolved[lookupIndices[j]] = record.toNote();
2753
+ }
2754
+ }
2755
+ const notes = resolved;
2568
2756
  if (notes.length === 0) {
2569
2757
  throw new Error("No notes found for provided IDs");
2570
2758
  }
2571
- if (notes.length !== options.noteIds.length) {
2759
+ if (notes.length !== options.notes.length) {
2572
2760
  throw new Error("Some notes could not be found for provided IDs");
2573
2761
  }
2574
2762
  const txRequest = client.newConsumeTransactionRequest(notes);
@@ -2640,9 +2828,9 @@ function useSwap() {
2640
2828
  const txRequest = client.newSwapTransactionRequest(
2641
2829
  accountIdObj,
2642
2830
  offeredFaucetIdObj,
2643
- options.offeredAmount,
2831
+ BigInt(options.offeredAmount),
2644
2832
  requestedFaucetIdObj,
2645
- options.requestedAmount,
2833
+ BigInt(options.requestedAmount),
2646
2834
  noteType,
2647
2835
  paybackNoteType
2648
2836
  );
@@ -2686,8 +2874,50 @@ function useSwap() {
2686
2874
 
2687
2875
  // src/hooks/useTransaction.ts
2688
2876
  var import_react21 = require("react");
2877
+
2878
+ // src/utils/transactions.ts
2879
+ var import_miden_sdk20 = require("@miden-sdk/miden-sdk");
2880
+ async function waitForTransactionCommit2(client, runExclusiveSafe, txId, maxWaitMs = 1e4, delayMs = 1e3) {
2881
+ let waited = 0;
2882
+ while (waited < maxWaitMs) {
2883
+ await runExclusiveSafe(() => client.syncState());
2884
+ const [record] = await runExclusiveSafe(
2885
+ () => client.getTransactions(import_miden_sdk20.TransactionFilter.ids([txId]))
2886
+ );
2887
+ if (record) {
2888
+ const status = record.transactionStatus();
2889
+ if (status.isCommitted()) {
2890
+ return;
2891
+ }
2892
+ if (status.isDiscarded()) {
2893
+ throw new Error("Transaction was discarded before commit");
2894
+ }
2895
+ }
2896
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
2897
+ waited += delayMs;
2898
+ }
2899
+ throw new Error("Timeout waiting for transaction commit");
2900
+ }
2901
+ function extractFullNotes(txResult) {
2902
+ try {
2903
+ const executedTx = txResult.executedTransaction?.();
2904
+ const notes = executedTx?.outputNotes?.().notes?.() ?? [];
2905
+ const result = [];
2906
+ for (const note of notes) {
2907
+ if (note.noteType?.() === import_miden_sdk20.NoteType.Private) {
2908
+ const full = note.intoFull?.();
2909
+ if (full) result.push(full);
2910
+ }
2911
+ }
2912
+ return result;
2913
+ } catch {
2914
+ return [];
2915
+ }
2916
+ }
2917
+
2918
+ // src/hooks/useTransaction.ts
2689
2919
  function useTransaction() {
2690
- const { client, isReady, sync, runExclusive, prover } = useMiden();
2920
+ const { client, isReady, sync, runExclusive } = useMiden();
2691
2921
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2692
2922
  const isBusyRef = (0, import_react21.useRef)(false);
2693
2923
  const [result, setResult] = (0, import_react21.useState)(null);
@@ -2714,20 +2944,41 @@ function useTransaction() {
2714
2944
  await sync();
2715
2945
  }
2716
2946
  const txRequest = await resolveRequest(options.request, client);
2717
- setStage("proving");
2718
- const txResult = await runExclusiveSafe(async () => {
2719
- const accountIdObj = resolveAccountId2(options.accountId);
2720
- const txId = prover ? await client.submitNewTransactionWithProver(
2721
- accountIdObj,
2722
- txRequest,
2723
- prover
2724
- ) : await client.submitNewTransaction(accountIdObj, txRequest);
2725
- return { transactionId: txId.toString() };
2947
+ const txResult = await runExclusiveSafe(() => {
2948
+ const accountIdObj = parseAccountId(options.accountId);
2949
+ return client.executeTransaction(accountIdObj, txRequest);
2726
2950
  });
2951
+ setStage("proving");
2952
+ const proverConfig = useMidenStore.getState().config;
2953
+ const provenTransaction = await proveWithFallback(
2954
+ (resolvedProver) => runExclusiveSafe(
2955
+ () => client.proveTransaction(txResult, resolvedProver)
2956
+ ),
2957
+ proverConfig
2958
+ );
2959
+ setStage("submitting");
2960
+ const submissionHeight = await runExclusiveSafe(
2961
+ () => client.submitProvenTransaction(provenTransaction, txResult)
2962
+ );
2963
+ await runExclusiveSafe(
2964
+ () => client.applyTransaction(txResult, submissionHeight)
2965
+ );
2966
+ const txId = txResult.id();
2967
+ if (options.privateNoteTarget != null) {
2968
+ await waitForTransactionCommit2(client, runExclusiveSafe, txId);
2969
+ const targetAddress = parseAddress(options.privateNoteTarget);
2970
+ const fullNotes = extractFullNotes(txResult);
2971
+ for (const note of fullNotes) {
2972
+ await runExclusiveSafe(
2973
+ () => client.sendPrivateNote(note, targetAddress)
2974
+ );
2975
+ }
2976
+ }
2977
+ const txSummary = { transactionId: txId.toString() };
2727
2978
  setStage("complete");
2728
- setResult(txResult);
2979
+ setResult(txSummary);
2729
2980
  await sync();
2730
- return txResult;
2981
+ return txSummary;
2731
2982
  } catch (err) {
2732
2983
  const error2 = err instanceof Error ? err : new Error(String(err));
2733
2984
  setError(error2);
@@ -2738,7 +2989,7 @@ function useTransaction() {
2738
2989
  isBusyRef.current = false;
2739
2990
  }
2740
2991
  },
2741
- [client, isReady, prover, runExclusive, sync]
2992
+ [client, isReady, runExclusive, sync]
2742
2993
  );
2743
2994
  const reset = (0, import_react21.useCallback)(() => {
2744
2995
  setResult(null);
@@ -2755,9 +3006,6 @@ function useTransaction() {
2755
3006
  reset
2756
3007
  };
2757
3008
  }
2758
- function resolveAccountId2(accountId) {
2759
- return parseAccountId(accountId);
2760
- }
2761
3009
  async function resolveRequest(request, client) {
2762
3010
  if (typeof request === "function") {
2763
3011
  return await request(client);
@@ -2765,27 +3013,112 @@ async function resolveRequest(request, client) {
2765
3013
  return request;
2766
3014
  }
2767
3015
 
2768
- // src/hooks/useSessionAccount.ts
3016
+ // src/hooks/useExecuteProgram.ts
2769
3017
  var import_react22 = require("react");
2770
3018
  var import_miden_sdk21 = require("@miden-sdk/miden-sdk");
2771
- function useSessionAccount(options) {
3019
+ function isForeignAccountWrapper(fa) {
3020
+ return fa !== null && typeof fa === "object" && "id" in fa && typeof fa.id !== "function";
3021
+ }
3022
+ function useExecuteProgram() {
2772
3023
  const { client, isReady, sync, runExclusive } = useMiden();
2773
3024
  const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2774
- const setAccounts = useMidenStore((state) => state.setAccounts);
2775
- const [sessionAccountId, setSessionAccountId] = (0, import_react22.useState)(null);
2776
- const [step, setStep] = (0, import_react22.useState)("idle");
2777
- const [error, setError] = (0, import_react22.useState)(null);
2778
- const cancelledRef = (0, import_react22.useRef)(false);
2779
3025
  const isBusyRef = (0, import_react22.useRef)(false);
3026
+ const [result, setResult] = (0, import_react22.useState)(null);
3027
+ const [isLoading, setIsLoading] = (0, import_react22.useState)(false);
3028
+ const [error, setError] = (0, import_react22.useState)(null);
3029
+ const execute = (0, import_react22.useCallback)(
3030
+ async (options) => {
3031
+ if (!client || !isReady) {
3032
+ throw new Error("Miden client is not ready");
3033
+ }
3034
+ if (isBusyRef.current) {
3035
+ throw new MidenError(
3036
+ "A program execution is already in progress. Await the previous call before starting another.",
3037
+ { code: "OPERATION_BUSY" }
3038
+ );
3039
+ }
3040
+ isBusyRef.current = true;
3041
+ setIsLoading(true);
3042
+ setError(null);
3043
+ try {
3044
+ if (!options.skipSync) {
3045
+ await sync();
3046
+ }
3047
+ const programResult = await runExclusiveSafe(async () => {
3048
+ const accountIdObj = parseAccountId(options.accountId);
3049
+ const adviceInputs = options.adviceInputs ?? new import_miden_sdk21.AdviceInputs();
3050
+ let foreignAccountsArray;
3051
+ if (options.foreignAccounts?.length) {
3052
+ const accounts = options.foreignAccounts.map((fa) => {
3053
+ const wrapper = isForeignAccountWrapper(fa);
3054
+ const id = parseAccountId(wrapper ? fa.id : fa);
3055
+ const storage = wrapper && fa.storage ? fa.storage : new import_miden_sdk21.AccountStorageRequirements();
3056
+ return import_miden_sdk21.ForeignAccount.public(id, storage);
3057
+ });
3058
+ foreignAccountsArray = new import_miden_sdk21.ForeignAccountArray(accounts);
3059
+ } else {
3060
+ foreignAccountsArray = new import_miden_sdk21.ForeignAccountArray();
3061
+ }
3062
+ const feltArray = await client.executeProgram(
3063
+ accountIdObj,
3064
+ options.script,
3065
+ adviceInputs,
3066
+ foreignAccountsArray
3067
+ );
3068
+ const stack = [];
3069
+ const len = feltArray.length();
3070
+ for (let i = 0; i < len; i++) {
3071
+ stack.push(feltArray.get(i).asInt());
3072
+ }
3073
+ return { stack };
3074
+ });
3075
+ setResult(programResult);
3076
+ return programResult;
3077
+ } catch (err) {
3078
+ const error2 = err instanceof Error ? err : new Error(String(err));
3079
+ setError(error2);
3080
+ throw error2;
3081
+ } finally {
3082
+ setIsLoading(false);
3083
+ isBusyRef.current = false;
3084
+ }
3085
+ },
3086
+ [client, isReady, runExclusive, sync]
3087
+ );
3088
+ const reset = (0, import_react22.useCallback)(() => {
3089
+ setResult(null);
3090
+ setIsLoading(false);
3091
+ setError(null);
3092
+ }, []);
3093
+ return {
3094
+ execute,
3095
+ result,
3096
+ isLoading,
3097
+ error,
3098
+ reset
3099
+ };
3100
+ }
3101
+
3102
+ // src/hooks/useSessionAccount.ts
3103
+ var import_react23 = require("react");
3104
+ var import_miden_sdk22 = require("@miden-sdk/miden-sdk");
3105
+ function useSessionAccount(options) {
3106
+ const { client, isReady, sync } = useMiden();
3107
+ const setAccounts = useMidenStore((state) => state.setAccounts);
3108
+ const [sessionAccountId, setSessionAccountId] = (0, import_react23.useState)(null);
3109
+ const [step, setStep] = (0, import_react23.useState)("idle");
3110
+ const [error, setError] = (0, import_react23.useState)(null);
3111
+ const cancelledRef = (0, import_react23.useRef)(false);
3112
+ const isBusyRef = (0, import_react23.useRef)(false);
2780
3113
  const storagePrefix = options.storagePrefix ?? "miden-session";
2781
3114
  const pollIntervalMs = options.pollIntervalMs ?? 3e3;
2782
3115
  const maxWaitMs = options.maxWaitMs ?? 6e4;
2783
3116
  const storageMode = options.walletOptions?.storageMode ?? "public";
2784
3117
  const mutable = options.walletOptions?.mutable ?? DEFAULTS.WALLET_MUTABLE;
2785
3118
  const authScheme = options.walletOptions?.authScheme ?? DEFAULTS.AUTH_SCHEME;
2786
- const fundRef = (0, import_react22.useRef)(options.fund);
3119
+ const fundRef = (0, import_react23.useRef)(options.fund);
2787
3120
  fundRef.current = options.fund;
2788
- (0, import_react22.useEffect)(() => {
3121
+ (0, import_react23.useEffect)(() => {
2789
3122
  try {
2790
3123
  const stored = localStorage.getItem(`${storagePrefix}:accountId`);
2791
3124
  const storedReady = localStorage.getItem(`${storagePrefix}:ready`);
@@ -2802,7 +3135,7 @@ function useSessionAccount(options) {
2802
3135
  localStorage.removeItem(`${storagePrefix}:ready`);
2803
3136
  }
2804
3137
  }, [storagePrefix]);
2805
- const initialize = (0, import_react22.useCallback)(async () => {
3138
+ const initialize = (0, import_react23.useCallback)(async () => {
2806
3139
  if (!client || !isReady) {
2807
3140
  throw new Error("Miden client is not ready");
2808
3141
  }
@@ -2820,17 +3153,14 @@ function useSessionAccount(options) {
2820
3153
  if (!walletId) {
2821
3154
  setStep("creating");
2822
3155
  const resolvedStorageMode = getStorageMode3(storageMode);
2823
- const wallet = await runExclusiveSafe(async () => {
2824
- const w = await client.newWallet(
2825
- resolvedStorageMode,
2826
- mutable,
2827
- authScheme
2828
- );
2829
- ensureAccountBech32(w);
2830
- const accounts = await client.getAccounts();
2831
- setAccounts(accounts);
2832
- return w;
2833
- });
3156
+ const wallet = await client.newWallet(
3157
+ resolvedStorageMode,
3158
+ mutable,
3159
+ authScheme
3160
+ );
3161
+ ensureAccountBech32(wallet);
3162
+ const accounts = await client.getAccounts();
3163
+ setAccounts(accounts);
2834
3164
  if (cancelledRef.current) return;
2835
3165
  walletId = wallet.id().toString();
2836
3166
  setSessionAccountId(walletId);
@@ -2842,7 +3172,6 @@ function useSessionAccount(options) {
2842
3172
  setStep("consuming");
2843
3173
  await waitAndConsume(
2844
3174
  client,
2845
- runExclusiveSafe,
2846
3175
  walletId,
2847
3176
  pollIntervalMs,
2848
3177
  maxWaitMs,
@@ -2866,7 +3195,6 @@ function useSessionAccount(options) {
2866
3195
  client,
2867
3196
  isReady,
2868
3197
  sync,
2869
- runExclusiveSafe,
2870
3198
  sessionAccountId,
2871
3199
  storageMode,
2872
3200
  mutable,
@@ -2876,7 +3204,7 @@ function useSessionAccount(options) {
2876
3204
  maxWaitMs,
2877
3205
  setAccounts
2878
3206
  ]);
2879
- const reset = (0, import_react22.useCallback)(() => {
3207
+ const reset = (0, import_react23.useCallback)(() => {
2880
3208
  cancelledRef.current = true;
2881
3209
  isBusyRef.current = false;
2882
3210
  setSessionAccountId(null);
@@ -2897,37 +3225,209 @@ function useSessionAccount(options) {
2897
3225
  function getStorageMode3(mode) {
2898
3226
  switch (mode) {
2899
3227
  case "private":
2900
- return import_miden_sdk21.AccountStorageMode.private();
3228
+ return import_miden_sdk22.AccountStorageMode.private();
2901
3229
  case "public":
2902
- return import_miden_sdk21.AccountStorageMode.public();
3230
+ return import_miden_sdk22.AccountStorageMode.public();
2903
3231
  default:
2904
- return import_miden_sdk21.AccountStorageMode.public();
3232
+ return import_miden_sdk22.AccountStorageMode.public();
2905
3233
  }
2906
3234
  }
2907
- async function waitAndConsume(client, runExclusiveSafe, walletId, pollIntervalMs, maxWaitMs, cancelledRef) {
3235
+ async function waitAndConsume(client, walletId, pollIntervalMs, maxWaitMs, cancelledRef) {
2908
3236
  const deadline = Date.now() + maxWaitMs;
2909
3237
  while (Date.now() < deadline) {
2910
3238
  if (cancelledRef.current) return;
2911
- await runExclusiveSafe(
2912
- () => client.syncState()
2913
- );
3239
+ await client.syncState();
2914
3240
  if (cancelledRef.current) return;
2915
- const consumed = await runExclusiveSafe(async () => {
2916
- const accountIdObj = parseAccountId(walletId);
2917
- const consumable = await client.getConsumableNotes(accountIdObj);
2918
- if (consumable.length === 0) return false;
3241
+ const accountIdObj = parseAccountId(walletId);
3242
+ const consumable = await client.getConsumableNotes(accountIdObj);
3243
+ if (consumable.length > 0) {
2919
3244
  const notes = consumable.map((c) => c.inputNoteRecord().toNote());
2920
3245
  const txRequest = client.newConsumeTransactionRequest(notes);
2921
3246
  const freshAccountId = parseAccountId(walletId);
2922
3247
  await client.submitNewTransaction(freshAccountId, txRequest);
2923
- return true;
2924
- });
2925
- if (consumed) return;
3248
+ return;
3249
+ }
2926
3250
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
2927
3251
  }
2928
3252
  throw new Error("Timeout waiting for session wallet funding");
2929
3253
  }
2930
3254
 
3255
+ // src/hooks/useExportStore.ts
3256
+ var import_react24 = require("react");
3257
+ var import_miden_sdk23 = require("@miden-sdk/miden-sdk");
3258
+ function useExportStore() {
3259
+ const { client, isReady, runExclusive } = useMiden();
3260
+ const [isExporting, setIsExporting] = (0, import_react24.useState)(false);
3261
+ const [error, setError] = (0, import_react24.useState)(null);
3262
+ const exportStore = (0, import_react24.useCallback)(async () => {
3263
+ if (!client || !isReady) {
3264
+ throw new Error("Miden client is not ready");
3265
+ }
3266
+ setIsExporting(true);
3267
+ setError(null);
3268
+ try {
3269
+ const storeName = client.storeIdentifier();
3270
+ const snapshot = await runExclusive(() => (0, import_miden_sdk23.exportStore)(storeName));
3271
+ return snapshot;
3272
+ } catch (err) {
3273
+ const error2 = err instanceof Error ? err : new Error(String(err));
3274
+ setError(error2);
3275
+ throw error2;
3276
+ } finally {
3277
+ setIsExporting(false);
3278
+ }
3279
+ }, [client, isReady, runExclusive]);
3280
+ const reset = (0, import_react24.useCallback)(() => {
3281
+ setIsExporting(false);
3282
+ setError(null);
3283
+ }, []);
3284
+ return {
3285
+ exportStore,
3286
+ isExporting,
3287
+ error,
3288
+ reset
3289
+ };
3290
+ }
3291
+
3292
+ // src/hooks/useImportStore.ts
3293
+ var import_react25 = require("react");
3294
+ var import_miden_sdk24 = require("@miden-sdk/miden-sdk");
3295
+ function useImportStore() {
3296
+ const { client, isReady, runExclusive, sync } = useMiden();
3297
+ const [isImporting, setIsImporting] = (0, import_react25.useState)(false);
3298
+ const [error, setError] = (0, import_react25.useState)(null);
3299
+ const importStore = (0, import_react25.useCallback)(
3300
+ async (storeDump, storeName, options) => {
3301
+ if (!client || !isReady) {
3302
+ throw new Error("Miden client is not ready");
3303
+ }
3304
+ setIsImporting(true);
3305
+ setError(null);
3306
+ try {
3307
+ await runExclusive(() => (0, import_miden_sdk24.importStore)(storeName, storeDump));
3308
+ if (!options?.skipSync) {
3309
+ await sync();
3310
+ }
3311
+ } catch (err) {
3312
+ const error2 = err instanceof Error ? err : new Error(String(err));
3313
+ setError(error2);
3314
+ throw error2;
3315
+ } finally {
3316
+ setIsImporting(false);
3317
+ }
3318
+ },
3319
+ [client, isReady, runExclusive, sync]
3320
+ );
3321
+ const reset = (0, import_react25.useCallback)(() => {
3322
+ setIsImporting(false);
3323
+ setError(null);
3324
+ }, []);
3325
+ return {
3326
+ importStore,
3327
+ isImporting,
3328
+ error,
3329
+ reset
3330
+ };
3331
+ }
3332
+
3333
+ // src/hooks/useImportNote.ts
3334
+ var import_react26 = require("react");
3335
+ var import_miden_sdk25 = require("@miden-sdk/miden-sdk");
3336
+ function useImportNote() {
3337
+ const { client, isReady, runExclusive, sync } = useMiden();
3338
+ const [isImporting, setIsImporting] = (0, import_react26.useState)(false);
3339
+ const [error, setError] = (0, import_react26.useState)(null);
3340
+ const importNote = (0, import_react26.useCallback)(
3341
+ async (noteBytes) => {
3342
+ if (!client || !isReady) {
3343
+ throw new Error("Miden client is not ready");
3344
+ }
3345
+ setIsImporting(true);
3346
+ setError(null);
3347
+ try {
3348
+ const noteFile = import_miden_sdk25.NoteFile.deserialize(noteBytes);
3349
+ const noteId = await runExclusive(
3350
+ () => client.importNoteFile(noteFile)
3351
+ );
3352
+ await sync();
3353
+ return noteId.toString();
3354
+ } catch (err) {
3355
+ const error2 = err instanceof Error ? err : new Error(String(err));
3356
+ setError(error2);
3357
+ throw error2;
3358
+ } finally {
3359
+ setIsImporting(false);
3360
+ }
3361
+ },
3362
+ [client, isReady, runExclusive, sync]
3363
+ );
3364
+ const reset = (0, import_react26.useCallback)(() => {
3365
+ setIsImporting(false);
3366
+ setError(null);
3367
+ }, []);
3368
+ return {
3369
+ importNote,
3370
+ isImporting,
3371
+ error,
3372
+ reset
3373
+ };
3374
+ }
3375
+
3376
+ // src/hooks/useExportNote.ts
3377
+ var import_react27 = require("react");
3378
+ var import_miden_sdk26 = require("@miden-sdk/miden-sdk");
3379
+ function useExportNote() {
3380
+ const { client, isReady, runExclusive } = useMiden();
3381
+ const [isExporting, setIsExporting] = (0, import_react27.useState)(false);
3382
+ const [error, setError] = (0, import_react27.useState)(null);
3383
+ const exportNote = (0, import_react27.useCallback)(
3384
+ async (noteId) => {
3385
+ if (!client || !isReady) {
3386
+ throw new Error("Miden client is not ready");
3387
+ }
3388
+ setIsExporting(true);
3389
+ setError(null);
3390
+ try {
3391
+ const noteFile = await runExclusive(
3392
+ () => client.exportNoteFile(noteId, import_miden_sdk26.NoteExportFormat.Full)
3393
+ );
3394
+ return noteFile.serialize();
3395
+ } catch (err) {
3396
+ const error2 = err instanceof Error ? err : new Error(String(err));
3397
+ setError(error2);
3398
+ throw error2;
3399
+ } finally {
3400
+ setIsExporting(false);
3401
+ }
3402
+ },
3403
+ [client, isReady, runExclusive]
3404
+ );
3405
+ const reset = (0, import_react27.useCallback)(() => {
3406
+ setIsExporting(false);
3407
+ setError(null);
3408
+ }, []);
3409
+ return {
3410
+ exportNote,
3411
+ isExporting,
3412
+ error,
3413
+ reset
3414
+ };
3415
+ }
3416
+
3417
+ // src/hooks/useSyncControl.ts
3418
+ var import_react28 = require("react");
3419
+ function useSyncControl() {
3420
+ const isPaused = useMidenStore((state) => state.syncPaused);
3421
+ const setSyncPaused = useMidenStore((state) => state.setSyncPaused);
3422
+ const pauseSync = (0, import_react28.useCallback)(() => setSyncPaused(true), [setSyncPaused]);
3423
+ const resumeSync = (0, import_react28.useCallback)(() => setSyncPaused(false), [setSyncPaused]);
3424
+ return {
3425
+ pauseSync,
3426
+ resumeSync,
3427
+ isPaused
3428
+ };
3429
+ }
3430
+
2931
3431
  // src/utils/bytes.ts
2932
3432
  function bytesToBigInt(bytes) {
2933
3433
  let result = 0n;
@@ -3083,7 +3583,9 @@ installAccountBech32();
3083
3583
  DEFAULTS,
3084
3584
  MidenError,
3085
3585
  MidenProvider,
3586
+ MultiSignerProvider,
3086
3587
  SignerContext,
3588
+ SignerSlot,
3087
3589
  accountIdsEqual,
3088
3590
  bigIntToBytes,
3089
3591
  bytesToBigInt,
@@ -3105,18 +3607,24 @@ installAccountBech32();
3105
3607
  useConsume,
3106
3608
  useCreateFaucet,
3107
3609
  useCreateWallet,
3610
+ useExecuteProgram,
3611
+ useExportNote,
3612
+ useExportStore,
3108
3613
  useImportAccount,
3109
- useInternalTransfer,
3614
+ useImportNote,
3615
+ useImportStore,
3110
3616
  useMiden,
3111
3617
  useMidenClient,
3112
3618
  useMint,
3113
3619
  useMultiSend,
3620
+ useMultiSigner,
3114
3621
  useNoteStream,
3115
3622
  useNotes,
3116
3623
  useSend,
3117
3624
  useSessionAccount,
3118
3625
  useSigner,
3119
3626
  useSwap,
3627
+ useSyncControl,
3120
3628
  useSyncState,
3121
3629
  useTransaction,
3122
3630
  useTransactionHistory,