@tatchi-xyz/sdk 0.16.0 → 0.17.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/cjs/core/EmailRecovery/index.js +12 -5
- package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js +35 -36
- package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/cjs/core/NearClient.js +2 -1
- package/dist/cjs/core/NearClient.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js +136 -27
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js +1 -0
- package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/index.js +25 -0
- package/dist/cjs/core/TatchiPasskey/index.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/linkDevice.js +2 -0
- package/dist/cjs/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/login.js +15 -4
- package/dist/cjs/core/TatchiPasskey/login.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/recoverAccount.js +1 -0
- package/dist/cjs/core/TatchiPasskey/recoverAccount.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/scanDevice.js +1 -0
- package/dist/cjs/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/cjs/core/WalletIframe/client/IframeTransport.js +10 -0
- package/dist/cjs/core/WalletIframe/client/IframeTransport.js.map +1 -1
- package/dist/cjs/core/WalletIframe/client/router.js +9 -0
- package/dist/cjs/core/WalletIframe/client/router.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
- package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
- package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +10 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/index.js +1 -0
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +6 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +1 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +4 -15
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +1 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +1 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +1 -0
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/index.js +17 -0
- package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
- package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +64 -54
- package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/credentialsHelpers.js +12 -2
- package/dist/cjs/core/WebAuthnManager/credentialsHelpers.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/index.js +6 -1
- package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/touchIdPrompt.js +209 -201
- package/dist/cjs/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/userHandle.js +2 -1
- package/dist/cjs/core/WebAuthnManager/userHandle.js.map +1 -1
- package/dist/cjs/core/defaultConfigs.js +1 -1
- package/dist/cjs/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/core/types/vrf-worker.js +10 -1
- package/dist/cjs/core/types/vrf-worker.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-STvIsylA.css → LinkedDevicesModal-B6api181.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-STvIsylA.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-B6api181.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-iARgUwK1.css → ProfileDropdown-B-DrG_u5.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-iARgUwK1.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-B-DrG_u5.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css → Web3AuthProfileButton-BnZDUeCL.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css.map → Web3AuthProfileButton-BnZDUeCL.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css → TouchIcon-CAGCi8MY.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css.map → TouchIcon-CAGCi8MY.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css → PasskeyAuthMenu-CNNxVj4L.css} +14 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css.map → PasskeyAuthMenu-CNNxVj4L.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +122 -53
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/components/{ShowQRCode-DCnR__fx.css → ShowQRCode-nZhZSaba.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-DCnR__fx.css.map → ShowQRCode-nZhZSaba.css.map} +1 -1
- package/dist/cjs/react/deviceDetection.js +75 -92
- package/dist/cjs/react/deviceDetection.js.map +1 -1
- package/dist/cjs/react/hooks/usePreconnectWalletAssets.js +32 -27
- package/dist/cjs/react/hooks/usePreconnectWalletAssets.js.map +1 -1
- package/dist/cjs/react/hooks/useQRCamera.js +1 -0
- package/dist/cjs/react/hooks/useQRCamera.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +12 -5
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js +35 -36
- package/dist/cjs/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/NearClient.js +2 -1
- package/dist/cjs/react/sdk/src/core/NearClient.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -27
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +1 -0
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js +25 -0
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -0
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/login.js +15 -4
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/login.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/recoverAccount.js +1 -0
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/recoverAccount.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js +1 -0
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/IframeTransport.js +10 -0
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/IframeTransport.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js +9 -0
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +10 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +6 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +4 -15
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js +17 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +64 -54
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/credentialsHelpers.js +12 -2
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/credentialsHelpers.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js +6 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js +209 -201
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/userHandle.js +2 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/userHandle.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/defaultConfigs.js +1 -1
- package/dist/cjs/react/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/types/vrf-worker.js +10 -1
- package/dist/cjs/react/sdk/src/core/types/vrf-worker.js.map +1 -1
- package/dist/cjs/react/sdk/src/utils/index.js +13 -3
- package/dist/cjs/server/email-recovery/emailEncryptor.js +11 -0
- package/dist/cjs/server/email-recovery/emailEncryptor.js.map +1 -1
- package/dist/cjs/server/email-recovery/emailParsers.js +57 -0
- package/dist/cjs/server/email-recovery/emailParsers.js.map +1 -1
- package/dist/cjs/server/email-recovery/index.js +1 -1
- package/dist/cjs/server/email-recovery/index.js.map +1 -1
- package/dist/cjs/server/email-recovery/rpcCalls.js +14 -1
- package/dist/cjs/server/email-recovery/rpcCalls.js.map +1 -1
- package/dist/cjs/server/index.js +1 -0
- package/dist/cjs/server/router/cloudflare.js.map +1 -1
- package/dist/cjs/server/router/express.js.map +1 -1
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js +1 -1
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/utils/index.js +13 -3
- package/dist/esm/core/EmailRecovery/index.js +12 -5
- package/dist/esm/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/core/IndexedDBManager/passkeyClientDB.js +35 -36
- package/dist/esm/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/esm/core/NearClient.js +2 -1
- package/dist/esm/core/NearClient.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/emailRecovery.js +136 -27
- package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js +2 -1
- package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/index.js +26 -1
- package/dist/esm/core/TatchiPasskey/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/linkDevice.js +4 -2
- package/dist/esm/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/login.js +13 -7
- package/dist/esm/core/TatchiPasskey/login.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/recoverAccount.js +2 -1
- package/dist/esm/core/TatchiPasskey/recoverAccount.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/scanDevice.js +2 -1
- package/dist/esm/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/esm/core/WalletIframe/client/IframeTransport.js +11 -1
- package/dist/esm/core/WalletIframe/client/IframeTransport.js.map +1 -1
- package/dist/esm/core/WalletIframe/client/router.js +9 -0
- package/dist/esm/core/WalletIframe/client/router.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
- package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
- package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +6 -2
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +4 -2
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/index.js +2 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +8 -2
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +2 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +2 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +5 -16
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +2 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +2 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +2 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/index.js +12 -0
- package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
- package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +61 -55
- package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/credentialsHelpers.js +8 -3
- package/dist/esm/core/WebAuthnManager/index.js +8 -3
- package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/touchIdPrompt.js +207 -204
- package/dist/esm/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/userHandle.js +2 -1
- package/dist/esm/core/WebAuthnManager/userHandle.js.map +1 -1
- package/dist/esm/core/defaultConfigs.js +1 -1
- package/dist/esm/core/defaultConfigs.js.map +1 -1
- package/dist/esm/core/types/vrf-worker.js +6 -2
- package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-STvIsylA.css → LinkedDevicesModal-B6api181.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-STvIsylA.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-B6api181.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-iARgUwK1.css → ProfileDropdown-B-DrG_u5.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-iARgUwK1.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-B-DrG_u5.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css → Web3AuthProfileButton-BnZDUeCL.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css.map → Web3AuthProfileButton-BnZDUeCL.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css → TouchIcon-CAGCi8MY.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css.map → TouchIcon-CAGCi8MY.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css → PasskeyAuthMenu-CNNxVj4L.css} +14 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css.map → PasskeyAuthMenu-CNNxVj4L.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +123 -54
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/components/{ShowQRCode-DCnR__fx.css → ShowQRCode-nZhZSaba.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-DCnR__fx.css.map → ShowQRCode-nZhZSaba.css.map} +1 -1
- package/dist/esm/react/deviceDetection.js +72 -93
- package/dist/esm/react/deviceDetection.js.map +1 -1
- package/dist/esm/react/hooks/usePreconnectWalletAssets.js +32 -27
- package/dist/esm/react/hooks/usePreconnectWalletAssets.js.map +1 -1
- package/dist/esm/react/hooks/useQRCamera.js +2 -1
- package/dist/esm/react/hooks/useQRCamera.js.map +1 -1
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +12 -5
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js +35 -36
- package/dist/esm/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/esm/react/sdk/src/core/NearClient.js +2 -1
- package/dist/esm/react/sdk/src/core/NearClient.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -27
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js +26 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js +4 -2
- package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/login.js +13 -7
- package/dist/esm/react/sdk/src/core/TatchiPasskey/login.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/recoverAccount.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/recoverAccount.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/IframeTransport.js +11 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/IframeTransport.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js +9 -0
- package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
- package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +6 -2
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +4 -2
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +8 -2
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +5 -16
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js +12 -0
- package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
- package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +61 -55
- package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/credentialsHelpers.js +8 -3
- package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js +8 -3
- package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js +207 -204
- package/dist/esm/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/userHandle.js +2 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/userHandle.js.map +1 -1
- package/dist/esm/react/sdk/src/core/defaultConfigs.js +1 -1
- package/dist/esm/react/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/react/sdk/src/core/types/vrf-worker.js +6 -2
- package/dist/esm/react/sdk/src/utils/index.js +10 -4
- package/dist/esm/react/styles/styles.css +13 -0
- package/dist/esm/sdk/{safari-fallbacks-oQKu9xUs.js → WebAuthnFallbacks-Bl4BTsNt.js} +131 -135
- package/dist/esm/sdk/{createAdapters-pNiL2KNq.js → createAdapters-BumKM2ft.js} +59 -54
- package/dist/esm/sdk/createAdapters-BumKM2ft.js.map +1 -0
- package/dist/esm/sdk/{createAdapters-BWLe9Ddo.js → createAdapters-qVGD6i0g.js} +10 -3
- package/dist/esm/sdk/{defaultConfigs-VzvDejmy.js → defaultConfigs-DpslkAQd.js} +1 -1
- package/dist/esm/sdk/{getDeviceNumber-CkWRT17I.js → getDeviceNumber-fXizNGQl.js} +2 -2
- package/dist/esm/sdk/getDeviceNumber-fXizNGQl.js.map +1 -0
- package/dist/esm/sdk/{getDeviceNumber-CfmlgfMX.js → getDeviceNumber-zsOHT_Um.js} +6 -3
- package/dist/esm/sdk/{localOnly-DnpSyDaF.js → localOnly-Byi3AK7A.js} +2 -2
- package/dist/esm/sdk/{localOnly-DnpSyDaF.js.map → localOnly-Byi3AK7A.js.map} +1 -1
- package/dist/esm/sdk/{localOnly-BdumO2st.js → localOnly-pXMTqh1m.js} +5 -4
- package/dist/esm/sdk/offline-export-app.js +46 -44
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{overlay-BTqPGG-o.js → overlay-ZGbucXIa.js} +2 -0
- package/dist/esm/sdk/{registration-C633u6x8.js → registration-CBiS4Ua_.js} +2 -2
- package/dist/esm/sdk/{registration-C633u6x8.js.map → registration-CBiS4Ua_.js.map} +1 -1
- package/dist/esm/sdk/{registration-xyYUFRqk.js → registration-DLPLsGCz.js} +5 -4
- package/dist/esm/sdk/{requestHelpers-DLBGBHMw.js → requestHelpers-Dh1hEYL9.js} +206 -204
- package/dist/esm/sdk/{router-BG6KC_p7.js → router-BLFegW7J.js} +20 -2
- package/dist/esm/sdk/{rpcCalls-fLObBbbz.js → rpcCalls-DEv9x5-f.js} +2 -2
- package/dist/esm/sdk/{rpcCalls-CAU5XYEF.js → rpcCalls-OhgEeFig.js} +1 -1
- package/dist/esm/sdk/{transactions-jH38BZ-Q.js → transactions-BIqKZeR0.js} +6 -18
- package/dist/esm/sdk/transactions-BIqKZeR0.js.map +1 -0
- package/dist/esm/sdk/{transactions-CzZAt1Yn.js → transactions-Bk-VavcV.js} +10 -21
- package/dist/esm/sdk/tx-confirm-ui.js +53 -53
- package/dist/esm/sdk/{tx-confirmer-wrapper-CqfVBUaA.js → tx-confirmer-wrapper-lHNgz9i4.js} +53 -53
- package/dist/esm/sdk/tx-confirmer.css +6 -4
- package/dist/esm/sdk/w3a-tx-confirmer.js +1 -1
- package/dist/esm/sdk/wallet-iframe-host.js +271 -89
- package/dist/esm/server/email-recovery/emailEncryptor.js +11 -1
- package/dist/esm/server/email-recovery/emailEncryptor.js.map +1 -1
- package/dist/esm/server/email-recovery/emailParsers.js +55 -1
- package/dist/esm/server/email-recovery/emailParsers.js.map +1 -1
- package/dist/esm/server/email-recovery/index.js +2 -2
- package/dist/esm/server/email-recovery/index.js.map +1 -1
- package/dist/esm/server/email-recovery/rpcCalls.js +14 -1
- package/dist/esm/server/email-recovery/rpcCalls.js.map +1 -1
- package/dist/esm/server/index.js +2 -2
- package/dist/esm/server/router/cloudflare.js.map +1 -1
- package/dist/esm/server/router/express.js.map +1 -1
- package/dist/esm/server/sdk/src/core/defaultConfigs.js +1 -1
- package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/utils/index.js +10 -4
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker.js +3 -0
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
- package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts +11 -21
- package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +12 -1
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/index.d.ts +8 -0
- package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts +4 -0
- package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/client/IframeTransport.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/client/router.d.ts +4 -0
- package/dist/types/src/core/WalletIframe/client/router.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/host/wallet-iframe-handlers.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/shared/messages.d.ts +6 -2
- package/dist/types/src/core/WalletIframe/shared/messages.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
- package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/types/src/react/hooks/usePreconnectWalletAssets.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/emailEncryptor.d.ts +4 -0
- package/dist/types/src/server/email-recovery/emailEncryptor.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/emailParsers.d.ts +7 -0
- package/dist/types/src/server/email-recovery/emailParsers.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/index.d.ts +1 -1
- package/dist/types/src/server/email-recovery/rpcCalls.d.ts +1 -1
- package/dist/types/src/server/email-recovery/rpcCalls.d.ts.map +1 -1
- package/dist/types/src/wasm_vrf_worker/pkg/wasm_vrf_worker.d.ts.map +1 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/workers/web3authn-vrf.worker.js +3 -0
- package/package.json +1 -1
- package/dist/esm/sdk/createAdapters-pNiL2KNq.js.map +0 -1
- package/dist/esm/sdk/getDeviceNumber-CkWRT17I.js.map +0 -1
- package/dist/esm/sdk/transactions-jH38BZ-Q.js.map +0 -1
|
@@ -2,7 +2,11 @@ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.js');
|
|
|
2
2
|
const require_validation = require('../../utils/validation.js');
|
|
3
3
|
const require_accountIds = require('../types/accountIds.js');
|
|
4
4
|
const require_index = require('../IndexedDBManager/index.js');
|
|
5
|
+
const require_vrf_worker = require('../types/vrf-worker.js');
|
|
5
6
|
const require_sdkSentEvents = require('../types/sdkSentEvents.js');
|
|
7
|
+
const require_rpc = require('../types/rpc.js');
|
|
8
|
+
const require_getDeviceNumber = require('../WebAuthnManager/SignerWorkerManager/getDeviceNumber.js');
|
|
9
|
+
const require_login = require('./login.js');
|
|
6
10
|
|
|
7
11
|
//#region src/core/TatchiPasskey/emailRecovery.ts
|
|
8
12
|
var emailRecovery_exports = {};
|
|
@@ -44,6 +48,10 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
44
48
|
require_validation.init_validation();
|
|
45
49
|
require_accountIds.init_accountIds();
|
|
46
50
|
require_sdkSentEvents.init_sdkSentEvents();
|
|
51
|
+
require_vrf_worker.init_vrf_worker();
|
|
52
|
+
require_rpc.init_rpc();
|
|
53
|
+
require_getDeviceNumber.init_getDeviceNumber();
|
|
54
|
+
require_login.init_login();
|
|
47
55
|
EmailRecoveryFlow = class {
|
|
48
56
|
context;
|
|
49
57
|
options;
|
|
@@ -85,6 +93,12 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
85
93
|
getConfig() {
|
|
86
94
|
return getEmailRecoveryConfig(this.context.configs);
|
|
87
95
|
}
|
|
96
|
+
getPendingIndexKey(accountId) {
|
|
97
|
+
return `pendingEmailRecovery:${accountId}`;
|
|
98
|
+
}
|
|
99
|
+
getPendingRecordKey(accountId, nearPublicKey) {
|
|
100
|
+
return `${this.getPendingIndexKey(accountId)}:${nearPublicKey}`;
|
|
101
|
+
}
|
|
88
102
|
async checkVerificationStatus(rec) {
|
|
89
103
|
const { dkimVerifierAccountId, verificationViewMethod } = this.getConfig();
|
|
90
104
|
if (!dkimVerifierAccountId) return null;
|
|
@@ -103,22 +117,26 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
103
117
|
return {
|
|
104
118
|
completed: true,
|
|
105
119
|
success: false,
|
|
106
|
-
errorMessage
|
|
120
|
+
errorMessage,
|
|
121
|
+
transactionHash: result.transaction_hash
|
|
107
122
|
};
|
|
108
123
|
}
|
|
109
124
|
if (result.account_id && result.account_id !== rec.accountId) return {
|
|
110
125
|
completed: true,
|
|
111
126
|
success: false,
|
|
112
|
-
errorMessage: "Email verification account_id does not match requested account."
|
|
127
|
+
errorMessage: "Email verification account_id does not match requested account.",
|
|
128
|
+
transactionHash: result.transaction_hash
|
|
113
129
|
};
|
|
114
130
|
if (result.new_public_key && result.new_public_key !== rec.nearPublicKey) return {
|
|
115
131
|
completed: true,
|
|
116
132
|
success: false,
|
|
117
|
-
errorMessage: "Email verification new_public_key does not match expected recovery key."
|
|
133
|
+
errorMessage: "Email verification new_public_key does not match expected recovery key.",
|
|
134
|
+
transactionHash: result.transaction_hash
|
|
118
135
|
};
|
|
119
136
|
return {
|
|
120
137
|
completed: true,
|
|
121
|
-
success: true
|
|
138
|
+
success: true,
|
|
139
|
+
transactionHash: result.transaction_hash
|
|
122
140
|
};
|
|
123
141
|
} catch (err) {
|
|
124
142
|
console.warn("[EmailRecoveryFlow] get_verification_result view failed; falling back to access key polling", err);
|
|
@@ -127,25 +145,37 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
127
145
|
}
|
|
128
146
|
async loadPending(accountId, nearPublicKey) {
|
|
129
147
|
const { pendingTtlMs } = this.getConfig();
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
148
|
+
const indexKey = this.getPendingIndexKey(accountId);
|
|
149
|
+
const indexedNearPublicKey = await require_index.IndexedDBManager.clientDB.getAppState(indexKey);
|
|
150
|
+
const resolvedNearPublicKey = nearPublicKey ?? indexedNearPublicKey;
|
|
151
|
+
if (!resolvedNearPublicKey) return null;
|
|
152
|
+
const recordKey = this.getPendingRecordKey(accountId, resolvedNearPublicKey);
|
|
153
|
+
const record = await require_index.IndexedDBManager.clientDB.getAppState(recordKey);
|
|
154
|
+
const shouldClearIndex = indexedNearPublicKey === resolvedNearPublicKey;
|
|
155
|
+
if (!record) {
|
|
156
|
+
if (shouldClearIndex) await require_index.IndexedDBManager.clientDB.setAppState(indexKey, void 0).catch(() => {});
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
134
159
|
if (Date.now() - record.createdAt > pendingTtlMs) {
|
|
135
|
-
await require_index.IndexedDBManager.clientDB.setAppState(
|
|
160
|
+
await require_index.IndexedDBManager.clientDB.setAppState(recordKey, void 0).catch(() => {});
|
|
161
|
+
if (shouldClearIndex) await require_index.IndexedDBManager.clientDB.setAppState(indexKey, void 0).catch(() => {});
|
|
136
162
|
return null;
|
|
137
163
|
}
|
|
164
|
+
await require_index.IndexedDBManager.clientDB.setAppState(indexKey, record.nearPublicKey).catch(() => {});
|
|
138
165
|
return record;
|
|
139
166
|
}
|
|
140
167
|
async savePending(rec) {
|
|
141
|
-
const key =
|
|
168
|
+
const key = this.getPendingRecordKey(rec.accountId, rec.nearPublicKey);
|
|
142
169
|
await require_index.IndexedDBManager.clientDB.setAppState(key, rec);
|
|
170
|
+
await require_index.IndexedDBManager.clientDB.setAppState(this.getPendingIndexKey(rec.accountId), rec.nearPublicKey).catch(() => {});
|
|
143
171
|
this.pending = rec;
|
|
144
172
|
}
|
|
145
173
|
async clearPending(accountId, nearPublicKey) {
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
174
|
+
const indexKey = this.getPendingIndexKey(accountId);
|
|
175
|
+
const idx = await require_index.IndexedDBManager.clientDB.getAppState(indexKey).catch(() => void 0);
|
|
176
|
+
const resolvedNearPublicKey = nearPublicKey || idx || "";
|
|
177
|
+
if (resolvedNearPublicKey) await require_index.IndexedDBManager.clientDB.setAppState(this.getPendingRecordKey(accountId, resolvedNearPublicKey), void 0).catch(() => {});
|
|
178
|
+
if (!nearPublicKey || idx === nearPublicKey) await require_index.IndexedDBManager.clientDB.setAppState(indexKey, void 0).catch(() => {});
|
|
149
179
|
if (this.pending && this.pending.accountId === accountId && (!nearPublicKey || this.pending.nearPublicKey === nearPublicKey)) this.pending = null;
|
|
150
180
|
}
|
|
151
181
|
getState() {
|
|
@@ -266,7 +296,10 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
266
296
|
message: "Collecting passkey for email recovery..."
|
|
267
297
|
});
|
|
268
298
|
try {
|
|
269
|
-
const confirmerText =
|
|
299
|
+
const confirmerText = {
|
|
300
|
+
title: this.options?.confirmerText?.title ?? "Register New Recovery Account",
|
|
301
|
+
body: this.options?.confirmerText?.body ?? "Create a recovery account and send an encrypted email to recover your account."
|
|
302
|
+
};
|
|
270
303
|
const confirm = await this.context.webAuthnManager.requestRegistrationCredentialConfirmation({
|
|
271
304
|
nearAccountId,
|
|
272
305
|
deviceNumber,
|
|
@@ -394,6 +427,22 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
394
427
|
this.pollIntervalResolver = void 0;
|
|
395
428
|
}
|
|
396
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Best-effort cancellation and local state reset so callers can retry.
|
|
432
|
+
* This does not remove any passkey created in the browser/OS (WebAuthn has no delete API),
|
|
433
|
+
* but it will stop polling and clear the pending IndexedDB record for the given key.
|
|
434
|
+
*/
|
|
435
|
+
async cancelAndReset(args) {
|
|
436
|
+
this.stopPolling();
|
|
437
|
+
const normalizedAccountId = (args?.accountId || this.pending?.accountId || "").toString().trim();
|
|
438
|
+
const nearPublicKey = (args?.nearPublicKey || this.pending?.nearPublicKey || "").toString().trim();
|
|
439
|
+
if (normalizedAccountId) try {
|
|
440
|
+
await this.clearPending(require_accountIds.toAccountId(normalizedAccountId), nearPublicKey);
|
|
441
|
+
} catch {}
|
|
442
|
+
this.pending = null;
|
|
443
|
+
this.error = void 0;
|
|
444
|
+
this.phase = require_sdkSentEvents.EmailRecoveryPhase.STEP_1_PREPARATION;
|
|
445
|
+
}
|
|
397
446
|
async finalize(args) {
|
|
398
447
|
const { accountId, nearPublicKey } = args;
|
|
399
448
|
this.cancelled = false;
|
|
@@ -468,11 +517,12 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
468
517
|
step: 4,
|
|
469
518
|
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_4_POLLING_VERIFICATION_RESULT,
|
|
470
519
|
status: require_sdkSentEvents.EmailRecoveryStatus.PROGRESS,
|
|
471
|
-
message: completed && success ? `
|
|
520
|
+
message: completed && success ? `Email verified for request ${rec.requestId}; finalizing registration` : `Waiting for email verification for request ${rec.requestId}`,
|
|
472
521
|
data: {
|
|
473
522
|
accountId: rec.accountId,
|
|
474
523
|
requestId: rec.requestId,
|
|
475
524
|
nearPublicKey: rec.nearPublicKey,
|
|
525
|
+
transactionHash: verification?.transactionHash,
|
|
476
526
|
elapsedMs: elapsed,
|
|
477
527
|
pollCount
|
|
478
528
|
}
|
|
@@ -489,6 +539,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
489
539
|
await this.savePending(rec);
|
|
490
540
|
return;
|
|
491
541
|
}
|
|
542
|
+
if (this.cancelled) break;
|
|
492
543
|
await new Promise((resolve) => {
|
|
493
544
|
this.pollIntervalResolver = resolve;
|
|
494
545
|
this.pollingTimer = setTimeout(() => {
|
|
@@ -539,7 +590,51 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
539
590
|
}
|
|
540
591
|
const signedTx = registrationResult.signedTransaction;
|
|
541
592
|
try {
|
|
542
|
-
await this.context.nearClient.sendTransaction(signedTx);
|
|
593
|
+
const txResult = await this.context.nearClient.sendTransaction(signedTx, require_rpc.DEFAULT_WAIT_STATUS.linkDeviceRegistration);
|
|
594
|
+
try {
|
|
595
|
+
const txHash = txResult?.transaction?.hash || txResult?.transaction_hash;
|
|
596
|
+
if (txHash) {
|
|
597
|
+
this.emit({
|
|
598
|
+
step: 5,
|
|
599
|
+
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
600
|
+
status: require_sdkSentEvents.EmailRecoveryStatus.PROGRESS,
|
|
601
|
+
message: "Registration transaction confirmed",
|
|
602
|
+
data: {
|
|
603
|
+
accountId: rec.accountId,
|
|
604
|
+
nearPublicKey: rec.nearPublicKey,
|
|
605
|
+
transactionHash: txHash
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
try {
|
|
609
|
+
await require_index.IndexedDBManager.clientDB.storeWebAuthnUserData({
|
|
610
|
+
nearAccountId: accountId,
|
|
611
|
+
deviceNumber: rec.deviceNumber,
|
|
612
|
+
clientNearPublicKey: rec.nearPublicKey,
|
|
613
|
+
passkeyCredential: {
|
|
614
|
+
id: rec.credential.id,
|
|
615
|
+
rawId: rec.credential.rawId
|
|
616
|
+
},
|
|
617
|
+
encryptedVrfKeypair: rec.encryptedVrfKeypair,
|
|
618
|
+
serverEncryptedVrfKeypair: rec.serverEncryptedVrfKeypair || void 0
|
|
619
|
+
});
|
|
620
|
+
const { syncAuthenticatorsContractCall } = await Promise.resolve().then(() => require("../rpcCalls.js"));
|
|
621
|
+
const authenticators = await syncAuthenticatorsContractCall(this.context.nearClient, this.context.configs.contractId, accountId);
|
|
622
|
+
const mappedAuthenticators = authenticators.map(({ authenticator }) => ({
|
|
623
|
+
credentialId: authenticator.credentialId,
|
|
624
|
+
credentialPublicKey: authenticator.credentialPublicKey,
|
|
625
|
+
transports: authenticator.transports,
|
|
626
|
+
name: authenticator.name,
|
|
627
|
+
registered: authenticator.registered.toISOString(),
|
|
628
|
+
vrfPublicKey: authenticator.vrfPublicKeys?.[0] || "",
|
|
629
|
+
deviceNumber: authenticator.deviceNumber
|
|
630
|
+
}));
|
|
631
|
+
await require_index.IndexedDBManager.clientDB.syncAuthenticatorsFromContract(accountId, mappedAuthenticators);
|
|
632
|
+
await require_index.IndexedDBManager.clientDB.setLastUser(accountId, rec.deviceNumber);
|
|
633
|
+
} catch (syncErr) {
|
|
634
|
+
console.warn("[EmailRecoveryFlow] Failed to sync authenticators after recovery:", syncErr);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
} catch {}
|
|
543
638
|
} catch (e) {
|
|
544
639
|
const msg = String(e?.message || "");
|
|
545
640
|
const err = this.emitError(5, msg || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)");
|
|
@@ -613,6 +708,8 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
613
708
|
});
|
|
614
709
|
const { webAuthnManager } = this.context;
|
|
615
710
|
const accountId = require_accountIds.toAccountId(rec.accountId);
|
|
711
|
+
const deviceNumber = require_getDeviceNumber.parseDeviceNumber(rec.deviceNumber, { min: 1 });
|
|
712
|
+
if (deviceNumber === null) throw new Error(`Invalid deviceNumber for auto-login: ${String(rec.deviceNumber)}`);
|
|
616
713
|
if (rec.serverEncryptedVrfKeypair && rec.serverEncryptedVrfKeypair.serverKeyId && this.context.configs.vrfWorkerConfigs?.shamir3pass?.relayServerUrl) try {
|
|
617
714
|
const unlockResult = await webAuthnManager.shamir3PassDecryptVrfKeypair({
|
|
618
715
|
nearAccountId: accountId,
|
|
@@ -621,8 +718,14 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
621
718
|
serverKeyId: rec.serverEncryptedVrfKeypair.serverKeyId
|
|
622
719
|
});
|
|
623
720
|
if (unlockResult.success) {
|
|
721
|
+
const vrfStatus$1 = await webAuthnManager.checkVrfStatus();
|
|
722
|
+
const vrfActiveForAccount$1 = vrfStatus$1.active && vrfStatus$1.nearAccountId && String(vrfStatus$1.nearAccountId) === String(accountId);
|
|
723
|
+
if (!vrfActiveForAccount$1) throw new Error("VRF session inactive after Shamir3Pass unlock");
|
|
724
|
+
await webAuthnManager.setLastUser(accountId, deviceNumber);
|
|
624
725
|
await webAuthnManager.initializeCurrentUser(accountId, this.context.nearClient);
|
|
625
|
-
|
|
726
|
+
try {
|
|
727
|
+
await require_login.getLoginSession(this.context, accountId);
|
|
728
|
+
} catch {}
|
|
626
729
|
this.emit({
|
|
627
730
|
step: 5,
|
|
628
731
|
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
@@ -635,27 +738,30 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
635
738
|
} catch (err) {
|
|
636
739
|
console.warn("[EmailRecoveryFlow] Shamir 3-pass unlock failed, falling back to TouchID", err);
|
|
637
740
|
}
|
|
638
|
-
const
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
blockHash: txBlockHash,
|
|
643
|
-
blockHeight: txBlockHeight
|
|
644
|
-
});
|
|
645
|
-
const authenticators = await webAuthnManager.getAuthenticatorsByUser(accountId);
|
|
741
|
+
const authChallenge = require_vrf_worker.createRandomVRFChallenge();
|
|
742
|
+
const storedCredentialId = String(rec.credential?.rawId || rec.credential?.id || "").trim();
|
|
743
|
+
const credentialIds = storedCredentialId ? [storedCredentialId] : [];
|
|
744
|
+
const authenticators = credentialIds.length > 0 ? [] : await webAuthnManager.getAuthenticatorsByUser(accountId);
|
|
646
745
|
const authCredential = await webAuthnManager.getAuthenticationCredentialsSerializedDualPrf({
|
|
647
746
|
nearAccountId: accountId,
|
|
648
747
|
challenge: authChallenge,
|
|
649
|
-
credentialIds: authenticators.map((a) => a.credentialId)
|
|
748
|
+
credentialIds: credentialIds.length > 0 ? credentialIds : authenticators.map((a) => a.credentialId)
|
|
650
749
|
});
|
|
750
|
+
if (storedCredentialId && authCredential.rawId !== storedCredentialId) throw new Error("Wrong passkey selected during recovery auto-login; please use the newly recovered passkey.");
|
|
651
751
|
const vrfUnlockResult = await webAuthnManager.unlockVRFKeypair({
|
|
652
752
|
nearAccountId: accountId,
|
|
653
753
|
encryptedVrfKeypair: rec.encryptedVrfKeypair,
|
|
654
754
|
credential: authCredential
|
|
655
755
|
});
|
|
656
756
|
if (!vrfUnlockResult.success) throw new Error(vrfUnlockResult.error || "VRF unlock failed during auto-login");
|
|
757
|
+
const vrfStatus = await webAuthnManager.checkVrfStatus();
|
|
758
|
+
const vrfActiveForAccount = vrfStatus.active && vrfStatus.nearAccountId && String(vrfStatus.nearAccountId) === String(accountId);
|
|
759
|
+
if (!vrfActiveForAccount) throw new Error("VRF session inactive after TouchID unlock");
|
|
760
|
+
await webAuthnManager.setLastUser(accountId, deviceNumber);
|
|
657
761
|
await webAuthnManager.initializeCurrentUser(accountId, this.context.nearClient);
|
|
658
|
-
|
|
762
|
+
try {
|
|
763
|
+
await require_login.getLoginSession(this.context, accountId);
|
|
764
|
+
} catch {}
|
|
659
765
|
this.emit({
|
|
660
766
|
step: 5,
|
|
661
767
|
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
@@ -665,6 +771,9 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
665
771
|
});
|
|
666
772
|
} catch (err) {
|
|
667
773
|
console.warn("[EmailRecoveryFlow] Auto-login failed after recovery", err);
|
|
774
|
+
try {
|
|
775
|
+
await this.context.webAuthnManager.clearVrfSession();
|
|
776
|
+
} catch {}
|
|
668
777
|
this.emit({
|
|
669
778
|
step: 5,
|
|
670
779
|
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emailRecovery.js","names":["EmailRecoveryPhase","EmailRecoveryStatus","IndexedDBManager","validateNearAccountId","toAccountId","e: any","rec: PendingEmailRecovery","err","err: any"],"sources":["../../../../src/core/TatchiPasskey/emailRecovery.ts"],"sourcesContent":["import type { PasskeyManagerContext } from './index';\nimport { IndexedDBManager } from '../IndexedDBManager';\nimport { validateNearAccountId } from '../../utils/validation';\nimport { toAccountId, type AccountId } from '../types/accountIds';\nimport {\n EmailRecoveryPhase,\n EmailRecoveryStatus,\n type EmailRecoverySSEEvent,\n type EventCallback,\n type AfterCall,\n} from '../types/sdkSentEvents';\nimport type { TatchiConfigs } from '../types/tatchi';\nimport { authenticatorsToAllowCredentials } from '../WebAuthnManager/touchIdPrompt';\nimport type {\n EncryptedVRFKeypair,\n ServerEncryptedVrfKeypair,\n VRFChallenge,\n} from '../types/vrf-worker';\nimport type { WebAuthnRegistrationCredential } from '../types';\nimport type { ConfirmationConfig } from '../types/signer-worker';\n\nexport type PendingEmailRecoveryStatus =\n | 'awaiting-email'\n | 'awaiting-add-key'\n | 'finalizing'\n | 'complete'\n | 'error';\n\nexport type PendingEmailRecovery = {\n accountId: AccountId;\n recoveryEmail: string;\n deviceNumber: number;\n nearPublicKey: string;\n requestId: string;\n encryptedVrfKeypair: EncryptedVRFKeypair;\n serverEncryptedVrfKeypair: ServerEncryptedVrfKeypair | null;\n vrfPublicKey: string;\n credential: WebAuthnRegistrationCredential;\n vrfChallenge?: VRFChallenge;\n createdAt: number;\n status: PendingEmailRecoveryStatus;\n};\n\nexport interface EmailRecoveryFlowOptions {\n onEvent?: EventCallback<EmailRecoverySSEEvent>;\n onError?: (error: Error) => void;\n afterCall?: AfterCall<void>;\n /**\n * Preferred grouping for per-call confirmer copy.\n */\n confirmerText?: { title?: string; body?: string };\n // Per-call confirmation configuration (non-persistent)\n confirmationConfig?: Partial<ConfirmationConfig>;\n}\n\nfunction getEmailRecoveryConfig(configs: TatchiConfigs): {\n minBalanceYocto: string;\n pollingIntervalMs: number;\n maxPollingDurationMs: number;\n pendingTtlMs: number;\n mailtoAddress: string;\n dkimVerifierAccountId: string;\n verificationViewMethod: string;\n} {\n const relayerEmailCfg = configs.relayer.emailRecovery;\n const minBalanceYocto = String(relayerEmailCfg.minBalanceYocto);\n const pollingIntervalMs = Number(relayerEmailCfg.pollingIntervalMs);\n const maxPollingDurationMs = Number(relayerEmailCfg.maxPollingDurationMs);\n const pendingTtlMs = Number(relayerEmailCfg.pendingTtlMs);\n const mailtoAddress = String(relayerEmailCfg.mailtoAddress);\n const dkimVerifierAccountId = String(relayerEmailCfg.dkimVerifierAccountId);\n const verificationViewMethod = String(relayerEmailCfg.verificationViewMethod);\n return {\n minBalanceYocto,\n pollingIntervalMs,\n maxPollingDurationMs,\n pendingTtlMs,\n mailtoAddress,\n dkimVerifierAccountId,\n verificationViewMethod,\n };\n}\n\nexport function generateEmailRecoveryRequestId(): string {\n // 6-character A–Z0–9 identifier, suitable for short-lived correlation.\n const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n const length = 6;\n const bytes = new Uint8Array(length);\n (globalThis.crypto || window.crypto).getRandomValues(bytes);\n let out = '';\n for (let i = 0; i < length; i++) {\n out += alphabet[bytes[i] % alphabet.length];\n }\n return out;\n}\n\nexport class EmailRecoveryFlow {\n private context: PasskeyManagerContext;\n private options?: EmailRecoveryFlowOptions;\n private pending: PendingEmailRecovery | null = null;\n private phase: EmailRecoveryPhase = EmailRecoveryPhase.STEP_1_PREPARATION;\n private pollingTimer: any;\n private pollIntervalResolver?: (value?: void | PromiseLike<void>) => void;\n private pollingStartedAt: number | null = null;\n private cancelled = false;\n private error?: Error;\n\n constructor(context: PasskeyManagerContext, options?: EmailRecoveryFlowOptions) {\n this.context = context;\n this.options = options;\n }\n\n setOptions(options?: EmailRecoveryFlowOptions) {\n if (!options) return;\n this.options = { ...(this.options || {}), ...options };\n }\n private emit(event: EmailRecoverySSEEvent) {\n this.options?.onEvent?.(event);\n }\n\n private emitError(step: number, message: string): Error {\n const err = new Error(message);\n this.phase = EmailRecoveryPhase.ERROR;\n this.error = err;\n this.emit({\n step,\n phase: EmailRecoveryPhase.ERROR,\n status: EmailRecoveryStatus.ERROR,\n message,\n error: message,\n } as EmailRecoverySSEEvent & { error: string });\n this.options?.onError?.(err);\n return err;\n }\n\n private getConfig() {\n return getEmailRecoveryConfig(this.context.configs);\n }\n\n private async checkVerificationStatus(\n rec: PendingEmailRecovery\n ): Promise<{ completed: boolean; success: boolean; errorMessage?: string } | null> {\n const { dkimVerifierAccountId, verificationViewMethod } = this.getConfig();\n if (!dkimVerifierAccountId) return null;\n\n try {\n type VerificationResult = {\n verified: boolean;\n account_id?: string;\n new_public_key?: string;\n error_code?: string;\n error_message?: string;\n };\n\n const result = await this.context.nearClient.view<\n { request_id: string },\n VerificationResult | null\n >({\n account: dkimVerifierAccountId,\n method: verificationViewMethod,\n args: { request_id: rec.requestId },\n });\n\n if (!result) {\n return { completed: false, success: false };\n }\n\n if (!result.verified) {\n const errorMessage = result.error_message || result.error_code || 'Email verification failed on relayer/contract';\n return { completed: true, success: false, errorMessage };\n }\n\n // Optional safety checks: ensure the bound account/key match expectations when available.\n if (result.account_id && result.account_id !== rec.accountId) {\n return {\n completed: true,\n success: false,\n errorMessage: 'Email verification account_id does not match requested account.',\n };\n }\n if (result.new_public_key && result.new_public_key !== rec.nearPublicKey) {\n return {\n completed: true,\n success: false,\n errorMessage: 'Email verification new_public_key does not match expected recovery key.',\n };\n }\n\n return { completed: true, success: true };\n } catch (err) {\n // If the view method is not available or fails, fall back to access key polling.\n // eslint-disable-next-line no-console\n console.warn('[EmailRecoveryFlow] get_verification_result view failed; falling back to access key polling', err);\n return null;\n }\n }\n\n private async loadPending(\n accountId: AccountId,\n nearPublicKey?: string\n ): Promise<PendingEmailRecovery | null> {\n const { pendingTtlMs } = this.getConfig();\n const keyPrefix = `pendingEmailRecovery:${accountId}`;\n const key = nearPublicKey ? `${keyPrefix}:${nearPublicKey}` : keyPrefix;\n const record = await IndexedDBManager.clientDB.getAppState<PendingEmailRecovery | null>(key);\n if (!record) return null;\n if (Date.now() - record.createdAt > pendingTtlMs) {\n await IndexedDBManager.clientDB.setAppState(key, undefined as any);\n return null;\n }\n return record;\n }\n\n private async savePending(rec: PendingEmailRecovery): Promise<void> {\n const key = `pendingEmailRecovery:${rec.accountId}:${rec.nearPublicKey}`;\n await IndexedDBManager.clientDB.setAppState(key, rec);\n this.pending = rec;\n }\n\n private async clearPending(accountId: AccountId, nearPublicKey?: string): Promise<void> {\n const keyPrefix = `pendingEmailRecovery:${accountId}`;\n const key = nearPublicKey ? `${keyPrefix}:${nearPublicKey}` : keyPrefix;\n await IndexedDBManager.clientDB.setAppState(key, undefined as any);\n if (this.pending && this.pending.accountId === accountId && (!nearPublicKey || this.pending.nearPublicKey === nearPublicKey)) {\n this.pending = null;\n }\n }\n\n getState() {\n return {\n phase: this.phase,\n pending: this.pending,\n error: this.error,\n };\n }\n\n async buildMailtoUrl(args: { accountId: string; nearPublicKey?: string }): Promise<string> {\n const { accountId, nearPublicKey } = args;\n this.cancelled = false;\n this.error = undefined;\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(3, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const nearAccountId = toAccountId(accountId as string);\n let rec = this.pending;\n if (!rec || rec.accountId !== nearAccountId || (nearPublicKey && rec.nearPublicKey !== nearPublicKey)) {\n rec = await this.loadPending(nearAccountId, nearPublicKey);\n this.pending = rec;\n }\n\n if (!rec) {\n const err = this.emitError(3, 'No pending email recovery record found for this account');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n if (rec.status === 'error') {\n const err = this.emitError(3, 'Pending email recovery is in an error state; please restart the flow');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n if (rec.status === 'finalizing' || rec.status === 'complete') {\n const err = this.emitError(3, 'Recovery email has already been processed on-chain for this request');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const mailtoUrl =\n rec.status === 'awaiting-email'\n ? await this.buildMailtoUrlAndUpdateStatus(rec)\n : this.buildMailtoUrlInternal(rec);\n this.phase = EmailRecoveryPhase.STEP_3_AWAIT_EMAIL;\n this.emit({\n step: 3,\n phase: EmailRecoveryPhase.STEP_3_AWAIT_EMAIL,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'New device key created; please send the recovery email from your registered address.',\n data: {\n accountId: rec.accountId,\n recoveryEmail: rec.recoveryEmail,\n nearPublicKey: rec.nearPublicKey,\n requestId: rec.requestId,\n mailtoUrl,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n await this.options?.afterCall?.(true, undefined as any);\n return mailtoUrl;\n }\n\n async start(args: { accountId: string; recoveryEmail: string }): Promise<{ mailtoUrl: string; nearPublicKey: string }> {\n const { accountId, recoveryEmail } = args;\n this.cancelled = false;\n this.error = undefined;\n this.phase = EmailRecoveryPhase.STEP_1_PREPARATION;\n\n this.emit({\n step: 1,\n phase: EmailRecoveryPhase.STEP_1_PREPARATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Preparing email recovery...',\n });\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(1, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const nearAccountId = toAccountId(accountId as string);\n const { minBalanceYocto } = this.getConfig();\n const STORAGE_PRICE_PER_BYTE = BigInt('10000000000000000000'); // 1e19 yocto NEAR per byte\n\n try {\n const accountView = await this.context.nearClient.viewAccount(nearAccountId);\n const amount = BigInt(accountView.amount || '0');\n const locked = BigInt((accountView as any).locked || '0');\n const storageUsage = BigInt((accountView as any).storage_usage || 0);\n const storageCost = storageUsage * STORAGE_PRICE_PER_BYTE;\n const rawAvailable = amount - locked - storageCost;\n const available = rawAvailable > 0 ? rawAvailable : BigInt(0);\n if (available < BigInt(minBalanceYocto)) {\n const err = this.emitError(\n 1,\n `This account does not have enough NEAR to finalize recovery. Available: ${available.toString()} yocto; required: ${String(minBalanceYocto)}. Please top up and try again.`\n );\n await this.options?.afterCall?.(false);\n throw err;\n }\n } catch (e: any) {\n const err = this.emitError(1, e?.message || 'Failed to fetch account balance for recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const canonicalEmail = String(recoveryEmail || '').trim().toLowerCase();\n if (!canonicalEmail) {\n const err = this.emitError(1, 'Recovery email is required for email-based account recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n // Determine deviceNumber from on-chain authenticators\n let deviceNumber = 1;\n try {\n const { syncAuthenticatorsContractCall } = await import('../rpcCalls');\n const authenticators = await syncAuthenticatorsContractCall(\n this.context.nearClient,\n this.context.configs.contractId,\n nearAccountId\n );\n const numbers = authenticators\n .map((a: any) => a?.authenticator?.deviceNumber)\n .filter((n: any) => typeof n === 'number' && Number.isFinite(n)) as number[];\n const max = numbers.length > 0 ? Math.max(...numbers) : 0;\n deviceNumber = max + 1;\n } catch {\n deviceNumber = 1;\n }\n\n this.phase = EmailRecoveryPhase.STEP_2_TOUCH_ID_REGISTRATION;\n this.emit({\n step: 2,\n phase: EmailRecoveryPhase.STEP_2_TOUCH_ID_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Collecting passkey for email recovery...',\n });\n\n try {\n const confirmerText = this.options?.confirmerText;\n const confirm = await this.context.webAuthnManager.requestRegistrationCredentialConfirmation({\n nearAccountId,\n deviceNumber,\n confirmerText,\n confirmationConfigOverride: this.options?.confirmationConfig,\n });\n if (!confirm.confirmed || !confirm.credential) {\n const err = this.emitError(2, 'User cancelled email recovery TouchID confirmation');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const vrfDerivationResult = await this.context.webAuthnManager.deriveVrfKeypair({\n credential: confirm.credential,\n nearAccountId,\n });\n\n if (!vrfDerivationResult.success || !vrfDerivationResult.encryptedVrfKeypair) {\n const err = this.emitError(2, 'Failed to derive VRF keypair from PRF for email recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const nearKeyResult = await this.context.webAuthnManager.deriveNearKeypairAndEncryptFromSerialized({\n nearAccountId,\n credential: confirm.credential,\n options: { deviceNumber },\n });\n\n if (!nearKeyResult.success || !nearKeyResult.publicKey) {\n const err = this.emitError(2, 'Failed to derive NEAR keypair for email recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const rec: PendingEmailRecovery = {\n accountId: nearAccountId,\n recoveryEmail: canonicalEmail,\n deviceNumber,\n nearPublicKey: nearKeyResult.publicKey,\n requestId: generateEmailRecoveryRequestId(),\n encryptedVrfKeypair: vrfDerivationResult.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: vrfDerivationResult.serverEncryptedVrfKeypair || null,\n vrfPublicKey: vrfDerivationResult.vrfPublicKey,\n credential: confirm.credential,\n vrfChallenge: confirm.vrfChallenge || undefined,\n createdAt: Date.now(),\n status: 'awaiting-email',\n };\n\n const mailtoUrl = await this.buildMailtoUrlAndUpdateStatus(rec);\n\n this.phase = EmailRecoveryPhase.STEP_3_AWAIT_EMAIL;\n this.emit({\n step: 3,\n phase: EmailRecoveryPhase.STEP_3_AWAIT_EMAIL,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'New device key created; please send the recovery email from your registered address.',\n data: {\n accountId: rec.accountId,\n recoveryEmail: rec.recoveryEmail,\n nearPublicKey: rec.nearPublicKey,\n requestId: rec.requestId,\n mailtoUrl,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n await this.options?.afterCall?.(true, undefined as any);\n\n return { mailtoUrl, nearPublicKey: rec.nearPublicKey };\n } catch (e: any) {\n const err = this.emitError(2, e?.message || 'Email recovery TouchID/derivation failed');\n await this.options?.afterCall?.(false);\n throw err;\n }\n }\n\n private buildMailtoUrlInternal(rec: PendingEmailRecovery): string {\n const { mailtoAddress } = this.getConfig();\n const to = encodeURIComponent(mailtoAddress);\n const subject = encodeURIComponent(`recover-${rec.requestId} ${rec.accountId} ${rec.nearPublicKey}`);\n const body = encodeURIComponent(`Recovering account ${rec.accountId} with a new passkey.`);\n return `mailto:${to}?subject=${subject}&body=${body}`;\n }\n\n private async buildMailtoUrlAndUpdateStatus(rec: PendingEmailRecovery): Promise<string> {\n rec.status = 'awaiting-add-key';\n await this.savePending(rec);\n return this.buildMailtoUrlInternal(rec);\n }\n\n async startPolling(args: { accountId: string; nearPublicKey?: string }): Promise<void> {\n const { accountId, nearPublicKey } = args;\n this.cancelled = false;\n this.error = undefined;\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(4, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n const nearAccountId = toAccountId(accountId as string);\n\n let rec = this.pending;\n if (!rec || rec.accountId !== nearAccountId || (nearPublicKey && rec.nearPublicKey !== nearPublicKey)) {\n rec = await this.loadPending(nearAccountId, nearPublicKey);\n this.pending = rec;\n }\n if (!rec) {\n const err = this.emitError(4, 'No pending email recovery record found for this account');\n await this.options?.afterCall?.(false);\n throw err;\n }\n if (rec.status === 'error') {\n const err = this.emitError(4, 'Pending email recovery is in an error state; please restart the flow');\n await this.options?.afterCall?.(false);\n throw err;\n }\n if (rec.status === 'complete' || rec.status === 'finalizing') {\n await this.options?.afterCall?.(true, undefined as any);\n return;\n }\n if (rec.status === 'awaiting-email') {\n await this.buildMailtoUrlAndUpdateStatus(rec);\n }\n\n await this.pollUntilAddKey(rec);\n await this.options?.afterCall?.(true, undefined as any);\n }\n\n stopPolling(): void {\n this.cancelled = true;\n if (this.pollingTimer) {\n clearTimeout(this.pollingTimer);\n this.pollingTimer = undefined;\n }\n if (this.pollIntervalResolver) {\n this.pollIntervalResolver();\n this.pollIntervalResolver = undefined;\n }\n }\n\n async finalize(args: { accountId: string; nearPublicKey?: string }): Promise<void> {\n const { accountId, nearPublicKey } = args;\n this.cancelled = false;\n this.error = undefined;\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(4, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n const nearAccountId = toAccountId(accountId as string);\n\n let rec = this.pending;\n if (!rec || rec.accountId !== nearAccountId || (nearPublicKey && rec.nearPublicKey !== nearPublicKey)) {\n rec = await this.loadPending(nearAccountId, nearPublicKey);\n this.pending = rec;\n }\n if (!rec) {\n const err = this.emitError(4, 'No pending email recovery record found for this account');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n this.emit({\n step: 0,\n phase: EmailRecoveryPhase.RESUMED_FROM_PENDING,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Resuming email recovery from pending state...',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n status: rec.status,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n if (rec.status === 'complete') {\n this.phase = EmailRecoveryPhase.STEP_6_COMPLETE;\n this.emit({\n step: 6,\n phase: EmailRecoveryPhase.STEP_6_COMPLETE,\n status: EmailRecoveryStatus.SUCCESS,\n message: 'Email recovery already completed for this key.',\n });\n await this.options?.afterCall?.(true, undefined as any);\n return;\n }\n\n // Ensure verification has completed successfully before finalizing registration.\n await this.pollUntilAddKey(rec);\n await this.finalizeRegistration(rec);\n await this.options?.afterCall?.(true, undefined as any);\n }\n\n private async pollUntilAddKey(rec: PendingEmailRecovery): Promise<void> {\n const { pollingIntervalMs, maxPollingDurationMs, dkimVerifierAccountId } = this.getConfig();\n if (!dkimVerifierAccountId) {\n const err = this.emitError(4, 'Email recovery verification contract (dkimVerifierAccountId) is not configured');\n await this.options?.afterCall?.(false);\n throw err;\n }\n this.phase = EmailRecoveryPhase.STEP_4_POLLING_VERIFICATION_RESULT;\n this.pollingStartedAt = Date.now();\n let pollCount = 0;\n\n while (!this.cancelled) {\n pollCount += 1;\n const elapsed = Date.now() - (this.pollingStartedAt || 0);\n if (elapsed > maxPollingDurationMs) {\n const err = this.emitError(4, 'Timed out waiting for recovery email to be processed on-chain');\n rec.status = 'error';\n await this.savePending(rec);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const verification = await this.checkVerificationStatus(rec);\n const completed = verification?.completed === true;\n const success = verification?.success === true;\n\n this.emit({\n step: 4,\n phase: EmailRecoveryPhase.STEP_4_POLLING_VERIFICATION_RESULT,\n status: EmailRecoveryStatus.PROGRESS,\n message: completed && success\n ? `Recovery email verified for request ${rec.requestId}; finalizing registration...`\n : `Waiting for recovery email verification for request ${rec.requestId}...`,\n data: {\n accountId: rec.accountId,\n requestId: rec.requestId,\n nearPublicKey: rec.nearPublicKey,\n elapsedMs: elapsed,\n pollCount,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n if (completed) {\n if (!success) {\n const err = this.emitError(4, verification?.errorMessage || 'Email verification failed');\n rec.status = 'error';\n await this.savePending(rec);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n rec.status = 'finalizing';\n await this.savePending(rec);\n return;\n }\n\n await new Promise<void>(resolve => {\n this.pollIntervalResolver = resolve;\n this.pollingTimer = setTimeout(() => {\n this.pollIntervalResolver = undefined;\n this.pollingTimer = undefined;\n resolve();\n }, pollingIntervalMs);\n }).finally(() => {\n this.pollIntervalResolver = undefined;\n });\n }\n\n const err = this.emitError(4, 'Email recovery polling was cancelled');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n private async finalizeRegistration(rec: PendingEmailRecovery): Promise<void> {\n this.phase = EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION;\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Finalizing email recovery registration...',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n const nonceManager = this.context.webAuthnManager.getNonceManager();\n const accountId = toAccountId(rec.accountId);\n nonceManager.initializeUser(accountId, rec.nearPublicKey);\n\n try {\n if (!rec.vrfChallenge) {\n const err = this.emitError(5, 'Missing VRF challenge for email recovery registration');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const registrationResult = await this.context.webAuthnManager.signDevice2RegistrationWithStoredKey({\n nearAccountId: accountId,\n credential: rec.credential,\n vrfChallenge: rec.vrfChallenge,\n deterministicVrfPublicKey: rec.vrfPublicKey,\n deviceNumber: rec.deviceNumber,\n });\n\n if (!registrationResult.success || !registrationResult.signedTransaction) {\n const err = this.emitError(5, registrationResult.error || 'Failed to sign email recovery registration transaction');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const signedTx = registrationResult.signedTransaction;\n\n try {\n await this.context.nearClient.sendTransaction(signedTx);\n } catch (e: any) {\n const msg = String(e?.message || '');\n const err = this.emitError(\n 5,\n msg || 'Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)'\n );\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n try {\n const txNonce = (signedTx.transaction as any)?.nonce;\n if (txNonce != null) {\n await nonceManager.updateNonceFromBlockchain(\n this.context.nearClient,\n String(txNonce)\n );\n }\n } catch {\n // best-effort; do not fail flow\n }\n\n const { webAuthnManager } = this.context;\n\n await webAuthnManager.storeUserData({\n nearAccountId: accountId,\n deviceNumber: rec.deviceNumber,\n clientNearPublicKey: rec.nearPublicKey,\n lastUpdated: Date.now(),\n passkeyCredential: {\n id: rec.credential.id,\n rawId: rec.credential.rawId,\n },\n encryptedVrfKeypair: {\n encryptedVrfDataB64u: rec.encryptedVrfKeypair.encryptedVrfDataB64u,\n chacha20NonceB64u: rec.encryptedVrfKeypair.chacha20NonceB64u,\n },\n serverEncryptedVrfKeypair: rec.serverEncryptedVrfKeypair || undefined,\n } as any);\n\n try {\n const attestationB64u = rec.credential.response.attestationObject;\n const credentialPublicKey = await webAuthnManager.extractCosePublicKey(attestationB64u);\n await webAuthnManager.storeAuthenticator({\n nearAccountId: accountId,\n deviceNumber: rec.deviceNumber,\n credentialId: rec.credential.rawId,\n credentialPublicKey,\n transports: ['internal'],\n name: `Device ${rec.deviceNumber} Passkey for ${rec.accountId.split('.')[0]}`,\n registered: new Date().toISOString(),\n syncedAt: new Date().toISOString(),\n vrfPublicKey: rec.vrfPublicKey,\n });\n } catch {\n // best-effort; do not fail flow\n }\n\n await this.attemptAutoLogin(rec);\n\n rec.status = 'complete';\n await this.savePending(rec);\n await this.clearPending(rec.accountId, rec.nearPublicKey);\n\n this.phase = EmailRecoveryPhase.STEP_6_COMPLETE;\n this.emit({\n step: 6,\n phase: EmailRecoveryPhase.STEP_6_COMPLETE,\n status: EmailRecoveryStatus.SUCCESS,\n message: 'Email recovery completed successfully',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n } catch (e: any) {\n const err = this.emitError(5, e?.message || 'Email recovery finalization failed');\n await this.options?.afterCall?.(false);\n throw err;\n }\n }\n\n private async attemptAutoLogin(rec: PendingEmailRecovery): Promise<void> {\n try {\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Attempting auto-login with recovered device...',\n data: { autoLogin: 'progress' },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n const { webAuthnManager } = this.context;\n const accountId = toAccountId(rec.accountId);\n\n // Try Shamir 3-pass unlock first if configured and available\n if (\n rec.serverEncryptedVrfKeypair &&\n rec.serverEncryptedVrfKeypair.serverKeyId &&\n this.context.configs.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ) {\n try {\n const unlockResult = await webAuthnManager.shamir3PassDecryptVrfKeypair({\n nearAccountId: accountId,\n kek_s_b64u: rec.serverEncryptedVrfKeypair.kek_s_b64u,\n ciphertextVrfB64u: rec.serverEncryptedVrfKeypair.ciphertextVrfB64u,\n serverKeyId: rec.serverEncryptedVrfKeypair.serverKeyId,\n });\n\n if (unlockResult.success) {\n await webAuthnManager.initializeCurrentUser(accountId, this.context.nearClient);\n await webAuthnManager.setLastUser(accountId, rec.deviceNumber);\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.SUCCESS,\n message: `Welcome ${accountId}`,\n data: { autoLogin: 'success' },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n return;\n }\n } catch (err) {\n // fall through to TouchID unlock\n console.warn('[EmailRecoveryFlow] Shamir 3-pass unlock failed, falling back to TouchID', err);\n }\n }\n\n // TouchID fallback unlock\n const { txBlockHash, txBlockHeight } = await webAuthnManager\n .getNonceManager()\n .getNonceBlockHashAndHeight(this.context.nearClient);\n\n const authChallenge = await webAuthnManager.generateVrfChallengeOnce({\n userId: accountId,\n rpId: webAuthnManager.getRpId(),\n blockHash: txBlockHash,\n blockHeight: txBlockHeight,\n });\n\n const authenticators = await webAuthnManager.getAuthenticatorsByUser(accountId);\n const authCredential = await webAuthnManager.getAuthenticationCredentialsSerializedDualPrf({\n nearAccountId: accountId,\n challenge: authChallenge,\n credentialIds: authenticators.map((a) => a.credentialId),\n });\n\n const vrfUnlockResult = await webAuthnManager.unlockVRFKeypair({\n nearAccountId: accountId,\n encryptedVrfKeypair: rec.encryptedVrfKeypair,\n credential: authCredential,\n });\n\n if (!vrfUnlockResult.success) {\n throw new Error(vrfUnlockResult.error || 'VRF unlock failed during auto-login');\n }\n\n await webAuthnManager.initializeCurrentUser(accountId, this.context.nearClient);\n await webAuthnManager.setLastUser(accountId, rec.deviceNumber);\n\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.SUCCESS,\n message: `Welcome ${accountId}`,\n data: { autoLogin: 'success' },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n } catch (err: any) {\n console.warn('[EmailRecoveryFlow] Auto-login failed after recovery', err);\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.ERROR,\n message: 'Auto-login failed; please log in manually on this device.',\n data: { error: err?.message || String(err), autoLogin: 'error' },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"emailRecovery.js","names":["EmailRecoveryPhase","EmailRecoveryStatus","IndexedDBManager","validateNearAccountId","toAccountId","e: any","rec: PendingEmailRecovery","err","DEFAULT_WAIT_STATUS","parseDeviceNumber","vrfStatus","vrfActiveForAccount","getLoginSession","createRandomVRFChallenge","err: any"],"sources":["../../../../src/core/TatchiPasskey/emailRecovery.ts"],"sourcesContent":["import type { PasskeyManagerContext } from './index';\nimport { IndexedDBManager } from '../IndexedDBManager';\nimport { validateNearAccountId } from '../../utils/validation';\nimport { toAccountId, type AccountId } from '../types/accountIds';\nimport {\n EmailRecoveryPhase,\n EmailRecoveryStatus,\n type EmailRecoverySSEEvent,\n type EventCallback,\n type AfterCall,\n} from '../types/sdkSentEvents';\nimport type { TatchiConfigs } from '../types/tatchi';\nimport { authenticatorsToAllowCredentials } from '../WebAuthnManager/touchIdPrompt';\nimport {\n createRandomVRFChallenge,\n type EncryptedVRFKeypair,\n type ServerEncryptedVrfKeypair,\n type VRFChallenge,\n} from '../types/vrf-worker';\nimport type { WebAuthnRegistrationCredential } from '../types';\nimport type { ConfirmationConfig } from '../types/signer-worker';\nimport { DEFAULT_WAIT_STATUS } from '../types/rpc';\nimport { parseDeviceNumber } from '../WebAuthnManager/SignerWorkerManager/getDeviceNumber';\nimport { getLoginSession } from './login';\n\nexport type PendingEmailRecoveryStatus =\n | 'awaiting-email'\n | 'awaiting-add-key'\n | 'finalizing'\n | 'complete'\n | 'error';\n\nexport type PendingEmailRecovery = {\n accountId: AccountId;\n recoveryEmail: string;\n deviceNumber: number;\n nearPublicKey: string;\n requestId: string;\n encryptedVrfKeypair: EncryptedVRFKeypair;\n serverEncryptedVrfKeypair: ServerEncryptedVrfKeypair | null;\n vrfPublicKey: string;\n credential: WebAuthnRegistrationCredential;\n vrfChallenge?: VRFChallenge;\n createdAt: number;\n status: PendingEmailRecoveryStatus;\n};\n\nexport interface EmailRecoveryFlowOptions {\n onEvent?: EventCallback<EmailRecoverySSEEvent>;\n onError?: (error: Error) => void;\n afterCall?: AfterCall<void>;\n /**\n * Preferred grouping for per-call confirmer copy.\n */\n confirmerText?: { title?: string; body?: string };\n // Per-call confirmation configuration (non-persistent)\n confirmationConfig?: Partial<ConfirmationConfig>;\n}\n\nfunction getEmailRecoveryConfig(configs: TatchiConfigs): {\n minBalanceYocto: string;\n pollingIntervalMs: number;\n maxPollingDurationMs: number;\n pendingTtlMs: number;\n mailtoAddress: string;\n dkimVerifierAccountId: string;\n verificationViewMethod: string;\n} {\n const relayerEmailCfg = configs.relayer.emailRecovery;\n const minBalanceYocto = String(relayerEmailCfg.minBalanceYocto);\n const pollingIntervalMs = Number(relayerEmailCfg.pollingIntervalMs);\n const maxPollingDurationMs = Number(relayerEmailCfg.maxPollingDurationMs);\n const pendingTtlMs = Number(relayerEmailCfg.pendingTtlMs);\n const mailtoAddress = String(relayerEmailCfg.mailtoAddress);\n const dkimVerifierAccountId = String(relayerEmailCfg.dkimVerifierAccountId);\n const verificationViewMethod = String(relayerEmailCfg.verificationViewMethod);\n return {\n minBalanceYocto,\n pollingIntervalMs,\n maxPollingDurationMs,\n pendingTtlMs,\n mailtoAddress,\n dkimVerifierAccountId,\n verificationViewMethod,\n };\n}\n\nexport function generateEmailRecoveryRequestId(): string {\n // 6-character A–Z0–9 identifier, suitable for short-lived correlation.\n const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n const length = 6;\n const bytes = new Uint8Array(length);\n (globalThis.crypto || window.crypto).getRandomValues(bytes);\n let out = '';\n for (let i = 0; i < length; i++) {\n out += alphabet[bytes[i] % alphabet.length];\n }\n return out;\n}\n\nexport class EmailRecoveryFlow {\n private context: PasskeyManagerContext;\n private options?: EmailRecoveryFlowOptions;\n private pending: PendingEmailRecovery | null = null;\n private phase: EmailRecoveryPhase = EmailRecoveryPhase.STEP_1_PREPARATION;\n private pollingTimer: any;\n private pollIntervalResolver?: (value?: void | PromiseLike<void>) => void;\n private pollingStartedAt: number | null = null;\n private cancelled = false;\n private error?: Error;\n\n constructor(context: PasskeyManagerContext, options?: EmailRecoveryFlowOptions) {\n this.context = context;\n this.options = options;\n }\n\n setOptions(options?: EmailRecoveryFlowOptions) {\n if (!options) return;\n this.options = { ...(this.options || {}), ...options };\n }\n private emit(event: EmailRecoverySSEEvent) {\n this.options?.onEvent?.(event);\n }\n\n private emitError(step: number, message: string): Error {\n const err = new Error(message);\n this.phase = EmailRecoveryPhase.ERROR;\n this.error = err;\n this.emit({\n step,\n phase: EmailRecoveryPhase.ERROR,\n status: EmailRecoveryStatus.ERROR,\n message,\n error: message,\n } as EmailRecoverySSEEvent & { error: string });\n this.options?.onError?.(err);\n return err;\n }\n\n private getConfig() {\n return getEmailRecoveryConfig(this.context.configs);\n }\n\n private getPendingIndexKey(accountId: AccountId): string {\n return `pendingEmailRecovery:${accountId}`;\n }\n\n private getPendingRecordKey(accountId: AccountId, nearPublicKey: string): string {\n return `${this.getPendingIndexKey(accountId)}:${nearPublicKey}`;\n }\n\n private async checkVerificationStatus(\n rec: PendingEmailRecovery\n ): Promise<{ completed: boolean; success: boolean; errorMessage?: string; transactionHash?: string } | null> {\n const { dkimVerifierAccountId, verificationViewMethod } = this.getConfig();\n if (!dkimVerifierAccountId) return null;\n\n try {\n type VerificationResult = {\n verified: boolean;\n account_id?: string;\n new_public_key?: string;\n transaction_hash?: string;\n error_code?: string;\n error_message?: string;\n };\n\n const result = await this.context.nearClient.view<\n { request_id: string },\n VerificationResult | null\n >({\n account: dkimVerifierAccountId,\n method: verificationViewMethod,\n args: { request_id: rec.requestId },\n });\n\n if (!result) {\n return { completed: false, success: false };\n }\n\n if (!result.verified) {\n const errorMessage = result.error_message || result.error_code || 'Email verification failed on relayer/contract';\n return {\n completed: true,\n success: false,\n errorMessage,\n transactionHash: result.transaction_hash,\n };\n }\n\n // Optional safety checks: ensure the bound account/key match expectations when available.\n if (result.account_id && result.account_id !== rec.accountId) {\n return {\n completed: true,\n success: false,\n errorMessage: 'Email verification account_id does not match requested account.',\n transactionHash: result.transaction_hash,\n };\n }\n if (result.new_public_key && result.new_public_key !== rec.nearPublicKey) {\n return {\n completed: true,\n success: false,\n errorMessage: 'Email verification new_public_key does not match expected recovery key.',\n transactionHash: result.transaction_hash,\n };\n }\n\n return {\n completed: true,\n success: true,\n transactionHash: result.transaction_hash\n };\n } catch (err) {\n // If the view method is not available or fails, fall back to access key polling.\n // eslint-disable-next-line no-console\n console.warn('[EmailRecoveryFlow] get_verification_result view failed; falling back to access key polling', err);\n return null;\n }\n }\n\n private async loadPending(\n accountId: AccountId,\n nearPublicKey?: string\n ): Promise<PendingEmailRecovery | null> {\n const { pendingTtlMs } = this.getConfig();\n\n const indexKey = this.getPendingIndexKey(accountId);\n const indexedNearPublicKey = await IndexedDBManager.clientDB.getAppState<string>(indexKey);\n const resolvedNearPublicKey = nearPublicKey ?? indexedNearPublicKey;\n if (!resolvedNearPublicKey) {\n return null;\n }\n\n const recordKey = this.getPendingRecordKey(accountId, resolvedNearPublicKey);\n const record = await IndexedDBManager.clientDB.getAppState<PendingEmailRecovery>(recordKey);\n const shouldClearIndex = indexedNearPublicKey === resolvedNearPublicKey;\n if (!record) {\n if (shouldClearIndex) {\n await IndexedDBManager.clientDB.setAppState(indexKey, undefined as any).catch(() => { });\n }\n return null;\n }\n\n if (Date.now() - record.createdAt > pendingTtlMs) {\n await IndexedDBManager.clientDB.setAppState(recordKey, undefined as any).catch(() => { });\n if (shouldClearIndex) {\n await IndexedDBManager.clientDB.setAppState(indexKey, undefined as any).catch(() => { });\n }\n return null;\n }\n\n // Keep the per-account pointer updated so `finalizeEmailRecovery({ accountId })` can resume.\n await IndexedDBManager.clientDB.setAppState(indexKey, record.nearPublicKey).catch(() => { });\n return record;\n }\n\n private async savePending(rec: PendingEmailRecovery): Promise<void> {\n const key = this.getPendingRecordKey(rec.accountId, rec.nearPublicKey);\n await IndexedDBManager.clientDB.setAppState(key, rec);\n await IndexedDBManager.clientDB.setAppState(this.getPendingIndexKey(rec.accountId), rec.nearPublicKey).catch(() => { });\n this.pending = rec;\n }\n\n private async clearPending(accountId: AccountId, nearPublicKey?: string): Promise<void> {\n const indexKey = this.getPendingIndexKey(accountId);\n const idx = await IndexedDBManager.clientDB.getAppState<string>(indexKey).catch(() => undefined);\n\n const resolvedNearPublicKey = nearPublicKey || idx || '';\n if (resolvedNearPublicKey) {\n await IndexedDBManager.clientDB\n .setAppState(this.getPendingRecordKey(accountId, resolvedNearPublicKey), undefined as any)\n .catch(() => { });\n }\n\n if (!nearPublicKey || idx === nearPublicKey) {\n await IndexedDBManager.clientDB.setAppState(indexKey, undefined as any).catch(() => { });\n }\n\n if (\n this.pending\n && this.pending.accountId === accountId\n && (!nearPublicKey || this.pending.nearPublicKey === nearPublicKey)\n ) {\n this.pending = null;\n }\n }\n\n getState() {\n return {\n phase: this.phase,\n pending: this.pending,\n error: this.error,\n };\n }\n\n async buildMailtoUrl(args: { accountId: string; nearPublicKey?: string }): Promise<string> {\n const { accountId, nearPublicKey } = args;\n this.cancelled = false;\n this.error = undefined;\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(3, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const nearAccountId = toAccountId(accountId as string);\n let rec = this.pending;\n if (!rec || rec.accountId !== nearAccountId || (nearPublicKey && rec.nearPublicKey !== nearPublicKey)) {\n rec = await this.loadPending(nearAccountId, nearPublicKey);\n this.pending = rec;\n }\n\n if (!rec) {\n const err = this.emitError(3, 'No pending email recovery record found for this account');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n if (rec.status === 'error') {\n const err = this.emitError(3, 'Pending email recovery is in an error state; please restart the flow');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n if (rec.status === 'finalizing' || rec.status === 'complete') {\n const err = this.emitError(3, 'Recovery email has already been processed on-chain for this request');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const mailtoUrl =\n rec.status === 'awaiting-email'\n ? await this.buildMailtoUrlAndUpdateStatus(rec)\n : this.buildMailtoUrlInternal(rec);\n this.phase = EmailRecoveryPhase.STEP_3_AWAIT_EMAIL;\n this.emit({\n step: 3,\n phase: EmailRecoveryPhase.STEP_3_AWAIT_EMAIL,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'New device key created; please send the recovery email from your registered address.',\n data: {\n accountId: rec.accountId,\n recoveryEmail: rec.recoveryEmail,\n nearPublicKey: rec.nearPublicKey,\n requestId: rec.requestId,\n mailtoUrl,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n await this.options?.afterCall?.(true, undefined as any);\n return mailtoUrl;\n }\n\n async start(args: { accountId: string; recoveryEmail: string }): Promise<{ mailtoUrl: string; nearPublicKey: string }> {\n const { accountId, recoveryEmail } = args;\n this.cancelled = false;\n this.error = undefined;\n this.phase = EmailRecoveryPhase.STEP_1_PREPARATION;\n\n this.emit({\n step: 1,\n phase: EmailRecoveryPhase.STEP_1_PREPARATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Preparing email recovery...',\n });\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(1, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const nearAccountId = toAccountId(accountId as string);\n const { minBalanceYocto } = this.getConfig();\n const STORAGE_PRICE_PER_BYTE = BigInt('10000000000000000000'); // 1e19 yocto NEAR per byte\n\n try {\n const accountView = await this.context.nearClient.viewAccount(nearAccountId);\n const amount = BigInt(accountView.amount || '0');\n const locked = BigInt((accountView as any).locked || '0');\n const storageUsage = BigInt((accountView as any).storage_usage || 0);\n const storageCost = storageUsage * STORAGE_PRICE_PER_BYTE;\n const rawAvailable = amount - locked - storageCost;\n const available = rawAvailable > 0 ? rawAvailable : BigInt(0);\n if (available < BigInt(minBalanceYocto)) {\n const err = this.emitError(\n 1,\n `This account does not have enough NEAR to finalize recovery. Available: ${available.toString()} yocto; required: ${String(minBalanceYocto)}. Please top up and try again.`\n );\n await this.options?.afterCall?.(false);\n throw err;\n }\n } catch (e: any) {\n const err = this.emitError(1, e?.message || 'Failed to fetch account balance for recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const canonicalEmail = String(recoveryEmail || '').trim().toLowerCase();\n if (!canonicalEmail) {\n const err = this.emitError(1, 'Recovery email is required for email-based account recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n // Determine deviceNumber from on-chain authenticators\n let deviceNumber = 1;\n try {\n const { syncAuthenticatorsContractCall } = await import('../rpcCalls');\n const authenticators = await syncAuthenticatorsContractCall(\n this.context.nearClient,\n this.context.configs.contractId,\n nearAccountId\n );\n const numbers = authenticators\n .map((a: any) => a?.authenticator?.deviceNumber)\n .filter((n: any) => typeof n === 'number' && Number.isFinite(n)) as number[];\n const max = numbers.length > 0 ? Math.max(...numbers) : 0;\n deviceNumber = max + 1;\n } catch {\n deviceNumber = 1;\n }\n\n this.phase = EmailRecoveryPhase.STEP_2_TOUCH_ID_REGISTRATION;\n this.emit({\n step: 2,\n phase: EmailRecoveryPhase.STEP_2_TOUCH_ID_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Collecting passkey for email recovery...',\n });\n\n try {\n const confirmerText = {\n title: this.options?.confirmerText?.title ?? 'Register New Recovery Account',\n body: this.options?.confirmerText?.body ?? 'Create a recovery account and send an encrypted email to recover your account.',\n };\n const confirm = await this.context.webAuthnManager.requestRegistrationCredentialConfirmation({\n nearAccountId,\n deviceNumber,\n confirmerText,\n confirmationConfigOverride: this.options?.confirmationConfig,\n });\n if (!confirm.confirmed || !confirm.credential) {\n const err = this.emitError(2, 'User cancelled email recovery TouchID confirmation');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const vrfDerivationResult = await this.context.webAuthnManager.deriveVrfKeypair({\n credential: confirm.credential,\n nearAccountId,\n });\n\n if (!vrfDerivationResult.success || !vrfDerivationResult.encryptedVrfKeypair) {\n const err = this.emitError(2, 'Failed to derive VRF keypair from PRF for email recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const nearKeyResult = await this.context.webAuthnManager.deriveNearKeypairAndEncryptFromSerialized({\n nearAccountId,\n credential: confirm.credential,\n options: { deviceNumber },\n });\n\n if (!nearKeyResult.success || !nearKeyResult.publicKey) {\n const err = this.emitError(2, 'Failed to derive NEAR keypair for email recovery');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const rec: PendingEmailRecovery = {\n accountId: nearAccountId,\n recoveryEmail: canonicalEmail,\n deviceNumber,\n nearPublicKey: nearKeyResult.publicKey,\n requestId: generateEmailRecoveryRequestId(),\n encryptedVrfKeypair: vrfDerivationResult.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: vrfDerivationResult.serverEncryptedVrfKeypair || null,\n vrfPublicKey: vrfDerivationResult.vrfPublicKey,\n credential: confirm.credential,\n vrfChallenge: confirm.vrfChallenge || undefined,\n createdAt: Date.now(),\n status: 'awaiting-email',\n };\n\n const mailtoUrl = await this.buildMailtoUrlAndUpdateStatus(rec);\n\n this.phase = EmailRecoveryPhase.STEP_3_AWAIT_EMAIL;\n this.emit({\n step: 3,\n phase: EmailRecoveryPhase.STEP_3_AWAIT_EMAIL,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'New device key created; please send the recovery email from your registered address.',\n data: {\n accountId: rec.accountId,\n recoveryEmail: rec.recoveryEmail,\n nearPublicKey: rec.nearPublicKey,\n requestId: rec.requestId,\n mailtoUrl,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n await this.options?.afterCall?.(true, undefined as any);\n\n return { mailtoUrl, nearPublicKey: rec.nearPublicKey };\n } catch (e: any) {\n const err = this.emitError(2, e?.message || 'Email recovery TouchID/derivation failed');\n await this.options?.afterCall?.(false);\n throw err;\n }\n }\n\n private buildMailtoUrlInternal(rec: PendingEmailRecovery): string {\n const { mailtoAddress } = this.getConfig();\n const to = encodeURIComponent(mailtoAddress);\n const subject = encodeURIComponent(`recover-${rec.requestId} ${rec.accountId} ${rec.nearPublicKey}`);\n const body = encodeURIComponent(`Recovering account ${rec.accountId} with a new passkey.`);\n return `mailto:${to}?subject=${subject}&body=${body}`;\n }\n\n private async buildMailtoUrlAndUpdateStatus(rec: PendingEmailRecovery): Promise<string> {\n rec.status = 'awaiting-add-key';\n await this.savePending(rec);\n return this.buildMailtoUrlInternal(rec);\n }\n\n async startPolling(args: { accountId: string; nearPublicKey?: string }): Promise<void> {\n const { accountId, nearPublicKey } = args;\n this.cancelled = false;\n this.error = undefined;\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(4, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n const nearAccountId = toAccountId(accountId as string);\n\n let rec = this.pending;\n if (!rec || rec.accountId !== nearAccountId || (nearPublicKey && rec.nearPublicKey !== nearPublicKey)) {\n rec = await this.loadPending(nearAccountId, nearPublicKey);\n this.pending = rec;\n }\n if (!rec) {\n const err = this.emitError(4, 'No pending email recovery record found for this account');\n await this.options?.afterCall?.(false);\n throw err;\n }\n if (rec.status === 'error') {\n const err = this.emitError(4, 'Pending email recovery is in an error state; please restart the flow');\n await this.options?.afterCall?.(false);\n throw err;\n }\n if (rec.status === 'complete' || rec.status === 'finalizing') {\n await this.options?.afterCall?.(true, undefined as any);\n return;\n }\n if (rec.status === 'awaiting-email') {\n await this.buildMailtoUrlAndUpdateStatus(rec);\n }\n\n await this.pollUntilAddKey(rec);\n await this.options?.afterCall?.(true, undefined as any);\n }\n\n stopPolling(): void {\n this.cancelled = true;\n if (this.pollingTimer) {\n clearTimeout(this.pollingTimer);\n this.pollingTimer = undefined;\n }\n if (this.pollIntervalResolver) {\n this.pollIntervalResolver();\n this.pollIntervalResolver = undefined;\n }\n }\n\n /**\n * Best-effort cancellation and local state reset so callers can retry.\n * This does not remove any passkey created in the browser/OS (WebAuthn has no delete API),\n * but it will stop polling and clear the pending IndexedDB record for the given key.\n */\n async cancelAndReset(args?: { accountId?: string; nearPublicKey?: string }): Promise<void> {\n this.stopPolling();\n\n const normalizedAccountId = (args?.accountId || this.pending?.accountId || '').toString().trim();\n const nearPublicKey = (args?.nearPublicKey || this.pending?.nearPublicKey || '').toString().trim();\n\n if (normalizedAccountId) {\n try {\n await this.clearPending(toAccountId(normalizedAccountId), nearPublicKey);\n } catch {\n // best-effort\n }\n }\n\n this.pending = null;\n this.error = undefined;\n this.phase = EmailRecoveryPhase.STEP_1_PREPARATION;\n }\n\n async finalize(args: { accountId: string; nearPublicKey?: string }): Promise<void> {\n const { accountId, nearPublicKey } = args;\n this.cancelled = false;\n this.error = undefined;\n\n const validation = validateNearAccountId(accountId as AccountId);\n if (!validation.valid) {\n const err = this.emitError(4, `Invalid NEAR account ID: ${validation.error}`);\n await this.options?.afterCall?.(false);\n throw err;\n }\n const nearAccountId = toAccountId(accountId as string);\n\n let rec = this.pending;\n if (!rec || rec.accountId !== nearAccountId || (nearPublicKey && rec.nearPublicKey !== nearPublicKey)) {\n rec = await this.loadPending(nearAccountId, nearPublicKey);\n this.pending = rec;\n }\n if (!rec) {\n const err = this.emitError(4, 'No pending email recovery record found for this account');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n this.emit({\n step: 0,\n phase: EmailRecoveryPhase.RESUMED_FROM_PENDING,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Resuming email recovery from pending state...',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n status: rec.status,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n if (rec.status === 'complete') {\n this.phase = EmailRecoveryPhase.STEP_6_COMPLETE;\n this.emit({\n step: 6,\n phase: EmailRecoveryPhase.STEP_6_COMPLETE,\n status: EmailRecoveryStatus.SUCCESS,\n message: 'Email recovery already completed for this key.',\n });\n await this.options?.afterCall?.(true, undefined as any);\n return;\n }\n\n // Ensure verification has completed successfully before finalizing registration.\n await this.pollUntilAddKey(rec);\n await this.finalizeRegistration(rec);\n await this.options?.afterCall?.(true, undefined as any);\n }\n\n private async pollUntilAddKey(rec: PendingEmailRecovery): Promise<void> {\n const { pollingIntervalMs, maxPollingDurationMs, dkimVerifierAccountId } = this.getConfig();\n if (!dkimVerifierAccountId) {\n const err = this.emitError(4, 'Email recovery verification contract (dkimVerifierAccountId) is not configured');\n await this.options?.afterCall?.(false);\n throw err;\n }\n this.phase = EmailRecoveryPhase.STEP_4_POLLING_VERIFICATION_RESULT;\n this.pollingStartedAt = Date.now();\n let pollCount = 0;\n\n while (!this.cancelled) {\n pollCount += 1;\n const elapsed = Date.now() - (this.pollingStartedAt || 0);\n if (elapsed > maxPollingDurationMs) {\n const err = this.emitError(4, 'Timed out waiting for recovery email to be processed on-chain');\n rec.status = 'error';\n await this.savePending(rec);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const verification = await this.checkVerificationStatus(rec);\n const completed = verification?.completed === true;\n const success = verification?.success === true;\n\n this.emit({\n step: 4,\n phase: EmailRecoveryPhase.STEP_4_POLLING_VERIFICATION_RESULT,\n status: EmailRecoveryStatus.PROGRESS,\n message: completed && success\n ? `Email verified for request ${rec.requestId}; finalizing registration`\n : `Waiting for email verification for request ${rec.requestId}`,\n data: {\n accountId: rec.accountId,\n requestId: rec.requestId,\n nearPublicKey: rec.nearPublicKey,\n transactionHash: verification?.transactionHash,\n elapsedMs: elapsed,\n pollCount,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n if (completed) {\n if (!success) {\n const err = this.emitError(4, verification?.errorMessage || 'Email verification failed');\n rec.status = 'error';\n await this.savePending(rec);\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n rec.status = 'finalizing';\n await this.savePending(rec);\n return;\n }\n\n // If cancellation happens mid-iteration (e.g. while awaiting a view call),\n // don't wait an extra pollingIntervalMs before unwinding.\n if (this.cancelled) break;\n\n await new Promise<void>(resolve => {\n this.pollIntervalResolver = resolve;\n this.pollingTimer = setTimeout(() => {\n this.pollIntervalResolver = undefined;\n this.pollingTimer = undefined;\n resolve();\n }, pollingIntervalMs);\n }).finally(() => {\n this.pollIntervalResolver = undefined;\n });\n }\n\n const err = this.emitError(4, 'Email recovery polling was cancelled');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n private async finalizeRegistration(rec: PendingEmailRecovery): Promise<void> {\n this.phase = EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION;\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Finalizing email recovery registration...',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n const nonceManager = this.context.webAuthnManager.getNonceManager();\n const accountId = toAccountId(rec.accountId);\n nonceManager.initializeUser(accountId, rec.nearPublicKey);\n\n try {\n if (!rec.vrfChallenge) {\n const err = this.emitError(5, 'Missing VRF challenge for email recovery registration');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const registrationResult = await this.context.webAuthnManager.signDevice2RegistrationWithStoredKey({\n nearAccountId: accountId,\n credential: rec.credential,\n vrfChallenge: rec.vrfChallenge,\n deterministicVrfPublicKey: rec.vrfPublicKey,\n deviceNumber: rec.deviceNumber,\n });\n\n if (!registrationResult.success || !registrationResult.signedTransaction) {\n const err = this.emitError(5, registrationResult.error || 'Failed to sign email recovery registration transaction');\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n const signedTx = registrationResult.signedTransaction;\n\n try {\n // Wait for finality so subsequent contract-gated signing (verify_authentication_response)\n // can reliably see the newly registered device/passkey.\n const txResult = await this.context.nearClient.sendTransaction(signedTx, DEFAULT_WAIT_STATUS.linkDeviceRegistration);\n try {\n const txHash = (txResult as any)?.transaction?.hash || (txResult as any)?.transaction_hash;\n if (txHash) {\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Registration transaction confirmed',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n transactionHash: txHash,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n // Store the new user record here, so `getLastUser()`\n // is aware of the new device context before any subsequent actions occur.\n try {\n // 1. Store the new user record (Device N) so that `getLastUser()` finds it\n // and `ensureCurrentPasskey` selects the correct credential for operations.\n await IndexedDBManager.clientDB.storeWebAuthnUserData({\n nearAccountId: accountId,\n deviceNumber: rec.deviceNumber,\n clientNearPublicKey: rec.nearPublicKey,\n passkeyCredential: {\n id: rec.credential.id,\n rawId: rec.credential.rawId,\n },\n encryptedVrfKeypair: rec.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: rec.serverEncryptedVrfKeypair || undefined,\n });\n\n // 2. Sync authenticators immediately for allowCredentials list\n const { syncAuthenticatorsContractCall } = await import('../rpcCalls');\n const authenticators = await syncAuthenticatorsContractCall(\n this.context.nearClient,\n this.context.configs.contractId,\n accountId\n );\n\n // Map RPC result to DB schema\n const mappedAuthenticators = authenticators.map(({ authenticator }) => ({\n credentialId: authenticator.credentialId,\n credentialPublicKey: authenticator.credentialPublicKey,\n transports: authenticator.transports,\n name: authenticator.name,\n registered: authenticator.registered.toISOString(),\n vrfPublicKey: authenticator.vrfPublicKeys?.[0] || '',\n deviceNumber: authenticator.deviceNumber,\n }));\n\n await IndexedDBManager.clientDB.syncAuthenticatorsFromContract(accountId, mappedAuthenticators);\n\n // 3. Set as active user\n await IndexedDBManager.clientDB.setLastUser(accountId, rec.deviceNumber);\n } catch (syncErr) {\n console.warn('[EmailRecoveryFlow] Failed to sync authenticators after recovery:', syncErr);\n // Non-fatal; user can still proceed but might need a refresh for some features\n }\n }\n } catch {\n // best-effort; do not fail flow\n }\n } catch (e: any) {\n const msg = String(e?.message || '');\n const err = this.emitError(\n 5,\n msg || 'Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)'\n );\n await this.options?.afterCall?.(false);\n throw err;\n }\n\n try {\n const txNonce = (signedTx.transaction as any)?.nonce;\n if (txNonce != null) {\n await nonceManager.updateNonceFromBlockchain(\n this.context.nearClient,\n String(txNonce)\n );\n }\n } catch {\n // best-effort; do not fail flow\n }\n\n const { webAuthnManager } = this.context;\n\n await webAuthnManager.storeUserData({\n nearAccountId: accountId,\n deviceNumber: rec.deviceNumber,\n clientNearPublicKey: rec.nearPublicKey,\n lastUpdated: Date.now(),\n passkeyCredential: {\n id: rec.credential.id,\n rawId: rec.credential.rawId,\n },\n encryptedVrfKeypair: {\n encryptedVrfDataB64u: rec.encryptedVrfKeypair.encryptedVrfDataB64u,\n chacha20NonceB64u: rec.encryptedVrfKeypair.chacha20NonceB64u,\n },\n serverEncryptedVrfKeypair: rec.serverEncryptedVrfKeypair || undefined,\n } as any);\n\n try {\n const attestationB64u = rec.credential.response.attestationObject;\n const credentialPublicKey = await webAuthnManager.extractCosePublicKey(attestationB64u);\n await webAuthnManager.storeAuthenticator({\n nearAccountId: accountId,\n deviceNumber: rec.deviceNumber,\n credentialId: rec.credential.rawId,\n credentialPublicKey,\n transports: ['internal'],\n name: `Device ${rec.deviceNumber} Passkey for ${rec.accountId.split('.')[0]}`,\n registered: new Date().toISOString(),\n syncedAt: new Date().toISOString(),\n vrfPublicKey: rec.vrfPublicKey,\n });\n } catch {\n // best-effort; do not fail flow\n }\n\n await this.attemptAutoLogin(rec);\n\n rec.status = 'complete';\n await this.savePending(rec);\n await this.clearPending(rec.accountId, rec.nearPublicKey);\n\n this.phase = EmailRecoveryPhase.STEP_6_COMPLETE;\n this.emit({\n step: 6,\n phase: EmailRecoveryPhase.STEP_6_COMPLETE,\n status: EmailRecoveryStatus.SUCCESS,\n message: 'Email recovery completed successfully',\n data: {\n accountId: rec.accountId,\n nearPublicKey: rec.nearPublicKey,\n },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n } catch (e: any) {\n const err = this.emitError(5, e?.message || 'Email recovery finalization failed');\n await this.options?.afterCall?.(false);\n throw err;\n }\n }\n\n private async attemptAutoLogin(rec: PendingEmailRecovery): Promise<void> {\n try {\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.PROGRESS,\n message: 'Attempting auto-login with recovered device...',\n data: { autoLogin: 'progress' },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n\n const { webAuthnManager } = this.context;\n const accountId = toAccountId(rec.accountId);\n const deviceNumber = parseDeviceNumber(rec.deviceNumber, { min: 1 });\n if (deviceNumber === null) {\n throw new Error(`Invalid deviceNumber for auto-login: ${String(rec.deviceNumber)}`);\n }\n\n // Try Shamir 3-pass unlock first if configured and available\n if (\n rec.serverEncryptedVrfKeypair &&\n rec.serverEncryptedVrfKeypair.serverKeyId &&\n this.context.configs.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ) {\n try {\n const unlockResult = await webAuthnManager.shamir3PassDecryptVrfKeypair({\n nearAccountId: accountId,\n kek_s_b64u: rec.serverEncryptedVrfKeypair.kek_s_b64u,\n ciphertextVrfB64u: rec.serverEncryptedVrfKeypair.ciphertextVrfB64u,\n serverKeyId: rec.serverEncryptedVrfKeypair.serverKeyId,\n });\n\n if (unlockResult.success) {\n const vrfStatus = await webAuthnManager.checkVrfStatus();\n const vrfActiveForAccount =\n vrfStatus.active\n && vrfStatus.nearAccountId\n && String(vrfStatus.nearAccountId) === String(accountId);\n if (!vrfActiveForAccount) {\n throw new Error('VRF session inactive after Shamir3Pass unlock');\n }\n\n await webAuthnManager.setLastUser(accountId, deviceNumber);\n await webAuthnManager.initializeCurrentUser(accountId, this.context.nearClient);\n try { await getLoginSession(this.context, accountId); } catch { }\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.SUCCESS,\n message: `Welcome ${accountId}`,\n data: { autoLogin: 'success' },\n });\n return;\n }\n } catch (err) {\n // fall through to TouchID unlock\n console.warn('[EmailRecoveryFlow] Shamir 3-pass unlock failed, falling back to TouchID', err);\n }\n }\n\n // TouchID fallback unlock\n // Use a random challenge (no VRF required) to collect PRF outputs and unlock the stored VRF keypair.\n const authChallenge = createRandomVRFChallenge() as VRFChallenge;\n\n const storedCredentialId = String(rec.credential?.rawId || rec.credential?.id || '').trim();\n const credentialIds = storedCredentialId ? [storedCredentialId] : [];\n const authenticators = credentialIds.length > 0\n ? []\n : await webAuthnManager.getAuthenticatorsByUser(accountId);\n const authCredential = await webAuthnManager.getAuthenticationCredentialsSerializedDualPrf({\n nearAccountId: accountId,\n challenge: authChallenge,\n credentialIds: credentialIds.length > 0 ? credentialIds : authenticators.map((a) => a.credentialId),\n });\n\n if (storedCredentialId && authCredential.rawId !== storedCredentialId) {\n throw new Error('Wrong passkey selected during recovery auto-login; please use the newly recovered passkey.');\n }\n\n const vrfUnlockResult = await webAuthnManager.unlockVRFKeypair({\n nearAccountId: accountId,\n encryptedVrfKeypair: rec.encryptedVrfKeypair,\n credential: authCredential,\n });\n\n if (!vrfUnlockResult.success) {\n throw new Error(vrfUnlockResult.error || 'VRF unlock failed during auto-login');\n }\n\n const vrfStatus = await webAuthnManager.checkVrfStatus();\n const vrfActiveForAccount =\n vrfStatus.active\n && vrfStatus.nearAccountId\n && String(vrfStatus.nearAccountId) === String(accountId);\n if (!vrfActiveForAccount) {\n throw new Error('VRF session inactive after TouchID unlock');\n }\n\n await webAuthnManager.setLastUser(accountId, deviceNumber);\n await webAuthnManager.initializeCurrentUser(accountId, this.context.nearClient);\n try { await getLoginSession(this.context, accountId); } catch { }\n\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.SUCCESS,\n message: `Welcome ${accountId}`,\n data: { autoLogin: 'success' },\n });\n\n } catch (err: any) {\n console.warn('[EmailRecoveryFlow] Auto-login failed after recovery', err);\n try {\n // Avoid leaving a stale/incompatible VRF keypair in-memory (can surface later as\n // \"Contract verification failed\" during signing). User can still log in manually.\n await this.context.webAuthnManager.clearVrfSession();\n } catch { }\n this.emit({\n step: 5,\n phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,\n status: EmailRecoveryStatus.ERROR,\n message: 'Auto-login failed; please log in manually on this device.',\n data: { error: err?.message || String(err), autoLogin: 'error' },\n } as EmailRecoverySSEEvent & { data: Record<string, unknown> });\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ const require_sdkSentEvents = require('../../types/sdkSentEvents.js');
|
|
|
9
9
|
//#region src/core/TatchiPasskey/faucets/createAccountRelayServer.ts
|
|
10
10
|
require_sdkSentEvents.init_sdkSentEvents();
|
|
11
11
|
require_encoders.init_encoders();
|
|
12
|
+
require_credentialsHelpers.init_credentialsHelpers();
|
|
12
13
|
require_validation.init_validation();
|
|
13
14
|
require_errors.init_errors();
|
|
14
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAccountRelayServer.js","names":["RegistrationPhase","RegistrationStatus","isObject","serialized: WebAuthnRegistrationCredential","normalizeRegistrationCredential","serializeRegistrationCredential","removePrfOutputGuard","requestData: CreateAccountAndRegisterUserRequest","base64UrlDecode","result: CreateAccountAndRegisterResult","errorMessage","error: unknown"],"sources":["../../../../../src/core/TatchiPasskey/faucets/createAccountRelayServer.ts"],"sourcesContent":["import { VRFChallenge } from '../../types/vrf-worker';\nimport { RegistrationSSEEvent, RegistrationPhase, RegistrationStatus } from '../../types/sdkSentEvents';\nimport { PasskeyManagerContext } from '..';\nimport { base64UrlDecode, base64UrlEncode } from '../../../utils/encoders';\nimport type { SignedTransaction } from '../../NearClient';\nimport { removePrfOutputGuard, serializeRegistrationCredential, normalizeRegistrationCredential } from '../../WebAuthnManager/credentialsHelpers';\nimport type { WebAuthnRegistrationCredential } from '../../types/webauthn';\nimport type { AuthenticatorOptions } from '../../types/authenticatorOptions';\nimport type { CreateAccountAndRegisterResult } from '../../../server/core/types';\nimport { isObject } from '../../WalletIframe/validation';\nimport { errorMessage } from '../../../utils/errors';\n\n/**\n * HTTP Request body for the relay server's /create_account_and_register_user endpoint\n */\nexport interface CreateAccountAndRegisterUserRequest {\n new_account_id: string;\n new_public_key: string;\n device_number: number;\n vrf_data: {\n vrf_input_data: number[];\n vrf_output: number[];\n vrf_proof: number[];\n public_key: number[];\n user_id: string;\n rp_id: string;\n block_height: number;\n block_hash: number[];\n };\n webauthn_registration: WebAuthnRegistrationCredential;\n deterministic_vrf_public_key: number[];\n authenticator_options?: AuthenticatorOptions;\n}\n\n/**\n * Create account and register user using relay-server atomic endpoint\n * Makes a single call to the relay-server's /create_account_and_register_user endpoint\n * which calls the contract's atomic create_account_and_register_user function\n */\nexport async function createAccountAndRegisterWithRelayServer(\n context: PasskeyManagerContext,\n nearAccountId: string,\n publicKey: string,\n credential: WebAuthnRegistrationCredential | PublicKeyCredential,\n vrfChallenge: VRFChallenge,\n deterministicVrfPublicKey: string,\n authenticatorOptions?: AuthenticatorOptions,\n onEvent?: (event: RegistrationSSEEvent) => void,\n): Promise<{\n success: boolean;\n transactionId?: string;\n error?: string;\n}> {\n const { configs } = context;\n\n if (!configs.relayer.url) {\n throw new Error('Relay server URL is required for atomic registration');\n }\n\n try {\n onEvent?.({\n step: 4,\n phase: RegistrationPhase.STEP_4_ACCESS_KEY_ADDITION,\n status: RegistrationStatus.PROGRESS,\n message: 'Creating account and adding access key...',\n });\n\n // Serialize the WebAuthn credential properly for the contract.\n // Accept both live PublicKeyCredential and already-serialized credentials from secureConfirm.\n const isSerialized = isObject(credential)\n && typeof (credential as any)?.response?.attestationObject === 'string';\n\n // Ensure proper serialization + normalization regardless of source\n const serialized: WebAuthnRegistrationCredential = isSerialized\n ? normalizeRegistrationCredential(credential as WebAuthnRegistrationCredential)\n : serializeRegistrationCredential(credential as PublicKeyCredential);\n\n // Strip PRF outputs before sending to relay/contract\n const serializedCredential = removePrfOutputGuard<WebAuthnRegistrationCredential>(serialized);\n // Normalize transports to an array (avoid null)\n if (!Array.isArray(serializedCredential?.response?.transports)) {\n serializedCredential.response.transports = [];\n }\n\n // Prepare data for atomic endpoint\n const requestData: CreateAccountAndRegisterUserRequest = {\n new_account_id: nearAccountId,\n new_public_key: publicKey,\n device_number: 1, // First device gets device number 1 (1-indexed)\n vrf_data: {\n vrf_input_data: Array.from(base64UrlDecode(vrfChallenge.vrfInput)),\n vrf_output: Array.from(base64UrlDecode(vrfChallenge.vrfOutput)),\n vrf_proof: Array.from(base64UrlDecode(vrfChallenge.vrfProof)),\n public_key: Array.from(base64UrlDecode(vrfChallenge.vrfPublicKey)),\n user_id: vrfChallenge.userId,\n rp_id: vrfChallenge.rpId,\n block_height: Number(vrfChallenge.blockHeight),\n block_hash: Array.from(base64UrlDecode(vrfChallenge.blockHash)),\n },\n webauthn_registration: serializedCredential,\n deterministic_vrf_public_key: Array.from(base64UrlDecode(deterministicVrfPublicKey)),\n authenticator_options: authenticatorOptions || context.configs.authenticatorOptions,\n };\n\n onEvent?.({\n step: 5,\n phase: RegistrationPhase.STEP_5_CONTRACT_REGISTRATION,\n status: RegistrationStatus.PROGRESS,\n message: 'Registering user with Web3Authn contract...',\n });\n\n // Call the atomic endpoint\n const response = await fetch(`${configs.relayer.url}/create_account_and_register_user`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestData)\n });\n\n // Handle both successful and failed responses\n const result: CreateAccountAndRegisterResult = await response.json();\n\n if (!response.ok) {\n // Extract specific error message from relay server response\n const errorMessage = result.error || result.message || `HTTP ${response.status}: ${response.statusText}`;\n throw new Error(errorMessage);\n }\n\n if (!result.success) {\n throw new Error(result.error || 'Atomic registration failed');\n }\n\n onEvent?.({\n step: 5,\n phase: RegistrationPhase.STEP_5_CONTRACT_REGISTRATION,\n status: RegistrationStatus.SUCCESS,\n message: 'User registered with Web3Authn contract successfully',\n });\n\n return {\n success: true,\n transactionId: result.transactionHash,\n };\n\n } catch (error: unknown) {\n console.error('Atomic registration failed:', error);\n\n onEvent?.({\n step: 0,\n phase: RegistrationPhase.REGISTRATION_ERROR,\n status: RegistrationStatus.ERROR,\n message: 'Registration failed',\n error: errorMessage(error),\n });\n\n return {\n success: false,\n error: errorMessage(error),\n };\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"createAccountRelayServer.js","names":["RegistrationPhase","RegistrationStatus","isObject","serialized: WebAuthnRegistrationCredential","normalizeRegistrationCredential","serializeRegistrationCredential","removePrfOutputGuard","requestData: CreateAccountAndRegisterUserRequest","base64UrlDecode","result: CreateAccountAndRegisterResult","errorMessage","error: unknown"],"sources":["../../../../../src/core/TatchiPasskey/faucets/createAccountRelayServer.ts"],"sourcesContent":["import { VRFChallenge } from '../../types/vrf-worker';\nimport { RegistrationSSEEvent, RegistrationPhase, RegistrationStatus } from '../../types/sdkSentEvents';\nimport { PasskeyManagerContext } from '..';\nimport { base64UrlDecode, base64UrlEncode } from '../../../utils/encoders';\nimport type { SignedTransaction } from '../../NearClient';\nimport { removePrfOutputGuard, serializeRegistrationCredential, normalizeRegistrationCredential } from '../../WebAuthnManager/credentialsHelpers';\nimport type { WebAuthnRegistrationCredential } from '../../types/webauthn';\nimport type { AuthenticatorOptions } from '../../types/authenticatorOptions';\nimport type { CreateAccountAndRegisterResult } from '../../../server/core/types';\nimport { isObject } from '../../WalletIframe/validation';\nimport { errorMessage } from '../../../utils/errors';\n\n/**\n * HTTP Request body for the relay server's /create_account_and_register_user endpoint\n */\nexport interface CreateAccountAndRegisterUserRequest {\n new_account_id: string;\n new_public_key: string;\n device_number: number;\n vrf_data: {\n vrf_input_data: number[];\n vrf_output: number[];\n vrf_proof: number[];\n public_key: number[];\n user_id: string;\n rp_id: string;\n block_height: number;\n block_hash: number[];\n };\n webauthn_registration: WebAuthnRegistrationCredential;\n deterministic_vrf_public_key: number[];\n authenticator_options?: AuthenticatorOptions;\n}\n\n/**\n * Create account and register user using relay-server atomic endpoint\n * Makes a single call to the relay-server's /create_account_and_register_user endpoint\n * which calls the contract's atomic create_account_and_register_user function\n */\nexport async function createAccountAndRegisterWithRelayServer(\n context: PasskeyManagerContext,\n nearAccountId: string,\n publicKey: string,\n credential: WebAuthnRegistrationCredential | PublicKeyCredential,\n vrfChallenge: VRFChallenge,\n deterministicVrfPublicKey: string,\n authenticatorOptions?: AuthenticatorOptions,\n onEvent?: (event: RegistrationSSEEvent) => void,\n): Promise<{\n success: boolean;\n transactionId?: string;\n error?: string;\n}> {\n const { configs } = context;\n\n if (!configs.relayer.url) {\n throw new Error('Relay server URL is required for atomic registration');\n }\n\n try {\n onEvent?.({\n step: 4,\n phase: RegistrationPhase.STEP_4_ACCESS_KEY_ADDITION,\n status: RegistrationStatus.PROGRESS,\n message: 'Creating account and adding access key...',\n });\n\n // Serialize the WebAuthn credential properly for the contract.\n // Accept both live PublicKeyCredential and already-serialized credentials from secureConfirm.\n const isSerialized = isObject(credential)\n && typeof (credential as any)?.response?.attestationObject === 'string';\n\n // Ensure proper serialization + normalization regardless of source\n const serialized: WebAuthnRegistrationCredential = isSerialized\n ? normalizeRegistrationCredential(credential as WebAuthnRegistrationCredential)\n : serializeRegistrationCredential(credential as PublicKeyCredential);\n\n // Strip PRF outputs before sending to relay/contract\n const serializedCredential = removePrfOutputGuard<WebAuthnRegistrationCredential>(serialized);\n // Normalize transports to an array (avoid null)\n if (!Array.isArray(serializedCredential?.response?.transports)) {\n serializedCredential.response.transports = [];\n }\n\n // Prepare data for atomic endpoint\n const requestData: CreateAccountAndRegisterUserRequest = {\n new_account_id: nearAccountId,\n new_public_key: publicKey,\n device_number: 1, // First device gets device number 1 (1-indexed)\n vrf_data: {\n vrf_input_data: Array.from(base64UrlDecode(vrfChallenge.vrfInput)),\n vrf_output: Array.from(base64UrlDecode(vrfChallenge.vrfOutput)),\n vrf_proof: Array.from(base64UrlDecode(vrfChallenge.vrfProof)),\n public_key: Array.from(base64UrlDecode(vrfChallenge.vrfPublicKey)),\n user_id: vrfChallenge.userId,\n rp_id: vrfChallenge.rpId,\n block_height: Number(vrfChallenge.blockHeight),\n block_hash: Array.from(base64UrlDecode(vrfChallenge.blockHash)),\n },\n webauthn_registration: serializedCredential,\n deterministic_vrf_public_key: Array.from(base64UrlDecode(deterministicVrfPublicKey)),\n authenticator_options: authenticatorOptions || context.configs.authenticatorOptions,\n };\n\n onEvent?.({\n step: 5,\n phase: RegistrationPhase.STEP_5_CONTRACT_REGISTRATION,\n status: RegistrationStatus.PROGRESS,\n message: 'Registering user with Web3Authn contract...',\n });\n\n // Call the atomic endpoint\n const response = await fetch(`${configs.relayer.url}/create_account_and_register_user`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestData)\n });\n\n // Handle both successful and failed responses\n const result: CreateAccountAndRegisterResult = await response.json();\n\n if (!response.ok) {\n // Extract specific error message from relay server response\n const errorMessage = result.error || result.message || `HTTP ${response.status}: ${response.statusText}`;\n throw new Error(errorMessage);\n }\n\n if (!result.success) {\n throw new Error(result.error || 'Atomic registration failed');\n }\n\n onEvent?.({\n step: 5,\n phase: RegistrationPhase.STEP_5_CONTRACT_REGISTRATION,\n status: RegistrationStatus.SUCCESS,\n message: 'User registered with Web3Authn contract successfully',\n });\n\n return {\n success: true,\n transactionId: result.transactionHash,\n };\n\n } catch (error: unknown) {\n console.error('Atomic registration failed:', error);\n\n onEvent?.({\n step: 0,\n phase: RegistrationPhase.REGISTRATION_ERROR,\n status: RegistrationStatus.ERROR,\n message: 'Registration failed',\n error: errorMessage(error),\n });\n\n return {\n success: false,\n error: errorMessage(error),\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuCA,eAAsB,wCACpB,SACA,eACA,WACA,YACA,cACA,2BACA,sBACA,SAKC;CACD,MAAM,EAAE,YAAY;AAEpB,KAAI,CAAC,QAAQ,QAAQ,IACnB,OAAM,IAAI,MAAM;AAGlB,KAAI;AACF,YAAU;GACR,MAAM;GACN,OAAOA,wCAAkB;GACzB,QAAQC,yCAAmB;GAC3B,SAAS;;EAKX,MAAM,eAAeC,4BAAS,eACzB,OAAQ,YAAoB,UAAU,sBAAsB;EAGjE,MAAMC,aAA6C,eAC/CC,2DAAgC,cAChCC,2DAAgC;EAGpC,MAAM,uBAAuBC,gDAAqD;AAElF,MAAI,CAAC,MAAM,QAAQ,sBAAsB,UAAU,YACjD,sBAAqB,SAAS,aAAa;EAI7C,MAAMC,cAAmD;GACvD,gBAAgB;GAChB,gBAAgB;GAChB,eAAe;GACf,UAAU;IACR,gBAAgB,MAAM,KAAKC,+BAAgB,aAAa;IACxD,YAAY,MAAM,KAAKA,+BAAgB,aAAa;IACpD,WAAW,MAAM,KAAKA,+BAAgB,aAAa;IACnD,YAAY,MAAM,KAAKA,+BAAgB,aAAa;IACpD,SAAS,aAAa;IACtB,OAAO,aAAa;IACpB,cAAc,OAAO,aAAa;IAClC,YAAY,MAAM,KAAKA,+BAAgB,aAAa;;GAEtD,uBAAuB;GACvB,8BAA8B,MAAM,KAAKA,+BAAgB;GACzD,uBAAuB,wBAAwB,QAAQ,QAAQ;;AAGjE,YAAU;GACR,MAAM;GACN,OAAOR,wCAAkB;GACzB,QAAQC,yCAAmB;GAC3B,SAAS;;EAIX,MAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,QAAQ,IAAI,oCAAoC;GACtF,QAAQ;GACR,SAAS,EAAE,gBAAgB;GAC3B,MAAM,KAAK,UAAU;;EAIvB,MAAMQ,SAAyC,MAAM,SAAS;AAE9D,MAAI,CAAC,SAAS,IAAI;GAEhB,MAAMC,iBAAe,OAAO,SAAS,OAAO,WAAW,QAAQ,SAAS,OAAO,IAAI,SAAS;AAC5F,SAAM,IAAI,MAAMA;;AAGlB,MAAI,CAAC,OAAO,QACV,OAAM,IAAI,MAAM,OAAO,SAAS;AAGlC,YAAU;GACR,MAAM;GACN,OAAOV,wCAAkB;GACzB,QAAQC,yCAAmB;GAC3B,SAAS;;AAGX,SAAO;GACL,SAAS;GACT,eAAe,OAAO;;UAGjBU,OAAgB;AACvB,UAAQ,MAAM,+BAA+B;AAE7C,YAAU;GACR,MAAM;GACN,OAAOX,wCAAkB;GACzB,QAAQC,yCAAmB;GAC3B,SAAS;GACT,OAAOS,4BAAa;;AAGtB,SAAO;GACL,SAAS;GACT,OAAOA,4BAAa"}
|
|
@@ -26,6 +26,7 @@ const require_index$3 = require('../EmailRecovery/index.js');
|
|
|
26
26
|
const require_emailRecovery = require('./emailRecovery.js');
|
|
27
27
|
|
|
28
28
|
//#region src/core/TatchiPasskey/index.ts
|
|
29
|
+
require_login.init_login();
|
|
29
30
|
require_sdkSentEvents.init_sdkSentEvents();
|
|
30
31
|
require_accountIds.init_accountIds();
|
|
31
32
|
require_index.init_IndexedDBManager();
|
|
@@ -1176,6 +1177,30 @@ var TatchiPasskey = class {
|
|
|
1176
1177
|
});
|
|
1177
1178
|
}
|
|
1178
1179
|
/**
|
|
1180
|
+
* Best-effort cancellation for an in-flight email recovery flow.
|
|
1181
|
+
* Intended for UI "user cancelled sending email" / retry UX.
|
|
1182
|
+
*/
|
|
1183
|
+
async cancelEmailRecovery(args) {
|
|
1184
|
+
const { accountId, nearPublicKey } = args || {};
|
|
1185
|
+
if (this.shouldUseWalletIframe()) {
|
|
1186
|
+
try {
|
|
1187
|
+
const router = await this.requireWalletIframeRouter();
|
|
1188
|
+
await router.stopEmailRecovery({
|
|
1189
|
+
accountId,
|
|
1190
|
+
nearPublicKey
|
|
1191
|
+
});
|
|
1192
|
+
} catch {}
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
try {
|
|
1196
|
+
await this.activeEmailRecoveryFlow?.cancelAndReset({
|
|
1197
|
+
accountId,
|
|
1198
|
+
nearPublicKey
|
|
1199
|
+
});
|
|
1200
|
+
} catch {}
|
|
1201
|
+
this.activeEmailRecoveryFlow = null;
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1179
1204
|
* Device2: Start device linking flow
|
|
1180
1205
|
* Returns QR payload and data URL to render; emits onEvent during the flow.
|
|
1181
1206
|
* Runs inside iframe when available for better isolation.
|