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