@chipi-stack/chipi-react 14.13.0 → 14.14.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/hooks.d.mts CHANGED
@@ -1,6 +1,7 @@
1
- export { g as ChipiWalletData, a1 as PrivacyConfig, a2 as PrivacyKeys, a5 as PrivacyLedgerEvent, a3 as PrivacyStep, a6 as PrivateBalanceInput, S as SessionState, k as SessionWallet, a4 as ShieldHookInput, X as ThresholdSignState, i as UseChipiSessionConfig, j as UseChipiSessionReturn, e as UseChipiWalletConfig, U as UseChipiWalletObjectConfig, f as UseChipiWalletReturn, R as UseGuardianRecoveryReturn, P as UseShhhSignerReturn, W as UseThresholdSignOptions, V as UseThresholdSignReturn, p as UseTransferConfig, M as UseX402PaymentConfig, N as UseX402PaymentReturn, $ as derivePrivacyAccount, a0 as netPrivateBalance, H as useAddSessionKeyToContract, q as useApprove, A as useCallAnyContract, h as useChipiSession, d as useChipiWallet, D as useChipiWalletObject, G as useCreateSessionKey, u as useCreateWallet, K as useExecuteWithSession, J as useGetSessionData, z as useGetSku, y as useGetSkuList, x as useGetSkuPurchase, F as useGetTokenBalance, s as useGetTransaction, r as useGetTransactionList, t as useGetTransactionStatus, c as useGetWallet, Q as useGuardianRecovery, l as useMigrateWalletToPasskey, n as useMigrateWalletToShhh, _ as usePrivateBalance, w as usePurchaseSku, E as useRecordSendTransaction, I as useRevokeSessionKey, O as useShhhSigner, Y as useShield, B as useSignTypedData, v as useSyncOnChainTransfers, T as useThresholdSign, o as useTransfer, Z as useUnshield, m as useUpdateWalletEncryption, L as useX402Payment } from './index-D9-uVlda.mjs';
1
+ export { g as ChipiWalletData, a2 as PrivacyConfig, a3 as PrivacyKeys, a6 as PrivacyLedgerEvent, a4 as PrivacyStep, a7 as PrivateBalanceInput, R as RegisterSessionConfig, S as SessionState, k as SessionWallet, a5 as ShieldHookInput, Y as ThresholdSignState, i as UseChipiSessionConfig, j as UseChipiSessionReturn, e as UseChipiWalletConfig, U as UseChipiWalletObjectConfig, f as UseChipiWalletReturn, T as UseGuardianRecoveryReturn, P as UseShhhSignerReturn, X as UseThresholdSignOptions, W as UseThresholdSignReturn, p as UseTransferConfig, M as UseX402PaymentConfig, N as UseX402PaymentReturn, a0 as derivePrivacyAccount, a1 as netPrivateBalance, H as useAddSessionKeyToContract, q as useApprove, A as useCallAnyContract, h as useChipiSession, d as useChipiWallet, D as useChipiWalletObject, G as useCreateSessionKey, u as useCreateWallet, K as useExecuteWithSession, J as useGetSessionData, z as useGetSku, y as useGetSkuList, x as useGetSkuPurchase, F as useGetTokenBalance, s as useGetTransaction, r as useGetTransactionList, t as useGetTransactionStatus, c as useGetWallet, Q as useGuardianRecovery, l as useMigrateWalletToPasskey, n as useMigrateWalletToShhh, $ as usePrivateBalance, w as usePurchaseSku, E as useRecordSendTransaction, I as useRevokeSessionKey, O as useShhhSigner, Z as useShield, B as useSignTypedData, v as useSyncOnChainTransfers, V as useThresholdSign, o as useTransfer, _ as useUnshield, m as useUpdateWalletEncryption, L as useX402Payment } from './index-B8OIdrOX.mjs';
2
2
  import '@chipi-stack/types';
3
3
  import '@tanstack/react-query';
4
+ import 'react';
4
5
  import '@chipi-stack/backend';
5
6
  import 'starknet';
6
7
  import '@starknet-io/types-js';
