decane-connect-kit 2.27.0 → 2.28.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.cjs CHANGED
@@ -59,11 +59,12 @@ __export(errors_exports, {
59
59
  UnlockTokenRejectedError: () => UnlockTokenRejectedError,
60
60
  UserCancelledError: () => UserCancelledError,
61
61
  WalletEnrolmentError: () => WalletEnrolmentError,
62
+ WalletExistsError: () => WalletExistsError,
62
63
  WebAuthnNotSupportedError: () => WebAuthnNotSupportedError,
63
64
  WrongPasswordError: () => WrongPasswordError,
64
65
  WrongUnlockPasswordError: () => WrongUnlockPasswordError
65
66
  });
66
- var DecaneConnectError, InvalidApiKeyError, OriginNotAllowedError, SessionExpiredError, UnlockRequiredError, ReconnectRequiredError, UserCancelledError, WebAuthnNotSupportedError, InvalidPinError, CallSequenceError, NetworkError, ShareCorruptedError, ProvisioningTimeoutError, NewDeviceError, StaleDeviceShareError, PromptPinNotConfiguredError, PromptPasswordNotConfiguredError, WrongUnlockPasswordError, InvalidAccessTokenError, UnlockTokenRejectedError, AttestationError, RecoveryFailedError, InvalidRecoveryFileError, WrongPasswordError, RecoveryWalletMismatchError, ExportNotAuthorizedError, WalletEnrolmentError, ProvisioningRateLimitedError, EnclaveHttpError;
67
+ var DecaneConnectError, InvalidApiKeyError, OriginNotAllowedError, SessionExpiredError, UnlockRequiredError, ReconnectRequiredError, UserCancelledError, WebAuthnNotSupportedError, InvalidPinError, CallSequenceError, NetworkError, ShareCorruptedError, ProvisioningTimeoutError, NewDeviceError, StaleDeviceShareError, PromptPinNotConfiguredError, PromptPasswordNotConfiguredError, WrongUnlockPasswordError, InvalidAccessTokenError, UnlockTokenRejectedError, AttestationError, RecoveryFailedError, InvalidRecoveryFileError, WrongPasswordError, RecoveryWalletMismatchError, ExportNotAuthorizedError, WalletExistsError, WalletEnrolmentError, ProvisioningRateLimitedError, EnclaveHttpError;
67
68
  var init_errors = __esm({
68
69
  "src/social/errors.ts"() {
69
70
  "use strict";
@@ -212,6 +213,11 @@ var init_errors = __esm({
212
213
  super("EXPORT_NOT_AUTHORIZED", "Export requires a fresh security check", true);
213
214
  }
214
215
  };
216
+ WalletExistsError = class extends DecaneConnectError {
217
+ constructor() {
218
+ super("WALLET_EXISTS", "This account already has a wallet; opening it instead.", true);
219
+ }
220
+ };
215
221
  WalletEnrolmentError = class extends DecaneConnectError {
216
222
  constructor(cause) {
217
223
  super(
@@ -279,6 +285,7 @@ __export(index_exports, {
279
285
  UnlockTokenRejectedError: () => UnlockTokenRejectedError,
280
286
  UserCancelledError: () => UserCancelledError,
281
287
  WalletEnrolmentError: () => WalletEnrolmentError,
288
+ WalletExistsError: () => WalletExistsError,
282
289
  WalletSelector: () => WalletSelector,
283
290
  WeakPasswordError: () => WeakPasswordError,
284
291
  WebAuthnNotSupportedError: () => WebAuthnNotSupportedError,
@@ -2109,7 +2116,9 @@ var ERROR_MAP = {
2109
2116
  // The backend's authMiddleware code for an expired/revoked JWT. Surfacing it
2110
2117
  // as ReconnectRequiredError routes callers to the sign-in UI instead of a
2111
2118
  // generic failure message.
2112
- UNAUTHORIZED: ReconnectRequiredError
2119
+ UNAUTHORIZED: ReconnectRequiredError,
2120
+ // A restorable wallet already exists: the client provisions instead of creating.
2121
+ WALLET_EXISTS: WalletExistsError
2113
2122
  };
2114
2123
  var REQUEST_TIMEOUT_MS = 3e4;
2115
2124
  var ApiClient = class {
@@ -2509,7 +2518,7 @@ function dropCollateral(teeUrl) {
2509
2518
  // src/social/attestation.ts
2510
2519
  init_errors();
2511
2520
 
2512
- // ../../infra/tee-measurement.json
2521
+ // ../infra/tee-measurement.json
2513
2522
  var tee_measurement_default = {
2514
2523
  signerVersion: "0.2.10",
2515
2524
  acceptedMrtd: [
@@ -4471,24 +4480,37 @@ async function createDecaneConnect(config) {
4471
4480
  if (unlockTokenKey) await attachUnlockToken(userId, jwt, unlockTokenKey);
4472
4481
  }
4473
4482
  const serverIv = generateRandomBytes(12);
4474
- await withDeadline(api.putShare(jwt, {
4475
- ciphertext: shareSet.server,
4476
- iv: serverIv,
4477
- wrappedShareMeta: {
4478
- // The server records this on the wallet_created event and nothing else.
4479
- unlockMethod: identityTier ? "identity" : unlockMethod
4480
- // credential IDs, prfSalt, pinSalt stay on-device — never sent to server
4481
- },
4482
- evmAddress,
4483
- solanaAddress,
4484
- tronAddress,
4485
- // Provisional until the enclave has sealed the auth share, just below. A
4486
- // backend that knows the flag keeps this row invisible to hasShare until
4487
- // then, so a creation that fails past this point leaves no wallet behind
4488
- // and the next sign-in simply creates again — with a new key, which is
4489
- // why the backend also replaces the recorded addresses outright.
4490
- pendingEnrolment: true
4491
- }), remainingBudget(), "storing your wallet");
4483
+ try {
4484
+ await withDeadline(api.putShare(jwt, {
4485
+ ciphertext: shareSet.server,
4486
+ iv: serverIv,
4487
+ wrappedShareMeta: {
4488
+ // The server records this on the wallet_created event and nothing else.
4489
+ unlockMethod: identityTier ? "identity" : unlockMethod
4490
+ // credential IDs, prfSalt, pinSalt stay on-device — never sent to server
4491
+ },
4492
+ evmAddress,
4493
+ solanaAddress,
4494
+ tronAddress,
4495
+ // Provisional until the enclave has sealed the auth share, just below. A
4496
+ // backend that knows the flag keeps this row invisible to hasShare until
4497
+ // then, so a creation that fails past this point leaves no wallet behind
4498
+ // and the next sign-in simply creates again — with a new key, which is
4499
+ // why the backend also replaces the recorded addresses outright.
4500
+ pendingEnrolment: true
4501
+ }), remainingBudget(), "storing your wallet");
4502
+ } catch (e) {
4503
+ if (e instanceof WalletExistsError) {
4504
+ zeroize(shareSet.server);
4505
+ zeroize(shareSet.device);
4506
+ zeroize(shareSet.recovery);
4507
+ if (wrappingKey) await storage2.deleteShare(userId).catch(() => {
4508
+ });
4509
+ events.emit("wallet-unlocking");
4510
+ return returningUserUnlock(userId, jwt);
4511
+ }
4512
+ throw e;
4513
+ }
4492
4514
  zeroize(shareSet.server);
4493
4515
  try {
4494
4516
  await enrolBlocking(jwt, new Uint8Array(shareSet.recovery), remainingBudget());
@@ -9052,6 +9074,7 @@ function useSignTypedData() {
9052
9074
  UnlockTokenRejectedError,
9053
9075
  UserCancelledError,
9054
9076
  WalletEnrolmentError,
9077
+ WalletExistsError,
9055
9078
  WalletSelector,
9056
9079
  WeakPasswordError,
9057
9080
  WebAuthnNotSupportedError,