@tatchi-xyz/sdk 0.18.0 → 0.20.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.
Files changed (112) hide show
  1. package/dist/cjs/core/EmailRecovery/index.js +25 -0
  2. package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
  3. package/dist/cjs/core/TatchiPasskey/emailRecovery.js +80 -60
  4. package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
  5. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  6. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  7. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  8. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  9. package/dist/cjs/core/WebAuthnManager/index.js +23 -0
  10. package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
  11. package/dist/cjs/core/types/emailRecovery.js +33 -0
  12. package/dist/cjs/core/types/emailRecovery.js.map +1 -0
  13. package/dist/cjs/index.js +4 -0
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BCrFe5p3.css} +1 -1
  16. package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
  17. package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
  18. package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
  19. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
  20. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
  21. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
  22. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
  23. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
  24. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
  25. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
  26. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  27. package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
  28. package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
  29. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +25 -0
  30. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  31. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +80 -60
  32. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  33. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  34. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  35. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  36. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  37. package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js +23 -0
  38. package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
  39. package/dist/cjs/react/sdk/src/core/types/emailRecovery.js +33 -0
  40. package/dist/cjs/react/sdk/src/core/types/emailRecovery.js.map +1 -0
  41. package/dist/esm/core/EmailRecovery/index.js +25 -1
  42. package/dist/esm/core/EmailRecovery/index.js.map +1 -1
  43. package/dist/esm/core/TatchiPasskey/emailRecovery.js +81 -61
  44. package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
  45. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  46. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  47. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  48. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  49. package/dist/esm/core/WebAuthnManager/index.js +23 -0
  50. package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
  51. package/dist/esm/core/types/emailRecovery.js +26 -0
  52. package/dist/esm/core/types/emailRecovery.js.map +1 -0
  53. package/dist/esm/index.js +3 -1
  54. package/dist/esm/index.js.map +1 -1
  55. package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BCrFe5p3.css} +1 -1
  56. package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
  57. package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
  58. package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
  59. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
  60. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
  61. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
  62. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
  63. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
  64. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
  65. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
  66. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  67. package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
  68. package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
  69. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +25 -1
  70. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  71. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +81 -61
  72. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  73. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  74. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  75. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  76. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  77. package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js +23 -0
  78. package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
  79. package/dist/esm/react/sdk/src/core/types/emailRecovery.js +26 -0
  80. package/dist/esm/react/sdk/src/core/types/emailRecovery.js.map +1 -0
  81. package/dist/esm/sdk/{createAdapters-qVGD6i0g.js → createAdapters-DIRR8_Z9.js} +1 -1
  82. package/dist/esm/sdk/{createAdapters-BumKM2ft.js → createAdapters-Yga6W0en.js} +2 -2
  83. package/dist/esm/sdk/{createAdapters-BumKM2ft.js.map → createAdapters-Yga6W0en.js.map} +1 -1
  84. package/dist/esm/sdk/{localOnly-pXMTqh1m.js → localOnly-BHScJasw.js} +2 -2
  85. package/dist/esm/sdk/{localOnly-Byi3AK7A.js → localOnly-VevCI7H0.js} +3 -3
  86. package/dist/esm/sdk/{localOnly-Byi3AK7A.js.map → localOnly-VevCI7H0.js.map} +1 -1
  87. package/dist/esm/sdk/offline-export-app.js +29 -6
  88. package/dist/esm/sdk/offline-export-app.js.map +1 -1
  89. package/dist/esm/sdk/{registration-CBiS4Ua_.js → registration-bKEg9Zr2.js} +2 -2
  90. package/dist/esm/sdk/{registration-CBiS4Ua_.js.map → registration-bKEg9Zr2.js.map} +1 -1
  91. package/dist/esm/sdk/{registration-DLPLsGCz.js → registration-lDD60Ytt.js} +1 -1
  92. package/dist/esm/sdk/{transactions-Bk-VavcV.js → transactions-BalIhtJ9.js} +1 -1
  93. package/dist/esm/sdk/{transactions-BIqKZeR0.js → transactions-bqaAwL4k.js} +2 -2
  94. package/dist/esm/sdk/{transactions-BIqKZeR0.js.map → transactions-bqaAwL4k.js.map} +1 -1
  95. package/dist/esm/sdk/wallet-iframe-host.js +150 -65
  96. package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
  97. package/dist/types/src/core/EmailRecovery/index.d.ts +8 -0
  98. package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
  99. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +7 -2
  100. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
  101. package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.d.ts.map +1 -1
  102. package/dist/types/src/core/WebAuthnManager/index.d.ts +7 -0
  103. package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
  104. package/dist/types/src/core/types/emailRecovery.d.ts +10 -0
  105. package/dist/types/src/core/types/emailRecovery.d.ts.map +1 -0
  106. package/dist/types/src/core/types/index.d.ts +1 -0
  107. package/dist/types/src/core/types/index.d.ts.map +1 -1
  108. package/dist/types/src/index.d.ts +1 -0
  109. package/dist/types/src/index.d.ts.map +1 -1
  110. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
  111. package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
  112. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { ERROR_MESSAGES, getIntentDigest, getNearAccountId, getRegisterAccountPayload, isSerializedRegistrationCredential, isUserCancelledSecureConfirm, serializeRegistrationCredentialWithPRF, toError } from "./requestHelpers-aUKhXiEl.js";
2
2
  import "./validation-DhPPUba7.js";
3
- import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-BumKM2ft.js";
3
+ import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-Yga6W0en.js";
4
4
  import "./css-loader-BrMMlG4X.js";
5
5
  import "./lit-events-BKobq01K.js";
6
6
  import "./tx-tree-themes-i3It4IYY.js";