package/dist/hooks.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { g as ChipiWalletData, a1 as PrivacyConfig, a2 as PrivacyKeys, a5 as PrivacyLedgerEvent, a3 as PrivacyStep, a6 as PrivateBalanceInput, S as SessionState, k as SessionWallet, a4 as ShieldHookInput, X as ThresholdSignState, i as UseChipiSessionConfig, j as UseChipiSessionReturn, e as UseChipiWalletConfig, U as UseChipiWalletObjectConfig, f as UseChipiWalletReturn, R as UseGuardianRecoveryReturn, P as UseShhhSignerReturn, W as UseThresholdSignOptions, V as UseThresholdSignReturn, p as UseTransferConfig, M as UseX402PaymentConfig, N as UseX402PaymentReturn, $ as derivePrivacyAccount, a0 as netPrivateBalance, H as useAddSessionKeyToContract, q as useApprove, A as useCallAnyContract, h as useChipiSession, d as useChipiWallet, D as useChipiWalletObject, G as useCreateSessionKey, u as useCreateWallet, K as useExecuteWithSession, J as useGetSessionData, z as useGetSku, y as useGetSkuList, x as useGetSkuPurchase, F as useGetTokenBalance, s as useGetTransaction, r as useGetTransactionList, t as useGetTransactionStatus, c as useGetWallet, Q as useGuardianRecovery, l as useMigrateWalletToPasskey, n as useMigrateWalletToShhh, _ as usePrivateBalance, w as usePurchaseSku, E as useRecordSendTransaction, I as useRevokeSessionKey, O as useShhhSigner, Y as useShield, B as useSignTypedData, v as useSyncOnChainTransfers, T as useThresholdSign, o as useTransfer, Z as useUnshield, m as useUpdateWalletEncryption, L as useX402Payment } from './index-D9-uVlda.js';
1
+ export { g as ChipiWalletData, a2 as PrivacyConfig, a3 as PrivacyKeys, a6 as PrivacyLedgerEvent, a4 as PrivacyStep, a7 as PrivateBalanceInput, R as RegisterSessionConfig, S as SessionState, k as SessionWallet, a5 as ShieldHookInput, Y as ThresholdSignState, i as UseChipiSessionConfig, j as UseChipiSessionReturn, e as UseChipiWalletConfig, U as UseChipiWalletObjectConfig, f as UseChipiWalletReturn, T as UseGuardianRecoveryReturn, P as UseShhhSignerReturn, X as UseThresholdSignOptions, W as UseThresholdSignReturn, p as UseTransferConfig, M as UseX402PaymentConfig, N as UseX402PaymentReturn, a0 as derivePrivacyAccount, a1 as netPrivateBalance, H as useAddSessionKeyToContract, q as useApprove, A as useCallAnyContract, h as useChipiSession, d as useChipiWallet, D as useChipiWalletObject, G as useCreateSessionKey, u as useCreateWallet, K as useExecuteWithSession, J as useGetSessionData, z as useGetSku, y as useGetSkuList, x as useGetSkuPurchase, F as useGetTokenBalance, s as useGetTransaction, r as useGetTransactionList, t as useGetTransactionStatus, c as useGetWallet, Q as useGuardianRecovery, l as useMigrateWalletToPasskey, n as useMigrateWalletToShhh, $ as usePrivateBalance, w as usePurchaseSku, E as useRecordSendTransaction, I as useRevokeSessionKey, O as useShhhSigner, Z as useShield, B as useSignTypedData, v as useSyncOnChainTransfers, V as useThresholdSign, o as useTransfer, _ as useUnshield, m as useUpdateWalletEncryption, L as useX402Payment } from './index-B8OIdrOX.js';
2
2
  import '@chipi-stack/types';
3
3
  import '@tanstack/react-query';
4
+ import 'react';
4
5
  import '@chipi-stack/backend';
5
6
  import 'starknet';
6
7
  import '@starknet-io/types-js';
package/dist/hooks.js CHANGED
@@ -45,6 +45,18 @@ function useChipiContext() {
45
45
  }
46
46
  return context;
47
47
  }
