@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/CLAUDE.md +2 -2
- package/README.md +111 -3
- package/dist/index.d.mts +328 -113
- package/dist/index.d.ts +328 -113
- package/dist/index.js +1021 -513
- package/dist/index.mjs +1029 -527
- package/package.json +2 -2
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
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
...
|
|
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
|
-
|
|
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
|
|
236
|
-
return value;
|
|
255
|
+
if (typeof value === "string") {
|
|
256
|
+
return parseAccountIdFromString(normalizeAccountIdInput(value));
|
|
237
257
|
}
|
|
238
|
-
|
|
239
|
-
|
|
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 (
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
490
|
+
target,
|
|
439
491
|
normalizeTimeout(config.proverTimeoutMs)
|
|
440
492
|
);
|
|
441
493
|
}
|
|
442
|
-
return createRemoteProver(
|
|
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
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
-
|
|
680
|
+
return cb(pubKey, signingInputs);
|
|
681
|
+
},
|
|
682
|
+
[]
|
|
683
|
+
);
|
|
600
684
|
(0, import_react2.useEffect)(() => {
|
|
601
|
-
if (
|
|
602
|
-
if (
|
|
603
|
-
|
|
604
|
-
|
|
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 &&
|
|
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
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
876
|
+
// src/context/MultiSignerProvider.tsx
|
|
751
877
|
var import_react3 = require("react");
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
var
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
778
|
-
(0,
|
|
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
|
|
1078
|
+
var import_react6 = require("react");
|
|
805
1079
|
|
|
806
1080
|
// src/hooks/useAssetMetadata.ts
|
|
807
|
-
var
|
|
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,
|
|
844
|
-
const uniqueAssetIds = (0,
|
|
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,
|
|
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
|
|
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,
|
|
873
|
-
const [error, setError] = (0,
|
|
874
|
-
const accountIdStr = (0,
|
|
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
|
-
|
|
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,
|
|
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
|
|
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,
|
|
902
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
1237
|
+
return amt.toString();
|
|
969
1238
|
}
|
|
970
1239
|
const factor = 10n ** BigInt(decimals);
|
|
971
|
-
const whole =
|
|
972
|
-
const fraction =
|
|
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
|
|
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,
|
|
1137
|
-
const refetch = (0,
|
|
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
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
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,
|
|
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,
|
|
1441
|
+
(0, import_react7.useEffect)(() => {
|
|
1183
1442
|
if (!isReady || !lastSyncTime) return;
|
|
1184
1443
|
refetch();
|
|
1185
1444
|
}, [isReady, lastSyncTime, refetch]);
|
|
1186
|
-
const noteAssetIds = (0,
|
|
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,
|
|
1457
|
+
const getMetadata = (0, import_react7.useCallback)(
|
|
1199
1458
|
(assetId) => assetMetadata.get(assetId),
|
|
1200
1459
|
[assetMetadata]
|
|
1201
1460
|
);
|
|
1202
|
-
const normalizedSender = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
1351
|
-
const [error, setError] = (0,
|
|
1352
|
-
const handledIdsRef = (0,
|
|
1353
|
-
const [handledVersion, setHandledVersion] = (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,
|
|
1615
|
+
const amountFilterRef = (0, import_react8.useRef)(options.amountFilter);
|
|
1358
1616
|
amountFilterRef.current = options.amountFilter;
|
|
1359
|
-
const excludeIdsKey = (0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
1386
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
1492
|
-
const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
|
|
1747
|
+
const { client, isReady } = useMiden();
|
|
1493
1748
|
const { lastSyncTime } = useSyncStateStore();
|
|
1494
|
-
const [records, setRecords] = (0,
|
|
1495
|
-
const [isLoading, setIsLoading] = (0,
|
|
1496
|
-
const [error, setError] = (0,
|
|
1497
|
-
const rawIds = (0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
1533
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
1606
|
-
const [isCreating, setIsCreating] = (0,
|
|
1607
|
-
const [error, setError] = (0,
|
|
1608
|
-
const createWallet = (0,
|
|
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,
|
|
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
|
|
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,
|
|
1679
|
-
const [isCreating, setIsCreating] = (0,
|
|
1680
|
-
const [error, setError] = (0,
|
|
1681
|
-
const createFaucet = (0,
|
|
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,
|
|
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
|
|
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,
|
|
1751
|
-
const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
|
|
2062
|
+
const { client, isReady, signerConnected } = useMiden();
|
|
1752
2063
|
const setAccounts = useMidenStore((state) => state.setAccounts);
|
|
1753
|
-
const [account, setAccount] = (0,
|
|
1754
|
-
const [isImporting, setIsImporting] = (0,
|
|
1755
|
-
const [error, setError] = (0,
|
|
1756
|
-
const importAccount = (0,
|
|
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
|
|
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 =
|
|
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,
|
|
2161
|
+
[client, isReady, setAccounts, signerConnected]
|
|
1850
2162
|
);
|
|
1851
|
-
const reset = (0,
|
|
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
|
|
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,
|
|
1954
|
-
const [result, setResult] = (0,
|
|
1955
|
-
const [isLoading, setIsLoading] = (0,
|
|
1956
|
-
const [stage, setStage] = (0,
|
|
1957
|
-
const [error, setError] = (0,
|
|
1958
|
-
const send = (0,
|
|
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.
|
|
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
|
|
2044
|
-
|
|
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
|
|
2372
|
+
const sendResult = {
|
|
2373
|
+
txId: txIdString,
|
|
2374
|
+
note: null
|
|
2375
|
+
};
|
|
2075
2376
|
setStage("complete");
|
|
2076
|
-
setResult(
|
|
2377
|
+
setResult(sendResult);
|
|
2077
2378
|
await sync();
|
|
2078
|
-
return
|
|
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,
|
|
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
|
|
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,
|
|
2122
|
-
const
|
|
2123
|
-
const
|
|
2124
|
-
const [
|
|
2125
|
-
const [
|
|
2126
|
-
const [
|
|
2127
|
-
const
|
|
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
|
|
2182
|
-
() => client.executeTransaction(txSenderId, txRequest)
|
|
2183
|
-
);
|
|
2479
|
+
const txResult = await client.executeTransaction(txSenderId, txRequest);
|
|
2184
2480
|
setStage("proving");
|
|
2185
|
-
const
|
|
2186
|
-
|
|
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
|
|
2190
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
2207
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
2547
|
+
var import_miden_sdk18 = require("@miden-sdk/miden-sdk");
|
|
2386
2548
|
function useWaitForCommit() {
|
|
2387
|
-
const { client, isReady
|
|
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
|
|
2402
|
-
|
|
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
|
|
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
|
|
2611
|
+
const consumable = await runExclusiveSafe(
|
|
2455
2612
|
() => client.getConsumableNotes(accountId)
|
|
2456
2613
|
);
|
|
2457
|
-
if (
|
|
2458
|
-
return
|
|
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
|
|
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.
|
|
2553
|
-
throw new Error("No
|
|
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
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
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(
|
|
2979
|
+
setResult(txSummary);
|
|
2729
2980
|
await sync();
|
|
2730
|
-
return
|
|
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,
|
|
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/
|
|
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
|
|
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,
|
|
3119
|
+
const fundRef = (0, import_react23.useRef)(options.fund);
|
|
2787
3120
|
fundRef.current = options.fund;
|
|
2788
|
-
(0,
|
|
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,
|
|
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
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
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,
|
|
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
|
|
3228
|
+
return import_miden_sdk22.AccountStorageMode.private();
|
|
2901
3229
|
case "public":
|
|
2902
|
-
return
|
|
3230
|
+
return import_miden_sdk22.AccountStorageMode.public();
|
|
2903
3231
|
default:
|
|
2904
|
-
return
|
|
3232
|
+
return import_miden_sdk22.AccountStorageMode.public();
|
|
2905
3233
|
}
|
|
2906
3234
|
}
|
|
2907
|
-
async function waitAndConsume(client,
|
|
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
|
|
2912
|
-
() => client.syncState()
|
|
2913
|
-
);
|
|
3239
|
+
await client.syncState();
|
|
2914
3240
|
if (cancelledRef.current) return;
|
|
2915
|
-
const
|
|
2916
|
-
|
|
2917
|
-
|
|
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
|
|
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
|
-
|
|
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,
|