@naculus/connect-appkit-vue 0.2.8 → 0.4.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 CHANGED
@@ -292,99 +292,145 @@ import { resolveSimulationEndpoint } from "@naculus/connect-appkit-core";
292
292
  import {
293
293
  SimulationManager
294
294
  } from "@naculus/connect-core";
295
- import { onScopeDispose as onScopeDispose2, shallowRef as shallowRef2, unref as unref2 } from "vue";
296
- function useSimulateTransfer(options = {}) {
297
- const result = shallowRef2(null);
298
- const loading = shallowRef2(false);
295
+ import { shallowRef as shallowRef3, unref as unref2 } from "vue";
296
+
297
+ // src/internal/action-guard.ts
298
+ import { onScopeDispose as onScopeDispose2, shallowRef as shallowRef2 } from "vue";
299
+ function useActionGuard() {
300
+ const busy = shallowRef2(false);
299
301
  const error = shallowRef2(null);
300
- let manager;
302
+ let active = 0;
301
303
  let generation = 0;
302
304
  let disposed = false;
303
- const simulate = async (tokenAddress, from, to, amount, callOptions) => {
305
+ const run = async (action, fallbackMessage, normalizeError, options = {}) => {
304
306
  const own = ++generation;
305
- loading.value = true;
306
- error.value = null;
307
+ const commit = (write) => {
308
+ if (!disposed && own === generation) write();
309
+ };
310
+ active++;
311
+ busy.value = true;
312
+ if (!options.keepError) error.value = null;
307
313
  try {
308
- const fallbackRpcUrl = unref2(options.rpcUrl);
309
- const endpoint = resolveSimulationEndpoint(
310
- callOptions?.chainId,
311
- unref2(options.chainId),
312
- callOptions?.rpcUrl,
313
- fallbackRpcUrl
314
- );
315
- manager ??= new SimulationManager({
316
- enabled: true,
317
- rpcUrl: fallbackRpcUrl,
318
- autoSimulate: false
319
- });
320
- const value = await manager.simulateERC20Transfer(
321
- tokenAddress,
322
- from,
323
- to,
324
- amount,
325
- endpoint.chainId,
326
- callOptions?.decimals,
327
- endpoint.rpcUrl
328
- );
329
- if (!disposed && own === generation) result.value = value;
330
- return value;
314
+ return await action(commit);
331
315
  } catch (cause) {
332
- const normalized = cause instanceof Error ? cause : new Error(String(cause));
316
+ const normalized = normalizeError ? normalizeError(cause) : cause instanceof Error ? cause : new Error(fallbackMessage);
333
317
  if (!disposed && own === generation) error.value = normalized;
334
318
  throw normalized;
335
319
  } finally {
336
- if (!disposed && own === generation) loading.value = false;
320
+ try {
321
+ if (options.onSettled) commit(options.onSettled);
322
+ } finally {
323
+ active--;
324
+ if (!disposed) busy.value = active > 0;
325
+ }
337
326
  }
338
327
  };
339
- const reset = () => {
328
+ const invalidate = () => {
340
329
  generation++;
341
- result.value = null;
330
+ };
331
+ const reset = () => {
332
+ invalidate();
333
+ error.value = null;
334
+ };
335
+ const clearError = () => {
342
336
  error.value = null;
343
- loading.value = false;
344
337
  };
345
- onScopeDispose2(() => {
338
+ const dispose = () => {
346
339
  disposed = true;
347
340
  generation++;
348
- });
349
- return { result, loading, error, simulate, reset };
341
+ };
342
+ onScopeDispose2(dispose);
343
+ return { busy, error, run, clearError, reset, invalidate, dispose };
344
+ }
345
+
346
+ // src/useSimulateTransfer.ts
347
+ function useSimulateTransfer(options = {}) {
348
+ const guard = useActionGuard();
349
+ const result = shallowRef3(null);
350
+ const loading = shallowRef3(false);
351
+ let manager;
352
+ const simulate = async (tokenAddress, from, to, amount, callOptions) => {
353
+ loading.value = true;
354
+ return await guard.run(
355
+ async (commit) => {
356
+ const fallbackRpcUrl = unref2(options.rpcUrl);
357
+ const endpoint = resolveSimulationEndpoint(
358
+ callOptions?.chainId,
359
+ unref2(options.chainId),
360
+ callOptions?.rpcUrl,
361
+ fallbackRpcUrl
362
+ );
363
+ manager ??= new SimulationManager({
364
+ enabled: true,
365
+ rpcUrl: fallbackRpcUrl,
366
+ autoSimulate: false
367
+ });
368
+ const value = await manager.simulateERC20Transfer(
369
+ tokenAddress,
370
+ from,
371
+ to,
372
+ amount,
373
+ endpoint.chainId,
374
+ callOptions?.decimals,
375
+ endpoint.rpcUrl
376
+ );
377
+ commit(() => {
378
+ result.value = value;
379
+ });
380
+ return value;
381
+ },
382
+ "Simulation failed",
383
+ (cause) => cause instanceof Error ? cause : new Error(String(cause)),
384
+ {
385
+ onSettled: () => {
386
+ loading.value = false;
387
+ }
388
+ }
389
+ );
390
+ };
391
+ const reset = () => {
392
+ guard.reset();
393
+ result.value = null;
394
+ loading.value = false;
395
+ };
396
+ return { result, loading, error: guard.error, simulate, reset };
350
397
  }
351
398
 
352
399
  // src/useTransactionSimulation.ts
353
400
  import {
354
401
  simulateTransactionPreview
355
402
  } from "@naculus/connect-appkit-core";
356
- import { onScopeDispose as onScopeDispose3, shallowRef as shallowRef3, toValue as toValue2, unref as unref3, watch } from "vue";
403
+ import { onScopeDispose as onScopeDispose3, shallowRef as shallowRef4, toValue as toValue2, unref as unref3, watch } from "vue";
357
404
  function useTransactionSimulation(tx, options = {}) {
358
- const result = shallowRef3(void 0);
359
- const isSimulating = shallowRef3(false);
360
- const error = shallowRef3(null);
405
+ const guard = useActionGuard();
406
+ const result = shallowRef4(void 0);
407
+ const isSimulating = shallowRef4(false);
361
408
  let timer;
362
- let generation = 0;
363
- let disposed = false;
364
409
  const simulate = async () => {
365
- const own = ++generation;
366
410
  const transaction = toValue2(tx);
367
- if (transaction) {
368
- isSimulating.value = true;
369
- error.value = null;
370
- }
371
- try {
372
- const value = await simulateTransactionPreview(transaction, {
373
- chainId: unref3(options.chainId),
374
- currentChain: unref3(options.currentChain),
375
- publicClient: unref3(options.publicClient),
376
- evmAccount: unref3(options.evmAccount)
377
- });
378
- if (!disposed && own === generation) result.value = value;
379
- return value;
380
- } catch (cause) {
381
- const normalized = cause instanceof Error ? cause : new Error("Simulation failed");
382
- if (!disposed && own === generation) error.value = normalized;
383
- throw normalized;
384
- } finally {
385
- if (transaction && !disposed && own === generation)
386
- isSimulating.value = false;
387
- }
411
+ if (transaction) isSimulating.value = true;
412
+ return await guard.run(
413
+ async (commit) => {
414
+ const value = await simulateTransactionPreview(transaction, {
415
+ chainId: unref3(options.chainId),
416
+ currentChain: unref3(options.currentChain),
417
+ publicClient: unref3(options.publicClient),
418
+ evmAccount: unref3(options.evmAccount)
419
+ });
420
+ commit(() => {
421
+ result.value = value;
422
+ });
423
+ return value;
424
+ },
425
+ "Simulation failed",
426
+ void 0,
427
+ {
428
+ keepError: !transaction,
429
+ onSettled: transaction ? () => {
430
+ isSimulating.value = false;
431
+ } : void 0
432
+ }
433
+ );
388
434
  };
389
435
  watch(
390
436
  [
@@ -395,9 +441,12 @@ function useTransactionSimulation(tx, options = {}) {
395
441
  () => unref3(options.evmAccount)
396
442
  ],
397
443
  ([transaction]) => {
398
- generation++;
444
+ guard.invalidate();
399
445
  if (timer) clearTimeout(timer);
400
- if (!transaction) return;
446
+ if (!transaction) {
447
+ isSimulating.value = false;
448
+ return;
449
+ }
401
450
  timer = setTimeout(() => {
402
451
  timer = void 0;
403
452
  void simulate().catch(() => {
@@ -407,17 +456,14 @@ function useTransactionSimulation(tx, options = {}) {
407
456
  { immediate: true }
408
457
  );
409
458
  const reset = () => {
410
- generation++;
459
+ guard.reset();
411
460
  result.value = void 0;
412
- error.value = null;
413
461
  isSimulating.value = false;
414
462
  };
415
463
  onScopeDispose3(() => {
416
- disposed = true;
417
- generation++;
418
464
  if (timer) clearTimeout(timer);
419
465
  });
420
- return { result, isSimulating, error, simulate, reset };
466
+ return { result, isSimulating, error: guard.error, simulate, reset };
421
467
  }
422
468
 
423
469
  // src/useERC20Transfer.ts
@@ -432,7 +478,7 @@ import {
432
478
  parseUnits,
433
479
  WalletError as WalletError2
434
480
  } from "@naculus/connect-core";
435
- import { onScopeDispose as onScopeDispose4, shallowRef as shallowRef4, toValue as toValue3, unref as unref4, watch as watch2 } from "vue";
481
+ import { onScopeDispose as onScopeDispose4, shallowRef as shallowRef5, toValue as toValue3, unref as unref4, watch as watch2 } from "vue";
436
482
 
437
483
  // src/erc20.ts
438
484
  import {
@@ -457,8 +503,8 @@ function assertErc20Context(token, chainId, account, connected) {
457
503
  function useERC20Transfer(options) {
458
504
  const initialToken = toValue3(options.token);
459
505
  const decimals = createDecimalsCache(initialToken, initialToken.decimals);
460
- const isSending = shallowRef4(false);
461
- const error = shallowRef4(null);
506
+ const isSending = shallowRef5(false);
507
+ const error = shallowRef5(null);
462
508
  let generation = 0;
463
509
  let disposed = false;
464
510
  watch2(
@@ -553,7 +599,7 @@ import {
553
599
  import {
554
600
  computed as computed3,
555
601
  onScopeDispose as onScopeDispose5,
556
- shallowRef as shallowRef5,
602
+ shallowRef as shallowRef6,
557
603
  toValue as toValue4,
558
604
  unref as unref5,
559
605
  watch as watch3
@@ -562,10 +608,10 @@ var MAX_UINT256 = (1n << 256n) - 1n;
562
608
  function useERC20Approve(options) {
563
609
  const initialToken = toValue4(options.token);
564
610
  const decimals = createDecimalsCache2(initialToken, initialToken.decimals);
565
- const allowanceRaw = shallowRef5(null);
566
- const isApproving = shallowRef5(false);
567
- const isFetchingAllowance = shallowRef5(false);
568
- const error = shallowRef5(null);
611
+ const allowanceRaw = shallowRef6(null);
612
+ const isApproving = shallowRef6(false);
613
+ const isFetchingAllowance = shallowRef6(false);
614
+ const error = shallowRef6(null);
569
615
  let generation = 0;
570
616
  let allowanceGeneration = 0;
571
617
  let disposed = false;
@@ -786,7 +832,7 @@ function useAccount(accounts, connected) {
786
832
  }
787
833
 
788
834
  // src/useSession.ts
789
- import { computed as computed6, shallowRef as shallowRef6, toValue as toValue7, watch as watch4 } from "vue";
835
+ import { computed as computed6, shallowRef as shallowRef7, toValue as toValue7, watch as watch4 } from "vue";
790
836
  function readSession(manager) {
791
837
  const bundle = manager?.getActiveBundle();
792
838
  if (!bundle) {
@@ -805,7 +851,7 @@ function readSession(manager) {
805
851
  };
806
852
  }
807
853
  function useSession(manager) {
808
- const snapshot = shallowRef6(readSession(toValue7(manager)));
854
+ const snapshot = shallowRef7(readSession(toValue7(manager)));
809
855
  watch4(
810
856
  () => toValue7(manager),
811
857
  (current, _previous, onCleanup) => {
@@ -841,50 +887,6 @@ function useSession(manager) {
841
887
  // src/useConnect.ts
842
888
  import { WalletError as WalletError4 } from "@naculus/connect-core";
843
889
  import { computed as computed7, toValue as toValue8, unref as unref6 } from "vue";
844
-
845
- // src/internal/action-guard.ts
846
- import { onScopeDispose as onScopeDispose6, shallowRef as shallowRef7 } from "vue";
847
- function useActionGuard() {
848
- const busy = shallowRef7(false);
849
- const error = shallowRef7(null);
850
- let active = 0;
851
- let generation = 0;
852
- let disposed = false;
853
- const run = async (action, fallbackMessage, normalizeError) => {
854
- const own = ++generation;
855
- const commit = (write) => {
856
- if (!disposed && own === generation) write();
857
- };
858
- active++;
859
- busy.value = true;
860
- error.value = null;
861
- try {
862
- return await action(commit);
863
- } catch (cause) {
864
- const normalized = normalizeError ? normalizeError(cause) : cause instanceof Error ? cause : new Error(fallbackMessage);
865
- if (!disposed && own === generation) error.value = normalized;
866
- throw normalized;
867
- } finally {
868
- active--;
869
- if (!disposed) busy.value = active > 0;
870
- }
871
- };
872
- const reset = () => {
873
- generation++;
874
- error.value = null;
875
- };
876
- const clearError = () => {
877
- error.value = null;
878
- };
879
- const dispose = () => {
880
- disposed = true;
881
- generation++;
882
- };
883
- onScopeDispose6(dispose);
884
- return { busy, error, run, clearError, reset, dispose };
885
- }
886
-
887
- // src/useConnect.ts
888
890
  function useConnect(action, status) {
889
891
  const guard = useActionGuard();
890
892
  let inFlight = null;
@@ -1052,46 +1054,32 @@ function useSolanaTransaction(options) {
1052
1054
  }
1053
1055
 
1054
1056
  // src/useSignInWithX.ts
1055
- import { onScopeDispose as onScopeDispose7, shallowRef as shallowRef10, unref as unref12 } from "vue";
1057
+ import { shallowRef as shallowRef10, unref as unref12 } from "vue";
1056
1058
  function useSignInWithX(action) {
1057
- const isSigningIn = shallowRef10(false);
1059
+ const guard = useActionGuard();
1058
1060
  const result = shallowRef10(null);
1059
- const error = shallowRef10(null);
1060
- let generation = 0;
1061
- let active = 0;
1062
- let disposed = false;
1063
- const signIn = async (options) => {
1061
+ const signIn = (options) => {
1064
1062
  const invoke = unref12(action);
1065
- const own = ++generation;
1066
- active++;
1067
- isSigningIn.value = true;
1068
- error.value = null;
1069
- try {
1063
+ return guard.run(async (commit) => {
1070
1064
  const next = await invoke(options);
1071
- if (!disposed && own === generation) result.value = next;
1065
+ commit(() => {
1066
+ result.value = next;
1067
+ });
1072
1068
  return next;
1073
- } catch (cause) {
1074
- const normalized = cause instanceof Error ? cause : new Error("SIWX sign-in failed");
1075
- if (!disposed && own === generation) error.value = normalized;
1076
- throw normalized;
1077
- } finally {
1078
- active--;
1079
- if (!disposed) isSigningIn.value = active > 0;
1080
- }
1081
- };
1082
- const clearError = () => {
1083
- error.value = null;
1069
+ }, "SIWX sign-in failed");
1084
1070
  };
1085
1071
  const reset = () => {
1086
- generation++;
1072
+ guard.reset();
1087
1073
  result.value = null;
1088
- error.value = null;
1089
1074
  };
1090
- onScopeDispose7(() => {
1091
- disposed = true;
1092
- generation++;
1093
- });
1094
- return { signIn, isSigningIn, result, error, clearError, reset };
1075
+ return {
1076
+ signIn,
1077
+ isSigningIn: guard.busy,
1078
+ result,
1079
+ error: guard.error,
1080
+ clearError: guard.clearError,
1081
+ reset
1082
+ };
1095
1083
  }
1096
1084
 
1097
1085
  // src/useSignInWithEthereum.ts
@@ -1131,7 +1119,7 @@ import {
1131
1119
  } from "@naculus/connect-appkit-core";
1132
1120
  import {
1133
1121
  computed as computed12,
1134
- onScopeDispose as onScopeDispose9,
1122
+ onScopeDispose as onScopeDispose7,
1135
1123
  shallowRef as shallowRef12,
1136
1124
  toValue as toValue13,
1137
1125
  unref as unref14,
@@ -1140,7 +1128,7 @@ import {
1140
1128
 
1141
1129
  // src/useSessionKeys.ts
1142
1130
  import { getSharedSessionKeyManager } from "@naculus/connect-appkit-core";
1143
- import { computed as computed11, onScopeDispose as onScopeDispose8, shallowRef as shallowRef11, toValue as toValue12, watch as watch5 } from "vue";
1131
+ import { computed as computed11, onScopeDispose as onScopeDispose6, shallowRef as shallowRef11, toValue as toValue12, watch as watch5 } from "vue";
1144
1132
  function resolveManager(config, options) {
1145
1133
  return options.manager ?? getSharedSessionKeyManager(config);
1146
1134
  }
@@ -1177,7 +1165,7 @@ function useSessionKeys(connected, config, options = {}) {
1177
1165
  },
1178
1166
  { immediate: true }
1179
1167
  );
1180
- onScopeDispose8(() => {
1168
+ onScopeDispose6(() => {
1181
1169
  disposed = true;
1182
1170
  generation++;
1183
1171
  });
@@ -1264,6 +1252,10 @@ function useDelegationPolicy(options) {
1264
1252
  previewExecution: (callCount, atomicity) => unref14(options.previewExecution)(callCount, atomicity),
1265
1253
  sponsorship: options.sponsorship,
1266
1254
  adapter: options.adapter,
1255
+ signTypedData: options.signTypedData ? (typedData) => unref14(
1256
+ options.signTypedData
1257
+ )(typedData) : void 0,
1258
+ chainId: () => toValue13(options.chainId) ?? null,
1267
1259
  delegation: () => toValue13(options.delegation),
1268
1260
  encryptionKeyConfigured: Boolean(options.managerConfig?.encryptionKey),
1269
1261
  storageAvailable: () => sessionKeys.storageAvailable,
@@ -1299,7 +1291,7 @@ function useDelegationPolicy(options) {
1299
1291
  },
1300
1292
  { immediate: true }
1301
1293
  );
1302
- onScopeDispose9(() => {
1294
+ onScopeDispose7(() => {
1303
1295
  disposed = true;
1304
1296
  verifyGeneration++;
1305
1297
  });
@@ -1342,7 +1334,7 @@ import {
1342
1334
  import { WalletError as WalletError5 } from "@naculus/connect-core";
1343
1335
  import {
1344
1336
  computed as computed13,
1345
- onScopeDispose as onScopeDispose10,
1337
+ onScopeDispose as onScopeDispose8,
1346
1338
  shallowRef as shallowRef13,
1347
1339
  toValue as toValue14,
1348
1340
  unref as unref15,
@@ -1473,7 +1465,7 @@ function useSmartAccount(options) {
1473
1465
  });
1474
1466
  return addr;
1475
1467
  }, "Failed to get smart account address");
1476
- onScopeDispose10(() => {
1468
+ onScopeDispose8(() => {
1477
1469
  disposed = true;
1478
1470
  generation++;
1479
1471
  });
@@ -1497,7 +1489,7 @@ import {
1497
1489
  resolveUserOpChain
1498
1490
  } from "@naculus/connect-appkit-core";
1499
1491
  import { WalletError as WalletError6 } from "@naculus/connect-core";
1500
- import { onScopeDispose as onScopeDispose11, shallowRef as shallowRef14, toValue as toValue15, unref as unref16 } from "vue";
1492
+ import { onScopeDispose as onScopeDispose9, shallowRef as shallowRef14, toValue as toValue15, unref as unref16 } from "vue";
1501
1493
  function useSendUserOperation(options) {
1502
1494
  const userOpHash = shallowRef14(null);
1503
1495
  const receipt = shallowRef14(null);
@@ -1588,7 +1580,7 @@ function useSendUserOperation(options) {
1588
1580
  isEstimating.value = false;
1589
1581
  error.value = null;
1590
1582
  };
1591
- onScopeDispose11(() => {
1583
+ onScopeDispose9(() => {
1592
1584
  disposed = true;
1593
1585
  requestId++;
1594
1586
  });
@@ -1608,7 +1600,7 @@ import {
1608
1600
  fetchUserOperationReceipt,
1609
1601
  InvalidUserOperationReceiptError
1610
1602
  } from "@naculus/connect-appkit-core";
1611
- import { onScopeDispose as onScopeDispose12, shallowRef as shallowRef15, toValue as toValue16 } from "vue";
1603
+ import { onScopeDispose as onScopeDispose10, shallowRef as shallowRef15, toValue as toValue16 } from "vue";
1612
1604
  function useUserOpStatus(options) {
1613
1605
  const status = shallowRef15("idle");
1614
1606
  const receipt = shallowRef15(null);
@@ -1722,7 +1714,7 @@ function useUserOpStatus(options) {
1722
1714
  attempts.value = 0;
1723
1715
  elapsedMs.value = 0;
1724
1716
  };
1725
- onScopeDispose12(stop);
1717
+ onScopeDispose10(stop);
1726
1718
  return {
1727
1719
  status,
1728
1720
  receipt,
@@ -1738,7 +1730,7 @@ function useUserOpStatus(options) {
1738
1730
  }
1739
1731
 
1740
1732
  // src/useSendCalls.ts
1741
- import { computed as computed14, onScopeDispose as onScopeDispose13, shallowRef as shallowRef16, toValue as toValue17, unref as unref17 } from "vue";
1733
+ import { computed as computed14, onScopeDispose as onScopeDispose11, shallowRef as shallowRef16, toValue as toValue17, unref as unref17 } from "vue";
1742
1734
  function useSendCalls(options) {
1743
1735
  const status = shallowRef16("idle");
1744
1736
  const error = shallowRef16(null);
@@ -1785,7 +1777,7 @@ function useSendCalls(options) {
1785
1777
  batchHash.value = null;
1786
1778
  callsStatus.value = null;
1787
1779
  };
1788
- onScopeDispose13(() => {
1780
+ onScopeDispose11(() => {
1789
1781
  disposed = true;
1790
1782
  sendGeneration++;
1791
1783
  statusGeneration++;
@@ -1897,37 +1889,45 @@ function useSiwxAuthSession(options) {
1897
1889
  // src/useBalance.ts
1898
1890
  import { bareEvmAddress as bareEvmAddress5 } from "@naculus/connect-appkit-core";
1899
1891
  import { formatUnits as formatUnits2 } from "@naculus/connect-core";
1900
- import { computed as computed18, onScopeDispose as onScopeDispose14, shallowRef as shallowRef17, toValue as toValue21, watch as watch8 } from "vue";
1892
+ import { computed as computed18, onScopeDispose as onScopeDispose12, shallowRef as shallowRef17, toValue as toValue21, watch as watch8 } from "vue";
1901
1893
  function useBalance(account, client, options = {}) {
1894
+ const guard = useActionGuard();
1902
1895
  const balance = shallowRef17(null);
1903
1896
  const isFetching = shallowRef17(false);
1904
- const error = shallowRef17(null);
1905
- let generation = 0;
1906
- let disposed = false;
1907
1897
  let timer = null;
1908
1898
  const refetch = async () => {
1909
1899
  const reader = toValue21(client);
1910
1900
  const address = bareEvmAddress5(toValue21(account));
1911
- const own = ++generation;
1912
1901
  if (!reader || !address) {
1902
+ guard.reset();
1913
1903
  balance.value = null;
1914
- error.value = null;
1915
1904
  isFetching.value = false;
1916
1905
  return;
1917
1906
  }
1918
1907
  isFetching.value = true;
1919
- error.value = null;
1920
- try {
1921
- const next = await reader.getBalance({ address });
1922
- if (disposed || own !== generation) return;
1923
- balance.value = next.toString();
1924
- } catch (cause) {
1925
- if (disposed || own !== generation) return;
1926
- balance.value = null;
1927
- error.value = cause instanceof Error ? cause : new Error("Balance read failed");
1928
- } finally {
1929
- if (!disposed && own === generation) isFetching.value = false;
1930
- }
1908
+ await guard.run(
1909
+ async (commit) => {
1910
+ try {
1911
+ const next = await reader.getBalance({ address });
1912
+ commit(() => {
1913
+ balance.value = next.toString();
1914
+ });
1915
+ } catch (cause) {
1916
+ commit(() => {
1917
+ balance.value = null;
1918
+ });
1919
+ throw cause;
1920
+ }
1921
+ },
1922
+ "Balance read failed",
1923
+ void 0,
1924
+ {
1925
+ onSettled: () => {
1926
+ isFetching.value = false;
1927
+ }
1928
+ }
1929
+ ).catch(() => {
1930
+ });
1931
1931
  };
1932
1932
  const stopTimer = () => {
1933
1933
  if (timer) clearInterval(timer);
@@ -1946,11 +1946,7 @@ function useBalance(account, client, options = {}) {
1946
1946
  },
1947
1947
  { immediate: true }
1948
1948
  );
1949
- onScopeDispose14(() => {
1950
- disposed = true;
1951
- generation++;
1952
- stopTimer();
1953
- });
1949
+ onScopeDispose12(stopTimer);
1954
1950
  return {
1955
1951
  balance,
1956
1952
  formatted: computed18(
@@ -1958,7 +1954,7 @@ function useBalance(account, client, options = {}) {
1958
1954
  ),
1959
1955
  symbol: computed18(() => toValue21(options.symbol) ?? null),
1960
1956
  isFetching,
1961
- error,
1957
+ error: guard.error,
1962
1958
  refetch
1963
1959
  };
1964
1960
  }
@@ -1967,47 +1963,66 @@ function useBalance(account, client, options = {}) {
1967
1963
  import {
1968
1964
  isQuotableInput
1969
1965
  } from "@naculus/connect-appkit-core";
1970
- import { onScopeDispose as onScopeDispose15, shallowRef as shallowRef18, toValue as toValue22, unref as unref21, watch as watch9 } from "vue";
1966
+ import { onScopeDispose as onScopeDispose13, shallowRef as shallowRef18, toValue as toValue22, unref as unref21, watch as watch9 } from "vue";
1971
1967
  function useRouteQuote(input, getQuotes, options = {}) {
1968
+ const guard = useActionGuard();
1972
1969
  const quotes = shallowRef18([]);
1973
1970
  const loading = shallowRef18(false);
1974
- const error = shallowRef18(null);
1975
- let generation = 0;
1976
- let disposed = false;
1977
1971
  let timer = null;
1978
1972
  const clearTimer = () => {
1979
1973
  if (timer) clearTimeout(timer);
1980
1974
  timer = null;
1981
1975
  };
1982
- const fetchQuotes = async () => {
1983
- const current = toValue22(input);
1984
- const fn = unref21(getQuotes);
1985
- const own = ++generation;
1976
+ const requestable = (current) => {
1986
1977
  if (!isQuotableInput(current)) {
1978
+ guard.invalidate();
1979
+ loading.value = false;
1987
1980
  quotes.value = [];
1988
- return;
1981
+ return null;
1989
1982
  }
1983
+ const fn = unref21(getQuotes);
1984
+ if (!fn) {
1985
+ guard.invalidate();
1986
+ loading.value = false;
1987
+ return null;
1988
+ }
1989
+ return fn;
1990
+ };
1991
+ const fetchQuotes = async () => {
1992
+ const current = toValue22(input);
1993
+ const fn = requestable(current);
1990
1994
  if (!fn) return;
1991
1995
  loading.value = true;
1992
- error.value = null;
1993
- try {
1994
- const result = await fn(
1995
- current.fromChain,
1996
- current.toChain,
1997
- current.fromToken,
1998
- current.amount,
1999
- current.options,
2000
- current.toToken
2001
- );
2002
- if (disposed || own !== generation) return;
2003
- quotes.value = result;
2004
- } catch (cause) {
2005
- if (disposed || own !== generation) return;
2006
- error.value = cause instanceof Error ? cause : new Error(String(cause));
2007
- quotes.value = [];
2008
- } finally {
2009
- if (!disposed && own === generation) loading.value = false;
2010
- }
1996
+ await guard.run(
1997
+ async (commit) => {
1998
+ try {
1999
+ const result = await fn(
2000
+ current.fromChain,
2001
+ current.toChain,
2002
+ current.fromToken,
2003
+ current.amount,
2004
+ current.options,
2005
+ current.toToken
2006
+ );
2007
+ commit(() => {
2008
+ quotes.value = result;
2009
+ });
2010
+ } catch (cause) {
2011
+ commit(() => {
2012
+ quotes.value = [];
2013
+ });
2014
+ throw cause;
2015
+ }
2016
+ },
2017
+ "Route quote failed",
2018
+ (cause) => cause instanceof Error ? cause : new Error(String(cause)),
2019
+ {
2020
+ onSettled: () => {
2021
+ loading.value = false;
2022
+ }
2023
+ }
2024
+ ).catch(() => {
2025
+ });
2011
2026
  };
2012
2027
  watch9(
2013
2028
  [
@@ -2018,12 +2033,10 @@ function useRouteQuote(input, getQuotes, options = {}) {
2018
2033
  () => toValue22(input).amount,
2019
2034
  () => unref21(getQuotes)
2020
2035
  ],
2021
- ([fromChain, toChain, fromToken, , amount]) => {
2036
+ () => {
2022
2037
  clearTimer();
2023
- if (!fromChain || !toChain || !fromToken || !amount) {
2024
- quotes.value = [];
2025
- return;
2026
- }
2038
+ guard.invalidate();
2039
+ if (!requestable(toValue22(input))) return;
2027
2040
  timer = setTimeout(() => {
2028
2041
  timer = null;
2029
2042
  void fetchQuotes();
@@ -2031,21 +2044,16 @@ function useRouteQuote(input, getQuotes, options = {}) {
2031
2044
  },
2032
2045
  { immediate: true }
2033
2046
  );
2034
- onScopeDispose15(() => {
2035
- disposed = true;
2036
- generation++;
2037
- clearTimer();
2038
- });
2047
+ onScopeDispose13(clearTimer);
2039
2048
  return {
2040
2049
  quotes,
2041
2050
  loading,
2042
- error,
2051
+ error: guard.error,
2043
2052
  refresh: fetchQuotes,
2044
2053
  clear: () => {
2045
2054
  clearTimer();
2046
- generation++;
2055
+ guard.reset();
2047
2056
  quotes.value = [];
2048
- error.value = null;
2049
2057
  loading.value = false;
2050
2058
  }
2051
2059
  };
@@ -2055,35 +2063,49 @@ function useRouteQuote(input, getQuotes, options = {}) {
2055
2063
  import {
2056
2064
  compareCostsKey
2057
2065
  } from "@naculus/connect-appkit-core";
2058
- import { onScopeDispose as onScopeDispose16, shallowRef as shallowRef19, toValue as toValue23, unref as unref22, watch as watch10 } from "vue";
2066
+ import { shallowRef as shallowRef19, toValue as toValue23, unref as unref22, watch as watch10 } from "vue";
2059
2067
  function useCompareCosts(input, compareCosts) {
2068
+ const guard = useActionGuard();
2060
2069
  const comparisons = shallowRef19([]);
2061
2070
  const loading = shallowRef19(false);
2062
- const error = shallowRef19(null);
2063
- let generation = 0;
2064
- let disposed = false;
2065
2071
  const fetchComparisons = async () => {
2066
2072
  const { operation, chains, options } = toValue23(input);
2067
2073
  const fn = unref22(compareCosts);
2068
- const own = ++generation;
2069
2074
  if (!chains || chains.length === 0) {
2075
+ guard.invalidate();
2076
+ loading.value = false;
2070
2077
  comparisons.value = [];
2071
2078
  return;
2072
2079
  }
2073
- if (!fn) return;
2074
- loading.value = true;
2075
- error.value = null;
2076
- try {
2077
- const result = await fn(operation, chains, options);
2078
- if (disposed || own !== generation) return;
2079
- comparisons.value = result;
2080
- } catch (cause) {
2081
- if (disposed || own !== generation) return;
2082
- error.value = cause instanceof Error ? cause : new Error(String(cause));
2083
- comparisons.value = [];
2084
- } finally {
2085
- if (!disposed && own === generation) loading.value = false;
2080
+ if (!fn) {
2081
+ guard.invalidate();
2082
+ loading.value = false;
2083
+ return;
2086
2084
  }
2085
+ loading.value = true;
2086
+ await guard.run(
2087
+ async (commit) => {
2088
+ try {
2089
+ const result = await fn(operation, chains, options);
2090
+ commit(() => {
2091
+ comparisons.value = result;
2092
+ });
2093
+ } catch (cause) {
2094
+ commit(() => {
2095
+ comparisons.value = [];
2096
+ });
2097
+ throw cause;
2098
+ }
2099
+ },
2100
+ "Cost comparison failed",
2101
+ (cause) => cause instanceof Error ? cause : new Error(String(cause)),
2102
+ {
2103
+ onSettled: () => {
2104
+ loading.value = false;
2105
+ }
2106
+ }
2107
+ ).catch(() => {
2108
+ });
2087
2109
  };
2088
2110
  watch10(
2089
2111
  [() => compareCostsKey(toValue23(input)), () => unref22(compareCosts)],
@@ -2092,11 +2114,12 @@ function useCompareCosts(input, compareCosts) {
2092
2114
  },
2093
2115
  { immediate: true }
2094
2116
  );
2095
- onScopeDispose16(() => {
2096
- disposed = true;
2097
- generation++;
2098
- });
2099
- return { comparisons, loading, error, refresh: fetchComparisons };
2117
+ return {
2118
+ comparisons,
2119
+ loading,
2120
+ error: guard.error,
2121
+ refresh: fetchComparisons
2122
+ };
2100
2123
  }
2101
2124
 
2102
2125
  // src/useExecuteRoute.ts
@@ -2104,7 +2127,7 @@ import {
2104
2127
  toExecuteRouteError,
2105
2128
  validateRouteRecipient
2106
2129
  } from "@naculus/connect-appkit-core";
2107
- import { onScopeDispose as onScopeDispose17, shallowRef as shallowRef20, unref as unref23 } from "vue";
2130
+ import { onScopeDispose as onScopeDispose14, shallowRef as shallowRef20, unref as unref23 } from "vue";
2108
2131
  function useExecuteRoute(executeRoute) {
2109
2132
  const executing = shallowRef20(false);
2110
2133
  const result = shallowRef20(null);
@@ -2150,7 +2173,7 @@ function useExecuteRoute(executeRoute) {
2150
2173
  if (!disposed) executing.value = false;
2151
2174
  }
2152
2175
  };
2153
- onScopeDispose17(() => {
2176
+ onScopeDispose14(() => {
2154
2177
  disposed = true;
2155
2178
  });
2156
2179
  return {
@@ -2171,17 +2194,15 @@ import { eip155ChainIdToNumber } from "@naculus/connect-appkit-core";
2171
2194
  import {
2172
2195
  TokenListManager
2173
2196
  } from "@naculus/connect-core";
2174
- import { onScopeDispose as onScopeDispose18, shallowRef as shallowRef21, toValue as toValue24, watch as watch11 } from "vue";
2197
+ import { shallowRef as shallowRef21, toValue as toValue24, watch as watch11 } from "vue";
2175
2198
  function useTokenList(chainId, options = {}) {
2176
2199
  const config = {};
2177
2200
  if (options.sources) config.sources = options.sources;
2178
2201
  const manager = options.manager ?? new TokenListManager(config);
2202
+ const guard = useActionGuard();
2179
2203
  const tokens = shallowRef21([]);
2180
2204
  const isLoading = shallowRef21(options.autoLoad !== false);
2181
2205
  const isLoaded = shallowRef21(false);
2182
- const error = shallowRef21(null);
2183
- let generation = 0;
2184
- let disposed = false;
2185
2206
  const select = () => {
2186
2207
  const id = toValue24(chainId);
2187
2208
  const numeric = id ? eip155ChainIdToNumber(id) : void 0;
@@ -2190,20 +2211,24 @@ function useTokenList(chainId, options = {}) {
2190
2211
  );
2191
2212
  };
2192
2213
  const run = async (op) => {
2193
- const own = ++generation;
2194
2214
  isLoading.value = true;
2195
- error.value = null;
2196
- try {
2197
- await op();
2198
- if (disposed || own !== generation) return;
2199
- tokens.value = select();
2200
- isLoaded.value = true;
2201
- } catch (cause) {
2202
- if (disposed || own !== generation) return;
2203
- error.value = cause instanceof Error ? cause : new Error(String(cause));
2204
- } finally {
2205
- if (!disposed && own === generation) isLoading.value = false;
2206
- }
2215
+ await guard.run(
2216
+ async (commit) => {
2217
+ await op();
2218
+ commit(() => {
2219
+ tokens.value = select();
2220
+ isLoaded.value = true;
2221
+ });
2222
+ },
2223
+ "Token list load failed",
2224
+ (cause) => cause instanceof Error ? cause : new Error(String(cause)),
2225
+ {
2226
+ onSettled: () => {
2227
+ isLoading.value = false;
2228
+ }
2229
+ }
2230
+ ).catch(() => {
2231
+ });
2207
2232
  };
2208
2233
  watch11(
2209
2234
  () => toValue24(chainId),
@@ -2212,15 +2237,11 @@ function useTokenList(chainId, options = {}) {
2212
2237
  },
2213
2238
  { immediate: true }
2214
2239
  );
2215
- onScopeDispose18(() => {
2216
- disposed = true;
2217
- generation++;
2218
- });
2219
2240
  return {
2220
2241
  tokens,
2221
2242
  isLoading,
2222
2243
  isLoaded,
2223
- error,
2244
+ error: guard.error,
2224
2245
  refetch: () => run(() => manager.refresh())
2225
2246
  };
2226
2247
  }
@@ -2230,7 +2251,7 @@ import { eip155ChainIdToNumber as eip155ChainIdToNumber2 } from "@naculus/connec
2230
2251
  import {
2231
2252
  TokenListManager as TokenListManager2
2232
2253
  } from "@naculus/connect-core";
2233
- import { onScopeDispose as onScopeDispose19, shallowRef as shallowRef22, toValue as toValue25, watch as watch12 } from "vue";
2254
+ import { onScopeDispose as onScopeDispose15, shallowRef as shallowRef22, toValue as toValue25, watch as watch12 } from "vue";
2234
2255
  var DEBOUNCE_MS = 300;
2235
2256
  var EMPTY = { exact: [], fuzzy: [], hasMore: false };
2236
2257
  var sharedManager = null;
@@ -2273,7 +2294,7 @@ function useTokenSearch(query, chainId, options = {}) {
2273
2294
  },
2274
2295
  { immediate: true }
2275
2296
  );
2276
- onScopeDispose19(clear);
2297
+ onScopeDispose15(clear);
2277
2298
  return { results, isSearching };
2278
2299
  }
2279
2300
 
@@ -2291,60 +2312,68 @@ function useValidateDestination(address) {
2291
2312
  // src/useTokenBalance.ts
2292
2313
  import { bareEvmAddress as bareEvmAddress6 } from "@naculus/connect-appkit-core";
2293
2314
  import { ERC20_MIN_ABI as ERC20_MIN_ABI3, formatUnits as formatUnits3 } from "@naculus/connect-core";
2294
- import { onScopeDispose as onScopeDispose20, shallowRef as shallowRef23, toValue as toValue27, watch as watch13 } from "vue";
2315
+ import { onScopeDispose as onScopeDispose16, shallowRef as shallowRef23, toValue as toValue27, watch as watch13 } from "vue";
2295
2316
  function tokensKey(tokens) {
2296
2317
  return tokens.map((t) => `${t.address.toLowerCase()}|${t.decimals}|${t.symbol}`).join(",");
2297
2318
  }
2298
2319
  function useTokenBalance(account, client, tokens, options = {}) {
2320
+ const guard = useActionGuard();
2299
2321
  const tokenBalances = shallowRef23([]);
2300
2322
  const isFetching = shallowRef23(false);
2301
- const error = shallowRef23(null);
2302
- let generation = 0;
2303
- let disposed = false;
2304
2323
  let timer = null;
2305
2324
  const refetch = async () => {
2306
2325
  const reader = toValue27(client);
2307
2326
  const address = bareEvmAddress6(toValue27(account));
2308
2327
  const list = toValue27(tokens) ?? [];
2309
- const own = ++generation;
2310
2328
  if (!reader || !address || list.length === 0) {
2329
+ guard.reset();
2311
2330
  tokenBalances.value = [];
2312
- error.value = null;
2313
2331
  isFetching.value = false;
2314
2332
  return;
2315
2333
  }
2316
2334
  isFetching.value = true;
2317
- error.value = null;
2318
- try {
2319
- const results = await Promise.all(
2320
- list.map(async (token) => {
2321
- try {
2322
- const raw = await reader.readContract({
2323
- address: token.address,
2324
- abi: ERC20_MIN_ABI3,
2325
- functionName: "balanceOf",
2326
- args: [address]
2327
- });
2328
- const value = BigInt(raw);
2329
- return {
2330
- ...token,
2331
- balance: value.toString(),
2332
- formatted: formatUnits3(value, token.decimals)
2333
- };
2334
- } catch {
2335
- return { ...token, balance: null, formatted: null };
2336
- }
2337
- })
2338
- );
2339
- if (disposed || own !== generation) return;
2340
- tokenBalances.value = results;
2341
- } catch (cause) {
2342
- if (disposed || own !== generation) return;
2343
- tokenBalances.value = [];
2344
- error.value = cause instanceof Error ? cause : new Error("Failed to fetch token balances");
2345
- } finally {
2346
- if (!disposed && own === generation) isFetching.value = false;
2347
- }
2335
+ await guard.run(
2336
+ async (commit) => {
2337
+ try {
2338
+ const results = await Promise.all(
2339
+ list.map(async (token) => {
2340
+ try {
2341
+ const raw = await reader.readContract({
2342
+ address: token.address,
2343
+ abi: ERC20_MIN_ABI3,
2344
+ functionName: "balanceOf",
2345
+ args: [address]
2346
+ });
2347
+ const value = BigInt(raw);
2348
+ return {
2349
+ ...token,
2350
+ balance: value.toString(),
2351
+ formatted: formatUnits3(value, token.decimals)
2352
+ };
2353
+ } catch {
2354
+ return { ...token, balance: null, formatted: null };
2355
+ }
2356
+ })
2357
+ );
2358
+ commit(() => {
2359
+ tokenBalances.value = results;
2360
+ });
2361
+ } catch (cause) {
2362
+ commit(() => {
2363
+ tokenBalances.value = [];
2364
+ });
2365
+ throw cause;
2366
+ }
2367
+ },
2368
+ "Failed to fetch token balances",
2369
+ void 0,
2370
+ {
2371
+ onSettled: () => {
2372
+ isFetching.value = false;
2373
+ }
2374
+ }
2375
+ ).catch(() => {
2376
+ });
2348
2377
  };
2349
2378
  const stopTimer = () => {
2350
2379
  if (timer) clearInterval(timer);
@@ -2364,15 +2393,11 @@ function useTokenBalance(account, client, tokens, options = {}) {
2364
2393
  },
2365
2394
  { immediate: true }
2366
2395
  );
2367
- onScopeDispose20(() => {
2368
- disposed = true;
2369
- generation++;
2370
- stopTimer();
2371
- });
2396
+ onScopeDispose16(stopTimer);
2372
2397
  return {
2373
2398
  tokenBalances,
2374
2399
  isFetching,
2375
- error,
2400
+ error: guard.error,
2376
2401
  refetch,
2377
2402
  getTokenBalance: (tokenAddress) => tokenBalances.value.find(
2378
2403
  (t) => t.address.toLowerCase() === tokenAddress.toLowerCase()
@@ -2388,7 +2413,7 @@ import {
2388
2413
  REVOKE_DELEGATE,
2389
2414
  WalletError as WalletError7
2390
2415
  } from "@naculus/connect-core";
2391
- import { onScopeDispose as onScopeDispose21, shallowRef as shallowRef24, toValue as toValue28, watch as watch14 } from "vue";
2416
+ import { onScopeDispose as onScopeDispose17, shallowRef as shallowRef24, toValue as toValue28, watch as watch14 } from "vue";
2392
2417
  function useDelegate(options) {
2393
2418
  const result = shallowRef24(null);
2394
2419
  const isPending = shallowRef24(false);
@@ -2463,7 +2488,7 @@ function useDelegate(options) {
2463
2488
  reset,
2464
2489
  { flush: "sync" }
2465
2490
  );
2466
- onScopeDispose21(() => {
2491
+ onScopeDispose17(() => {
2467
2492
  disposed = true;
2468
2493
  requestId++;
2469
2494
  });
@@ -2483,37 +2508,44 @@ import {
2483
2508
  readDelegation,
2484
2509
  UNKNOWN_DELEGATION
2485
2510
  } from "@naculus/connect-core";
2486
- import { computed as computed20, onScopeDispose as onScopeDispose22, shallowRef as shallowRef25, toValue as toValue29, watch as watch15 } from "vue";
2511
+ import { computed as computed20, shallowRef as shallowRef25, toValue as toValue29, watch as watch15 } from "vue";
2487
2512
  function useDelegation(account, client, chainId) {
2513
+ const guard = useActionGuard();
2488
2514
  const status = shallowRef25(UNKNOWN_DELEGATION);
2489
2515
  const isFetching = shallowRef25(false);
2490
- const error = shallowRef25(null);
2491
- let generation = 0;
2492
- let disposed = false;
2493
2516
  const refetch = async () => {
2494
- const mine = ++generation;
2495
2517
  const reader = toValue29(client);
2496
2518
  const address = bareEvmAddress8(toValue29(account));
2497
2519
  status.value = UNKNOWN_DELEGATION;
2498
- error.value = null;
2499
2520
  if (!reader || !address) {
2521
+ guard.reset();
2500
2522
  isFetching.value = false;
2501
2523
  return;
2502
2524
  }
2503
2525
  isFetching.value = true;
2504
- try {
2505
- const code = await reader.getCode({ address });
2506
- if (!disposed && mine === generation) {
2507
- status.value = readDelegation(code ?? "0x");
2508
- }
2509
- } catch (cause) {
2510
- if (!disposed && mine === generation) {
2511
- status.value = UNKNOWN_DELEGATION;
2512
- error.value = cause instanceof Error ? cause : new Error("Code read failed");
2526
+ await guard.run(
2527
+ async (commit) => {
2528
+ try {
2529
+ const code = await reader.getCode({ address });
2530
+ commit(() => {
2531
+ status.value = readDelegation(code ?? "0x");
2532
+ });
2533
+ } catch (cause) {
2534
+ commit(() => {
2535
+ status.value = UNKNOWN_DELEGATION;
2536
+ });
2537
+ throw cause;
2538
+ }
2539
+ },
2540
+ "Code read failed",
2541
+ void 0,
2542
+ {
2543
+ onSettled: () => {
2544
+ isFetching.value = false;
2545
+ }
2513
2546
  }
2514
- } finally {
2515
- if (!disposed && mine === generation) isFetching.value = false;
2516
- }
2547
+ ).catch(() => {
2548
+ });
2517
2549
  };
2518
2550
  watch15(
2519
2551
  [() => toValue29(account), () => toValue29(client), () => toValue29(chainId)],
@@ -2522,52 +2554,94 @@ function useDelegation(account, client, chainId) {
2522
2554
  },
2523
2555
  { immediate: true, flush: "sync" }
2524
2556
  );
2525
- onScopeDispose22(() => {
2526
- disposed = true;
2527
- generation++;
2528
- });
2529
2557
  return {
2530
2558
  delegated: computed20(() => status.value.delegated),
2531
2559
  delegate: computed20(() => status.value.delegate),
2532
2560
  isFetching,
2533
- error,
2561
+ error: guard.error,
2534
2562
  refetch
2535
2563
  };
2536
2564
  }
2537
2565
 
2566
+ // src/usePaymentFetch.ts
2567
+ import {
2568
+ describePayment
2569
+ } from "@naculus/connect-appkit-core";
2570
+ import { onScopeDispose as onScopeDispose18, shallowRef as shallowRef26, unref as unref24 } from "vue";
2571
+ function usePaymentFetch(pay) {
2572
+ const guard = useActionGuard();
2573
+ const lastPayment = shallowRef26(null);
2574
+ let epoch = 0;
2575
+ onScopeDispose18(() => {
2576
+ epoch++;
2577
+ });
2578
+ const payFetch = (input, init) => {
2579
+ const invoke = unref24(pay);
2580
+ const own = epoch;
2581
+ return guard.run(async () => {
2582
+ const result = await invoke(input, init);
2583
+ const payment = describePayment(input, result);
2584
+ if (payment && own === epoch) lastPayment.value = payment;
2585
+ return result;
2586
+ }, "Paid request failed");
2587
+ };
2588
+ return {
2589
+ payFetch,
2590
+ isPending: guard.busy,
2591
+ lastPayment,
2592
+ error: guard.error,
2593
+ reset: () => {
2594
+ epoch++;
2595
+ guard.reset();
2596
+ lastPayment.value = null;
2597
+ }
2598
+ };
2599
+ }
2600
+
2538
2601
  // src/name-lookup.ts
2539
2602
  import { getResolver } from "@naculus/connect-appkit-core";
2540
- import { computed as computed21, onScopeDispose as onScopeDispose23, shallowRef as shallowRef26, toValue as toValue30, watch as watch16 } from "vue";
2603
+ import { computed as computed21, shallowRef as shallowRef27, toValue as toValue30, watch as watch16 } from "vue";
2541
2604
  function useNameLookup(options) {
2542
- const data = shallowRef26(null);
2543
- const loading = shallowRef26(false);
2544
- const error = shallowRef26(null);
2545
- let generation = 0;
2546
- let disposed = false;
2605
+ const guard = useActionGuard();
2606
+ const data = shallowRef27(null);
2607
+ const loading = shallowRef27(false);
2547
2608
  const run = () => {
2548
2609
  const input = toValue30(options.input).trim();
2549
2610
  const skip = toValue30(options.skip) ?? false;
2550
2611
  const scope = toValue30(options.scope);
2551
2612
  const config = toValue30(options.resolverConfig);
2552
- const mine = ++generation;
2553
2613
  if (!input || skip) {
2614
+ guard.reset();
2554
2615
  data.value = null;
2555
2616
  loading.value = false;
2556
- error.value = null;
2557
2617
  return;
2558
2618
  }
2559
2619
  data.value = null;
2560
2620
  loading.value = true;
2561
- error.value = null;
2562
- Promise.resolve().then(() => options.query(getResolver(config), input, scope)).then((result) => {
2563
- if (disposed || mine !== generation) return;
2564
- data.value = result;
2565
- loading.value = false;
2566
- }).catch((cause) => {
2567
- if (disposed || mine !== generation) return;
2568
- data.value = null;
2569
- error.value = cause instanceof Error ? cause : new Error(String(cause));
2570
- loading.value = false;
2621
+ void guard.run(
2622
+ async (commit) => {
2623
+ try {
2624
+ const result = await Promise.resolve().then(
2625
+ () => options.query(getResolver(config), input, scope)
2626
+ );
2627
+ commit(() => {
2628
+ data.value = result;
2629
+ });
2630
+ } catch (cause) {
2631
+ commit(() => {
2632
+ data.value = null;
2633
+ });
2634
+ throw cause;
2635
+ }
2636
+ },
2637
+ "Name lookup failed",
2638
+ (cause) => cause instanceof Error ? cause : new Error(String(cause)),
2639
+ {
2640
+ onSettled: () => {
2641
+ loading.value = false;
2642
+ }
2643
+ }
2644
+ ).catch(() => {
2571
2645
  });
2572
2646
  };
2573
2647
  watch16(
@@ -2580,14 +2654,10 @@ function useNameLookup(options) {
2580
2654
  run,
2581
2655
  { immediate: true, flush: "sync", deep: true }
2582
2656
  );
2583
- onScopeDispose23(() => {
2584
- disposed = true;
2585
- generation++;
2586
- });
2587
2657
  return {
2588
2658
  data,
2589
2659
  isLoading: computed21(() => loading.value),
2590
- error,
2660
+ error: guard.error,
2591
2661
  refetch: run
2592
2662
  };
2593
2663
  }
@@ -2662,13 +2732,13 @@ function useChain(chains, chainId) {
2662
2732
  }
2663
2733
 
2664
2734
  // src/usePassphraseGate.ts
2665
- import { onScopeDispose as onScopeDispose24, readonly, shallowRef as shallowRef27 } from "vue";
2735
+ import { onScopeDispose as onScopeDispose19, readonly, shallowRef as shallowRef28 } from "vue";
2666
2736
  function usePassphraseGate(gate) {
2667
- const request = shallowRef27(gate.getSnapshot());
2737
+ const request = shallowRef28(gate.getSnapshot());
2668
2738
  const unsubscribe = gate.subscribe(() => {
2669
2739
  request.value = gate.getSnapshot();
2670
2740
  });
2671
- onScopeDispose24(unsubscribe);
2741
+ onScopeDispose19(unsubscribe);
2672
2742
  return {
2673
2743
  request: readonly(request),
2674
2744
  submit: (passphrase) => gate.submit(passphrase),
@@ -2678,55 +2748,60 @@ function usePassphraseGate(gate) {
2678
2748
  }
2679
2749
 
2680
2750
  // src/useSolanaBalance.ts
2681
- import {
2682
- getSolanaBalance
2683
- } from "@naculus/connect-core";
2684
- import { onScopeDispose as onScopeDispose25, ref, shallowRef as shallowRef28, toValue as toValue33, watchEffect } from "vue";
2751
+ import { getSolanaBalance } from "@naculus/connect-core";
2752
+ import { ref, shallowRef as shallowRef29, toValue as toValue33, watchEffect } from "vue";
2685
2753
  function useSolanaBalance(address, rpcUrl) {
2686
- const balance = shallowRef28(null);
2754
+ const guard = useActionGuard();
2755
+ const balance = shallowRef29(null);
2687
2756
  const isFetching = ref(false);
2688
- const error = shallowRef28(null);
2689
- let generation = 0;
2690
- let disposed = false;
2691
2757
  const refetch = async () => {
2692
2758
  const addr = toValue33(address);
2693
2759
  const url = toValue33(rpcUrl);
2694
2760
  if (!addr || !url) {
2761
+ guard.invalidate();
2762
+ isFetching.value = false;
2695
2763
  balance.value = null;
2696
2764
  return;
2697
2765
  }
2698
- const own = ++generation;
2699
2766
  isFetching.value = true;
2700
- error.value = null;
2701
- try {
2702
- const next = await getSolanaBalance(url, addr);
2703
- if (disposed || own !== generation) return;
2704
- balance.value = next;
2705
- } catch (err) {
2706
- if (disposed || own !== generation) return;
2707
- balance.value = null;
2708
- error.value = err instanceof Error ? err : new Error("Balance read failed");
2709
- } finally {
2710
- if (!disposed && own === generation) isFetching.value = false;
2711
- }
2767
+ await guard.run(
2768
+ async (commit) => {
2769
+ try {
2770
+ const next = await getSolanaBalance(url, addr);
2771
+ commit(() => {
2772
+ balance.value = next;
2773
+ });
2774
+ } catch (err) {
2775
+ commit(() => {
2776
+ balance.value = null;
2777
+ });
2778
+ throw err;
2779
+ }
2780
+ },
2781
+ "Balance read failed",
2782
+ void 0,
2783
+ {
2784
+ onSettled: () => {
2785
+ isFetching.value = false;
2786
+ }
2787
+ }
2788
+ ).catch(() => {
2789
+ });
2712
2790
  };
2713
2791
  watchEffect(() => {
2714
2792
  toValue33(address);
2715
2793
  toValue33(rpcUrl);
2716
2794
  void refetch();
2717
2795
  });
2718
- onScopeDispose25(() => {
2719
- disposed = true;
2720
- });
2721
- return { balance, isFetching, error, refetch };
2796
+ return { balance, isFetching, error: guard.error, refetch };
2722
2797
  }
2723
2798
 
2724
2799
  // src/useLastTx.ts
2725
- import { shallowRef as shallowRef29, toValue as toValue34, watch as watch17 } from "vue";
2800
+ import { shallowRef as shallowRef30, toValue as toValue34, watch as watch17 } from "vue";
2726
2801
  function useLastTx(monitor) {
2727
- const lastTx = shallowRef29(null);
2728
- const lastConfirmedTx = shallowRef29(null);
2729
- const lastFailedTx = shallowRef29(null);
2802
+ const lastTx = shallowRef30(null);
2803
+ const lastConfirmedTx = shallowRef30(null);
2804
+ const lastFailedTx = shallowRef30(null);
2730
2805
  watch17(
2731
2806
  () => toValue34(monitor),
2732
2807
  (activeMonitor, _previous, onCleanup) => {
@@ -2766,35 +2841,39 @@ function useLastTx(monitor) {
2766
2841
  }
2767
2842
 
2768
2843
  // src/useTxHistory.ts
2769
- import { computed as computed24, shallowRef as shallowRef30, toValue as toValue35, watch as watch18 } from "vue";
2844
+ import { computed as computed24, shallowRef as shallowRef31, toValue as toValue35, watch as watch18 } from "vue";
2770
2845
  function useTxHistory(address, chainId, monitor) {
2771
- const entries = shallowRef30([]);
2772
- const isLoading = shallowRef30(false);
2773
- const error = shallowRef30(null);
2774
- let generation = 0;
2846
+ const guard = useActionGuard();
2847
+ const entries = shallowRef31([]);
2848
+ const isLoading = shallowRef31(false);
2775
2849
  const refresh = async () => {
2776
- const mine = ++generation;
2777
2850
  const activeMonitor = toValue35(monitor);
2778
2851
  if (!activeMonitor) {
2852
+ guard.reset();
2779
2853
  entries.value = [];
2780
2854
  isLoading.value = false;
2781
- error.value = null;
2782
2855
  return;
2783
2856
  }
2784
2857
  isLoading.value = true;
2785
- error.value = null;
2786
- try {
2787
- const result = await activeMonitor.getTxHistory(
2788
- toValue35(address) ?? void 0,
2789
- toValue35(chainId) ?? void 0
2790
- );
2791
- if (mine === generation) entries.value = result;
2792
- } catch (err) {
2793
- if (mine !== generation) return;
2794
- error.value = err instanceof Error ? err : new Error("Failed to load transaction history");
2795
- } finally {
2796
- if (mine === generation) isLoading.value = false;
2797
- }
2858
+ await guard.run(
2859
+ async (commit) => {
2860
+ const result = await activeMonitor.getTxHistory(
2861
+ toValue35(address) ?? void 0,
2862
+ toValue35(chainId) ?? void 0
2863
+ );
2864
+ commit(() => {
2865
+ entries.value = result;
2866
+ });
2867
+ },
2868
+ "Failed to load transaction history",
2869
+ void 0,
2870
+ {
2871
+ onSettled: () => {
2872
+ isLoading.value = false;
2873
+ }
2874
+ }
2875
+ ).catch(() => {
2876
+ });
2798
2877
  };
2799
2878
  watch18(
2800
2879
  [() => toValue35(monitor), () => toValue35(address), () => toValue35(chainId)],
@@ -2815,7 +2894,7 @@ function useTxHistory(address, chainId, monitor) {
2815
2894
  return {
2816
2895
  entries,
2817
2896
  isLoading,
2818
- error,
2897
+ error: guard.error,
2819
2898
  refresh,
2820
2899
  summary: computed24(() => ({
2821
2900
  pending: entries.value.filter((item) => item.status === "pending").length,
@@ -2826,12 +2905,12 @@ function useTxHistory(address, chainId, monitor) {
2826
2905
  }
2827
2906
 
2828
2907
  // src/useTxMonitor.ts
2829
- import { computed as computed25, shallowRef as shallowRef31, toValue as toValue36, watch as watch19 } from "vue";
2908
+ import { computed as computed25, shallowRef as shallowRef32, toValue as toValue36, watch as watch19 } from "vue";
2830
2909
  function useTxMonitor(hash, chainId, monitor) {
2831
- const entry = shallowRef31(null);
2832
- const isLoading = shallowRef31(false);
2833
- const isWatching = shallowRef31(false);
2834
- const error = shallowRef31(null);
2910
+ const entry = shallowRef32(null);
2911
+ const isLoading = shallowRef32(false);
2912
+ const isWatching = shallowRef32(false);
2913
+ const error = shallowRef32(null);
2835
2914
  let generation = 0;
2836
2915
  const refresh = async () => {
2837
2916
  const activeMonitor = toValue36(monitor);
@@ -2917,37 +2996,46 @@ import {
2917
2996
  normalizeCapabilities,
2918
2997
  selectChainCapabilities
2919
2998
  } from "@naculus/connect-appkit-core";
2920
- import { computed as computed26, shallowRef as shallowRef32, toValue as toValue37, watchEffect as watchEffect2 } from "vue";
2999
+ import { computed as computed26, shallowRef as shallowRef33, toValue as toValue37, watchEffect as watchEffect2 } from "vue";
2921
3000
  function useCapabilities(client, session, chainId) {
2922
- const capabilities = shallowRef32(
3001
+ const guard = useActionGuard();
3002
+ const capabilities = shallowRef33(
2923
3003
  null
2924
3004
  );
2925
- const isFetching = shallowRef32(false);
2926
- const error = shallowRef32(null);
2927
- let generation = 0;
3005
+ const isFetching = shallowRef33(false);
2928
3006
  const refetch = async () => {
2929
- const mine = ++generation;
2930
3007
  const activeClient = toValue37(client);
2931
3008
  const activeSession = toValue37(session);
2932
3009
  if (!activeClient?.getCapabilities || !activeSession) {
3010
+ guard.reset();
2933
3011
  capabilities.value = null;
2934
3012
  isFetching.value = false;
2935
- error.value = null;
2936
3013
  return;
2937
3014
  }
2938
3015
  isFetching.value = true;
2939
- error.value = null;
2940
- try {
2941
- const raw = await activeClient.getCapabilities(activeSession);
2942
- if (mine !== generation) return;
2943
- capabilities.value = normalizeCapabilities(raw);
2944
- } catch (err) {
2945
- if (mine !== generation) return;
2946
- capabilities.value = null;
2947
- error.value = err instanceof Error ? err : new Error("Capability query failed");
2948
- } finally {
2949
- if (mine === generation) isFetching.value = false;
2950
- }
3016
+ await guard.run(
3017
+ async (commit) => {
3018
+ try {
3019
+ const raw = await activeClient.getCapabilities(activeSession);
3020
+ commit(() => {
3021
+ capabilities.value = normalizeCapabilities(raw);
3022
+ });
3023
+ } catch (err) {
3024
+ commit(() => {
3025
+ capabilities.value = null;
3026
+ });
3027
+ throw err;
3028
+ }
3029
+ },
3030
+ "Capability query failed",
3031
+ void 0,
3032
+ {
3033
+ onSettled: () => {
3034
+ isFetching.value = false;
3035
+ }
3036
+ }
3037
+ ).catch(() => {
3038
+ });
2951
3039
  };
2952
3040
  watchEffect2(() => {
2953
3041
  void toValue37(client);
@@ -2963,7 +3051,7 @@ function useCapabilities(client, session, chainId) {
2963
3051
  () => atomicSupportFor(capabilities.value, toValue37(chainId))
2964
3052
  ),
2965
3053
  isFetching,
2966
- error,
3054
+ error: guard.error,
2967
3055
  refetch
2968
3056
  };
2969
3057
  }
@@ -3036,6 +3124,7 @@ export {
3036
3124
  useLookupAddress,
3037
3125
  useNotification,
3038
3126
  usePassphraseGate,
3127
+ usePaymentFetch,
3039
3128
  useResolveName,
3040
3129
  useRevokeSession,
3041
3130
  useRouteQuote,