48
+
49
+ // src/utils/with-error-code.ts
50
+ function withErrorCode(wrapped, original) {
51
+ const code = original.code;
52
+ if (typeof code === "string") {
53
+ Object.defineProperty(wrapped, "code", { value: code, enumerable: true });
54
+ }
55
+ Object.defineProperty(wrapped, "cause", { value: original, enumerable: false });
56
+ return wrapped;
57
+ }
58
+
59
+ // src/hooks/useCreateWallet.ts
48
60
  function useCreateWallet() {
49
61
  const { chipiSDK } = useChipiContext();
50
62
  const mutation = reactQuery.useMutation({
@@ -75,7 +87,7 @@ function useCreateWallet() {
75
87
  }
76
88
  } catch (error) {
77
89
  if (error instanceof Error) {
78
- throw new Error(`Passkey creation failed: ${error.message}`);
90
+ throw withErrorCode(new Error(`Passkey creation failed: ${error.message}`), error);
79
91
  }
80
92
  throw new Error("Failed to create passkey for wallet");
81
93
  }
@@ -155,6 +167,17 @@ function useGetWallet(input) {
155
167
  fetchWallet
156
168
  };
157
169
  }
170
+
171
+ // src/utils/wallet-capabilities.ts
172
+ var SHHH_SESSION_SIGNER_KINDS = /* @__PURE__ */ new Set(["STARK", "ED25519"]);
173
+ function walletSupportsSessions(wallet) {
174
+ if (!wallet) return false;
175
+ if (wallet.walletType === "CHIPI") return true;
176
+ if (wallet.walletType === "SHHH") {
177
+ return !wallet.signerKind || SHHH_SESSION_SIGNER_KINDS.has(wallet.signerKind);
178
+ }
179
+ return false;
180
+ }
158
181
  function useChipiWallet(config3) {
159
182
  const { chipiSDK } = useChipiContext();
160
183
  const queryClient = reactQuery.useQueryClient();
@@ -235,7 +258,7 @@ function useChipiWallet(config3) {
235
258
  const data = walletQuery.data;
236
259
  return {
237
260
  ...data,
238
- supportsSessionKeys: data.walletType === "CHIPI",
261
+ supportsSessionKeys: walletSupportsSessions(data),
239
262
  shortAddress: formatAddress(data.publicKey)
240
263
  };
241
264
  }, [walletQuery.data, walletQuery.isLoading]);
@@ -292,6 +315,7 @@ function useChipiSession(config3) {
292
315
  const {
293
316
  wallet,
294
317
  encryptKey,
318
+ getEncryptKey,
295
319
  getBearerToken,
296
320
  storedSession,
297
321
  onSessionCreated,
@@ -305,10 +329,13 @@ function useChipiSession(config3) {
305
329
  react.useEffect(() => {
306
330
  setLocalSession(storedSession ?? null);
307
331
  }, [storedSession]);
308
- const supportsSession = react.useMemo(() => {
309
- if (!wallet) return false;
310
- return wallet.walletType === "CHIPI";
311
- }, [wallet]);
332
+ const supportsSession = react.useMemo(() => walletSupportsSessions(wallet), [wallet]);
333
+ const resolveEncryptKey = react.useCallback(async () => {
334
+ const key = encryptKey || (getEncryptKey ? await getEncryptKey() : void 0);
335
+ if (!key) throw new Error("Encryption key (PIN) is required");
336
+ return key;
337
+ }, [encryptKey, getEncryptKey]);
338
+ const [awaitingRegistrationUntil, setAwaitingRegistrationUntil] = react.useState(null);
312
339
  const sessionStatusQuery = reactQuery.useQuery({
313
340
  queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey],
314
341
  queryFn: async () => {
@@ -321,34 +348,41 @@ function useChipiSession(config3) {
321
348
  enabled: Boolean(
322
349
  autoCheckStatus && wallet?.publicKey && localSession?.publicKey && supportsSession
323
350
  ),
324
- staleTime: 3e4
351
+ staleTime: 3e4,
325
352
  // 30 seconds
353
+ // The registration hash comes back before the transaction is in a block, so
354
+ // right after registerSession the struct can still read as zero. Poll until
355
+ // it shows up (or for two minutes), then go back to on-demand reads.
356
+ refetchInterval: (query) => awaitingRegistrationUntil !== null && Date.now() < awaitingRegistrationUntil && (query.state.data?.validUntil ?? 0) === 0 ? 3e3 : false
326
357
  });
358
+ const [revokedSessionKey, setRevokedSessionKey] = react.useState(null);
327
359
  const sessionState = react.useMemo(() => {
328
360
  if (!localSession) return "none";
361
+ if (revokedSessionKey === localSession.publicKey) return "revoked";
362
+ if (localSession.validUntil * 1e3 < Date.now()) return "expired";
329
363
  const status = sessionStatusQuery.data;
330
364
  if (status) {
331
- if (!status.isActive) return "revoked";
365
+ if (status.validUntil === 0) return "created";
332
366
  if (status.validUntil * 1e3 < Date.now()) return "expired";
333
367
  if (status.remainingCalls <= 0) return "expired";
368
+ if (!status.isActive) return "revoked";
334
369
  return "active";
335
370
  }
336
- if (localSession.validUntil * 1e3 < Date.now()) return "expired";
337
371
  return "created";
338
- }, [localSession, sessionStatusQuery.data]);
372
+ }, [localSession, revokedSessionKey, sessionStatusQuery.data]);
339
373
  const hasActiveSession = sessionState === "active";
340
374
  const isSessionExpired = sessionState === "expired";
341
375
  const remainingCalls = sessionStatusQuery.data?.remainingCalls;
342
376
  const createSessionMutation = reactQuery.useMutation(
343
377
  {
344
378
  mutationFn: async (params = {}) => {
345
- if (!encryptKey) throw new Error("Encryption key (PIN) is required");
346
379
  if (!supportsSession)
347
380
  throw new Error(
348
- "Wallet does not support sessions. Only CHIPI wallets support session keys."
381
+ "Wallet does not support sessions. Session keys need a CHIPI wallet or a SHHH wallet with a STARK / ED25519 signer."
349
382
  );
383
+ const key = await resolveEncryptKey();
350
384
  const sessionData = chipiSDK.sessions.createSessionKey({
351
- encryptKey,
385
+ encryptKey: key,
352
386
  durationSeconds: params.durationSeconds ?? defaultDurationSeconds
353
387
  });
354
388
  return sessionData;
@@ -368,28 +402,38 @@ function useChipiSession(config3) {
368
402
  const registerSessionMutation = reactQuery.useMutation({
369
403
  mutationFn: async (sessionConfig = {}) => {
370
404
  if (!wallet) throw new Error("Wallet is required");
371
- if (!localSession) throw new Error("No session to register. Call createSession first.");
372
- if (!encryptKey) throw new Error("Encryption key (PIN) is required");
405
+ const sessionPublicKey = sessionConfig.sessionPublicKey ?? localSession?.publicKey;
406
+ const validUntil = sessionConfig.validUntil ?? localSession?.validUntil;
407
+ if (!sessionPublicKey || validUntil === void 0)
408
+ throw new Error(
409
+ "No session to register. Call createSession first, or pass sessionPublicKey and validUntil."
410
+ );
373
411
  if (!supportsSession) throw new Error("Wallet does not support sessions");
412
+ const key = await resolveEncryptKey();
374
413
  const bearerToken = await getBearerToken();
375
414
  if (!bearerToken) throw new Error("Bearer token is required");
376
- const txHash = await chipiSDK.sessions.addSessionKeyToContract(
377
- {
378
- encryptKey,
379
- wallet,
380
- sessionConfig: {
381
- sessionPublicKey: localSession.publicKey,
382
- validUntil: sessionConfig.validUntil ?? localSession.validUntil,
383
- maxCalls: sessionConfig.maxCalls ?? defaultMaxCalls,
384
- allowedEntrypoints: sessionConfig.allowedEntrypoints ?? []
385
- }
386
- },
387
- bearerToken
388
- );
389
- return txHash;
415
+ const params = {
416
+ encryptKey: key,
417
+ wallet,
418
+ sessionConfig: {
419
+ sessionPublicKey,
420
+ validUntil,
421
+ maxCalls: sessionConfig.maxCalls ?? defaultMaxCalls,
422
+ allowedEntrypoints: sessionConfig.allowedEntrypoints ?? []
423
+ }
424
+ };
425
+ if (sessionConfig.spendingPolicies?.length) {
426
+ return chipiSDK.sessions.setupSession(
427
+ { ...params, spendingPolicies: sessionConfig.spendingPolicies },
428
+ bearerToken
429
+ );
430
+ }
431
+ return chipiSDK.sessions.addSessionKeyToContract(params, bearerToken);
390
432
  },
391
433
  onSuccess: () => {
392
434
  setError(null);
435
+ if (localSession && revokedSessionKey === localSession.publicKey) setRevokedSessionKey(null);
436
+ setAwaitingRegistrationUntil(Date.now() + 12e4);
393
437
  queryClient.invalidateQueries({
394
438
  queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
395
439
  });
@@ -399,25 +443,28 @@ function useChipiSession(config3) {
399
443
  }
400
444
  });
401
445
  const revokeSessionMutation = reactQuery.useMutation({
402
- mutationFn: async () => {
446
+ mutationFn: async (sessionPublicKey) => {
403
447
  if (!wallet) throw new Error("Wallet is required");
404
- if (!localSession) throw new Error("No session to revoke");
405
- if (!encryptKey) throw new Error("Encryption key (PIN) is required");
448
+ const target = sessionPublicKey ?? localSession?.publicKey;
449
+ if (!target) throw new Error("No session to revoke");
406
450
  if (!supportsSession) throw new Error("Wallet does not support sessions");
451
+ const key = await resolveEncryptKey();
407
452
  const bearerToken = await getBearerToken();
408
453
  if (!bearerToken) throw new Error("Bearer token is required");
409
454
  const txHash = await chipiSDK.sessions.revokeSessionKey(
410
455
  {
411
- encryptKey,
456
+ encryptKey: key,
412
457
  wallet,
413
- sessionPublicKey: localSession.publicKey
458
+ sessionPublicKey: target
414
459
  },
415
460
  bearerToken
416
461
  );
417
462
  return txHash;
418
463
  },
419
- onSuccess: () => {
464
+ onSuccess: (_txHash, sessionPublicKey) => {
420
465
  setError(null);
466
+ const target = sessionPublicKey ?? localSession?.publicKey;
467
+ if (target) setRevokedSessionKey(target);
421
468
  queryClient.invalidateQueries({
422
469
  queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
423
470
  });
@@ -430,13 +477,13 @@ function useChipiSession(config3) {
430
477
  mutationFn: async (calls) => {
431
478
  if (!wallet) throw new Error("Wallet is required");
432
479
  if (!localSession) throw new Error("No active session");
433
- if (!encryptKey) throw new Error("Encryption key (PIN) is required");
434
480
  if (!hasActiveSession) throw new Error("Session is not active. Register the session first.");
481
+ const key = await resolveEncryptKey();
435
482
  const bearerToken = await getBearerToken();
436
483
  if (!bearerToken) throw new Error("Bearer token is required");
437
484
  const txHash = await chipiSDK.executeTransactionWithSession({
438
485
  params: {
439
- encryptKey,
486
+ encryptKey: key,
440
487
  wallet,
441
488
  session: localSession,
442
489
  calls
@@ -460,13 +507,13 @@ function useChipiSession(config3) {
460
507
  if (!wallet) throw new Error("Wallet is required");
461
508
  if (!localSession)
462
509
  throw new Error("No session to set policy on. Create and register a session first.");
463
- if (!encryptKey) throw new Error("Encryption key (PIN) is required");
464
510
  if (!supportsSession) throw new Error("Wallet does not support sessions");
511
+ const key = await resolveEncryptKey();
465
512
  const bearerToken = await getBearerToken();
466
513
  if (!bearerToken) throw new Error("Bearer token is required");
467
514
  const txHash = await chipiSDK.sessions.setSpendingPolicy(
468
515
  {
469
- encryptKey,
516
+ encryptKey: key,
470
517
  wallet,
471
518
  spendingPolicyConfig: {
472
519
  sessionPublicKey: localSession.publicKey,
@@ -488,13 +535,13 @@ function useChipiSession(config3) {
488
535
  mutationFn: async (token) => {
489
536
  if (!wallet) throw new Error("Wallet is required");
490
537
  if (!localSession) throw new Error("No session to remove policy from");
491
- if (!encryptKey) throw new Error("Encryption key (PIN) is required");
492
538
  if (!supportsSession) throw new Error("Wallet does not support sessions");
539
+ const key = await resolveEncryptKey();
493
540
  const bearerToken = await getBearerToken();
494
541
  if (!bearerToken) throw new Error("Bearer token is required");
495
542
  const txHash = await chipiSDK.sessions.removeSpendingPolicy(
496
543
  {
497
- encryptKey,
544
+ encryptKey: key,
498
545
  wallet,
499
546
  sessionPublicKey: localSession.publicKey,
500
547
  token
@@ -522,9 +569,14 @@ function useChipiSession(config3) {
522
569
  },
523
570
  [registerSessionMutation]
524
571
  );
525
- const revokeSession = react.useCallback(async () => {
526
- return revokeSessionMutation.mutateAsync();
527
- }, [revokeSessionMutation]);
572
+ const revokeSession = react.useCallback(
573
+ async (sessionPublicKey) => {
574
+ return revokeSessionMutation.mutateAsync(
575
+ typeof sessionPublicKey === "string" ? sessionPublicKey : void 0
576
+ );
577
+ },
578
+ [revokeSessionMutation]
579
+ );
528
580
  const executeWithSession = react.useCallback(
529
581
  async (calls) => {
530
582
  return executeWithSessionMutation.mutateAsync(calls);
@@ -658,7 +710,7 @@ function useMigrateWalletToPasskey() {
658
710
  };
659
711
  } catch (error) {
660
712
  if (error instanceof Error) {
661
- throw new Error(`Migration failed: ${error.message}`);
713
+ throw withErrorCode(new Error(`Migration failed: ${error.message}`), error);
662
714
  }
663
715
  throw new Error("Failed to migrate wallet to passkey");
664
716
  }