@miden-sdk/react 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2214 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULTS: () => DEFAULTS,
24
+ MidenProvider: () => MidenProvider,
25
+ formatAssetAmount: () => formatAssetAmount,
26
+ formatNoteSummary: () => formatNoteSummary,
27
+ getNoteSummary: () => getNoteSummary,
28
+ parseAssetAmount: () => parseAssetAmount,
29
+ toBech32AccountId: () => toBech32AccountId,
30
+ useAccount: () => useAccount,
31
+ useAccounts: () => useAccounts,
32
+ useAssetMetadata: () => useAssetMetadata,
33
+ useConsume: () => useConsume,
34
+ useCreateFaucet: () => useCreateFaucet,
35
+ useCreateWallet: () => useCreateWallet,
36
+ useImportAccount: () => useImportAccount,
37
+ useInternalTransfer: () => useInternalTransfer,
38
+ useMiden: () => useMiden,
39
+ useMidenClient: () => useMidenClient,
40
+ useMint: () => useMint,
41
+ useMultiSend: () => useMultiSend,
42
+ useNotes: () => useNotes,
43
+ useSend: () => useSend,
44
+ useSwap: () => useSwap,
45
+ useSyncState: () => useSyncState,
46
+ useTransaction: () => useTransaction,
47
+ useTransactionHistory: () => useTransactionHistory,
48
+ useWaitForCommit: () => useWaitForCommit,
49
+ useWaitForNotes: () => useWaitForNotes
50
+ });
51
+ module.exports = __toCommonJS(index_exports);
52
+
53
+ // src/types/augmentations.ts
54
+ var import_miden_sdk = require("@miden-sdk/miden-sdk");
55
+
56
+ // src/utils/accountBech32.ts
57
+ var import_miden_sdk3 = require("@miden-sdk/miden-sdk");
58
+
59
+ // src/store/MidenStore.ts
60
+ var import_zustand = require("zustand");
61
+ var initialSyncState = {
62
+ syncHeight: 0,
63
+ isSyncing: false,
64
+ lastSyncTime: null,
65
+ error: null
66
+ };
67
+ var initialState = {
68
+ client: null,
69
+ isReady: false,
70
+ isInitializing: false,
71
+ initError: null,
72
+ config: {},
73
+ sync: initialSyncState,
74
+ accounts: [],
75
+ accountDetails: /* @__PURE__ */ new Map(),
76
+ notes: [],
77
+ consumableNotes: [],
78
+ assetMetadata: /* @__PURE__ */ new Map(),
79
+ isLoadingAccounts: false,
80
+ isLoadingNotes: false
81
+ };
82
+ var useMidenStore = (0, import_zustand.create)()((set) => ({
83
+ ...initialState,
84
+ setClient: (client) => set({
85
+ client,
86
+ isReady: true,
87
+ isInitializing: false,
88
+ initError: null
89
+ }),
90
+ setInitializing: (isInitializing) => set({ isInitializing }),
91
+ setInitError: (initError) => set({
92
+ initError,
93
+ isInitializing: false,
94
+ isReady: false
95
+ }),
96
+ setConfig: (config) => set({ config }),
97
+ setSyncState: (sync) => set((state) => ({
98
+ sync: { ...state.sync, ...sync }
99
+ })),
100
+ setAccounts: (accounts) => set({ accounts }),
101
+ setAccountDetails: (accountId, account) => set((state) => {
102
+ const newMap = new Map(state.accountDetails);
103
+ newMap.set(accountId, account);
104
+ return { accountDetails: newMap };
105
+ }),
106
+ setNotes: (notes) => set({ notes }),
107
+ setConsumableNotes: (consumableNotes) => set({ consumableNotes }),
108
+ setAssetMetadata: (assetId, metadata) => set((state) => {
109
+ const newMap = new Map(state.assetMetadata);
110
+ newMap.set(assetId, metadata);
111
+ return { assetMetadata: newMap };
112
+ }),
113
+ setLoadingAccounts: (isLoadingAccounts) => set({ isLoadingAccounts }),
114
+ setLoadingNotes: (isLoadingNotes) => set({ isLoadingNotes }),
115
+ reset: () => set(initialState)
116
+ }));
117
+ var useSyncStateStore = () => useMidenStore((state) => state.sync);
118
+ var useAccountsStore = () => useMidenStore((state) => state.accounts);
119
+ var useNotesStore = () => useMidenStore((state) => state.notes);
120
+ var useConsumableNotesStore = () => useMidenStore((state) => state.consumableNotes);
121
+ var useAssetMetadataStore = () => useMidenStore((state) => state.assetMetadata);
122
+
123
+ // src/utils/accountParsing.ts
124
+ var import_miden_sdk2 = require("@miden-sdk/miden-sdk");
125
+ var normalizeAccountIdInput = (value) => value.trim().replace(/^miden:/i, "");
126
+ var isBech32Input = (value) => value.startsWith("m") || value.startsWith("M");
127
+ var normalizeHexInput = (value) => value.startsWith("0x") || value.startsWith("0X") ? value : `0x${value}`;
128
+ var parseAccountIdFromString = (value) => {
129
+ if (isBech32Input(value)) {
130
+ try {
131
+ return import_miden_sdk2.Address.fromBech32(value).accountId();
132
+ } catch {
133
+ return import_miden_sdk2.AccountId.fromBech32(value);
134
+ }
135
+ }
136
+ return import_miden_sdk2.AccountId.fromHex(normalizeHexInput(value));
137
+ };
138
+ var parseAccountId = (value) => {
139
+ if (typeof value !== "string") {
140
+ return value;
141
+ }
142
+ const normalized = normalizeAccountIdInput(value);
143
+ return parseAccountIdFromString(normalized);
144
+ };
145
+ var parseAddress = (value, accountId) => {
146
+ const normalized = normalizeAccountIdInput(value);
147
+ if (isBech32Input(normalized)) {
148
+ try {
149
+ return import_miden_sdk2.Address.fromBech32(normalized);
150
+ } catch {
151
+ const resolvedAccountId2 = accountId ?? import_miden_sdk2.AccountId.fromBech32(normalized);
152
+ return import_miden_sdk2.Address.fromAccountId(resolvedAccountId2, "BasicWallet");
153
+ }
154
+ }
155
+ const resolvedAccountId = accountId ?? import_miden_sdk2.AccountId.fromHex(normalizeHexInput(normalized));
156
+ return import_miden_sdk2.Address.fromAccountId(resolvedAccountId, "BasicWallet");
157
+ };
158
+
159
+ // src/utils/accountBech32.ts
160
+ var inferNetworkId = () => {
161
+ const { rpcUrl } = useMidenStore.getState().config;
162
+ if (!rpcUrl) {
163
+ return import_miden_sdk3.NetworkId.testnet();
164
+ }
165
+ const url = rpcUrl.toLowerCase();
166
+ if (url.includes("devnet") || url.includes("mdev")) {
167
+ return import_miden_sdk3.NetworkId.devnet();
168
+ }
169
+ if (url.includes("mainnet")) {
170
+ return import_miden_sdk3.NetworkId.mainnet();
171
+ }
172
+ if (url.includes("testnet") || url.includes("mtst")) {
173
+ return import_miden_sdk3.NetworkId.testnet();
174
+ }
175
+ return import_miden_sdk3.NetworkId.testnet();
176
+ };
177
+ var toBech32FromAccountId = (id) => {
178
+ try {
179
+ const address = import_miden_sdk3.Address.fromAccountId(id, "BasicWallet");
180
+ return address.toBech32(inferNetworkId());
181
+ } catch {
182
+ }
183
+ try {
184
+ const maybeBech32 = id.toBech32?.(
185
+ inferNetworkId(),
186
+ import_miden_sdk3.AccountInterface.BasicWallet
187
+ );
188
+ if (typeof maybeBech32 === "string") {
189
+ return maybeBech32;
190
+ }
191
+ } catch {
192
+ }
193
+ return id.toString();
194
+ };
195
+ var defineBech32 = (target) => {
196
+ try {
197
+ Object.defineProperty(target, "bech32id", {
198
+ value: function bech32id() {
199
+ try {
200
+ const id = this.id?.();
201
+ if (id) {
202
+ return toBech32FromAccountId(id);
203
+ }
204
+ } catch {
205
+ }
206
+ const fallback = typeof this.toString === "function" ? this.toString() : "";
207
+ return fallback ? toBech32AccountId(fallback) : "";
208
+ }
209
+ });
210
+ return true;
211
+ } catch {
212
+ return false;
213
+ }
214
+ };
215
+ var installAccountBech32 = () => {
216
+ const proto = import_miden_sdk3.Account.prototype;
217
+ if (proto.bech32id) {
218
+ return;
219
+ }
220
+ defineBech32(proto);
221
+ };
222
+ var ensureAccountBech32 = (account) => {
223
+ if (!account) {
224
+ return;
225
+ }
226
+ if (typeof account.bech32id === "function") {
227
+ return;
228
+ }
229
+ const proto = Object.getPrototypeOf(account);
230
+ if (proto?.bech32id) {
231
+ return;
232
+ }
233
+ if (proto && defineBech32(proto)) {
234
+ return;
235
+ }
236
+ defineBech32(account);
237
+ };
238
+ var toBech32AccountId = (accountId) => {
239
+ try {
240
+ const id = parseAccountId(accountId);
241
+ return toBech32FromAccountId(id);
242
+ } catch {
243
+ return accountId;
244
+ }
245
+ };
246
+
247
+ // src/context/MidenProvider.tsx
248
+ var import_react = require("react");
249
+ var import_miden_sdk5 = require("@miden-sdk/miden-sdk");
250
+
251
+ // src/types/index.ts
252
+ var DEFAULTS = {
253
+ RPC_URL: void 0,
254
+ // Will use SDK's testnet default
255
+ AUTO_SYNC_INTERVAL: 15e3,
256
+ STORAGE_MODE: "private",
257
+ WALLET_MUTABLE: true,
258
+ AUTH_SCHEME: 0,
259
+ NOTE_TYPE: "private",
260
+ FAUCET_DECIMALS: 8
261
+ };
262
+
263
+ // src/utils/asyncLock.ts
264
+ var AsyncLock = class {
265
+ constructor() {
266
+ this.pending = Promise.resolve();
267
+ }
268
+ runExclusive(fn) {
269
+ const run = this.pending.then(fn, fn);
270
+ this.pending = run.then(
271
+ () => void 0,
272
+ () => void 0
273
+ );
274
+ return run;
275
+ }
276
+ };
277
+
278
+ // src/utils/network.ts
279
+ var RPC_URLS = {
280
+ testnet: "https://rpc.testnet.miden.io",
281
+ devnet: "https://rpc.devnet.miden.io",
282
+ localhost: "http://localhost:57291"
283
+ };
284
+ function resolveRpcUrl(rpcUrl) {
285
+ if (!rpcUrl) {
286
+ return void 0;
287
+ }
288
+ const normalized = rpcUrl.trim().toLowerCase();
289
+ if (normalized === "testnet") {
290
+ return RPC_URLS.testnet;
291
+ }
292
+ if (normalized === "devnet") {
293
+ return RPC_URLS.devnet;
294
+ }
295
+ if (normalized === "localhost" || normalized === "local") {
296
+ return RPC_URLS.localhost;
297
+ }
298
+ return rpcUrl;
299
+ }
300
+
301
+ // src/utils/prover.ts
302
+ var import_miden_sdk4 = require("@miden-sdk/miden-sdk");
303
+ var DEFAULT_PROVER_URLS = {
304
+ devnet: "https://tx-prover.devnet.miden.io",
305
+ testnet: "https://tx-prover.testnet.miden.io"
306
+ };
307
+ function resolveTransactionProver(config) {
308
+ const { prover } = config;
309
+ if (!prover) {
310
+ return null;
311
+ }
312
+ if (typeof prover === "string") {
313
+ const normalized = prover.trim().toLowerCase();
314
+ if (normalized === "local") {
315
+ return import_miden_sdk4.TransactionProver.newLocalProver();
316
+ }
317
+ if (normalized === "devnet" || normalized === "testnet") {
318
+ const url = config.proverUrls?.[normalized] ?? DEFAULT_PROVER_URLS[normalized] ?? null;
319
+ if (!url) {
320
+ throw new Error(`Missing ${normalized} prover URL`);
321
+ }
322
+ return import_miden_sdk4.TransactionProver.newRemoteProver(
323
+ url,
324
+ normalizeTimeout(config.proverTimeoutMs)
325
+ );
326
+ }
327
+ return import_miden_sdk4.TransactionProver.newRemoteProver(
328
+ prover,
329
+ normalizeTimeout(config.proverTimeoutMs)
330
+ );
331
+ }
332
+ return createRemoteProver(prover, config.proverTimeoutMs);
333
+ }
334
+ function createRemoteProver(config, fallbackTimeout) {
335
+ const { url, timeoutMs } = config;
336
+ if (!url) {
337
+ throw new Error("Remote prover requires a URL");
338
+ }
339
+ return import_miden_sdk4.TransactionProver.newRemoteProver(
340
+ url,
341
+ normalizeTimeout(timeoutMs ?? fallbackTimeout)
342
+ );
343
+ }
344
+ function normalizeTimeout(timeoutMs) {
345
+ if (timeoutMs === void 0) {
346
+ return void 0;
347
+ }
348
+ if (timeoutMs === null) {
349
+ return null;
350
+ }
351
+ return typeof timeoutMs === "bigint" ? timeoutMs : BigInt(timeoutMs);
352
+ }
353
+
354
+ // src/context/MidenProvider.tsx
355
+ var import_jsx_runtime = require("react/jsx-runtime");
356
+ var MidenContext = (0, import_react.createContext)(null);
357
+ function MidenProvider({
358
+ children,
359
+ config = {},
360
+ loadingComponent,
361
+ errorComponent
362
+ }) {
363
+ const {
364
+ client,
365
+ isReady,
366
+ isInitializing,
367
+ initError,
368
+ setClient,
369
+ setInitializing,
370
+ setInitError,
371
+ setConfig,
372
+ setSyncState
373
+ } = useMidenStore();
374
+ const syncIntervalRef = (0, import_react.useRef)(null);
375
+ const isInitializedRef = (0, import_react.useRef)(false);
376
+ const clientLockRef = (0, import_react.useRef)(new AsyncLock());
377
+ const resolvedConfig = (0, import_react.useMemo)(
378
+ () => ({
379
+ ...config,
380
+ rpcUrl: resolveRpcUrl(config.rpcUrl)
381
+ }),
382
+ [config]
383
+ );
384
+ const defaultProver = (0, import_react.useMemo)(
385
+ () => resolveTransactionProver(resolvedConfig),
386
+ [
387
+ resolvedConfig.prover,
388
+ resolvedConfig.proverTimeoutMs,
389
+ resolvedConfig.proverUrls?.devnet,
390
+ resolvedConfig.proverUrls?.testnet
391
+ ]
392
+ );
393
+ const runExclusive = (0, import_react.useCallback)(
394
+ async (fn) => clientLockRef.current.runExclusive(fn),
395
+ []
396
+ );
397
+ const sync = (0, import_react.useCallback)(async () => {
398
+ if (!client || !isReady) return;
399
+ const store = useMidenStore.getState();
400
+ if (store.sync.isSyncing) return;
401
+ setSyncState({ isSyncing: true, error: null });
402
+ await runExclusive(async () => {
403
+ try {
404
+ const summary = await client.syncState();
405
+ const syncHeight = summary.blockNum();
406
+ setSyncState({
407
+ syncHeight,
408
+ isSyncing: false,
409
+ lastSyncTime: Date.now(),
410
+ error: null
411
+ });
412
+ const accounts = await client.getAccounts();
413
+ useMidenStore.getState().setAccounts(accounts);
414
+ } catch (error) {
415
+ setSyncState({
416
+ isSyncing: false,
417
+ error: error instanceof Error ? error : new Error(String(error))
418
+ });
419
+ }
420
+ });
421
+ }, [client, isReady, runExclusive, setSyncState]);
422
+ (0, import_react.useEffect)(() => {
423
+ if (isInitializedRef.current) return;
424
+ isInitializedRef.current = true;
425
+ const initClient = async () => {
426
+ setInitializing(true);
427
+ setConfig(resolvedConfig);
428
+ try {
429
+ const seed = resolvedConfig.seed;
430
+ const webClient = await import_miden_sdk5.WebClient.createClient(
431
+ resolvedConfig.rpcUrl,
432
+ resolvedConfig.noteTransportUrl,
433
+ seed
434
+ );
435
+ setClient(webClient);
436
+ try {
437
+ const summary = await runExclusive(() => webClient.syncState());
438
+ setSyncState({
439
+ syncHeight: summary.blockNum(),
440
+ lastSyncTime: Date.now()
441
+ });
442
+ } catch {
443
+ }
444
+ } catch (error) {
445
+ setInitError(error instanceof Error ? error : new Error(String(error)));
446
+ }
447
+ };
448
+ initClient();
449
+ }, [
450
+ runExclusive,
451
+ resolvedConfig,
452
+ setClient,
453
+ setConfig,
454
+ setInitError,
455
+ setInitializing,
456
+ setSyncState
457
+ ]);
458
+ (0, import_react.useEffect)(() => {
459
+ if (!isReady || !client) return;
460
+ const interval = config.autoSyncInterval ?? DEFAULTS.AUTO_SYNC_INTERVAL;
461
+ if (interval <= 0) return;
462
+ syncIntervalRef.current = setInterval(() => {
463
+ sync();
464
+ }, interval);
465
+ return () => {
466
+ if (syncIntervalRef.current) {
467
+ clearInterval(syncIntervalRef.current);
468
+ syncIntervalRef.current = null;
469
+ }
470
+ };
471
+ }, [isReady, client, config.autoSyncInterval, sync]);
472
+ if (isInitializing && loadingComponent) {
473
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: loadingComponent });
474
+ }
475
+ if (initError && errorComponent) {
476
+ if (typeof errorComponent === "function") {
477
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: errorComponent(initError) });
478
+ }
479
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: errorComponent });
480
+ }
481
+ const contextValue = {
482
+ client,
483
+ isReady,
484
+ isInitializing,
485
+ error: initError,
486
+ sync,
487
+ runExclusive,
488
+ prover: defaultProver
489
+ };
490
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MidenContext.Provider, { value: contextValue, children });
491
+ }
492
+ function useMiden() {
493
+ const context = (0, import_react.useContext)(MidenContext);
494
+ if (!context) {
495
+ throw new Error("useMiden must be used within a MidenProvider");
496
+ }
497
+ return context;
498
+ }
499
+ function useMidenClient() {
500
+ const { client, isReady } = useMiden();
501
+ if (!client || !isReady) {
502
+ throw new Error(
503
+ "Miden client is not ready. Make sure you are inside a MidenProvider and the client has initialized."
504
+ );
505
+ }
506
+ return client;
507
+ }
508
+
509
+ // src/hooks/useAccounts.ts
510
+ var import_react2 = require("react");
511
+
512
+ // src/utils/runExclusive.ts
513
+ var runExclusiveDirect = async (fn) => fn();
514
+
515
+ // src/hooks/useAccounts.ts
516
+ function useAccounts() {
517
+ const { client, isReady, runExclusive } = useMiden();
518
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
519
+ const accounts = useAccountsStore();
520
+ const isLoadingAccounts = useMidenStore((state) => state.isLoadingAccounts);
521
+ const setLoadingAccounts = useMidenStore((state) => state.setLoadingAccounts);
522
+ const setAccounts = useMidenStore((state) => state.setAccounts);
523
+ const refetch = (0, import_react2.useCallback)(async () => {
524
+ if (!client || !isReady) return;
525
+ setLoadingAccounts(true);
526
+ try {
527
+ const fetchedAccounts = await runExclusiveSafe(
528
+ () => client.getAccounts()
529
+ );
530
+ setAccounts(fetchedAccounts);
531
+ } catch (error) {
532
+ console.error("Failed to fetch accounts:", error);
533
+ } finally {
534
+ setLoadingAccounts(false);
535
+ }
536
+ }, [client, isReady, runExclusive, setAccounts, setLoadingAccounts]);
537
+ (0, import_react2.useEffect)(() => {
538
+ if (isReady && accounts.length === 0) {
539
+ refetch();
540
+ }
541
+ }, [isReady, accounts.length, refetch]);
542
+ const wallets = [];
543
+ const faucets = [];
544
+ for (const account of accounts) {
545
+ const accountId = account.id();
546
+ if (isFaucetId(accountId)) {
547
+ faucets.push(account);
548
+ } else {
549
+ wallets.push(account);
550
+ }
551
+ }
552
+ return {
553
+ accounts,
554
+ wallets,
555
+ faucets,
556
+ isLoading: isLoadingAccounts,
557
+ error: null,
558
+ refetch
559
+ };
560
+ }
561
+ function isFaucetId(accountId) {
562
+ try {
563
+ const hex = typeof accountId.toHex === "function" ? accountId.toHex() : String(accountId);
564
+ const firstByte = parseInt(hex.slice(0, 2), 16);
565
+ const accountType = firstByte >> 4 & 3;
566
+ return accountType === 2 || accountType === 3;
567
+ } catch {
568
+ return false;
569
+ }
570
+ }
571
+
572
+ // src/hooks/useAccount.ts
573
+ var import_react4 = require("react");
574
+
575
+ // src/hooks/useAssetMetadata.ts
576
+ var import_react3 = require("react");
577
+ var import_miden_sdk6 = require("@miden-sdk/miden-sdk");
578
+ var inflight = /* @__PURE__ */ new Map();
579
+ var rpcClients = /* @__PURE__ */ new Map();
580
+ var getRpcClient = (rpcUrl) => {
581
+ const key = rpcUrl ?? "__default__";
582
+ const existing = rpcClients.get(key);
583
+ if (existing) return existing;
584
+ try {
585
+ const endpoint = rpcUrl ? new import_miden_sdk6.Endpoint(rpcUrl) : import_miden_sdk6.Endpoint.testnet();
586
+ const client = new import_miden_sdk6.RpcClient(endpoint);
587
+ rpcClients.set(key, client);
588
+ return client;
589
+ } catch {
590
+ return null;
591
+ }
592
+ };
593
+ var fetchAssetMetadata = async (client, rpcClient, assetId) => {
594
+ try {
595
+ const accountId = parseAccountId(assetId);
596
+ let account = await client.getAccount(accountId);
597
+ if (!account && rpcClient) {
598
+ try {
599
+ const fetched = await rpcClient.getAccountDetails(accountId);
600
+ account = fetched.account?.();
601
+ } catch {
602
+ }
603
+ }
604
+ if (!account) return null;
605
+ const faucet = import_miden_sdk6.BasicFungibleFaucetComponent.fromAccount(account);
606
+ const symbol = faucet.symbol().toString();
607
+ const decimals = faucet.decimals();
608
+ return { assetId, symbol, decimals };
609
+ } catch {
610
+ return null;
611
+ }
612
+ };
613
+ function useAssetMetadata(assetIds = []) {
614
+ const { client, isReady, runExclusive } = useMiden();
615
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
616
+ const assetMetadata = useAssetMetadataStore();
617
+ const setAssetMetadata = useMidenStore((state) => state.setAssetMetadata);
618
+ const rpcUrl = useMidenStore((state) => state.config.rpcUrl);
619
+ const rpcClient = (0, import_react3.useMemo)(() => getRpcClient(rpcUrl), [rpcUrl]);
620
+ const uniqueAssetIds = (0, import_react3.useMemo)(
621
+ () => Array.from(new Set(assetIds.filter(Boolean))),
622
+ [assetIds]
623
+ );
624
+ (0, import_react3.useEffect)(() => {
625
+ if (!client || !isReady || uniqueAssetIds.length === 0) return;
626
+ uniqueAssetIds.forEach((assetId) => {
627
+ const existing = assetMetadata.get(assetId);
628
+ const hasMetadata = existing?.symbol !== void 0 || existing?.decimals !== void 0;
629
+ if (hasMetadata || inflight.has(assetId)) return;
630
+ const promise = runExclusiveSafe(async () => {
631
+ const metadata = await fetchAssetMetadata(
632
+ client,
633
+ rpcClient,
634
+ assetId
635
+ );
636
+ setAssetMetadata(assetId, metadata ?? { assetId });
637
+ }).finally(() => {
638
+ inflight.delete(assetId);
639
+ });
640
+ inflight.set(assetId, promise);
641
+ });
642
+ }, [
643
+ client,
644
+ isReady,
645
+ uniqueAssetIds,
646
+ assetMetadata,
647
+ runExclusiveSafe,
648
+ setAssetMetadata,
649
+ rpcClient
650
+ ]);
651
+ return { assetMetadata };
652
+ }
653
+
654
+ // src/hooks/useAccount.ts
655
+ function useAccount(accountId) {
656
+ const { client, isReady, runExclusive } = useMiden();
657
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
658
+ const accountDetails = useMidenStore((state) => state.accountDetails);
659
+ const setAccountDetails = useMidenStore((state) => state.setAccountDetails);
660
+ const { lastSyncTime } = useSyncStateStore();
661
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
662
+ const [error, setError] = (0, import_react4.useState)(null);
663
+ const accountIdStr = (0, import_react4.useMemo)(() => {
664
+ if (!accountId) return void 0;
665
+ if (typeof accountId === "string") return accountId;
666
+ if (typeof accountId.toString === "function") {
667
+ return accountId.toString();
668
+ }
669
+ return String(accountId);
670
+ }, [accountId]);
671
+ const account = accountIdStr ? accountDetails.get(accountIdStr) ?? null : null;
672
+ const refetch = (0, import_react4.useCallback)(async () => {
673
+ if (!client || !isReady || !accountIdStr) return;
674
+ setIsLoading(true);
675
+ setError(null);
676
+ try {
677
+ const accountIdObj = parseAccountId(accountIdStr);
678
+ const fetchedAccount = await runExclusiveSafe(
679
+ () => client.getAccount(accountIdObj)
680
+ );
681
+ if (fetchedAccount) {
682
+ ensureAccountBech32(fetchedAccount);
683
+ setAccountDetails(accountIdStr, fetchedAccount);
684
+ }
685
+ } catch (err) {
686
+ setError(err instanceof Error ? err : new Error(String(err)));
687
+ } finally {
688
+ setIsLoading(false);
689
+ }
690
+ }, [client, isReady, runExclusive, accountIdStr, setAccountDetails]);
691
+ (0, import_react4.useEffect)(() => {
692
+ if (isReady && accountIdStr && !account) {
693
+ refetch();
694
+ }
695
+ }, [isReady, accountIdStr, account, refetch]);
696
+ (0, import_react4.useEffect)(() => {
697
+ if (!isReady || !accountIdStr || !lastSyncTime) return;
698
+ refetch();
699
+ }, [isReady, accountIdStr, lastSyncTime, refetch]);
700
+ const rawAssets = (0, import_react4.useMemo)(() => {
701
+ if (!account) return [];
702
+ try {
703
+ const vault = account.vault();
704
+ const assetsList = [];
705
+ const vaultAssets = vault.fungibleAssets();
706
+ for (const asset of vaultAssets) {
707
+ assetsList.push({
708
+ assetId: asset.faucetId().toString(),
709
+ amount: asset.amount()
710
+ });
711
+ }
712
+ return assetsList;
713
+ } catch {
714
+ return [];
715
+ }
716
+ }, [account]);
717
+ const assetIds = (0, import_react4.useMemo)(
718
+ () => rawAssets.map((asset) => asset.assetId),
719
+ [rawAssets]
720
+ );
721
+ const { assetMetadata } = useAssetMetadata(assetIds);
722
+ const assets = (0, import_react4.useMemo)(
723
+ () => rawAssets.map((asset) => {
724
+ const metadata = assetMetadata.get(asset.assetId);
725
+ return {
726
+ ...asset,
727
+ symbol: metadata?.symbol,
728
+ decimals: metadata?.decimals
729
+ };
730
+ }),
731
+ [rawAssets, assetMetadata]
732
+ );
733
+ const getBalance = (0, import_react4.useCallback)(
734
+ (assetId) => {
735
+ const asset = assets.find((a) => a.assetId === assetId);
736
+ return asset?.amount ?? 0n;
737
+ },
738
+ [assets]
739
+ );
740
+ return {
741
+ account,
742
+ assets,
743
+ isLoading,
744
+ error,
745
+ refetch,
746
+ getBalance
747
+ };
748
+ }
749
+
750
+ // src/hooks/useNotes.ts
751
+ var import_react5 = require("react");
752
+ var import_miden_sdk7 = require("@miden-sdk/miden-sdk");
753
+
754
+ // src/utils/amounts.ts
755
+ var formatAssetAmount = (amount, decimals) => {
756
+ if (!decimals || decimals <= 0) {
757
+ return amount.toString();
758
+ }
759
+ const factor = 10n ** BigInt(decimals);
760
+ const whole = amount / factor;
761
+ const fraction = amount % factor;
762
+ if (fraction === 0n) {
763
+ return whole.toString();
764
+ }
765
+ const fractionText = fraction.toString().padStart(decimals, "0").replace(/0+$/, "");
766
+ return `${whole.toString()}.${fractionText}`;
767
+ };
768
+ var parseAssetAmount = (input, decimals) => {
769
+ const value = input.trim();
770
+ if (!value) {
771
+ throw new Error("Amount is required");
772
+ }
773
+ if (!decimals || decimals <= 0) {
774
+ if (value.includes(".")) {
775
+ throw new Error("Amount must be a whole number");
776
+ }
777
+ return BigInt(value);
778
+ }
779
+ const [wholeText, fractionText = ""] = value.split(".");
780
+ if (value.split(".").length > 2) {
781
+ throw new Error("Amount has too many decimal points");
782
+ }
783
+ const normalizedWhole = wholeText.length ? wholeText : "0";
784
+ if (fractionText.length > decimals) {
785
+ throw new Error("Amount has too many decimal places");
786
+ }
787
+ const paddedFraction = fractionText.padEnd(decimals, "0");
788
+ const factor = 10n ** BigInt(decimals);
789
+ return BigInt(normalizedWhole) * factor + BigInt(paddedFraction || "0");
790
+ };
791
+
792
+ // src/utils/notes.ts
793
+ var getInputNoteRecord = (note) => {
794
+ const maybeConsumable = note;
795
+ if (typeof maybeConsumable.inputNoteRecord === "function") {
796
+ return maybeConsumable.inputNoteRecord();
797
+ }
798
+ return note;
799
+ };
800
+ var getNoteSummary = (note, getAssetMetadata) => {
801
+ try {
802
+ const record = getInputNoteRecord(note);
803
+ const id = record.id().toString();
804
+ const assets = [];
805
+ try {
806
+ const details = record.details();
807
+ const assetsList = details?.assets?.().fungibleAssets?.() ?? [];
808
+ for (const asset of assetsList) {
809
+ const assetId = asset.faucetId().toString();
810
+ const metadata2 = getAssetMetadata?.(assetId);
811
+ assets.push({
812
+ assetId,
813
+ amount: BigInt(asset.amount()),
814
+ symbol: metadata2?.symbol,
815
+ decimals: metadata2?.decimals
816
+ });
817
+ }
818
+ } catch {
819
+ }
820
+ const metadata = record.metadata?.();
821
+ const senderHex = metadata?.sender?.()?.toString?.();
822
+ const sender = senderHex ? toBech32AccountId(senderHex) : void 0;
823
+ return { id, assets, sender };
824
+ } catch {
825
+ return null;
826
+ }
827
+ };
828
+ var formatNoteSummary = (summary, formatAsset = (asset) => `${formatAssetAmount(asset.amount, asset.decimals)} ${asset.symbol ?? asset.assetId}`) => {
829
+ if (!summary.assets.length) {
830
+ return summary.id;
831
+ }
832
+ const assetsText = summary.assets.map(formatAsset).join(" + ");
833
+ return summary.sender ? `${assetsText} from ${summary.sender}` : assetsText;
834
+ };
835
+
836
+ // src/hooks/useNotes.ts
837
+ function useNotes(options) {
838
+ const { client, isReady, runExclusive } = useMiden();
839
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
840
+ const notes = useNotesStore();
841
+ const consumableNotes = useConsumableNotesStore();
842
+ const isLoadingNotes = useMidenStore((state) => state.isLoadingNotes);
843
+ const setLoadingNotes = useMidenStore((state) => state.setLoadingNotes);
844
+ const setNotes = useMidenStore((state) => state.setNotes);
845
+ const setConsumableNotes = useMidenStore((state) => state.setConsumableNotes);
846
+ const { lastSyncTime } = useSyncStateStore();
847
+ const [error, setError] = (0, import_react5.useState)(null);
848
+ const refetch = (0, import_react5.useCallback)(async () => {
849
+ if (!client || !isReady) return;
850
+ setLoadingNotes(true);
851
+ setError(null);
852
+ try {
853
+ const { fetchedNotes, fetchedConsumable } = await runExclusiveSafe(
854
+ async () => {
855
+ const filterType = getNoteFilterType(options?.status);
856
+ const filter = new import_miden_sdk7.NoteFilter(filterType);
857
+ const notesResult = await client.getInputNotes(filter);
858
+ let consumableResult;
859
+ if (options?.accountId) {
860
+ const accountIdObj = parseAccountId(options.accountId);
861
+ consumableResult = await client.getConsumableNotes(accountIdObj);
862
+ } else {
863
+ consumableResult = await client.getConsumableNotes();
864
+ }
865
+ return {
866
+ fetchedNotes: notesResult,
867
+ fetchedConsumable: consumableResult
868
+ };
869
+ }
870
+ );
871
+ setNotes(fetchedNotes);
872
+ setConsumableNotes(fetchedConsumable);
873
+ } catch (err) {
874
+ setError(err instanceof Error ? err : new Error(String(err)));
875
+ } finally {
876
+ setLoadingNotes(false);
877
+ }
878
+ }, [
879
+ client,
880
+ isReady,
881
+ runExclusive,
882
+ options?.status,
883
+ options?.accountId,
884
+ setLoadingNotes,
885
+ setNotes,
886
+ setConsumableNotes
887
+ ]);
888
+ (0, import_react5.useEffect)(() => {
889
+ if (isReady && notes.length === 0) {
890
+ refetch();
891
+ }
892
+ }, [isReady, notes.length, refetch]);
893
+ (0, import_react5.useEffect)(() => {
894
+ if (!isReady || !lastSyncTime) return;
895
+ refetch();
896
+ }, [isReady, lastSyncTime, refetch]);
897
+ const noteAssetIds = (0, import_react5.useMemo)(() => {
898
+ const ids = /* @__PURE__ */ new Set();
899
+ const collect = (note) => {
900
+ const summary = getNoteSummary(note);
901
+ if (!summary) return;
902
+ summary.assets.forEach((asset) => ids.add(asset.assetId));
903
+ };
904
+ notes.forEach(collect);
905
+ consumableNotes.forEach(collect);
906
+ return Array.from(ids);
907
+ }, [notes, consumableNotes]);
908
+ const { assetMetadata } = useAssetMetadata(noteAssetIds);
909
+ const getMetadata = (0, import_react5.useCallback)(
910
+ (assetId) => assetMetadata.get(assetId),
911
+ [assetMetadata]
912
+ );
913
+ const noteSummaries = (0, import_react5.useMemo)(
914
+ () => notes.map((note) => getNoteSummary(note, getMetadata)).filter(Boolean),
915
+ [notes, getMetadata]
916
+ );
917
+ const consumableNoteSummaries = (0, import_react5.useMemo)(
918
+ () => consumableNotes.map((note) => getNoteSummary(note, getMetadata)).filter(Boolean),
919
+ [consumableNotes, getMetadata]
920
+ );
921
+ return {
922
+ notes,
923
+ consumableNotes,
924
+ noteSummaries,
925
+ consumableNoteSummaries,
926
+ isLoading: isLoadingNotes,
927
+ error,
928
+ refetch
929
+ };
930
+ }
931
+ function getNoteFilterType(status) {
932
+ switch (status) {
933
+ case "consumed":
934
+ return import_miden_sdk7.NoteFilterTypes.Consumed;
935
+ case "committed":
936
+ return import_miden_sdk7.NoteFilterTypes.Committed;
937
+ case "expected":
938
+ return import_miden_sdk7.NoteFilterTypes.Expected;
939
+ case "processing":
940
+ return import_miden_sdk7.NoteFilterTypes.Processing;
941
+ case "all":
942
+ default:
943
+ return import_miden_sdk7.NoteFilterTypes.All;
944
+ }
945
+ }
946
+
947
+ // src/hooks/useTransactionHistory.ts
948
+ var import_react6 = require("react");
949
+ var import_miden_sdk8 = require("@miden-sdk/miden-sdk");
950
+ function useTransactionHistory(options = {}) {
951
+ const { client, isReady, runExclusive } = useMiden();
952
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
953
+ const { lastSyncTime } = useSyncStateStore();
954
+ const [records, setRecords] = (0, import_react6.useState)([]);
955
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
956
+ const [error, setError] = (0, import_react6.useState)(null);
957
+ const rawIds = (0, import_react6.useMemo)(() => {
958
+ if (options.id) return [options.id];
959
+ if (options.ids && options.ids.length > 0) return options.ids;
960
+ return null;
961
+ }, [options.id, options.ids]);
962
+ const idsHex = (0, import_react6.useMemo)(() => {
963
+ if (!rawIds) return null;
964
+ return rawIds.map(
965
+ (id) => normalizeHex(typeof id === "string" ? id : id.toHex())
966
+ );
967
+ }, [rawIds]);
968
+ const filter = options.filter;
969
+ const refreshOnSync = options.refreshOnSync !== false;
970
+ const refetch = (0, import_react6.useCallback)(async () => {
971
+ if (!client || !isReady) return;
972
+ setIsLoading(true);
973
+ setError(null);
974
+ try {
975
+ const { filter: resolvedFilter, localFilterHexes } = buildFilter(
976
+ filter,
977
+ rawIds,
978
+ idsHex
979
+ );
980
+ const fetched = await runExclusiveSafe(
981
+ () => client.getTransactions(resolvedFilter)
982
+ );
983
+ const filtered = localFilterHexes ? fetched.filter(
984
+ (record2) => localFilterHexes.includes(normalizeHex(record2.id().toHex()))
985
+ ) : fetched;
986
+ setRecords(filtered);
987
+ } catch (err) {
988
+ setError(err instanceof Error ? err : new Error(String(err)));
989
+ } finally {
990
+ setIsLoading(false);
991
+ }
992
+ }, [client, isReady, runExclusiveSafe, filter, rawIds, idsHex]);
993
+ (0, import_react6.useEffect)(() => {
994
+ if (!isReady) return;
995
+ refetch();
996
+ }, [isReady, refetch]);
997
+ (0, import_react6.useEffect)(() => {
998
+ if (!isReady || !refreshOnSync || !lastSyncTime) return;
999
+ refetch();
1000
+ }, [isReady, lastSyncTime, refreshOnSync, refetch]);
1001
+ const record = (0, import_react6.useMemo)(() => {
1002
+ if (!idsHex || idsHex.length !== 1) return null;
1003
+ return records.find((item) => normalizeHex(item.id().toHex()) === idsHex[0]) ?? null;
1004
+ }, [records, idsHex]);
1005
+ const status = (0, import_react6.useMemo)(() => {
1006
+ if (!record) return null;
1007
+ const current = record.transactionStatus();
1008
+ if (current.isCommitted()) return "committed";
1009
+ if (current.isDiscarded()) return "discarded";
1010
+ if (current.isPending()) return "pending";
1011
+ return null;
1012
+ }, [record]);
1013
+ return {
1014
+ records,
1015
+ record,
1016
+ status,
1017
+ isLoading,
1018
+ error,
1019
+ refetch
1020
+ };
1021
+ }
1022
+ function buildFilter(filter, ids, idsHex) {
1023
+ if (filter) {
1024
+ return { filter };
1025
+ }
1026
+ if (!ids || ids.length === 0) {
1027
+ return { filter: import_miden_sdk8.TransactionFilter.all() };
1028
+ }
1029
+ const allTransactionIds = ids.every((id) => typeof id !== "string");
1030
+ if (allTransactionIds) {
1031
+ return { filter: import_miden_sdk8.TransactionFilter.ids(ids) };
1032
+ }
1033
+ return {
1034
+ filter: import_miden_sdk8.TransactionFilter.all(),
1035
+ localFilterHexes: idsHex ?? []
1036
+ };
1037
+ }
1038
+ function normalizeHex(value) {
1039
+ const trimmed = value.trim();
1040
+ const normalized = trimmed.startsWith("0x") || trimmed.startsWith("0X") ? trimmed : `0x${trimmed}`;
1041
+ return normalized.toLowerCase();
1042
+ }
1043
+
1044
+ // src/hooks/useSyncState.ts
1045
+ var import_react7 = require("react");
1046
+ function useSyncState() {
1047
+ const { sync: triggerSync } = useMiden();
1048
+ const syncState = useSyncStateStore();
1049
+ const sync = (0, import_react7.useCallback)(async () => {
1050
+ await triggerSync();
1051
+ }, [triggerSync]);
1052
+ return {
1053
+ ...syncState,
1054
+ sync
1055
+ };
1056
+ }
1057
+
1058
+ // src/hooks/useCreateWallet.ts
1059
+ var import_react8 = require("react");
1060
+ var import_miden_sdk9 = require("@miden-sdk/miden-sdk");
1061
+ function useCreateWallet() {
1062
+ const { client, isReady, sync, runExclusive } = useMiden();
1063
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1064
+ const setAccounts = useMidenStore((state) => state.setAccounts);
1065
+ const [wallet, setWallet] = (0, import_react8.useState)(null);
1066
+ const [isCreating, setIsCreating] = (0, import_react8.useState)(false);
1067
+ const [error, setError] = (0, import_react8.useState)(null);
1068
+ const createWallet = (0, import_react8.useCallback)(
1069
+ async (options = {}) => {
1070
+ if (!client || !isReady) {
1071
+ throw new Error("Miden client is not ready");
1072
+ }
1073
+ await sync();
1074
+ setIsCreating(true);
1075
+ setError(null);
1076
+ try {
1077
+ const storageMode = getStorageMode(
1078
+ options.storageMode ?? DEFAULTS.STORAGE_MODE
1079
+ );
1080
+ const mutable = options.mutable ?? DEFAULTS.WALLET_MUTABLE;
1081
+ const authScheme = options.authScheme ?? DEFAULTS.AUTH_SCHEME;
1082
+ const newWallet = await runExclusiveSafe(async () => {
1083
+ const createdWallet = await client.newWallet(
1084
+ storageMode,
1085
+ mutable,
1086
+ authScheme,
1087
+ options.initSeed
1088
+ );
1089
+ ensureAccountBech32(createdWallet);
1090
+ const accounts = await client.getAccounts();
1091
+ setAccounts(accounts);
1092
+ return createdWallet;
1093
+ });
1094
+ setWallet(newWallet);
1095
+ return newWallet;
1096
+ } catch (err) {
1097
+ const error2 = err instanceof Error ? err : new Error(String(err));
1098
+ setError(error2);
1099
+ throw error2;
1100
+ } finally {
1101
+ setIsCreating(false);
1102
+ }
1103
+ },
1104
+ [client, isReady, runExclusive, setAccounts]
1105
+ );
1106
+ const reset = (0, import_react8.useCallback)(() => {
1107
+ setWallet(null);
1108
+ setIsCreating(false);
1109
+ setError(null);
1110
+ }, []);
1111
+ return {
1112
+ createWallet,
1113
+ wallet,
1114
+ isCreating,
1115
+ error,
1116
+ reset
1117
+ };
1118
+ }
1119
+ function getStorageMode(mode) {
1120
+ switch (mode) {
1121
+ case "private":
1122
+ return import_miden_sdk9.AccountStorageMode.private();
1123
+ case "public":
1124
+ return import_miden_sdk9.AccountStorageMode.public();
1125
+ case "network":
1126
+ return import_miden_sdk9.AccountStorageMode.network();
1127
+ default:
1128
+ return import_miden_sdk9.AccountStorageMode.private();
1129
+ }
1130
+ }
1131
+
1132
+ // src/hooks/useCreateFaucet.ts
1133
+ var import_react9 = require("react");
1134
+ var import_miden_sdk10 = require("@miden-sdk/miden-sdk");
1135
+ function useCreateFaucet() {
1136
+ const { client, isReady, runExclusive } = useMiden();
1137
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1138
+ const setAccounts = useMidenStore((state) => state.setAccounts);
1139
+ const [faucet, setFaucet] = (0, import_react9.useState)(null);
1140
+ const [isCreating, setIsCreating] = (0, import_react9.useState)(false);
1141
+ const [error, setError] = (0, import_react9.useState)(null);
1142
+ const createFaucet = (0, import_react9.useCallback)(
1143
+ async (options) => {
1144
+ if (!client || !isReady) {
1145
+ throw new Error("Miden client is not ready");
1146
+ }
1147
+ setIsCreating(true);
1148
+ setError(null);
1149
+ try {
1150
+ const storageMode = getStorageMode2(
1151
+ options.storageMode ?? DEFAULTS.STORAGE_MODE
1152
+ );
1153
+ const decimals = options.decimals ?? DEFAULTS.FAUCET_DECIMALS;
1154
+ const authScheme = options.authScheme ?? DEFAULTS.AUTH_SCHEME;
1155
+ const newFaucet = await runExclusiveSafe(async () => {
1156
+ const createdFaucet = await client.newFaucet(
1157
+ storageMode,
1158
+ false,
1159
+ // nonFungible - currently only fungible faucets supported
1160
+ options.tokenSymbol,
1161
+ decimals,
1162
+ options.maxSupply,
1163
+ authScheme
1164
+ );
1165
+ const accounts = await client.getAccounts();
1166
+ setAccounts(accounts);
1167
+ return createdFaucet;
1168
+ });
1169
+ setFaucet(newFaucet);
1170
+ return newFaucet;
1171
+ } catch (err) {
1172
+ const error2 = err instanceof Error ? err : new Error(String(err));
1173
+ setError(error2);
1174
+ throw error2;
1175
+ } finally {
1176
+ setIsCreating(false);
1177
+ }
1178
+ },
1179
+ [client, isReady, runExclusive, setAccounts]
1180
+ );
1181
+ const reset = (0, import_react9.useCallback)(() => {
1182
+ setFaucet(null);
1183
+ setIsCreating(false);
1184
+ setError(null);
1185
+ }, []);
1186
+ return {
1187
+ createFaucet,
1188
+ faucet,
1189
+ isCreating,
1190
+ error,
1191
+ reset
1192
+ };
1193
+ }
1194
+ function getStorageMode2(mode) {
1195
+ switch (mode) {
1196
+ case "private":
1197
+ return import_miden_sdk10.AccountStorageMode.private();
1198
+ case "public":
1199
+ return import_miden_sdk10.AccountStorageMode.public();
1200
+ case "network":
1201
+ return import_miden_sdk10.AccountStorageMode.network();
1202
+ default:
1203
+ return import_miden_sdk10.AccountStorageMode.private();
1204
+ }
1205
+ }
1206
+
1207
+ // src/hooks/useImportAccount.ts
1208
+ var import_react10 = require("react");
1209
+ var import_miden_sdk11 = require("@miden-sdk/miden-sdk");
1210
+ function useImportAccount() {
1211
+ const { client, isReady, runExclusive } = useMiden();
1212
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1213
+ const setAccounts = useMidenStore((state) => state.setAccounts);
1214
+ const [account, setAccount] = (0, import_react10.useState)(null);
1215
+ const [isImporting, setIsImporting] = (0, import_react10.useState)(false);
1216
+ const [error, setError] = (0, import_react10.useState)(null);
1217
+ const importAccount = (0, import_react10.useCallback)(
1218
+ async (options) => {
1219
+ if (!client || !isReady) {
1220
+ throw new Error("Miden client is not ready");
1221
+ }
1222
+ setIsImporting(true);
1223
+ setError(null);
1224
+ try {
1225
+ let accountsAfter = null;
1226
+ const imported = await runExclusiveSafe(async () => {
1227
+ switch (options.type) {
1228
+ case "file": {
1229
+ const accountsBefore = await client.getAccounts();
1230
+ const accountFile = await resolveAccountFile(options.file);
1231
+ const accountFileWithAccount = accountFile;
1232
+ const fileBytes = getAccountFileBytes(
1233
+ accountFileWithAccount,
1234
+ options.file
1235
+ );
1236
+ const accountFromFile = typeof accountFileWithAccount.account === "function" ? accountFileWithAccount.account() : null;
1237
+ const accountIdFromFile = accountFromFile === null && typeof accountFileWithAccount.accountId === "function" ? accountFileWithAccount.accountId() : null;
1238
+ try {
1239
+ await client.importAccountFile(accountFile);
1240
+ } catch (err) {
1241
+ const message = err instanceof Error ? err.message : String(err);
1242
+ if (!message.includes("already being tracked")) {
1243
+ throw err;
1244
+ }
1245
+ }
1246
+ accountsAfter = await client.getAccounts();
1247
+ if (accountFromFile) {
1248
+ return accountFromFile;
1249
+ }
1250
+ const beforeIds = new Set(
1251
+ accountsBefore.map((account2) => account2.id().toString())
1252
+ );
1253
+ const newAccountHeader = accountsAfter.find(
1254
+ (account2) => !beforeIds.has(account2.id().toString())
1255
+ );
1256
+ const accountId = accountIdFromFile ?? newAccountHeader?.id();
1257
+ if (accountId) {
1258
+ const fetchedAccount = await client.getAccount(accountId);
1259
+ if (fetchedAccount) {
1260
+ return fetchedAccount;
1261
+ }
1262
+ }
1263
+ if (fileBytes) {
1264
+ for (const header of accountsAfter) {
1265
+ const exported = await client.exportAccountFile(header.id());
1266
+ const exportedBytes = getAccountFileBytes(exported, exported);
1267
+ if (exportedBytes && bytesEqual(exportedBytes, fileBytes)) {
1268
+ const fetchedAccount = await client.getAccount(header.id());
1269
+ if (fetchedAccount) {
1270
+ return fetchedAccount;
1271
+ }
1272
+ }
1273
+ }
1274
+ }
1275
+ throw new Error("Account not found after import");
1276
+ }
1277
+ case "id": {
1278
+ const accountId = resolveAccountId(options.accountId);
1279
+ await client.importAccountById(accountId);
1280
+ const fetchedAccount = await client.getAccount(accountId);
1281
+ if (!fetchedAccount) {
1282
+ throw new Error("Account not found after import");
1283
+ }
1284
+ return fetchedAccount;
1285
+ }
1286
+ case "seed": {
1287
+ const mutable = options.mutable ?? DEFAULTS.WALLET_MUTABLE;
1288
+ const authScheme = options.authScheme ?? DEFAULTS.AUTH_SCHEME;
1289
+ return await client.importPublicAccountFromSeed(
1290
+ options.seed,
1291
+ mutable,
1292
+ authScheme
1293
+ );
1294
+ }
1295
+ }
1296
+ });
1297
+ ensureAccountBech32(imported);
1298
+ const accounts = accountsAfter ?? await client.getAccounts();
1299
+ setAccounts(accounts);
1300
+ setAccount(imported);
1301
+ return imported;
1302
+ } catch (err) {
1303
+ const error2 = err instanceof Error ? err : new Error(String(err));
1304
+ setError(error2);
1305
+ throw error2;
1306
+ } finally {
1307
+ setIsImporting(false);
1308
+ }
1309
+ },
1310
+ [client, isReady, runExclusive, setAccounts]
1311
+ );
1312
+ const reset = (0, import_react10.useCallback)(() => {
1313
+ setAccount(null);
1314
+ setIsImporting(false);
1315
+ setError(null);
1316
+ }, []);
1317
+ return {
1318
+ importAccount,
1319
+ account,
1320
+ isImporting,
1321
+ error,
1322
+ reset
1323
+ };
1324
+ }
1325
+ function resolveAccountId(accountId) {
1326
+ return parseAccountId(accountId);
1327
+ }
1328
+ async function resolveAccountFile(file) {
1329
+ if (file instanceof Uint8Array) {
1330
+ return import_miden_sdk11.AccountFile.deserialize(file);
1331
+ }
1332
+ if (file instanceof ArrayBuffer) {
1333
+ return import_miden_sdk11.AccountFile.deserialize(new Uint8Array(file));
1334
+ }
1335
+ return file;
1336
+ }
1337
+ function getAccountFileBytes(accountFile, original) {
1338
+ if (original instanceof Uint8Array) {
1339
+ return original;
1340
+ }
1341
+ if (original instanceof ArrayBuffer) {
1342
+ return new Uint8Array(original);
1343
+ }
1344
+ if (typeof accountFile.serialize === "function") {
1345
+ return accountFile.serialize();
1346
+ }
1347
+ return null;
1348
+ }
1349
+ function bytesEqual(left, right) {
1350
+ if (left.length !== right.length) {
1351
+ return false;
1352
+ }
1353
+ for (let i = 0; i < left.length; i += 1) {
1354
+ if (left[i] !== right[i]) {
1355
+ return false;
1356
+ }
1357
+ }
1358
+ return true;
1359
+ }
1360
+
1361
+ // src/hooks/useSend.ts
1362
+ var import_react11 = require("react");
1363
+ var import_miden_sdk12 = require("@miden-sdk/miden-sdk");
1364
+ function useSend() {
1365
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
1366
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1367
+ const [result, setResult] = (0, import_react11.useState)(null);
1368
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
1369
+ const [stage, setStage] = (0, import_react11.useState)("idle");
1370
+ const [error, setError] = (0, import_react11.useState)(null);
1371
+ const send = (0, import_react11.useCallback)(
1372
+ async (options) => {
1373
+ if (!client || !isReady) {
1374
+ throw new Error("Miden client is not ready");
1375
+ }
1376
+ setIsLoading(true);
1377
+ setStage("executing");
1378
+ setError(null);
1379
+ try {
1380
+ const noteType = getNoteType(options.noteType ?? DEFAULTS.NOTE_TYPE);
1381
+ const fromAccountId = parseAccountId(options.from);
1382
+ const toAccountId = parseAccountId(options.to);
1383
+ const assetId = options.assetId ?? options.faucetId ?? null;
1384
+ if (!assetId) {
1385
+ throw new Error("Asset ID is required");
1386
+ }
1387
+ const assetIdObj = parseAccountId(assetId);
1388
+ const txResult = await runExclusiveSafe(async () => {
1389
+ const txRequest = client.newSendTransactionRequest(
1390
+ fromAccountId,
1391
+ toAccountId,
1392
+ assetIdObj,
1393
+ noteType,
1394
+ options.amount,
1395
+ options.recallHeight ?? null,
1396
+ options.timelockHeight ?? null
1397
+ );
1398
+ return await client.executeTransaction(fromAccountId, txRequest);
1399
+ });
1400
+ setStage("proving");
1401
+ const provenTransaction = await runExclusiveSafe(
1402
+ () => client.proveTransaction(txResult, prover ?? void 0)
1403
+ );
1404
+ setStage("submitting");
1405
+ const submissionHeight = await runExclusiveSafe(
1406
+ () => client.submitProvenTransaction(provenTransaction, txResult)
1407
+ );
1408
+ await runExclusiveSafe(
1409
+ () => client.applyTransaction(txResult, submissionHeight)
1410
+ );
1411
+ const txId = txResult.id();
1412
+ await waitForTransactionCommit(client, runExclusiveSafe, txId);
1413
+ if (noteType === import_miden_sdk12.NoteType.Private) {
1414
+ const fullNote = extractFullNote(txResult);
1415
+ if (!fullNote) {
1416
+ throw new Error("Missing full note for private send");
1417
+ }
1418
+ const recipientAddress = parseAddress(options.to, toAccountId);
1419
+ await runExclusiveSafe(
1420
+ () => client.sendPrivateNote(fullNote, recipientAddress)
1421
+ );
1422
+ }
1423
+ const txSummary = { transactionId: txResult.id().toString() };
1424
+ setStage("complete");
1425
+ setResult(txSummary);
1426
+ await sync();
1427
+ return txSummary;
1428
+ } catch (err) {
1429
+ const error2 = err instanceof Error ? err : new Error(String(err));
1430
+ setError(error2);
1431
+ setStage("idle");
1432
+ throw error2;
1433
+ } finally {
1434
+ setIsLoading(false);
1435
+ }
1436
+ },
1437
+ [client, isReady, prover, runExclusive, sync]
1438
+ );
1439
+ const reset = (0, import_react11.useCallback)(() => {
1440
+ setResult(null);
1441
+ setIsLoading(false);
1442
+ setStage("idle");
1443
+ setError(null);
1444
+ }, []);
1445
+ return {
1446
+ send,
1447
+ result,
1448
+ isLoading,
1449
+ stage,
1450
+ error,
1451
+ reset
1452
+ };
1453
+ }
1454
+ function getNoteType(type) {
1455
+ switch (type) {
1456
+ case "private":
1457
+ return import_miden_sdk12.NoteType.Private;
1458
+ case "public":
1459
+ return import_miden_sdk12.NoteType.Public;
1460
+ case "encrypted":
1461
+ return import_miden_sdk12.NoteType.Encrypted;
1462
+ default:
1463
+ return import_miden_sdk12.NoteType.Private;
1464
+ }
1465
+ }
1466
+ async function waitForTransactionCommit(client, runExclusiveSafe, txId, maxWaitMs = 1e4, delayMs = 1e3) {
1467
+ let waited = 0;
1468
+ while (waited < maxWaitMs) {
1469
+ await runExclusiveSafe(() => client.syncState());
1470
+ const [record] = await runExclusiveSafe(
1471
+ () => client.getTransactions(import_miden_sdk12.TransactionFilter.ids([txId]))
1472
+ );
1473
+ if (record) {
1474
+ const status = record.transactionStatus();
1475
+ if (status.isCommitted()) {
1476
+ return;
1477
+ }
1478
+ if (status.isDiscarded()) {
1479
+ throw new Error("Transaction was discarded before commit");
1480
+ }
1481
+ }
1482
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
1483
+ waited += delayMs;
1484
+ }
1485
+ throw new Error("Timeout waiting for transaction commit");
1486
+ }
1487
+ function extractFullNote(txResult) {
1488
+ try {
1489
+ const executedTx = txResult.executedTransaction?.();
1490
+ const notes = executedTx?.outputNotes?.().notes?.() ?? [];
1491
+ const note = notes[0];
1492
+ return note?.intoFull?.() ?? null;
1493
+ } catch {
1494
+ return null;
1495
+ }
1496
+ }
1497
+
1498
+ // src/hooks/useMultiSend.ts
1499
+ var import_react12 = require("react");
1500
+ var import_miden_sdk13 = require("@miden-sdk/miden-sdk");
1501
+ function useMultiSend() {
1502
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
1503
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1504
+ const [result, setResult] = (0, import_react12.useState)(null);
1505
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
1506
+ const [stage, setStage] = (0, import_react12.useState)("idle");
1507
+ const [error, setError] = (0, import_react12.useState)(null);
1508
+ const sendMany = (0, import_react12.useCallback)(
1509
+ async (options) => {
1510
+ if (!client || !isReady) {
1511
+ throw new Error("Miden client is not ready");
1512
+ }
1513
+ if (options.recipients.length === 0) {
1514
+ throw new Error("No recipients provided");
1515
+ }
1516
+ setIsLoading(true);
1517
+ setStage("executing");
1518
+ setError(null);
1519
+ try {
1520
+ const noteType = getNoteType2(options.noteType ?? DEFAULTS.NOTE_TYPE);
1521
+ const senderId = parseAccountId(options.from);
1522
+ const assetId = parseAccountId(options.assetId);
1523
+ const outputs = options.recipients.map(({ to, amount }) => {
1524
+ const receiverId = parseAccountId(to);
1525
+ const assets = new import_miden_sdk13.NoteAssets([new import_miden_sdk13.FungibleAsset(assetId, amount)]);
1526
+ const note = import_miden_sdk13.Note.createP2IDNote(
1527
+ senderId,
1528
+ receiverId,
1529
+ assets,
1530
+ noteType,
1531
+ new import_miden_sdk13.NoteAttachment()
1532
+ );
1533
+ const recipientAddress = parseAddress(to, receiverId);
1534
+ return {
1535
+ outputNote: import_miden_sdk13.OutputNote.full(note),
1536
+ note,
1537
+ recipientAddress
1538
+ };
1539
+ });
1540
+ const txRequest = new import_miden_sdk13.TransactionRequestBuilder().withOwnOutputNotes(
1541
+ new import_miden_sdk13.OutputNoteArray(outputs.map((o) => o.outputNote))
1542
+ ).build();
1543
+ const txResult = await runExclusiveSafe(
1544
+ () => client.executeTransaction(senderId, txRequest)
1545
+ );
1546
+ setStage("proving");
1547
+ const provenTransaction = await runExclusiveSafe(
1548
+ () => client.proveTransaction(txResult, prover ?? void 0)
1549
+ );
1550
+ setStage("submitting");
1551
+ const submissionHeight = await runExclusiveSafe(
1552
+ () => client.submitProvenTransaction(provenTransaction, txResult)
1553
+ );
1554
+ await runExclusiveSafe(
1555
+ () => client.applyTransaction(txResult, submissionHeight)
1556
+ );
1557
+ const txId = txResult.id();
1558
+ if (noteType === import_miden_sdk13.NoteType.Private) {
1559
+ await waitForTransactionCommit2(
1560
+ client,
1561
+ runExclusiveSafe,
1562
+ txId
1563
+ );
1564
+ for (const output of outputs) {
1565
+ await runExclusiveSafe(
1566
+ () => client.sendPrivateNote(output.note, output.recipientAddress)
1567
+ );
1568
+ }
1569
+ }
1570
+ const txSummary = { transactionId: txId.toString() };
1571
+ setStage("complete");
1572
+ setResult(txSummary);
1573
+ await sync();
1574
+ return txSummary;
1575
+ } catch (err) {
1576
+ const error2 = err instanceof Error ? err : new Error(String(err));
1577
+ setError(error2);
1578
+ setStage("idle");
1579
+ throw error2;
1580
+ } finally {
1581
+ setIsLoading(false);
1582
+ }
1583
+ },
1584
+ [client, isReady, prover, runExclusive, sync]
1585
+ );
1586
+ const reset = (0, import_react12.useCallback)(() => {
1587
+ setResult(null);
1588
+ setIsLoading(false);
1589
+ setStage("idle");
1590
+ setError(null);
1591
+ }, []);
1592
+ return {
1593
+ sendMany,
1594
+ result,
1595
+ isLoading,
1596
+ stage,
1597
+ error,
1598
+ reset
1599
+ };
1600
+ }
1601
+ function getNoteType2(type) {
1602
+ switch (type) {
1603
+ case "private":
1604
+ return import_miden_sdk13.NoteType.Private;
1605
+ case "public":
1606
+ return import_miden_sdk13.NoteType.Public;
1607
+ case "encrypted":
1608
+ return import_miden_sdk13.NoteType.Encrypted;
1609
+ default:
1610
+ return import_miden_sdk13.NoteType.Private;
1611
+ }
1612
+ }
1613
+ async function waitForTransactionCommit2(client, runExclusiveSafe, txId, maxWaitMs = 1e4, delayMs = 1e3) {
1614
+ let waited = 0;
1615
+ while (waited < maxWaitMs) {
1616
+ await runExclusiveSafe(() => client.syncState());
1617
+ const [record] = await runExclusiveSafe(
1618
+ () => client.getTransactions(import_miden_sdk13.TransactionFilter.ids([txId]))
1619
+ );
1620
+ if (record) {
1621
+ const status = record.transactionStatus();
1622
+ if (status.isCommitted()) {
1623
+ return;
1624
+ }
1625
+ if (status.isDiscarded()) {
1626
+ throw new Error("Transaction was discarded before commit");
1627
+ }
1628
+ }
1629
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
1630
+ waited += delayMs;
1631
+ }
1632
+ throw new Error("Timeout waiting for transaction commit");
1633
+ }
1634
+
1635
+ // src/hooks/useInternalTransfer.ts
1636
+ var import_react13 = require("react");
1637
+ var import_miden_sdk14 = require("@miden-sdk/miden-sdk");
1638
+ function useInternalTransfer() {
1639
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
1640
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1641
+ const [result, setResult] = (0, import_react13.useState)(null);
1642
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
1643
+ const [stage, setStage] = (0, import_react13.useState)("idle");
1644
+ const [error, setError] = (0, import_react13.useState)(null);
1645
+ const transferOnce = (0, import_react13.useCallback)(
1646
+ async (options) => {
1647
+ if (!client || !isReady) {
1648
+ throw new Error("Miden client is not ready");
1649
+ }
1650
+ const noteType = getNoteType3(options.noteType ?? DEFAULTS.NOTE_TYPE);
1651
+ const senderId = parseAccountId(options.from);
1652
+ const receiverId = parseAccountId(options.to);
1653
+ const assetId = parseAccountId(options.assetId);
1654
+ const assets = new import_miden_sdk14.NoteAssets([
1655
+ new import_miden_sdk14.FungibleAsset(assetId, options.amount)
1656
+ ]);
1657
+ const note = import_miden_sdk14.Note.createP2IDNote(
1658
+ senderId,
1659
+ receiverId,
1660
+ assets,
1661
+ noteType,
1662
+ new import_miden_sdk14.NoteAttachment()
1663
+ );
1664
+ const noteId = note.id().toString();
1665
+ const createRequest = new import_miden_sdk14.TransactionRequestBuilder().withOwnOutputNotes(new import_miden_sdk14.OutputNoteArray([import_miden_sdk14.OutputNote.full(note)])).build();
1666
+ const createTxId = await runExclusiveSafe(
1667
+ () => prover ? client.submitNewTransactionWithProver(
1668
+ senderId,
1669
+ createRequest,
1670
+ prover
1671
+ ) : client.submitNewTransaction(senderId, createRequest)
1672
+ );
1673
+ const consumeRequest = new import_miden_sdk14.TransactionRequestBuilder().withInputNotes(new import_miden_sdk14.NoteAndArgsArray([new import_miden_sdk14.NoteAndArgs(note, null)])).build();
1674
+ const consumeTxId = await runExclusiveSafe(
1675
+ () => prover ? client.submitNewTransactionWithProver(
1676
+ receiverId,
1677
+ consumeRequest,
1678
+ prover
1679
+ ) : client.submitNewTransaction(receiverId, consumeRequest)
1680
+ );
1681
+ return {
1682
+ createTransactionId: createTxId.toString(),
1683
+ consumeTransactionId: consumeTxId.toString(),
1684
+ noteId
1685
+ };
1686
+ },
1687
+ [client, isReady, prover, runExclusiveSafe]
1688
+ );
1689
+ const transfer = (0, import_react13.useCallback)(
1690
+ async (options) => {
1691
+ if (!client || !isReady) {
1692
+ throw new Error("Miden client is not ready");
1693
+ }
1694
+ setIsLoading(true);
1695
+ setStage("executing");
1696
+ setError(null);
1697
+ try {
1698
+ setStage("proving");
1699
+ const txResult = await transferOnce(options);
1700
+ setStage("complete");
1701
+ setResult(txResult);
1702
+ await sync();
1703
+ return txResult;
1704
+ } catch (err) {
1705
+ const error2 = err instanceof Error ? err : new Error(String(err));
1706
+ setError(error2);
1707
+ setStage("idle");
1708
+ throw error2;
1709
+ } finally {
1710
+ setIsLoading(false);
1711
+ }
1712
+ },
1713
+ [client, isReady, sync, transferOnce]
1714
+ );
1715
+ const transferChain = (0, import_react13.useCallback)(
1716
+ async (options) => {
1717
+ if (!client || !isReady) {
1718
+ throw new Error("Miden client is not ready");
1719
+ }
1720
+ if (options.recipients.length === 0) {
1721
+ throw new Error("No recipients provided");
1722
+ }
1723
+ setIsLoading(true);
1724
+ setStage("executing");
1725
+ setError(null);
1726
+ try {
1727
+ const results = [];
1728
+ let currentSender = options.from;
1729
+ for (const recipient of options.recipients) {
1730
+ setStage("proving");
1731
+ const txResult = await transferOnce({
1732
+ from: currentSender,
1733
+ to: recipient,
1734
+ assetId: options.assetId,
1735
+ amount: options.amount,
1736
+ noteType: options.noteType
1737
+ });
1738
+ results.push(txResult);
1739
+ currentSender = recipient;
1740
+ }
1741
+ setStage("complete");
1742
+ setResult(results);
1743
+ await sync();
1744
+ return results;
1745
+ } catch (err) {
1746
+ const error2 = err instanceof Error ? err : new Error(String(err));
1747
+ setError(error2);
1748
+ setStage("idle");
1749
+ throw error2;
1750
+ } finally {
1751
+ setIsLoading(false);
1752
+ }
1753
+ },
1754
+ [client, isReady, sync, transferOnce]
1755
+ );
1756
+ const reset = (0, import_react13.useCallback)(() => {
1757
+ setResult(null);
1758
+ setIsLoading(false);
1759
+ setStage("idle");
1760
+ setError(null);
1761
+ }, []);
1762
+ return {
1763
+ transfer,
1764
+ transferChain,
1765
+ result,
1766
+ isLoading,
1767
+ stage,
1768
+ error,
1769
+ reset
1770
+ };
1771
+ }
1772
+ function getNoteType3(type) {
1773
+ switch (type) {
1774
+ case "private":
1775
+ return import_miden_sdk14.NoteType.Private;
1776
+ case "public":
1777
+ return import_miden_sdk14.NoteType.Public;
1778
+ case "encrypted":
1779
+ return import_miden_sdk14.NoteType.Encrypted;
1780
+ default:
1781
+ return import_miden_sdk14.NoteType.Private;
1782
+ }
1783
+ }
1784
+
1785
+ // src/hooks/useWaitForCommit.ts
1786
+ var import_react14 = require("react");
1787
+ var import_miden_sdk15 = require("@miden-sdk/miden-sdk");
1788
+ function useWaitForCommit() {
1789
+ const { client, isReady, runExclusive } = useMiden();
1790
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1791
+ const waitForCommit = (0, import_react14.useCallback)(
1792
+ async (txId, options) => {
1793
+ if (!client || !isReady) {
1794
+ throw new Error("Miden client is not ready");
1795
+ }
1796
+ const timeoutMs = Math.max(0, options?.timeoutMs ?? 1e4);
1797
+ const intervalMs = Math.max(1, options?.intervalMs ?? 1e3);
1798
+ const targetHex = normalizeHex2(
1799
+ typeof txId === "string" ? txId : txId.toHex()
1800
+ );
1801
+ let waited = 0;
1802
+ while (waited < timeoutMs) {
1803
+ await runExclusiveSafe(
1804
+ () => client.syncState()
1805
+ );
1806
+ const records = await runExclusiveSafe(
1807
+ () => client.getTransactions(
1808
+ typeof txId === "string" ? import_miden_sdk15.TransactionFilter.all() : import_miden_sdk15.TransactionFilter.ids([txId])
1809
+ )
1810
+ );
1811
+ const record = records.find(
1812
+ (item) => normalizeHex2(item.id().toHex()) === targetHex
1813
+ );
1814
+ if (record) {
1815
+ const status = record.transactionStatus();
1816
+ if (status.isCommitted()) {
1817
+ return;
1818
+ }
1819
+ if (status.isDiscarded()) {
1820
+ throw new Error("Transaction was discarded before commit");
1821
+ }
1822
+ }
1823
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
1824
+ waited += intervalMs;
1825
+ }
1826
+ throw new Error("Timeout waiting for transaction commit");
1827
+ },
1828
+ [client, isReady, runExclusiveSafe]
1829
+ );
1830
+ return { waitForCommit };
1831
+ }
1832
+ function normalizeHex2(value) {
1833
+ const trimmed = value.trim();
1834
+ const normalized = trimmed.startsWith("0x") || trimmed.startsWith("0X") ? trimmed : `0x${trimmed}`;
1835
+ return normalized.toLowerCase();
1836
+ }
1837
+
1838
+ // src/hooks/useWaitForNotes.ts
1839
+ var import_react15 = require("react");
1840
+ function useWaitForNotes() {
1841
+ const { client, isReady, runExclusive } = useMiden();
1842
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1843
+ const waitForConsumableNotes = (0, import_react15.useCallback)(
1844
+ async (options) => {
1845
+ if (!client || !isReady) {
1846
+ throw new Error("Miden client is not ready");
1847
+ }
1848
+ const timeoutMs = Math.max(0, options.timeoutMs ?? 1e4);
1849
+ const intervalMs = Math.max(1, options.intervalMs ?? 1e3);
1850
+ const minCount = Math.max(1, options.minCount ?? 1);
1851
+ const accountId = parseAccountId(options.accountId);
1852
+ let waited = 0;
1853
+ while (waited < timeoutMs) {
1854
+ await runExclusiveSafe(() => client.syncState());
1855
+ const notes = await runExclusiveSafe(
1856
+ () => client.getConsumableNotes(accountId)
1857
+ );
1858
+ if (notes.length >= minCount) {
1859
+ return notes;
1860
+ }
1861
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
1862
+ waited += intervalMs;
1863
+ }
1864
+ throw new Error("Timeout waiting for consumable notes");
1865
+ },
1866
+ [client, isReady, runExclusiveSafe]
1867
+ );
1868
+ return { waitForConsumableNotes };
1869
+ }
1870
+
1871
+ // src/hooks/useMint.ts
1872
+ var import_react16 = require("react");
1873
+ var import_miden_sdk16 = require("@miden-sdk/miden-sdk");
1874
+ function useMint() {
1875
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
1876
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1877
+ const [result, setResult] = (0, import_react16.useState)(null);
1878
+ const [isLoading, setIsLoading] = (0, import_react16.useState)(false);
1879
+ const [stage, setStage] = (0, import_react16.useState)("idle");
1880
+ const [error, setError] = (0, import_react16.useState)(null);
1881
+ const mint = (0, import_react16.useCallback)(
1882
+ async (options) => {
1883
+ if (!client || !isReady) {
1884
+ throw new Error("Miden client is not ready");
1885
+ }
1886
+ setIsLoading(true);
1887
+ setStage("executing");
1888
+ setError(null);
1889
+ try {
1890
+ const noteType = getNoteType4(options.noteType ?? DEFAULTS.NOTE_TYPE);
1891
+ const targetAccountIdObj = parseAccountId(options.targetAccountId);
1892
+ const faucetIdObj = parseAccountId(options.faucetId);
1893
+ setStage("proving");
1894
+ const txResult = await runExclusiveSafe(async () => {
1895
+ const txRequest = client.newMintTransactionRequest(
1896
+ targetAccountIdObj,
1897
+ faucetIdObj,
1898
+ noteType,
1899
+ options.amount
1900
+ );
1901
+ const txId = prover ? await client.submitNewTransactionWithProver(
1902
+ faucetIdObj,
1903
+ txRequest,
1904
+ prover
1905
+ ) : await client.submitNewTransaction(faucetIdObj, txRequest);
1906
+ return { transactionId: txId.toString() };
1907
+ });
1908
+ setStage("complete");
1909
+ setResult(txResult);
1910
+ await sync();
1911
+ return txResult;
1912
+ } catch (err) {
1913
+ const error2 = err instanceof Error ? err : new Error(String(err));
1914
+ setError(error2);
1915
+ setStage("idle");
1916
+ throw error2;
1917
+ } finally {
1918
+ setIsLoading(false);
1919
+ }
1920
+ },
1921
+ [client, isReady, prover, runExclusive, sync]
1922
+ );
1923
+ const reset = (0, import_react16.useCallback)(() => {
1924
+ setResult(null);
1925
+ setIsLoading(false);
1926
+ setStage("idle");
1927
+ setError(null);
1928
+ }, []);
1929
+ return {
1930
+ mint,
1931
+ result,
1932
+ isLoading,
1933
+ stage,
1934
+ error,
1935
+ reset
1936
+ };
1937
+ }
1938
+ function getNoteType4(type) {
1939
+ switch (type) {
1940
+ case "private":
1941
+ return import_miden_sdk16.NoteType.Private;
1942
+ case "public":
1943
+ return import_miden_sdk16.NoteType.Public;
1944
+ case "encrypted":
1945
+ return import_miden_sdk16.NoteType.Encrypted;
1946
+ default:
1947
+ return import_miden_sdk16.NoteType.Private;
1948
+ }
1949
+ }
1950
+
1951
+ // src/hooks/useConsume.ts
1952
+ var import_react17 = require("react");
1953
+ var import_miden_sdk17 = require("@miden-sdk/miden-sdk");
1954
+ function useConsume() {
1955
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
1956
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
1957
+ const [result, setResult] = (0, import_react17.useState)(null);
1958
+ const [isLoading, setIsLoading] = (0, import_react17.useState)(false);
1959
+ const [stage, setStage] = (0, import_react17.useState)("idle");
1960
+ const [error, setError] = (0, import_react17.useState)(null);
1961
+ const consume = (0, import_react17.useCallback)(
1962
+ async (options) => {
1963
+ if (!client || !isReady) {
1964
+ throw new Error("Miden client is not ready");
1965
+ }
1966
+ if (options.noteIds.length === 0) {
1967
+ throw new Error("No note IDs provided");
1968
+ }
1969
+ setIsLoading(true);
1970
+ setStage("executing");
1971
+ setError(null);
1972
+ try {
1973
+ const accountIdObj = parseAccountId(options.accountId);
1974
+ setStage("proving");
1975
+ const txResult = await runExclusiveSafe(async () => {
1976
+ const noteIds = options.noteIds.map(
1977
+ (noteId) => import_miden_sdk17.NoteId.fromHex(noteId)
1978
+ );
1979
+ const filter = new import_miden_sdk17.NoteFilter(import_miden_sdk17.NoteFilterTypes.List, noteIds);
1980
+ const noteRecords = await client.getInputNotes(filter);
1981
+ const notes = noteRecords.map((record) => record.toNote());
1982
+ if (notes.length === 0) {
1983
+ throw new Error("No notes found for provided IDs");
1984
+ }
1985
+ if (notes.length !== options.noteIds.length) {
1986
+ throw new Error("Some notes could not be found for provided IDs");
1987
+ }
1988
+ const txRequest = client.newConsumeTransactionRequest(notes);
1989
+ const txId = prover ? await client.submitNewTransactionWithProver(
1990
+ accountIdObj,
1991
+ txRequest,
1992
+ prover
1993
+ ) : await client.submitNewTransaction(accountIdObj, txRequest);
1994
+ return { transactionId: txId.toString() };
1995
+ });
1996
+ setStage("complete");
1997
+ setResult(txResult);
1998
+ await sync();
1999
+ return txResult;
2000
+ } catch (err) {
2001
+ const error2 = err instanceof Error ? err : new Error(String(err));
2002
+ setError(error2);
2003
+ setStage("idle");
2004
+ throw error2;
2005
+ } finally {
2006
+ setIsLoading(false);
2007
+ }
2008
+ },
2009
+ [client, isReady, prover, runExclusive, sync]
2010
+ );
2011
+ const reset = (0, import_react17.useCallback)(() => {
2012
+ setResult(null);
2013
+ setIsLoading(false);
2014
+ setStage("idle");
2015
+ setError(null);
2016
+ }, []);
2017
+ return {
2018
+ consume,
2019
+ result,
2020
+ isLoading,
2021
+ stage,
2022
+ error,
2023
+ reset
2024
+ };
2025
+ }
2026
+
2027
+ // src/hooks/useSwap.ts
2028
+ var import_react18 = require("react");
2029
+ var import_miden_sdk18 = require("@miden-sdk/miden-sdk");
2030
+ function useSwap() {
2031
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
2032
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2033
+ const [result, setResult] = (0, import_react18.useState)(null);
2034
+ const [isLoading, setIsLoading] = (0, import_react18.useState)(false);
2035
+ const [stage, setStage] = (0, import_react18.useState)("idle");
2036
+ const [error, setError] = (0, import_react18.useState)(null);
2037
+ const swap = (0, import_react18.useCallback)(
2038
+ async (options) => {
2039
+ if (!client || !isReady) {
2040
+ throw new Error("Miden client is not ready");
2041
+ }
2042
+ setIsLoading(true);
2043
+ setStage("executing");
2044
+ setError(null);
2045
+ try {
2046
+ const noteType = getNoteType5(options.noteType ?? DEFAULTS.NOTE_TYPE);
2047
+ const paybackNoteType = getNoteType5(
2048
+ options.paybackNoteType ?? DEFAULTS.NOTE_TYPE
2049
+ );
2050
+ const accountIdObj = parseAccountId(options.accountId);
2051
+ const offeredFaucetIdObj = parseAccountId(options.offeredFaucetId);
2052
+ const requestedFaucetIdObj = parseAccountId(options.requestedFaucetId);
2053
+ setStage("proving");
2054
+ const txResult = await runExclusiveSafe(async () => {
2055
+ const txRequest = client.newSwapTransactionRequest(
2056
+ accountIdObj,
2057
+ offeredFaucetIdObj,
2058
+ options.offeredAmount,
2059
+ requestedFaucetIdObj,
2060
+ options.requestedAmount,
2061
+ noteType,
2062
+ paybackNoteType
2063
+ );
2064
+ const txId = prover ? await client.submitNewTransactionWithProver(
2065
+ accountIdObj,
2066
+ txRequest,
2067
+ prover
2068
+ ) : await client.submitNewTransaction(accountIdObj, txRequest);
2069
+ return { transactionId: txId.toString() };
2070
+ });
2071
+ setStage("complete");
2072
+ setResult(txResult);
2073
+ await sync();
2074
+ return txResult;
2075
+ } catch (err) {
2076
+ const error2 = err instanceof Error ? err : new Error(String(err));
2077
+ setError(error2);
2078
+ setStage("idle");
2079
+ throw error2;
2080
+ } finally {
2081
+ setIsLoading(false);
2082
+ }
2083
+ },
2084
+ [client, isReady, prover, runExclusive, sync]
2085
+ );
2086
+ const reset = (0, import_react18.useCallback)(() => {
2087
+ setResult(null);
2088
+ setIsLoading(false);
2089
+ setStage("idle");
2090
+ setError(null);
2091
+ }, []);
2092
+ return {
2093
+ swap,
2094
+ result,
2095
+ isLoading,
2096
+ stage,
2097
+ error,
2098
+ reset
2099
+ };
2100
+ }
2101
+ function getNoteType5(type) {
2102
+ switch (type) {
2103
+ case "private":
2104
+ return import_miden_sdk18.NoteType.Private;
2105
+ case "public":
2106
+ return import_miden_sdk18.NoteType.Public;
2107
+ case "encrypted":
2108
+ return import_miden_sdk18.NoteType.Encrypted;
2109
+ default:
2110
+ return import_miden_sdk18.NoteType.Private;
2111
+ }
2112
+ }
2113
+
2114
+ // src/hooks/useTransaction.ts
2115
+ var import_react19 = require("react");
2116
+ function useTransaction() {
2117
+ const { client, isReady, sync, runExclusive, prover } = useMiden();
2118
+ const runExclusiveSafe = runExclusive ?? runExclusiveDirect;
2119
+ const [result, setResult] = (0, import_react19.useState)(null);
2120
+ const [isLoading, setIsLoading] = (0, import_react19.useState)(false);
2121
+ const [stage, setStage] = (0, import_react19.useState)("idle");
2122
+ const [error, setError] = (0, import_react19.useState)(null);
2123
+ const execute = (0, import_react19.useCallback)(
2124
+ async (options) => {
2125
+ if (!client || !isReady) {
2126
+ throw new Error("Miden client is not ready");
2127
+ }
2128
+ setIsLoading(true);
2129
+ setStage("executing");
2130
+ setError(null);
2131
+ try {
2132
+ setStage("proving");
2133
+ const txResult = await runExclusiveSafe(async () => {
2134
+ const accountIdObj = resolveAccountId2(options.accountId);
2135
+ const txRequest = await resolveRequest(options.request, client);
2136
+ const txId = prover ? await client.submitNewTransactionWithProver(
2137
+ accountIdObj,
2138
+ txRequest,
2139
+ prover
2140
+ ) : await client.submitNewTransaction(accountIdObj, txRequest);
2141
+ return { transactionId: txId.toString() };
2142
+ });
2143
+ setStage("complete");
2144
+ setResult(txResult);
2145
+ await sync();
2146
+ return txResult;
2147
+ } catch (err) {
2148
+ const error2 = err instanceof Error ? err : new Error(String(err));
2149
+ setError(error2);
2150
+ setStage("idle");
2151
+ throw error2;
2152
+ } finally {
2153
+ setIsLoading(false);
2154
+ }
2155
+ },
2156
+ [client, isReady, prover, runExclusive, sync]
2157
+ );
2158
+ const reset = (0, import_react19.useCallback)(() => {
2159
+ setResult(null);
2160
+ setIsLoading(false);
2161
+ setStage("idle");
2162
+ setError(null);
2163
+ }, []);
2164
+ return {
2165
+ execute,
2166
+ result,
2167
+ isLoading,
2168
+ stage,
2169
+ error,
2170
+ reset
2171
+ };
2172
+ }
2173
+ function resolveAccountId2(accountId) {
2174
+ return parseAccountId(accountId);
2175
+ }
2176
+ async function resolveRequest(request, client) {
2177
+ if (typeof request === "function") {
2178
+ return await request(client);
2179
+ }
2180
+ return request;
2181
+ }
2182
+
2183
+ // src/index.ts
2184
+ installAccountBech32();
2185
+ // Annotate the CommonJS export names for ESM import in node:
2186
+ 0 && (module.exports = {
2187
+ DEFAULTS,
2188
+ MidenProvider,
2189
+ formatAssetAmount,
2190
+ formatNoteSummary,
2191
+ getNoteSummary,
2192
+ parseAssetAmount,
2193
+ toBech32AccountId,
2194
+ useAccount,
2195
+ useAccounts,
2196
+ useAssetMetadata,
2197
+ useConsume,
2198
+ useCreateFaucet,
2199
+ useCreateWallet,
2200
+ useImportAccount,
2201
+ useInternalTransfer,
2202
+ useMiden,
2203
+ useMidenClient,
2204
+ useMint,
2205
+ useMultiSend,
2206
+ useNotes,
2207
+ useSend,
2208
+ useSwap,
2209
+ useSyncState,
2210
+ useTransaction,
2211
+ useTransactionHistory,
2212
+ useWaitForCommit,
2213
+ useWaitForNotes
2214
+ });