@@ -130,4 +130,4 @@ async function handleRegistrationFlow(ctx, request, worker, opts) {
130
130
 
131
131
  //#endregion
132
132
  export { handleRegistrationFlow };
133
- //# sourceMappingURL=registration-CBiS4Ua_.js.map
133
+ //# sourceMappingURL=registration-bKEg9Zr2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registration-CBiS4Ua_.js","names":["uiVrfChallenge: VRFChallenge","credential: PublicKeyCredential | undefined","e: unknown","serialized: WebAuthnRegistrationCredential","err: unknown"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n TransactionSummary,\n RegistrationSecureConfirmRequest,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport type { WebAuthnRegistrationCredential } from '../../../../types/webauthn';\nimport {\n getNearAccountId,\n getIntentDigest,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getRegisterAccountPayload,\n} from './index';\nimport { isSerializedRegistrationCredential, serializeRegistrationCredentialWithPRF } from '../../../credentialsHelpers';\nimport { toError } from '../../../../../utils/errors';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nexport async function handleRegistrationFlow(\n ctx: VrfWorkerManagerContext,\n request: RegistrationSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n\n console.debug('[RegistrationFlow] start', {\n nearAccountId,\n uiMode: confirmationConfig?.uiMode,\n behavior: confirmationConfig?.behavior,\n theme: confirmationConfig?.theme,\n intentDigest: transactionSummary?.intentDigest,\n });\n\n // 1) NEAR context\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: 1, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n const transactionContext = nearRpc.transactionContext as TransactionContext;\n session.setReservedNonces(nearRpc.reservedNonces);\n\n // 2) Initial VRF challenge via bootstrap\n const rpId = adapters.vrf.getRpId();\n const bootstrap = await adapters.vrf.generateVrfKeypairBootstrap({\n vrfInputData: {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n saveInMemory: true,\n sessionId: request.requestId,\n });\n let uiVrfChallenge: VRFChallenge = bootstrap.vrfChallenge;\n console.debug('[RegistrationFlow] VRF bootstrap ok', { blockHeight: uiVrfChallenge.blockHeight });\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallenge });\n if (!confirmed) {\n console.debug('[RegistrationFlow] user cancelled');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) JIT refresh VRF (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n console.debug('[RegistrationFlow] VRF JIT refresh ok', { blockHeight: uiVrfChallenge.blockHeight });\n } catch (e) {\n console.debug('[RegistrationFlow] VRF JIT refresh skipped', e);\n }\n\n // 5) Collect registration credentials (with duplicate retry)\n let credential: PublicKeyCredential | undefined;\n let deviceNumber = request.payload?.deviceNumber;\n\n const tryCreate = async (dn?: number): Promise<PublicKeyCredential> => {\n console.debug('[RegistrationFlow] navigator.credentials.create start', { deviceNumber: dn });\n return await adapters.webauthn.createRegistrationCredential({\n nearAccountId,\n challenge: uiVrfChallenge,\n deviceNumber: dn,\n });\n };\n\n try {\n try {\n credential = await tryCreate(deviceNumber);\n console.debug('[RegistrationFlow] credentials.create ok');\n } catch (e: unknown) {\n const err = toError(e);\n const name = String(err?.name || '');\n const msg = String(err?.message || '');\n const isDuplicate = name === 'InvalidStateError' || /excluded|already\\s*registered/i.test(msg);\n if (isDuplicate) {\n const nextDeviceNumber = (deviceNumber !== undefined && Number.isFinite(deviceNumber)) ? (deviceNumber + 1) : 2;\n console.debug('[RegistrationFlow] duplicate credential, retry with next deviceNumber', { nextDeviceNumber });\n credential = await tryCreate(nextDeviceNumber);\n getRegisterAccountPayload(request).deviceNumber = nextDeviceNumber;\n } else {\n console.error('[RegistrationFlow] credentials.create failed (non-duplicate)', { name, msg });\n throw err;\n }\n }\n\n // We require registration credentials to include dual PRF outputs (first + second)\n // so VRF/NEAR key derivation can happen inside the workers without passing PRF outputs\n // as separate main-thread values.\n const serialized: WebAuthnRegistrationCredential = isSerializedRegistrationCredential(credential as unknown)\n ? (credential as unknown as WebAuthnRegistrationCredential)\n : serializeRegistrationCredentialWithPRF({\n credential: credential! as PublicKeyCredential,\n firstPrfOutput: true,\n secondPrfOutput: true,\n });\n\n // 6) Respond + close\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serialized,\n // PRF outputs are embedded in serialized credential; VRF worker extracts and sends via MessagePort\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n\n } catch (err: unknown) {\n const cancelled = isUserCancelledSecureConfirm(err);\n const msg = String((toError(err))?.message || err || '');\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n\n const isPrfBrowserUnsupported =\n /WebAuthn PRF output is missing from navigator\\.credentials\\.create\\(\\)/i.test(msg)\n || /does not fully support the WebAuthn PRF extension during registration/i.test(msg)\n || /roaming hardware authenticators .* not supported in this flow/i.test(msg);\n\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isPrfBrowserUnsupported ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registration-bKEg9Zr2.js","names":["uiVrfChallenge: VRFChallenge","credential: PublicKeyCredential | undefined","e: unknown","serialized: WebAuthnRegistrationCredential","err: unknown"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n TransactionSummary,\n RegistrationSecureConfirmRequest,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport type { WebAuthnRegistrationCredential } from '../../../../types/webauthn';\nimport {\n getNearAccountId,\n getIntentDigest,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getRegisterAccountPayload,\n} from './index';\nimport { isSerializedRegistrationCredential, serializeRegistrationCredentialWithPRF } from '../../../credentialsHelpers';\nimport { toError } from '../../../../../utils/errors';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nexport async function handleRegistrationFlow(\n ctx: VrfWorkerManagerContext,\n request: RegistrationSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n\n console.debug('[RegistrationFlow] start', {\n nearAccountId,\n uiMode: confirmationConfig?.uiMode,\n behavior: confirmationConfig?.behavior,\n theme: confirmationConfig?.theme,\n intentDigest: transactionSummary?.intentDigest,\n });\n\n // 1) NEAR context\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: 1, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n const transactionContext = nearRpc.transactionContext as TransactionContext;\n session.setReservedNonces(nearRpc.reservedNonces);\n\n // 2) Initial VRF challenge via bootstrap\n const rpId = adapters.vrf.getRpId();\n const bootstrap = await adapters.vrf.generateVrfKeypairBootstrap({\n vrfInputData: {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n saveInMemory: true,\n sessionId: request.requestId,\n });\n let uiVrfChallenge: VRFChallenge = bootstrap.vrfChallenge;\n console.debug('[RegistrationFlow] VRF bootstrap ok', { blockHeight: uiVrfChallenge.blockHeight });\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallenge });\n if (!confirmed) {\n console.debug('[RegistrationFlow] user cancelled');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) JIT refresh VRF (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n console.debug('[RegistrationFlow] VRF JIT refresh ok', { blockHeight: uiVrfChallenge.blockHeight });\n } catch (e) {\n console.debug('[RegistrationFlow] VRF JIT refresh skipped', e);\n }\n\n // 5) Collect registration credentials (with duplicate retry)\n let credential: PublicKeyCredential | undefined;\n let deviceNumber = request.payload?.deviceNumber;\n\n const tryCreate = async (dn?: number): Promise<PublicKeyCredential> => {\n console.debug('[RegistrationFlow] navigator.credentials.create start', { deviceNumber: dn });\n return await adapters.webauthn.createRegistrationCredential({\n nearAccountId,\n challenge: uiVrfChallenge,\n deviceNumber: dn,\n });\n };\n\n try {\n try {\n credential = await tryCreate(deviceNumber);\n console.debug('[RegistrationFlow] credentials.create ok');\n } catch (e: unknown) {\n const err = toError(e);\n const name = String(err?.name || '');\n const msg = String(err?.message || '');\n const isDuplicate = name === 'InvalidStateError' || /excluded|already\\s*registered/i.test(msg);\n if (isDuplicate) {\n const nextDeviceNumber = (deviceNumber !== undefined && Number.isFinite(deviceNumber)) ? (deviceNumber + 1) : 2;\n console.debug('[RegistrationFlow] duplicate credential, retry with next deviceNumber', { nextDeviceNumber });\n credential = await tryCreate(nextDeviceNumber);\n getRegisterAccountPayload(request).deviceNumber = nextDeviceNumber;\n } else {\n console.error('[RegistrationFlow] credentials.create failed (non-duplicate)', { name, msg });\n throw err;\n }\n }\n\n // We require registration credentials to include dual PRF outputs (first + second)\n // so VRF/NEAR key derivation can happen inside the workers without passing PRF outputs\n // as separate main-thread values.\n const serialized: WebAuthnRegistrationCredential = isSerializedRegistrationCredential(credential as unknown)\n ? (credential as unknown as WebAuthnRegistrationCredential)\n : serializeRegistrationCredentialWithPRF({\n credential: credential! as PublicKeyCredential,\n firstPrfOutput: true,\n secondPrfOutput: true,\n });\n\n // 6) Respond + close\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serialized,\n // PRF outputs are embedded in serialized credential; VRF worker extracts and sends via MessagePort\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n\n } catch (err: unknown) {\n const cancelled = isUserCancelledSecureConfirm(err);\n const msg = String((toError(err))?.message || err || '');\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n\n const isPrfBrowserUnsupported =\n /WebAuthn PRF output is missing from navigator\\.credentials\\.create\\(\\)/i.test(msg)\n || /does not fully support the WebAuthn PRF extension during registration/i.test(msg)\n || /roaming hardware authenticators .* not supported in this flow/i.test(msg);\n\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isPrfBrowserUnsupported ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":"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"}
@@ -11,7 +11,7 @@ import "./tx-confirmer-wrapper-lHNgz9i4.js";
11
11
  import { init_errors, toError } from "./errors-D9ar28Dr.js";
12
12
  import { init_credentialsHelpers, isSerializedRegistrationCredential, serializeRegistrationCredentialWithPRF } from "./WebAuthnFallbacks-Bl4BTsNt.js";
13
13
  import { ERROR_MESSAGES, getIntentDigest, getNearAccountId, getRegisterAccountPayload, isUserCancelledSecureConfirm } from "./requestHelpers-Dh1hEYL9.js";
14
- import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-qVGD6i0g.js";
14
+ import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-DIRR8_Z9.js";
15
15
 
16
16
  //#region src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.ts
17
17
  init_credentialsHelpers();
@@ -13,7 +13,7 @@ import "./WebAuthnFallbacks-Bl4BTsNt.js";
13
13
  import { ERROR_MESSAGES, SecureConfirmationType, getIntentDigest, getNearAccountId, getSignTransactionPayload, getTxCount, init_accountIds, isUserCancelledSecureConfirm, toAccountId } from "./requestHelpers-Dh1hEYL9.js";
14
14
  import { PASSKEY_MANAGER_DEFAULT_CONFIGS, init_defaultConfigs } from "./defaultConfigs-DpslkAQd.js";
15
15
  import { getLastLoggedInDeviceNumber, init_getDeviceNumber } from "./getDeviceNumber-zsOHT_Um.js";
16
- import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-qVGD6i0g.js";
16
+ import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-DIRR8_Z9.js";
17
17
 
18
18
  //#region src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.ts
19
19
  init_accountIds();
@@ -1,7 +1,7 @@
1
1
  import { ERROR_MESSAGES, SecureConfirmationType, getIntentDigest, getNearAccountId, getSignTransactionPayload, getTxCount, isUserCancelledSecureConfirm, toAccountId, toError } from "./requestHelpers-aUKhXiEl.js";
2
2
  import "./validation-DhPPUba7.js";
3
3
  import { PASSKEY_MANAGER_DEFAULT_CONFIGS, getLastLoggedInDeviceNumber } from "./getDeviceNumber-fXizNGQl.js";
4
- import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-BumKM2ft.js";
4
+ import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-Yga6W0en.js";
5
5
  import "./css-loader-BrMMlG4X.js";
6
6
  import "./lit-events-BKobq01K.js";
7
7
  import "./tx-tree-themes-i3It4IYY.js";
@@ -163,4 +163,4 @@ async function handleTransactionSigningFlow(ctx, request, worker, opts) {
163
163
 
164
164
  //#endregion
165
165
  export { handleTransactionSigningFlow };
166
- //# sourceMappingURL=transactions-BIqKZeR0.js.map
166
+ //# sourceMappingURL=transactions-bqaAwL4k.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transactions-BIqKZeR0.js","names":["uiVrfChallenge: VRFChallenge | undefined","uiVrfChallengeForUi: Partial<VRFChallenge> | undefined","err: unknown","contractId: string | undefined","nearRpcUrl: string | undefined"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n SecureConfirmationType,\n TransactionSummary,\n SigningSecureConfirmRequest,\n SigningAuthMode,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport {\n getNearAccountId,\n getIntentDigest,\n getTxCount,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getSignTransactionPayload,\n} from './index';\nimport { toAccountId } from '../../../../types/accountIds';\nimport { getLastLoggedInDeviceNumber } from '../../../SignerWorkerManager/getDeviceNumber';\nimport { toError } from '../../../../../utils/errors';\nimport { PASSKEY_MANAGER_DEFAULT_CONFIGS } from '../../../../defaultConfigs';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nfunction getSigningAuthMode(request: SigningSecureConfirmRequest): SigningAuthMode {\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n return getSignTransactionPayload(request).signingAuthMode ?? 'webauthn';\n }\n if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const p = request.payload as any;\n return (p?.signingAuthMode as SigningAuthMode | undefined) ?? 'webauthn';\n }\n return 'webauthn';\n}\n\nexport async function handleTransactionSigningFlow(\n ctx: VrfWorkerManagerContext,\n request: SigningSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n const signingAuthMode = getSigningAuthMode(request);\n const usesNeeded = getTxCount(request);\n\n // 1) NEAR context + nonce reservation\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: usesNeeded, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n // eslint-disable-next-line no-console\n console.error('[SigningFlow] fetchNearContext failed', { error: nearRpc.error, details: nearRpc.details });\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n session.setReservedNonces(nearRpc.reservedNonces);\n let transactionContext = nearRpc.transactionContext as TransactionContext;\n\n // 2) Security context shown in the confirmer (rpId + block height).\n // For warmSession signing we still want to show this context even though\n // we won't collect a WebAuthn credential.\n const rpId = adapters.vrf.getRpId();\n let uiVrfChallenge: VRFChallenge | undefined;\n let uiVrfChallengeForUi: Partial<VRFChallenge> | undefined = rpId\n ? {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n }\n : undefined;\n\n // Initial VRF challenge (only needed for WebAuthn credential collection)\n if (signingAuthMode === 'webauthn') {\n uiVrfChallenge = await adapters.vrf.generateVrfChallengeForSession(\n {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n request.requestId,\n );\n uiVrfChallengeForUi = uiVrfChallenge;\n }\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallengeForUi });\n if (!confirmed) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) Warm session: dispense WrapKeySeed and skip WebAuthn\n if (signingAuthMode === 'warmSession') {\n try {\n await adapters.vrf.dispenseSessionKey({ sessionId: request.requestId, uses: usesNeeded });\n } catch (err: unknown) {\n const msg = String((toError(err))?.message || err || '');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: msg || 'Failed to dispense warm session key',\n });\n }\n\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n transactionContext,\n });\n return;\n }\n\n // 5) JIT refresh VRF + ctx (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n transactionContext = refreshed.transactionContext;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n } catch (e) {\n console.debug('[SigningFlow] VRF JIT refresh skipped', e);\n }\n\n // 6) Collect authentication credential\n try {\n if (!uiVrfChallenge) {\n throw new Error('Missing vrfChallenge for WebAuthn signing flow');\n }\n const serializedCredential = await adapters.webauthn.collectAuthenticationCredentialWithPRF({\n nearAccountId,\n vrfChallenge: uiVrfChallenge,\n });\n\n // 5c) Derive WrapKeySeed inside the VRF worker and deliver it to the signer worker via\n // the reserved WrapKeySeed MessagePort. Main thread only sees wrapKeySalt metadata.\n let contractId: string | undefined;\n let nearRpcUrl: string | undefined;\n try {\n // Ensure VRF session is active and bound to the same account we are signing for.\n const vrfStatus = await adapters.vrf.checkVrfStatus();\n if (!vrfStatus.active) {\n throw new Error('VRF keypair not active in memory. VRF session may have expired or was not properly initialized. Please refresh and try again.');\n }\n if (!vrfStatus.nearAccountId || String(vrfStatus.nearAccountId) !== String(toAccountId(nearAccountId))) {\n throw new Error('VRF session is active but bound to a different account than the one being signed. Please log in again on this device.');\n }\n\n const deviceNumber = await getLastLoggedInDeviceNumber(toAccountId(nearAccountId), ctx.indexedDB.clientDB);\n const encryptedKeyData = await ctx.indexedDB.nearKeysDB.getEncryptedKey(nearAccountId, deviceNumber);\n // For v2+ vaults, wrapKeySalt is the canonical salt.\n const wrapKeySalt = encryptedKeyData?.wrapKeySalt || '';\n if (!wrapKeySalt) {\n throw new Error('Missing wrapKeySalt in vault; re-register to upgrade vault format.');\n }\n\n // Extract contract verification context when available.\n // - SIGN_TRANSACTION: use per-request rpcCall (already normalized by caller).\n // - SIGN_NEP413_MESSAGE: allow per-request override; fall back to PASSKEY_MANAGER_DEFAULT_CONFIGS.\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n const payload = getSignTransactionPayload(request);\n contractId = payload?.rpcCall?.contractId;\n nearRpcUrl = payload?.rpcCall?.nearRpcUrl;\n } else if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const payload = request.payload as any;\n contractId = payload?.contractId\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.contractId;\n nearRpcUrl = payload?.nearRpcUrl\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.nearRpcUrl;\n }\n\n await adapters.vrf.mintSessionKeysAndSendToSigner({\n sessionId: request.requestId,\n wrapKeySalt,\n contractId,\n nearRpcUrl,\n credential: serializedCredential,\n });\n\t } catch (err) {\n\t console.error('[SigningFlow] WrapKeySeed derivation failed:', err);\n\t throw err; // Don't silently ignore - propagate the error\n\t }\n\n // 6) Respond; keep nonces reserved for worker to use\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serializedCredential,\n // prfOutput intentionally omitted to keep signer PRF-free\n // WrapKeySeed travels only over the dedicated VRF→Signer MessagePort; do not echo in the main-thread envelope\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n } catch (err: unknown) {\n // Treat TouchID/FaceID cancellation and related errors as a negative decision\n const cancelled = isUserCancelledSecureConfirm(err);\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n const msg = String((toError(err))?.message || err || '');\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n // Ensure UI is closed and nonces released, then rethrow\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n const isWrongPasskeyError = /multiple passkeys \\(devicenumbers\\) for account/i.test(msg);\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isWrongPasskeyError ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"transactions-bqaAwL4k.js","names":["uiVrfChallenge: VRFChallenge | undefined","uiVrfChallengeForUi: Partial<VRFChallenge> | undefined","err: unknown","contractId: string | undefined","nearRpcUrl: string | undefined"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n SecureConfirmationType,\n TransactionSummary,\n SigningSecureConfirmRequest,\n SigningAuthMode,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport {\n getNearAccountId,\n getIntentDigest,\n getTxCount,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getSignTransactionPayload,\n} from './index';\nimport { toAccountId } from '../../../../types/accountIds';\nimport { getLastLoggedInDeviceNumber } from '../../../SignerWorkerManager/getDeviceNumber';\nimport { toError } from '../../../../../utils/errors';\nimport { PASSKEY_MANAGER_DEFAULT_CONFIGS } from '../../../../defaultConfigs';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nfunction getSigningAuthMode(request: SigningSecureConfirmRequest): SigningAuthMode {\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n return getSignTransactionPayload(request).signingAuthMode ?? 'webauthn';\n }\n if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const p = request.payload as any;\n return (p?.signingAuthMode as SigningAuthMode | undefined) ?? 'webauthn';\n }\n return 'webauthn';\n}\n\nexport async function handleTransactionSigningFlow(\n ctx: VrfWorkerManagerContext,\n request: SigningSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n const signingAuthMode = getSigningAuthMode(request);\n const usesNeeded = getTxCount(request);\n\n // 1) NEAR context + nonce reservation\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: usesNeeded, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n // eslint-disable-next-line no-console\n console.error('[SigningFlow] fetchNearContext failed', { error: nearRpc.error, details: nearRpc.details });\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n session.setReservedNonces(nearRpc.reservedNonces);\n let transactionContext = nearRpc.transactionContext as TransactionContext;\n\n // 2) Security context shown in the confirmer (rpId + block height).\n // For warmSession signing we still want to show this context even though\n // we won't collect a WebAuthn credential.\n const rpId = adapters.vrf.getRpId();\n let uiVrfChallenge: VRFChallenge | undefined;\n let uiVrfChallengeForUi: Partial<VRFChallenge> | undefined = rpId\n ? {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n }\n : undefined;\n\n // Initial VRF challenge (only needed for WebAuthn credential collection)\n if (signingAuthMode === 'webauthn') {\n uiVrfChallenge = await adapters.vrf.generateVrfChallengeForSession(\n {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n request.requestId,\n );\n uiVrfChallengeForUi = uiVrfChallenge;\n }\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallengeForUi });\n if (!confirmed) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) Warm session: dispense WrapKeySeed and skip WebAuthn\n if (signingAuthMode === 'warmSession') {\n try {\n await adapters.vrf.dispenseSessionKey({ sessionId: request.requestId, uses: usesNeeded });\n } catch (err: unknown) {\n const msg = String((toError(err))?.message || err || '');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: msg || 'Failed to dispense warm session key',\n });\n }\n\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n transactionContext,\n });\n return;\n }\n\n // 5) JIT refresh VRF + ctx (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n transactionContext = refreshed.transactionContext;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n } catch (e) {\n console.debug('[SigningFlow] VRF JIT refresh skipped', e);\n }\n\n // 6) Collect authentication credential\n try {\n if (!uiVrfChallenge) {\n throw new Error('Missing vrfChallenge for WebAuthn signing flow');\n }\n const serializedCredential = await adapters.webauthn.collectAuthenticationCredentialWithPRF({\n nearAccountId,\n vrfChallenge: uiVrfChallenge,\n });\n\n // 5c) Derive WrapKeySeed inside the VRF worker and deliver it to the signer worker via\n // the reserved WrapKeySeed MessagePort. Main thread only sees wrapKeySalt metadata.\n let contractId: string | undefined;\n let nearRpcUrl: string | undefined;\n try {\n // Ensure VRF session is active and bound to the same account we are signing for.\n const vrfStatus = await adapters.vrf.checkVrfStatus();\n if (!vrfStatus.active) {\n throw new Error('VRF keypair not active in memory. VRF session may have expired or was not properly initialized. Please refresh and try again.');\n }\n if (!vrfStatus.nearAccountId || String(vrfStatus.nearAccountId) !== String(toAccountId(nearAccountId))) {\n throw new Error('VRF session is active but bound to a different account than the one being signed. Please log in again on this device.');\n }\n\n const deviceNumber = await getLastLoggedInDeviceNumber(toAccountId(nearAccountId), ctx.indexedDB.clientDB);\n const encryptedKeyData = await ctx.indexedDB.nearKeysDB.getEncryptedKey(nearAccountId, deviceNumber);\n // For v2+ vaults, wrapKeySalt is the canonical salt.\n const wrapKeySalt = encryptedKeyData?.wrapKeySalt || '';\n if (!wrapKeySalt) {\n throw new Error('Missing wrapKeySalt in vault; re-register to upgrade vault format.');\n }\n\n // Extract contract verification context when available.\n // - SIGN_TRANSACTION: use per-request rpcCall (already normalized by caller).\n // - SIGN_NEP413_MESSAGE: allow per-request override; fall back to PASSKEY_MANAGER_DEFAULT_CONFIGS.\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n const payload = getSignTransactionPayload(request);\n contractId = payload?.rpcCall?.contractId;\n nearRpcUrl = payload?.rpcCall?.nearRpcUrl;\n } else if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const payload = request.payload as any;\n contractId = payload?.contractId\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.contractId;\n nearRpcUrl = payload?.nearRpcUrl\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.nearRpcUrl;\n }\n\n await adapters.vrf.mintSessionKeysAndSendToSigner({\n sessionId: request.requestId,\n wrapKeySalt,\n contractId,\n nearRpcUrl,\n credential: serializedCredential,\n });\n\t } catch (err) {\n\t console.error('[SigningFlow] WrapKeySeed derivation failed:', err);\n\t throw err; // Don't silently ignore - propagate the error\n\t }\n\n // 6) Respond; keep nonces reserved for worker to use\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serializedCredential,\n // prfOutput intentionally omitted to keep signer PRF-free\n // WrapKeySeed travels only over the dedicated VRF→Signer MessagePort; do not echo in the main-thread envelope\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n } catch (err: unknown) {\n // Treat TouchID/FaceID cancellation and related errors as a negative decision\n const cancelled = isUserCancelledSecureConfirm(err);\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n const msg = String((toError(err))?.message || err || '');\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n // Ensure UI is closed and nonces released, then rethrow\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n const isWrongPasskeyError = /multiple passkeys \\(devicenumbers\\) for account/i.test(msg);\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isWrongPasskeyError ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":";;;;;;;;;AAwBA,SAAS,mBAAmB,SAAuD;AACjF,KAAI,QAAQ,SAAS,uBAAuB,iBAC1C,QAAO,0BAA0B,SAAS,mBAAmB;AAE/D,KAAI,QAAQ,SAAS,uBAAuB,qBAAqB;EAC/D,MAAM,IAAI,QAAQ;AAClB,SAAQ,GAAG,mBAAmD;;AAEhE,QAAO;;AAGT,eAAsB,6BACpB,KACA,SACA,QACA,MACe;CACf,MAAM,EAAE,oBAAoB,uBAAuB;CACnD,MAAM,WAAW,4BAA4B;CAC7C,MAAM,UAAU,qBAAqB;EACnC;EACA;EACA;EACA;EACA;;CAEF,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,kBAAkB,mBAAmB;CAC3C,MAAM,aAAa,WAAW;CAG9B,MAAM,UAAU,MAAM,SAAS,KAAK,iBAAiB;EAAE;EAAe,SAAS;EAAY,eAAe;;AAC1G,KAAI,QAAQ,SAAS,CAAC,QAAQ,oBAAoB;AAEhD,UAAQ,MAAM,yCAAyC;GAAE,OAAO,QAAQ;GAAO,SAAS,QAAQ;;AAChG,SAAO,QAAQ,qBAAqB;GAClC,WAAW,QAAQ;GACnB,cAAc,gBAAgB;GAC9B,WAAW;GACX,OAAO,GAAG,eAAe,cAAc,IAAI,QAAQ;;;AAGvD,SAAQ,kBAAkB,QAAQ;CAClC,IAAI,qBAAqB,QAAQ;CAKjC,MAAM,OAAO,SAAS,IAAI;CAC1B,IAAIA;CACJ,IAAIC,sBAAyD,OACzD;EACE,QAAQ;EACR;EACA,aAAa,mBAAmB;EAChC,WAAW,mBAAmB;KAEhC;AAGJ,KAAI,oBAAoB,YAAY;AAClC,mBAAiB,MAAM,SAAS,IAAI,+BAClC;GACE,QAAQ;GACR;GACA,aAAa,mBAAmB;GAChC,WAAW,mBAAmB;KAEhC,QAAQ;AAEV,wBAAsB;;CAIxB,MAAM,EAAE,WAAW,OAAO,YAAY,MAAM,QAAQ,WAAW,EAAE,cAAc;AAC/E,KAAI,CAAC,UACH,QAAO,QAAQ,qBAAqB;EAClC,WAAW,QAAQ;EACnB,cAAc,gBAAgB;EAC9B,WAAW;EACX,OAAO;;AAKX,KAAI,oBAAoB,eAAe;AACrC,MAAI;AACF,SAAM,SAAS,IAAI,mBAAmB;IAAE,WAAW,QAAQ;IAAW,MAAM;;WACrEC,KAAc;GACrB,MAAM,MAAM,OAAQ,QAAQ,MAAO,WAAW,OAAO;AACrD,UAAO,QAAQ,qBAAqB;IAClC,WAAW,QAAQ;IACnB,cAAc,gBAAgB;IAC9B,WAAW;IACX,OAAO,OAAO;;;AAIlB,UAAQ,qBAAqB;GAC3B,WAAW,QAAQ;GACnB,cAAc,gBAAgB;GAC9B,WAAW;GACX;;AAEF;;AAIF,KAAI;EACF,MAAM,YAAY,MAAM,SAAS,IAAI,yBAAyB,SAAS;AACvE,mBAAiB,UAAU;AAC3B,uBAAqB,UAAU;AAC/B,UAAQ,SAAS,EAAE,cAAc;UAC1B,GAAG;AACV,UAAQ,MAAM,yCAAyC;;AAIzD,KAAI;AACF,MAAI,CAAC,eACH,OAAM,IAAI,MAAM;EAElB,MAAM,uBAAuB,MAAM,SAAS,SAAS,uCAAuC;GAC1F;GACA,cAAc;;EAKhB,IAAIC;EACJ,IAAIC;AACJ,MAAI;GAEF,MAAM,YAAY,MAAM,SAAS,IAAI;AACrC,OAAI,CAAC,UAAU,OACb,OAAM,IAAI,MAAM;AAElB,OAAI,CAAC,UAAU,iBAAiB,OAAO,UAAU,mBAAmB,OAAO,YAAY,gBACrF,OAAM,IAAI,MAAM;GAGlB,MAAM,eAAe,MAAM,4BAA4B,YAAY,gBAAgB,IAAI,UAAU;GACjG,MAAM,mBAAmB,MAAM,IAAI,UAAU,WAAW,gBAAgB,eAAe;GAEvF,MAAM,cAAc,kBAAkB,eAAe;AACrD,OAAI,CAAC,YACH,OAAM,IAAI,MAAM;AAMlB,OAAI,QAAQ,SAAS,uBAAuB,kBAAkB;IAC5D,MAAM,UAAU,0BAA0B;AAC1C,iBAAa,SAAS,SAAS;AAC/B,iBAAa,SAAS,SAAS;cACtB,QAAQ,SAAS,uBAAuB,qBAAqB;IACtE,MAAM,UAAU,QAAQ;AACxB,iBAAa,SAAS,cACjB,gCAAgC;AACrC,iBAAa,SAAS,cACjB,gCAAgC;;AAGvC,SAAM,SAAS,IAAI,+BAA+B;IAChD,WAAW,QAAQ;IACnB;IACA;IACA;IACA,YAAY;;WAEN,KAAK;AACZ,WAAQ,MAAM,gDAAgD;AAC9D,SAAM;;AAIT,UAAQ,qBAAqB;GAC3B,WAAW,QAAQ;GACnB,cAAc,gBAAgB;GAC9B,WAAW;GACX,YAAY;GAGZ,cAAc;GACd;;UAEKF,KAAc;EAErB,MAAM,YAAY,6BAA6B;EAE/C,MAAM,MAAM,OAAQ,QAAQ,MAAO,WAAW,OAAO;AACrD,MAAI,sBAAsB,KAAK,QAAQ,uBAAuB,KAAK,KAEjE,QAAO,QAAQ,kBAAkB;AAEnC,MAAI,UACF,QAAO,QAAQ,YAAY,EAAE,MAAM,sBAAsB;EAE3D,MAAM,sBAAsB,mDAAmD,KAAK;AACpF,SAAO,QAAQ,qBAAqB;GAClC,WAAW,QAAQ;GACnB,cAAc,gBAAgB;GAC9B,WAAW;GACX,OAAO,YACH,eAAe,YACd,sBAAsB,MAAM,eAAe"}
@@ -6,7 +6,7 @@ import "./asset-base-K63RlTrt.js";
6
6
  import "./tx-tree-themes-BND0SU2h.js";
7
7
  import { CONFIRM_UI_ELEMENT_SELECTORS, W3A_TX_BUTTON_HOST_ID, W3A_TX_BUTTON_ID, defineTag } from "./tags-C2Wlhqjd.js";
8
8
  import { WalletIframeDomEvents, computeUiIntentDigestFromTxs, orderActionForDigest } from "./txDigest-CxjhSCgm.js";
9
- import { base64UrlDecode } from "./base64-DBPGuXh4.js";
9
+ import { base64Decode, base64UrlDecode, init_base64 } from "./base64-DBPGuXh4.js";
10
10
  import { ActionType, init_actions, toActionArgsWasm, validateActionArgsWasm } from "./actions-O1FD5Bq8.js";
11
11
  import { ensureKnownW3aElement } from "./ensure-defined-CHInSx7l.js";
12
12
  import { base58Encode, errorMessage, esm_default, getNearShortErrorMessage, getUserFriendlyErrorMessage, init_base58, init_encoders, init_errors, init_esm, isTouchIdCancellationError, toError } from "./errors-D9ar28Dr.js";
@@ -2226,6 +2226,7 @@ init_utils();
2226
2226
  init_encoders();
2227
2227
  init_base58();
2228
2228
  init_esm();
2229
+ init_base64();
2229
2230
  /**
2230
2231
  * Control messages exchanged between worker shims and the main thread.
2231
2232
  *
@@ -3271,42 +3272,42 @@ async function importFlow(label, loader) {
3271
3272
  }
3272
3273
  const HANDLERS = {
3273
3274
  [SecureConfirmationType.DECRYPT_PRIVATE_KEY_WITH_PRF]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
3274
- const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-pXMTqh1m.js"));
3275
+ const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-BHScJasw.js"));
3275
3276
  await handleLocalOnlyFlow(ctx, request, worker, {
3276
3277
  confirmationConfig,
3277
3278
  transactionSummary
3278
3279
  });
3279
3280
  },
3280
3281
  [SecureConfirmationType.SHOW_SECURE_PRIVATE_KEY_UI]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
3281
- const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-pXMTqh1m.js"));
3282
+ const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-BHScJasw.js"));
3282
3283
  await handleLocalOnlyFlow(ctx, request, worker, {
3283
3284
  confirmationConfig,
3284
3285
  transactionSummary
3285
3286
  });
3286
3287
  },
3287
3288
  [SecureConfirmationType.REGISTER_ACCOUNT]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
3288
- const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-DLPLsGCz.js"));
3289
+ const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-lDD60Ytt.js"));
3289
3290
  await handleRegistrationFlow(ctx, request, worker, {
3290
3291
  confirmationConfig,
3291
3292
  transactionSummary
3292
3293
  });
3293
3294
  },
3294
3295
  [SecureConfirmationType.LINK_DEVICE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
3295
- const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-DLPLsGCz.js"));
3296
+ const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-lDD60Ytt.js"));
3296
3297
  await handleRegistrationFlow(ctx, request, worker, {
3297
3298
  confirmationConfig,
3298
3299
  transactionSummary
3299
3300
  });
3300
3301
  },
3301
3302
  [SecureConfirmationType.SIGN_TRANSACTION]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
3302
- const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-Bk-VavcV.js"));
3303
+ const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-BalIhtJ9.js"));
3303
3304
  await handleTransactionSigningFlow(ctx, request, worker, {
3304
3305
  confirmationConfig,
3305
3306
  transactionSummary
3306
3307
  });
3307
3308
  },
3308
3309
  [SecureConfirmationType.SIGN_NEP413_MESSAGE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
3309
- const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-Bk-VavcV.js"));
3310
+ const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-BalIhtJ9.js"));
3310
3311
  await handleTransactionSigningFlow(ctx, request, worker, {
3311
3312
  confirmationConfig,
3312
3313
  transactionSummary
@@ -6385,6 +6386,29 @@ var WebAuthnManager = class {
6385
6386
  async extractCosePublicKey(attestationObjectBase64url) {
6386
6387
  return await this.signerWorkerManager.extractCosePublicKey(attestationObjectBase64url);
6387
6388
  }
6389
+ /**
6390
+ * Helper to ensure the local `lastUser` pointer is consistent with the latest DB updates.
6391
+ * This fixes issues where a recovery or registration might have updated the user record
6392
+ * but failed to update the `lastUser` pointer (e.g. due to previous bugs or interruptions),
6393
+ * preventing the strict `ensureCurrentPasskey` check from passing.
6394
+ */
6395
+ async autoHealLastUserPointer(nearAccountId) {
6396
+ try {
6397
+ const lastUser = await this.getLastUser();
6398
+ if (lastUser && lastUser.nearAccountId === nearAccountId) {
6399
+ const freshest = await IndexedDBManager.clientDB.getLastDBUpdatedUser(nearAccountId);
6400
+ if (freshest && freshest.deviceNumber !== lastUser.deviceNumber) {
6401
+ console.log(`[WebAuthnManager] Auto-healing lastUser pointer from device ${lastUser.deviceNumber} to ${freshest.deviceNumber}`);
6402
+ await this.setLastUser(nearAccountId, freshest.deviceNumber);
6403
+ }
6404
+ } else {
6405
+ const freshest = await IndexedDBManager.clientDB.getLastDBUpdatedUser(nearAccountId);
6406
+ if (freshest) await this.setLastUser(nearAccountId, freshest.deviceNumber);
6407
+ }
6408
+ } catch (e) {
6409
+ console.warn("[WebAuthnManager] Auto-heal pointer failed (non-fatal):", e);
6410
+ }
6411
+ }
6388
6412
  /** Worker-driven export: two-phase V2 (collect PRF → decrypt → show UI) */
6389
6413
  async exportNearKeypairWithUIWorkerDriven(nearAccountId, options) {
6390
6414
  await this.withSigningSession({
@@ -10014,6 +10038,28 @@ var init_emailRecoveryPendingStore = __esm({ "src/core/EmailRecovery/emailRecove
10014
10038
 
10015
10039
  //#endregion
10016
10040
  //#region src/core/EmailRecovery/index.ts
10041
+ function getTxSuccessValueBase64(outcome) {
10042
+ const status = outcome.status;
10043
+ if (!status || typeof status !== "object") return null;
10044
+ if (!("SuccessValue" in status)) return null;
10045
+ const value = status.SuccessValue;
10046
+ return typeof value === "string" && value.length > 0 ? value : null;
10047
+ }
10048
+ function parseLinkDeviceRegisterUserResponse(outcome) {
10049
+ try {
10050
+ const successValueB64 = getTxSuccessValueBase64(outcome);
10051
+ if (!successValueB64) return null;
10052
+ const bytes = base64Decode(successValueB64);
10053
+ const text = new TextDecoder().decode(bytes);
10054
+ if (!text.trim()) return null;
10055
+ const parsed = JSON.parse(text);
10056
+ if (!parsed || typeof parsed !== "object") return null;
10057
+ const candidate = parsed;
10058
+ return typeof candidate.verified === "boolean" ? candidate : null;
10059
+ } catch {
10060
+ return null;
10061
+ }
10062
+ }
10017
10063
  async function hashRecoveryEmails(emails, accountId) {
10018
10064
  const encoder = new TextEncoder();
10019
10065
  const salt = (accountId || "").trim().toLowerCase();
@@ -10085,6 +10131,27 @@ var init_EmailRecovery = __esm({ "src/core/EmailRecovery/index.ts": (() => {
10085
10131
  };
10086
10132
  }) });
10087
10133
 
10134
+ //#endregion
10135
+ //#region src/core/types/emailRecovery.ts
10136
+ var EmailRecoveryErrorCode, EmailRecoveryError;
10137
+ var init_emailRecovery$1 = __esm({ "src/core/types/emailRecovery.ts": (() => {
10138
+ EmailRecoveryErrorCode = /* @__PURE__ */ function(EmailRecoveryErrorCode$1) {
10139
+ EmailRecoveryErrorCode$1["REGISTRATION_NOT_VERIFIED"] = "EMAIL_RECOVERY_REGISTRATION_NOT_VERIFIED";
10140
+ EmailRecoveryErrorCode$1["VRF_CHALLENGE_EXPIRED"] = "EMAIL_RECOVERY_VRF_CHALLENGE_EXPIRED";
10141
+ return EmailRecoveryErrorCode$1;
10142
+ }({});
10143
+ EmailRecoveryError = class extends Error {
10144
+ code;
10145
+ context;
10146
+ constructor(message, code, context) {
10147
+ super(message);
10148
+ this.name = "EmailRecoveryError";
10149
+ this.code = code;
10150
+ this.context = context;
10151
+ }
10152
+ };
10153
+ }) });
10154
+
10088
10155
  //#endregion
10089
10156
  //#region src/core/TatchiPasskey/emailRecovery.ts
10090
10157
  var emailRecovery_exports = {};
@@ -10124,6 +10191,7 @@ var EmailRecoveryFlow;
10124
10191
  var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (() => {
10125
10192
  init_IndexedDBManager();
10126
10193
  init_validation$1();
10194
+ init_errors();
10127
10195
  init_accountIds();
10128
10196
  init_sdkSentEvents();
10129
10197
  init_vrf_worker();
@@ -10131,6 +10199,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10131
10199
  init_getDeviceNumber();
10132
10200
  init_login();
10133
10201
  init_EmailRecovery();
10202
+ init_emailRecovery$1();
10134
10203
  EmailRecoveryFlow = class {
10135
10204
  context;
10136
10205
  options;
@@ -10158,8 +10227,9 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10158
10227
  emit(event) {
10159
10228
  this.options?.onEvent?.(event);
10160
10229
  }
10161
- emitError(step, message) {
10162
- const err$1 = new Error(message);
10230
+ emitError(step, messageOrError) {
10231
+ const err$1 = typeof messageOrError === "string" ? new Error(messageOrError) : messageOrError;
10232
+ const message = err$1.message || (typeof messageOrError === "string" ? messageOrError : "Unknown error");
10163
10233
  this.phase = EmailRecoveryPhase.ERROR;
10164
10234
  this.error = err$1;
10165
10235
  this.emit({
@@ -10218,8 +10288,8 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10218
10288
  const accountView = await this.context.nearClient.viewAccount(nearAccountId);
10219
10289
  const available = this.computeAvailableBalance(accountView);
10220
10290
  if (available < BigInt(minBalanceYocto)) await this.fail(1, `This account does not have enough NEAR to finalize recovery. Available: ${available.toString()} yocto; required: ${String(minBalanceYocto)}. Please top up and try again.`);
10221
- } catch (e) {
10222
- await this.fail(1, e?.message || "Failed to fetch account balance for recovery");
10291
+ } catch (err$1) {
10292
+ await this.fail(1, errorMessage(err$1) || "Failed to fetch account balance for recovery");
10223
10293
  }
10224
10294
  }
10225
10295
  async getCanonicalRecoveryEmailOrFail(recoveryEmail) {
@@ -10231,7 +10301,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10231
10301
  try {
10232
10302
  const { syncAuthenticatorsContractCall: syncAuthenticatorsContractCall$1 } = await import("./rpcCalls-BQrJMTdg.js");
10233
10303
  const authenticators = await syncAuthenticatorsContractCall$1(this.context.nearClient, this.context.configs.contractId, nearAccountId);
10234
- const numbers = authenticators.map((a) => a?.authenticator?.deviceNumber).filter((n) => typeof n === "number" && Number.isFinite(n));
10304
+ const numbers = authenticators.map(({ authenticator }) => authenticator.deviceNumber).filter((n) => typeof n === "number" && Number.isFinite(n));
10235
10305
  const max = numbers.length > 0 ? Math.max(...numbers) : 0;
10236
10306
  return max + 1;
10237
10307
  } catch {
@@ -10479,7 +10549,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10479
10549
  nearPublicKey: rec.nearPublicKey
10480
10550
  };
10481
10551
  } catch (e) {
10482
- const err$1 = this.emitError(2, e?.message || "Email recovery TouchID/derivation failed");
10552
+ const err$1 = this.emitError(2, errorMessage(e) || "Email recovery TouchID/derivation failed");
10483
10553
  await this.options?.afterCall?.(false);
10484
10554
  throw err$1;
10485
10555
  }
@@ -10649,7 +10719,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10649
10719
  accountId
10650
10720
  };
10651
10721
  }
10652
- async signRegistrationTx(rec, accountId) {
10722
+ async signNewDevice2RegistrationTx(rec, accountId) {
10653
10723
  const vrfChallenge = rec.vrfChallenge;
10654
10724
  if (!vrfChallenge) return this.fail(5, "Missing VRF challenge for email recovery registration");
10655
10725
  const registrationResult = await this.context.webAuthnManager.signDevice2RegistrationWithStoredKey({
@@ -10663,47 +10733,56 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10663
10733
  return registrationResult.signedTransaction;
10664
10734
  }
10665
10735
  async broadcastRegistrationTxAndWaitFinal(rec, signedTx) {
10736
+ let txResult;
10666
10737
  try {
10667
- const txResult = await this.context.nearClient.sendTransaction(signedTx, DEFAULT_WAIT_STATUS.linkDeviceRegistration);
10668
- try {
10669
- const txHash = txResult?.transaction?.hash || txResult?.transaction_hash;
10670
- if (txHash) this.emit({
10671
- step: 5,
10672
- phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
10673
- status: EmailRecoveryStatus.PROGRESS,
10674
- message: "Registration transaction confirmed",
10675
- data: {
10676
- accountId: rec.accountId,
10677
- nearPublicKey: rec.nearPublicKey,
10678
- transactionHash: txHash
10679
- }
10680
- });
10681
- return txHash;
10682
- } catch {}
10683
- } catch (e) {
10684
- const msg = String(e?.message || "");
10685
- await this.fail(5, msg || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)");
10738
+ txResult = await this.context.nearClient.sendTransaction(signedTx, DEFAULT_WAIT_STATUS.linkDeviceRegistration);
10739
+ } catch (err$1) {
10740
+ const msg = errorMessage(err$1) || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)";
10741
+ throw new Error(msg);
10686
10742
  }
10687
- return void 0;
10688
- }
10689
- async persistRecoveredUserRecordBestEffort(rec, accountId) {
10690
- try {
10691
- await IndexedDBManager.clientDB.storeWebAuthnUserData({
10692
- nearAccountId: accountId,
10693
- deviceNumber: rec.deviceNumber,
10694
- clientNearPublicKey: rec.nearPublicKey,
10695
- passkeyCredential: {
10696
- id: rec.credential.id,
10697
- rawId: rec.credential.rawId
10698
- },
10699
- encryptedVrfKeypair: rec.encryptedVrfKeypair,
10700
- serverEncryptedVrfKeypair: rec.serverEncryptedVrfKeypair || void 0
10743
+ const txHash = this.getTxHash(txResult);
10744
+ const linkDeviceResult = parseLinkDeviceRegisterUserResponse(txResult);
10745
+ if (linkDeviceResult?.verified === false) {
10746
+ const logs = this.extractNearExecutionLogs(txResult);
10747
+ const isStaleChallenge = logs.some((log) => /StaleChallenge|freshness validation failed/i.test(log));
10748
+ const txHint = txHash ? ` (tx: ${txHash})` : "";
10749
+ const code = isStaleChallenge ? EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED : EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED;
10750
+ const message = isStaleChallenge ? `Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again${txHint}.` : `Registration did not verify on-chain. Please try again${txHint}.`;
10751
+ throw new EmailRecoveryError(message, code, {
10752
+ accountId: rec.accountId,
10753
+ nearPublicKey: rec.nearPublicKey,
10754
+ transactionHash: txHash,
10755
+ logs,
10756
+ result: linkDeviceResult
10701
10757
  });
10702
- return true;
10703
- } catch (err$1) {
10704
- console.warn("[EmailRecoveryFlow] Failed to store recovery user record:", err$1);
10705
- return false;
10706
10758
  }
10759
+ if (txHash) this.emit({
10760
+ step: 5,
10761
+ phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
10762
+ status: EmailRecoveryStatus.PROGRESS,
10763
+ message: "Registration transaction confirmed",
10764
+ data: {
10765
+ accountId: rec.accountId,
10766
+ nearPublicKey: rec.nearPublicKey,
10767
+ transactionHash: txHash
10768
+ }
10769
+ });
10770
+ return txHash;
10771
+ }
10772
+ getTxHash(outcome) {
10773
+ const txUnknown = outcome.transaction;
10774
+ if (txUnknown && typeof txUnknown === "object") {
10775
+ const hash = txUnknown.hash;
10776
+ if (typeof hash === "string" && hash.length > 0) return hash;
10777
+ }
10778
+ const fallback = outcome.transaction_hash;
10779
+ return typeof fallback === "string" && fallback.length > 0 ? fallback : void 0;
10780
+ }
10781
+ extractNearExecutionLogs(outcome) {
10782
+ const logs = [];
10783
+ for (const entry of outcome.transaction_outcome.outcome.logs) logs.push(String(entry));
10784
+ for (const receipt of outcome.receipts_outcome) for (const entry of receipt.outcome.logs) logs.push(String(entry));
10785
+ return logs;
10707
10786
  }
10708
10787
  mapAuthenticatorsFromContract(authenticators) {
10709
10788
  return authenticators.map(({ authenticator }) => ({
@@ -10739,7 +10818,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10739
10818
  }
10740
10819
  async updateNonceBestEffort(nonceManager, signedTx) {
10741
10820
  try {
10742
- const txNonce = signedTx.transaction?.nonce;
10821
+ const txNonce = signedTx.transaction.nonce;
10743
10822
  if (txNonce != null) await nonceManager.updateNonceFromBlockchain(this.context.nearClient, String(txNonce));
10744
10823
  } catch {}
10745
10824
  }
@@ -10762,6 +10841,10 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10762
10841
  };
10763
10842
  await webAuthnManager.storeUserData(payload);
10764
10843
  }
10844
+ /**
10845
+ * Explicitly persist the authenticator from the recovery record into the local cache.
10846
+ * This ensures the key is available immediately, bridging the gap before RPC sync sees it.
10847
+ */
10765
10848
  async persistAuthenticatorBestEffort(rec, accountId) {
10766
10849
  try {
10767
10850
  const { webAuthnManager } = this.context;
@@ -10778,7 +10861,10 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10778
10861
  syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
10779
10862
  vrfPublicKey: rec.vrfPublicKey
10780
10863
  });
10781
- } catch {}
10864
+ console.log("[EmailRecoveryFlow] Locally persisted recovered authenticator for immediate use.");
10865
+ } catch (e) {
10866
+ console.error("[EmailRecoveryFlow] Failed to locally persist authenticator (critical for immediate export):", e);
10867
+ }
10782
10868
  }
10783
10869
  async markCompleteAndClearPending(rec) {
10784
10870
  rec.status = "complete";
@@ -10848,7 +10934,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10848
10934
  } catch (err$1) {
10849
10935
  return {
10850
10936
  success: false,
10851
- reason: err$1?.message || String(err$1)
10937
+ reason: errorMessage(err$1) || String(err$1)
10852
10938
  };
10853
10939
  }
10854
10940
  }
@@ -10876,18 +10962,14 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10876
10962
  });
10877
10963
  try {
10878
10964
  const { nonceManager, accountId } = this.initializeNonceManager(rec);
10879
- const signedTx = await this.signRegistrationTx(rec, accountId);
10965
+ const signedTx = await this.signNewDevice2RegistrationTx(rec, accountId);
10880
10966
  const txHash = await this.broadcastRegistrationTxAndWaitFinal(rec, signedTx);
10881
- if (txHash) {
10882
- const storedUser = await this.persistRecoveredUserRecordBestEffort(rec, accountId);
10883
- if (storedUser) {
10884
- const syncedAuthenticators = await this.syncAuthenticatorsBestEffort(accountId);
10885
- if (syncedAuthenticators) await this.setLastUserBestEffort(accountId, rec.deviceNumber);
10886
- }
10887
- }
10888
- await this.updateNonceBestEffort(nonceManager, signedTx);
10967
+ if (!txHash) console.warn("[EmailRecoveryFlow] Registration transaction confirmed without hash; continuing local persistence");
10889
10968
  await this.persistRecoveredUserData(rec, accountId);
10969
+ await this.syncAuthenticatorsBestEffort(accountId);
10890
10970
  await this.persistAuthenticatorBestEffort(rec, accountId);
10971
+ await this.setLastUserBestEffort(accountId, rec.deviceNumber);
10972
+ await this.updateNonceBestEffort(nonceManager, signedTx);
10891
10973
  this.emitAutoLoginEvent(EmailRecoveryStatus.PROGRESS, "Attempting auto-login with recovered device...", { autoLogin: "progress" });
10892
10974
  const autoLoginResult = await this.attemptAutoLogin(rec);
10893
10975
  if (autoLoginResult.success) this.emitAutoLoginEvent(EmailRecoveryStatus.SUCCESS, `Welcome ${accountId}`, { autoLogin: "success" });
@@ -10908,7 +10990,10 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10908
10990
  }
10909
10991
  });
10910
10992
  } catch (e) {
10911
- const err$1 = this.emitError(5, e?.message || "Email recovery finalization failed");
10993
+ rec.status = "error";
10994
+ await this.savePending(rec).catch(() => {});
10995
+ const original = e instanceof Error ? e : new Error(errorMessage(e) || "Email recovery finalization failed");
10996
+ const err$1 = this.emitError(5, original);
10912
10997
  await this.options?.afterCall?.(false);
10913
10998
  throw err$1;
10914
10999
  }
@@ -10930,7 +11015,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
10930
11015
  };
10931
11016
  return this.handleAutoLoginFailure(touchIdResult.reason || "Auto-login failed");
10932
11017
  } catch (err$1) {
10933
- return this.handleAutoLoginFailure(err$1?.message || String(err$1), err$1);
11018
+ return this.handleAutoLoginFailure(errorMessage(err$1) || String(err$1), err$1);
10934
11019
  }
10935
11020
  }
10936
11021
  };
@@ -1,11 +1,19 @@
1
1
  import type { AccountId } from '../types/accountIds';
2
2
  import { type RecoveryEmailRecord } from '../IndexedDBManager';
3
+ import type { FinalExecutionOutcome } from '@near-js/types';
3
4
  export { EmailRecoveryPendingStore, type PendingStore } from './emailRecoveryPendingStore';
4
5
  export type RecoveryEmailEntry = {
5
6
  hashHex: string;
6
7
  email: string;
7
8
  };
8
9
  export { type RecoveryEmailRecord };
10
+ export type LinkDeviceRegisterUserResponse = {
11
+ verified?: boolean;
12
+ registration_info?: unknown;
13
+ registrationInfo?: unknown;
14
+ error?: unknown;
15
+ };
16
+ export declare function parseLinkDeviceRegisterUserResponse(outcome: FinalExecutionOutcome): LinkDeviceRegisterUserResponse | null;
9
17
  export declare const canonicalizeEmail: (email: string) => string;
10
18
  export declare const bytesToHex: (bytes: number[] | Uint8Array) => string;
11
19
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/EmailRecovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3F,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,OAAO,EAAE,KAAK,mBAAmB,EAAE,CAAC;AAEpC,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MA2BjD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,GAAG,UAAU,KAAG,MAKzD,CAAC;AA4BF;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACvG,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B,CAAC,CAqBD;AAED,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAErG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/EmailRecovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,yBAAyB,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3F,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,OAAO,EAAE,KAAK,mBAAmB,EAAE,CAAC;AAEpC,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAUF,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,qBAAqB,GAC7B,8BAA8B,GAAG,IAAI,CAgBvC;AAED,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MA2BjD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,GAAG,UAAU,KAAG,MAKzD,CAAC;AA4BF;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACvG,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B,CAAC,CAqBD;AAED,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAErG"}
@@ -105,14 +105,19 @@ export declare class EmailRecoveryFlow {
105
105
  }): Promise<void>;
106
106
  private pollUntilAddKey;
107
107
  private initializeNonceManager;
108
- private signRegistrationTx;
108
+ private signNewDevice2RegistrationTx;
109
109
  private broadcastRegistrationTxAndWaitFinal;
110
- private persistRecoveredUserRecordBestEffort;
110
+ private getTxHash;
111
+ private extractNearExecutionLogs;
111
112
  private mapAuthenticatorsFromContract;
112
113
  private syncAuthenticatorsBestEffort;
113
114
  private setLastUserBestEffort;
114
115
  private updateNonceBestEffort;
115
116
  private persistRecoveredUserData;
117
+ /**
118
+ * Explicitly persist the authenticator from the recovery record into the local cache.
119
+ * This ensures the key is available immediately, bridging the gap before RPC sync sees it.
120
+ */
116
121
  private persistAuthenticatorBestEffort;
117
122
  private markCompleteAndClearPending;
118
123
  private assertVrfActiveForAccount;
@@ -1 +1 @@
1
- {"version":3,"file":"emailRecovery.d.ts","sourceRoot":"","sources":["../../../../../src/core/TatchiPasskey/emailRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGrD,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EACL,kBAAkB,EAElB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAKjE,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhF,MAAM,MAAM,0BAA0B,GAClC,gBAAgB,GAChB,kBAAkB,GAClB,YAAY,GACZ,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,yBAAyB,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,8BAA8B,CAAC;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAqCF,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClD;AA8BD,wBAAgB,8BAA8B,IAAI,MAAM,CAWvD;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAAC,CAA2B;IAC3C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,KAAK,CAA6D;IAC1E,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAA6C;IAC1E,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAC,CAAQ;gBAEV,OAAO,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,wBAAwB;IAQ9E,UAAU,CAAC,OAAO,CAAC,EAAE,wBAAwB;IAO7C,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,SAAS;YAeH,IAAI;YAMJ,0BAA0B;YAQ1B,oBAAoB;IAiClC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,uBAAuB;YAUjB,uBAAuB;YAiBvB,+BAA+B;YAQ/B,+BAA+B;YAkB/B,+BAA+B;YAyB/B,wBAAwB;IAgCtC,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,kBAAkB;YAcZ,sBAAsB;IA4DpC,OAAO,CAAC,qBAAqB;YAcf,oBAAoB;YAapB,SAAS;YAoCT,WAAW;YAOX,WAAW;YAKX,YAAY;IAY1B,QAAQ;;;;;IAQF,cAAc,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBpF,KAAK,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IA6DtH,OAAO,CAAC,sBAAsB;YAQhB,6BAA6B;IAMrC,YAAY,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBtF,WAAW,IAAI,IAAI;IAYnB;;;;OAIG;IACG,cAAc,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpF,QAAQ,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA0CpE,eAAe;IA8E7B,OAAO,CAAC,sBAAsB;YAYhB,kBAAkB;YAqBlB,mCAAmC;YAwCnC,oCAAoC;IAuBlD,OAAO,CAAC,6BAA6B;YAYvB,4BAA4B;YAkB5B,qBAAqB;YAUrB,qBAAqB;YAiBrB,wBAAwB;YAsBxB,8BAA8B;YAqB9B,2BAA2B;YAM3B,yBAAyB;YAWzB,uBAAuB;YAOvB,eAAe;YAmCf,gBAAgB;YA6ChB,sBAAsB;YAQtB,oBAAoB;YAoEpB,gBAAgB;CAyB/B"}
1
+ {"version":3,"file":"emailRecovery.d.ts","sourceRoot":"","sources":["../../../../../src/core/TatchiPasskey/emailRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAIrD,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EACL,kBAAkB,EAElB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAuB,8BAA8B,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAKjE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,MAAM,0BAA0B,GAClC,gBAAgB,GAChB,kBAAkB,GAClB,YAAY,GACZ,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,yBAAyB,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,8BAA8B,CAAC;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAqCF,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClD;AA8BD,wBAAgB,8BAA8B,IAAI,MAAM,CAWvD;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAAC,CAA2B;IAC3C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,KAAK,CAA6D;IAC1E,OAAO,CAAC,YAAY,CAA4C;IAChE,OAAO,CAAC,oBAAoB,CAAC,CAAa;IAC1C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAC,CAAQ;gBAEV,OAAO,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,wBAAwB;IAQ9E,UAAU,CAAC,OAAO,CAAC,EAAE,wBAAwB;IAO7C,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,SAAS;YAgBH,IAAI;YAMJ,0BAA0B;YAQ1B,oBAAoB;IAiClC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,uBAAuB;YAUjB,uBAAuB;YAiBvB,+BAA+B;YAQ/B,+BAA+B;YAkB/B,+BAA+B;YAyB/B,wBAAwB;IAgCtC,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,kBAAkB;YAcZ,sBAAsB;IA4DpC,OAAO,CAAC,qBAAqB;YAcf,oBAAoB;YAapB,SAAS;YAoCT,WAAW;YAOX,WAAW;YAKX,YAAY;IAY1B,QAAQ;;;;;IAQF,cAAc,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBpF,KAAK,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IA6DtH,OAAO,CAAC,sBAAsB;YAQhB,6BAA6B;IAMrC,YAAY,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBtF,WAAW,IAAI,IAAI;IAYnB;;;;OAIG;IACG,cAAc,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpF,QAAQ,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA0CpE,eAAe;IA8E7B,OAAO,CAAC,sBAAsB;YAehB,4BAA4B;YAqB5B,mCAAmC;IAyDjD,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,6BAA6B;YAcvB,4BAA4B;YAkB5B,qBAAqB;YAUrB,qBAAqB;YAiBrB,wBAAwB;IAsBtC;;;OAGG;YACW,8BAA8B;YAwB9B,2BAA2B;YAM3B,yBAAyB;YAWzB,uBAAuB;YAOvB,eAAe;YAmCf,gBAAgB;YA6ChB,sBAAsB;YAQtB,oBAAoB;YAgFpB,gBAAgB;CAyB/B"}