@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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canonicalizeEmail } from "./emailParsers.js";
|
|
1
2
|
import { sha256 } from "../node_modules/.pnpm/@noble_hashes@2.0.1/node_modules/@noble/hashes/sha2.js";
|
|
2
3
|
import { x25519 } from "../node_modules/.pnpm/@noble_curves@2.0.1/node_modules/@noble/curves/ed25519.js";
|
|
3
4
|
import { hkdf } from "../node_modules/.pnpm/@noble_hashes@2.0.1/node_modules/@noble/hashes/hkdf.js";
|
|
@@ -71,7 +72,16 @@ async function encryptEmailForOutlayer(input) {
|
|
|
71
72
|
aeadContext
|
|
72
73
|
};
|
|
73
74
|
}
|
|
75
|
+
function hashRecoveryEmailForAccount(args) {
|
|
76
|
+
const salt = (args.accountId || "").trim().toLowerCase();
|
|
77
|
+
const canonical = canonicalizeEmail(String(args.recoveryEmail || ""));
|
|
78
|
+
if (!canonical) throw new Error("Missing From email address for encrypted email recovery");
|
|
79
|
+
const input = `${canonical}|${salt}`;
|
|
80
|
+
const bytes = new TextEncoder().encode(input);
|
|
81
|
+
const digest = sha256(bytes);
|
|
82
|
+
return Array.from(digest);
|
|
83
|
+
}
|
|
74
84
|
|
|
75
85
|
//#endregion
|
|
76
|
-
export { deriveOutlayerStaticKeyFromSeedHex, encryptEmailForOutlayer };
|
|
86
|
+
export { deriveOutlayerStaticKeyFromSeedHex, encryptEmailForOutlayer, hashRecoveryEmailForAccount };
|
|
77
87
|
//# sourceMappingURL=emailEncryptor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emailEncryptor.js","names":["ephemeralSk: Uint8Array","ephemeralPk: Uint8Array","nonce: Uint8Array","envelope: EncryptedEmailEnvelope"],"sources":["../../../../src/server/email-recovery/emailEncryptor.ts"],"sourcesContent":["import { x25519 } from '@noble/curves/ed25519.js';\nimport { hkdf } from '@noble/hashes/hkdf.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { chacha20poly1305 } from '@noble/ciphers/chacha.js';\n\nexport interface EncryptedEmailEnvelope {\n version: number;\n ephemeral_pub: string;\n nonce: string;\n ciphertext: string;\n}\n\nexport interface EmailEncryptionContext {\n account_id: string;\n payer_account_id: string;\n network_id: string;\n // Allow relayers to include additional metadata bound into AAD\n [key: string]: unknown;\n}\n\nexport interface EncryptEmailForOutlayerInput {\n emailRaw: string;\n aeadContext: EmailEncryptionContext;\n recipientPk: Uint8Array;\n /**\n * Test-only overrides to make encryption deterministic for round-trip tests.\n */\n testOverrides?: {\n ephemeralSecretKey?: Uint8Array;\n nonce?: Uint8Array;\n };\n}\n\nexport interface EncryptEmailForOutlayerResult {\n envelope: EncryptedEmailEnvelope;\n aeadContext: EmailEncryptionContext;\n}\n\n// IMPORTANT: The exact JSON byte sequence here is used as AEAD AAD and must\n// match what the AEAD context being passed into decrypt_encrypted_email().\n// see: https://github.com/web3-authn/email-dkim-verifier-contract/blob/f06cf33b484cd9750661bf418812f259f0674b69/src/api.rs#L175\n//\n// The contract serializes `args` with serde_json, which orders keys\n// lexicographically, so we must mirror that here. Changing this logic or\n// adding/removing keys requires updating the Outlayer compat tests and\n// verifying decryption end-to-end.\n//\n// Canonical form (alphabetical by key):\n// ```\n// {\n// \"account_id\": \"...\",\n// \"network_id\": \"...\",\n// \"payer_account_id\": \"...\"\n// }\n// ```\nfunction serializeContextForAad(context: EmailEncryptionContext): string {\n const entries = Object.entries(context).sort(([a], [b]) => a.localeCompare(b));\n return JSON.stringify(Object.fromEntries(entries));\n}\n\nexport function deriveOutlayerStaticKeyFromSeedHex(seedHex: string): { secretKey: Uint8Array; publicKey: Uint8Array } {\n const cleaned = seedHex.trim();\n if (cleaned.length !== 64) {\n throw new Error('OUTLAYER_WORKER_SK_SEED_HEX32 must be a 64-char hex string');\n }\n const seed = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n const byteHex = cleaned.slice(i * 2, i * 2 + 2);\n const value = Number.parseInt(byteHex, 16);\n if (Number.isNaN(value)) {\n throw new Error('OUTLAYER_WORKER_SK_SEED_HEX32 contains non-hex characters');\n }\n seed[i] = value;\n }\n const encoder = new TextEncoder();\n const okm = hkdf(sha256, seed, undefined, encoder.encode('outlayer-email-dkim-x25519'), 32);\n const secretKey = okm instanceof Uint8Array ? okm : new Uint8Array(okm);\n const publicKey = x25519.getPublicKey(secretKey);\n return { secretKey, publicKey };\n}\n\nexport async function encryptEmailForOutlayer(\n input: EncryptEmailForOutlayerInput\n): Promise<EncryptEmailForOutlayerResult> {\n const { emailRaw, aeadContext, recipientPk, testOverrides } = input;\n\n if (!(recipientPk instanceof Uint8Array) || recipientPk.length !== 32) {\n throw new Error('recipientPk must be a 32-byte X25519 public key');\n }\n\n const encoder = new TextEncoder();\n\n // 1. Generate ephemeral X25519 keypair\n let ephemeralSk: Uint8Array;\n let ephemeralPk: Uint8Array;\n if (testOverrides?.ephemeralSecretKey) {\n if (!(testOverrides.ephemeralSecretKey instanceof Uint8Array) || testOverrides.ephemeralSecretKey.length !== 32) {\n throw new Error('testOverrides.ephemeralSecretKey must be a 32-byte Uint8Array');\n }\n ephemeralSk = testOverrides.ephemeralSecretKey;\n ephemeralPk = x25519.getPublicKey(ephemeralSk);\n } else {\n const { secretKey, publicKey } = x25519.keygen();\n ephemeralSk = secretKey;\n ephemeralPk = publicKey;\n }\n\n // 2. Derive shared secret via X25519 ECDH\n const sharedSecret = x25519.getSharedSecret(ephemeralSk, recipientPk); // 32 bytes\n\n // 3. Derive symmetric key via HKDF-SHA256 (info=\"email-dkim-encryption-key\")\n const info = encoder.encode('email-dkim-encryption-key');\n const symmetricKey = hkdf(sha256, sharedSecret, undefined, info, 32);\n\n // 4. Encrypt using ChaCha20-Poly1305 with JSON(context) as AAD\n let nonce: Uint8Array;\n if (testOverrides?.nonce) {\n if (!(testOverrides.nonce instanceof Uint8Array) || testOverrides.nonce.length !== 12) {\n throw new Error('testOverrides.nonce must be a 12-byte Uint8Array');\n }\n nonce = testOverrides.nonce;\n } else {\n nonce = crypto.getRandomValues(new Uint8Array(12));\n }\n const aad = encoder.encode(serializeContextForAad(aeadContext));\n const plaintext = encoder.encode(emailRaw);\n\n const cipher = chacha20poly1305(symmetricKey, nonce, aad);\n const ciphertext = cipher.encrypt(plaintext);\n\n // 5. Serialize fields as base64 strings\n const b64 = (bytes: Uint8Array): string => {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n };\n\n const envelope: EncryptedEmailEnvelope = {\n version: 1,\n ephemeral_pub: b64(ephemeralPk),\n nonce: b64(nonce),\n ciphertext: b64(ciphertext),\n };\n\n return { envelope, aeadContext };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"emailEncryptor.js","names":["ephemeralSk: Uint8Array","ephemeralPk: Uint8Array","nonce: Uint8Array","envelope: EncryptedEmailEnvelope"],"sources":["../../../../src/server/email-recovery/emailEncryptor.ts"],"sourcesContent":["import { x25519 } from '@noble/curves/ed25519.js';\nimport { hkdf } from '@noble/hashes/hkdf.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { chacha20poly1305 } from '@noble/ciphers/chacha.js';\nimport { canonicalizeEmail } from './emailParsers';\n\nexport interface EncryptedEmailEnvelope {\n version: number;\n ephemeral_pub: string;\n nonce: string;\n ciphertext: string;\n}\n\nexport interface EmailEncryptionContext {\n account_id: string;\n payer_account_id: string;\n network_id: string;\n // Allow relayers to include additional metadata bound into AAD\n [key: string]: unknown;\n}\n\nexport interface EncryptEmailForOutlayerInput {\n emailRaw: string;\n aeadContext: EmailEncryptionContext;\n recipientPk: Uint8Array;\n /**\n * Test-only overrides to make encryption deterministic for round-trip tests.\n */\n testOverrides?: {\n ephemeralSecretKey?: Uint8Array;\n nonce?: Uint8Array;\n };\n}\n\nexport interface EncryptEmailForOutlayerResult {\n envelope: EncryptedEmailEnvelope;\n aeadContext: EmailEncryptionContext;\n}\n\n// IMPORTANT: The exact JSON byte sequence here is used as AEAD AAD and must\n// match what the AEAD context being passed into decrypt_encrypted_email().\n// see: https://github.com/web3-authn/email-dkim-verifier-contract/blob/f06cf33b484cd9750661bf418812f259f0674b69/src/api.rs#L175\n//\n// The contract serializes `args` with serde_json, which orders keys\n// lexicographically, so we must mirror that here. Changing this logic or\n// adding/removing keys requires updating the Outlayer compat tests and\n// verifying decryption end-to-end.\n//\n// Canonical form (alphabetical by key):\n// ```\n// {\n// \"account_id\": \"...\",\n// \"network_id\": \"...\",\n// \"payer_account_id\": \"...\"\n// }\n// ```\nfunction serializeContextForAad(context: EmailEncryptionContext): string {\n const entries = Object.entries(context).sort(([a], [b]) => a.localeCompare(b));\n return JSON.stringify(Object.fromEntries(entries));\n}\n\nexport function deriveOutlayerStaticKeyFromSeedHex(seedHex: string): { secretKey: Uint8Array; publicKey: Uint8Array } {\n const cleaned = seedHex.trim();\n if (cleaned.length !== 64) {\n throw new Error('OUTLAYER_WORKER_SK_SEED_HEX32 must be a 64-char hex string');\n }\n const seed = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n const byteHex = cleaned.slice(i * 2, i * 2 + 2);\n const value = Number.parseInt(byteHex, 16);\n if (Number.isNaN(value)) {\n throw new Error('OUTLAYER_WORKER_SK_SEED_HEX32 contains non-hex characters');\n }\n seed[i] = value;\n }\n const encoder = new TextEncoder();\n const okm = hkdf(sha256, seed, undefined, encoder.encode('outlayer-email-dkim-x25519'), 32);\n const secretKey = okm instanceof Uint8Array ? okm : new Uint8Array(okm);\n const publicKey = x25519.getPublicKey(secretKey);\n return { secretKey, publicKey };\n}\n\nexport async function encryptEmailForOutlayer(\n input: EncryptEmailForOutlayerInput\n): Promise<EncryptEmailForOutlayerResult> {\n const { emailRaw, aeadContext, recipientPk, testOverrides } = input;\n\n if (!(recipientPk instanceof Uint8Array) || recipientPk.length !== 32) {\n throw new Error('recipientPk must be a 32-byte X25519 public key');\n }\n\n const encoder = new TextEncoder();\n\n // 1. Generate ephemeral X25519 keypair\n let ephemeralSk: Uint8Array;\n let ephemeralPk: Uint8Array;\n if (testOverrides?.ephemeralSecretKey) {\n if (!(testOverrides.ephemeralSecretKey instanceof Uint8Array) || testOverrides.ephemeralSecretKey.length !== 32) {\n throw new Error('testOverrides.ephemeralSecretKey must be a 32-byte Uint8Array');\n }\n ephemeralSk = testOverrides.ephemeralSecretKey;\n ephemeralPk = x25519.getPublicKey(ephemeralSk);\n } else {\n const { secretKey, publicKey } = x25519.keygen();\n ephemeralSk = secretKey;\n ephemeralPk = publicKey;\n }\n\n // 2. Derive shared secret via X25519 ECDH\n const sharedSecret = x25519.getSharedSecret(ephemeralSk, recipientPk); // 32 bytes\n\n // 3. Derive symmetric key via HKDF-SHA256 (info=\"email-dkim-encryption-key\")\n const info = encoder.encode('email-dkim-encryption-key');\n const symmetricKey = hkdf(sha256, sharedSecret, undefined, info, 32);\n\n // 4. Encrypt using ChaCha20-Poly1305 with JSON(context) as AAD\n let nonce: Uint8Array;\n if (testOverrides?.nonce) {\n if (!(testOverrides.nonce instanceof Uint8Array) || testOverrides.nonce.length !== 12) {\n throw new Error('testOverrides.nonce must be a 12-byte Uint8Array');\n }\n nonce = testOverrides.nonce;\n } else {\n nonce = crypto.getRandomValues(new Uint8Array(12));\n }\n const aad = encoder.encode(serializeContextForAad(aeadContext));\n const plaintext = encoder.encode(emailRaw);\n\n const cipher = chacha20poly1305(symmetricKey, nonce, aad);\n const ciphertext = cipher.encrypt(plaintext);\n\n // 5. Serialize fields as base64 strings\n const b64 = (bytes: Uint8Array): string => {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n };\n\n const envelope: EncryptedEmailEnvelope = {\n version: 1,\n ephemeral_pub: b64(ephemeralPk),\n nonce: b64(nonce),\n ciphertext: b64(ciphertext),\n };\n\n return { envelope, aeadContext };\n}\n\nexport function hashRecoveryEmailForAccount(args: { recoveryEmail: string; accountId: string }): number[] {\n const salt = (args.accountId || '').trim().toLowerCase();\n const canonical = canonicalizeEmail(String(args.recoveryEmail || ''));\n if (!canonical) {\n throw new Error('Missing From email address for encrypted email recovery');\n }\n const input = `${canonical}|${salt}`;\n const bytes = new TextEncoder().encode(input);\n const digest = sha256(bytes);\n return Array.from(digest);\n}\n"],"mappings":";;;;;;;AAwDA,SAAS,uBAAuB,SAAyC;CACvE,MAAM,UAAU,OAAO,QAAQ,SAAS,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc;AAC3E,QAAO,KAAK,UAAU,OAAO,YAAY;;AAG3C,SAAgB,mCAAmC,SAAmE;CACpH,MAAM,UAAU,QAAQ;AACxB,KAAI,QAAQ,WAAW,GACrB,OAAM,IAAI,MAAM;CAElB,MAAM,OAAO,IAAI,WAAW;AAC5B,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,UAAU,QAAQ,MAAM,IAAI,GAAG,IAAI,IAAI;EAC7C,MAAM,QAAQ,OAAO,SAAS,SAAS;AACvC,MAAI,OAAO,MAAM,OACf,OAAM,IAAI,MAAM;AAElB,OAAK,KAAK;;CAEZ,MAAM,UAAU,IAAI;CACpB,MAAM,MAAM,KAAK,QAAQ,MAAM,QAAW,QAAQ,OAAO,+BAA+B;CACxF,MAAM,YAAY,eAAe,aAAa,MAAM,IAAI,WAAW;CACnE,MAAM,YAAY,OAAO,aAAa;AACtC,QAAO;EAAE;EAAW;;;AAGtB,eAAsB,wBACpB,OACwC;CACxC,MAAM,EAAE,UAAU,aAAa,aAAa,kBAAkB;AAE9D,KAAI,EAAE,uBAAuB,eAAe,YAAY,WAAW,GACjE,OAAM,IAAI,MAAM;CAGlB,MAAM,UAAU,IAAI;CAGpB,IAAIA;CACJ,IAAIC;AACJ,KAAI,eAAe,oBAAoB;AACrC,MAAI,EAAE,cAAc,8BAA8B,eAAe,cAAc,mBAAmB,WAAW,GAC3G,OAAM,IAAI,MAAM;AAElB,gBAAc,cAAc;AAC5B,gBAAc,OAAO,aAAa;QAC7B;EACL,MAAM,EAAE,WAAW,cAAc,OAAO;AACxC,gBAAc;AACd,gBAAc;;CAIhB,MAAM,eAAe,OAAO,gBAAgB,aAAa;CAGzD,MAAM,OAAO,QAAQ,OAAO;CAC5B,MAAM,eAAe,KAAK,QAAQ,cAAc,QAAW,MAAM;CAGjE,IAAIC;AACJ,KAAI,eAAe,OAAO;AACxB,MAAI,EAAE,cAAc,iBAAiB,eAAe,cAAc,MAAM,WAAW,GACjF,OAAM,IAAI,MAAM;AAElB,UAAQ,cAAc;OAEtB,SAAQ,OAAO,gBAAgB,IAAI,WAAW;CAEhD,MAAM,MAAM,QAAQ,OAAO,uBAAuB;CAClD,MAAM,YAAY,QAAQ,OAAO;CAEjC,MAAM,SAAS,iBAAiB,cAAc,OAAO;CACrD,MAAM,aAAa,OAAO,QAAQ;CAGlC,MAAM,OAAO,UAA8B;AACzC,MAAI,OAAO,WAAW,YACpB,QAAO,OAAO,KAAK,OAAO,SAAS;EAErC,IAAI,SAAS;AACb,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IAChC,WAAU,OAAO,aAAa,MAAM;AAEtC,SAAO,KAAK;;CAGd,MAAMC,WAAmC;EACvC,SAAS;EACT,eAAe,IAAI;EACnB,OAAO,IAAI;EACX,YAAY,IAAI;;AAGlB,QAAO;EAAE;EAAU;;;AAGrB,SAAgB,4BAA4B,MAA8D;CACxG,MAAM,QAAQ,KAAK,aAAa,IAAI,OAAO;CAC3C,MAAM,YAAY,kBAAkB,OAAO,KAAK,iBAAiB;AACjE,KAAI,CAAC,UACH,OAAM,IAAI,MAAM;CAElB,MAAM,QAAQ,GAAG,UAAU,GAAG;CAC9B,MAAM,QAAQ,IAAI,cAAc,OAAO;CACvC,MAAM,SAAS,OAAO;AACtB,QAAO,MAAM,KAAK"}
|
|
@@ -30,7 +30,61 @@ function extractRecoveryModeFromBody(emailBlob) {
|
|
|
30
30
|
if (lower.includes(EmailRecoveryModeHint.OnchainPublic)) return "onchain-public";
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
+
const EMAIL_ADDRESS_REGEX = /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)/;
|
|
34
|
+
function canonicalizeEmail(input) {
|
|
35
|
+
const raw = String(input || "").trim();
|
|
36
|
+
if (!raw) return "";
|
|
37
|
+
const withoutHeaderName = raw.replace(/^[a-z0-9-]+\s*:\s*/i, "").trim();
|
|
38
|
+
const angleMatch = withoutHeaderName.match(/<([^>]+)>/);
|
|
39
|
+
const candidates = [angleMatch?.[1], withoutHeaderName].filter((v) => typeof v === "string" && v.length > 0);
|
|
40
|
+
for (const candidate of candidates) {
|
|
41
|
+
const cleaned = candidate.replace(/^mailto:\s*/i, "");
|
|
42
|
+
const match = cleaned.match(EMAIL_ADDRESS_REGEX);
|
|
43
|
+
if (match?.[1]) return match[1].trim().toLowerCase();
|
|
44
|
+
}
|
|
45
|
+
return withoutHeaderName.toLowerCase();
|
|
46
|
+
}
|
|
47
|
+
function parseHeaderValue(rawEmail, name) {
|
|
48
|
+
try {
|
|
49
|
+
const raw = String(rawEmail || "");
|
|
50
|
+
if (!raw) return void 0;
|
|
51
|
+
const lines = raw.split(/\r?\n/);
|
|
52
|
+
const headerLines = [];
|
|
53
|
+
for (const line of lines) {
|
|
54
|
+
if (line.trim() === "") break;
|
|
55
|
+
if (/^\s/.test(line) && headerLines.length > 0) {
|
|
56
|
+
headerLines[headerLines.length - 1] += ` ${line.trim()}`;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
headerLines.push(line);
|
|
60
|
+
}
|
|
61
|
+
const headerName = name.trim();
|
|
62
|
+
if (!headerName) return void 0;
|
|
63
|
+
const re = new RegExp(`^${headerName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*:`, "i");
|
|
64
|
+
const found = headerLines.find((l) => re.test(l));
|
|
65
|
+
if (!found) return void 0;
|
|
66
|
+
const idx = found.indexOf(":");
|
|
67
|
+
const value = idx >= 0 ? found.slice(idx + 1).trim() : "";
|
|
68
|
+
return value || void 0;
|
|
69
|
+
} catch {
|
|
70
|
+
return void 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function parseRecoverSubjectBindings(rawEmail) {
|
|
74
|
+
let subjectText = (parseHeaderValue(rawEmail, "subject") || String(rawEmail || "")).trim();
|
|
75
|
+
if (!subjectText) return null;
|
|
76
|
+
subjectText = subjectText.replace(/^(re|fwd):\s*/i, "").trim();
|
|
77
|
+
if (!subjectText) return null;
|
|
78
|
+
const match = subjectText.match(/^recover-([A-Za-z0-9]{6})\s+([^\s]+)\s+ed25519:([^\s]+)\s*$/i);
|
|
79
|
+
if (!match) return null;
|
|
80
|
+
const [, requestId, accountId, newPublicKey] = match;
|
|
81
|
+
return {
|
|
82
|
+
requestId,
|
|
83
|
+
accountId,
|
|
84
|
+
newPublicKey
|
|
85
|
+
};
|
|
86
|
+
}
|
|
33
87
|
|
|
34
88
|
//#endregion
|
|
35
|
-
export { extractRecoveryModeFromBody, normalizeRecoveryMode };
|
|
89
|
+
export { canonicalizeEmail, extractRecoveryModeFromBody, normalizeRecoveryMode, parseHeaderValue, parseRecoverSubjectBindings };
|
|
36
90
|
//# sourceMappingURL=emailParsers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emailParsers.js","names":[],"sources":["../../../../src/server/email-recovery/emailParsers.ts"],"sourcesContent":["import type { EmailRecoveryMode } from './types';\nimport { normalizeForwardableEmailPayload, parseAccountIdFromSubject } from './zkEmail';\n\nexport enum EmailRecoveryModeHint {\n ZkEmail = 'zk-email',\n TeeEncrypted = 'tee-encrypted',\n OnchainPublic = 'onchain-public',\n}\n\nexport function normalizeRecoveryMode(raw: string | undefined | null): EmailRecoveryMode | null {\n if (!raw) return null;\n const value = raw.trim().toLowerCase();\n if (value === EmailRecoveryModeHint.ZkEmail) return 'zk-email';\n if (value === EmailRecoveryModeHint.TeeEncrypted) return 'tee-encrypted';\n if (value === EmailRecoveryModeHint.OnchainPublic) return 'onchain-public';\n return null;\n}\n\nexport function extractRecoveryModeFromBody(emailBlob?: string): EmailRecoveryMode | null {\n if (!emailBlob) return null;\n\n const lines = emailBlob.split(/\\r?\\n/);\n const bodyStartIndex = lines.findIndex(line => line.trim() === '');\n if (bodyStartIndex === -1) return null;\n\n const bodyLines = lines.slice(bodyStartIndex + 1);\n const firstNonEmptyBodyLine = bodyLines.find(line => line.trim() !== '');\n if (!firstNonEmptyBodyLine) return null;\n\n const candidate = firstNonEmptyBodyLine.trim();\n const normalized = normalizeRecoveryMode(candidate);\n if (normalized) return normalized;\n\n const lower = candidate.toLowerCase();\n if (lower.includes(EmailRecoveryModeHint.ZkEmail)) return 'zk-email';\n if (lower.includes(EmailRecoveryModeHint.TeeEncrypted)) return 'tee-encrypted';\n if (lower.includes(EmailRecoveryModeHint.OnchainPublic)) return 'onchain-public';\n\n return null;\n}\n\ntype HeaderValue = string | string[] | undefined;\ntype HeadersLike = Headers | Record<string, HeaderValue> | undefined;\n\nexport type RecoverEmailParseResult =\n | { ok: true; accountId: string; emailBlob: string; explicitMode?: string }\n | { ok: false; status: number; code: string; message: string };\n\nfunction getHeader(headers: HeadersLike, name: string): string | undefined {\n if (!headers) return undefined;\n\n const maybeHeaders = headers as any;\n if (typeof maybeHeaders.get === 'function') {\n const v = maybeHeaders.get(name);\n return (typeof v === 'string') ? v : undefined;\n }\n\n const record = headers as Record<string, HeaderValue>;\n const v = record[name.toLowerCase()] ?? record[name];\n if (Array.isArray(v)) return (typeof v[0] === 'string') ? v[0] : undefined;\n return (typeof v === 'string') ? v : undefined;\n}\n\nfunction parseExplicitMode(body: unknown, headers?: HeadersLike): string | undefined {\n const modeFromBody =\n (typeof (body as any)?.explicitMode === 'string' ? String((body as any).explicitMode) : '') ||\n (typeof (body as any)?.explicit_mode === 'string' ? String((body as any).explicit_mode) : '');\n const modeFromHeader = getHeader(headers, 'x-email-recovery-mode') || getHeader(headers, 'x-recovery-mode') || '';\n const raw = (modeFromBody || modeFromHeader).trim();\n return raw ? raw : undefined;\n}\n\nexport function parseRecoverEmailRequest(body: unknown, opts: { headers?: HeadersLike } = {}): RecoverEmailParseResult {\n const explicitMode = parseExplicitMode(body, opts.headers);\n\n const normalized = normalizeForwardableEmailPayload(body);\n if (!normalized.ok) {\n return { ok: false, status: 400, code: normalized.code, message: normalized.message };\n }\n\n const payload = normalized.payload;\n const emailBlob = payload.raw || '';\n const emailHeaders = payload.headers || {};\n\n const subjectHeader = emailHeaders['subject'];\n const parsedAccountId = parseAccountIdFromSubject(subjectHeader || emailBlob);\n const headerAccountId = String(emailHeaders['x-near-account-id'] || emailHeaders['x-account-id'] || '').trim();\n const accountId = (parsedAccountId || headerAccountId || '').trim();\n\n if (!accountId) {\n return { ok: false, status: 400, code: 'missing_account', message: 'x-near-account-id header is required' };\n }\n if (!emailBlob) {\n return { ok: false, status: 400, code: 'missing_email', message: 'raw email blob is required' };\n }\n\n return { ok: true, accountId, emailBlob, explicitMode };\n}\n"],"mappings":";AAGA,IAAY,0EAAL;AACL;AACA;AACA;;;AAGF,SAAgB,sBAAsB,KAA0D;AAC9F,KAAI,CAAC,IAAK,QAAO;CACjB,MAAM,QAAQ,IAAI,OAAO;AACzB,KAAI,UAAU,sBAAsB,QAAS,QAAO;AACpD,KAAI,UAAU,sBAAsB,aAAc,QAAO;AACzD,KAAI,UAAU,sBAAsB,cAAe,QAAO;AAC1D,QAAO;;AAGT,SAAgB,4BAA4B,WAA8C;AACxF,KAAI,CAAC,UAAW,QAAO;CAEvB,MAAM,QAAQ,UAAU,MAAM;CAC9B,MAAM,iBAAiB,MAAM,WAAU,SAAQ,KAAK,WAAW;AAC/D,KAAI,mBAAmB,GAAI,QAAO;CAElC,MAAM,YAAY,MAAM,MAAM,iBAAiB;CAC/C,MAAM,wBAAwB,UAAU,MAAK,SAAQ,KAAK,WAAW;AACrE,KAAI,CAAC,sBAAuB,QAAO;CAEnC,MAAM,YAAY,sBAAsB;CACxC,MAAM,aAAa,sBAAsB;AACzC,KAAI,WAAY,QAAO;CAEvB,MAAM,QAAQ,UAAU;AACxB,KAAI,MAAM,SAAS,sBAAsB,SAAU,QAAO;AAC1D,KAAI,MAAM,SAAS,sBAAsB,cAAe,QAAO;AAC/D,KAAI,MAAM,SAAS,sBAAsB,eAAgB,QAAO;AAEhE,QAAO"}
|
|
1
|
+
{"version":3,"file":"emailParsers.js","names":["headerLines: string[]"],"sources":["../../../../src/server/email-recovery/emailParsers.ts"],"sourcesContent":["import type { EmailRecoveryMode } from './types';\nimport { normalizeForwardableEmailPayload, parseAccountIdFromSubject } from './zkEmail';\n\nexport enum EmailRecoveryModeHint {\n ZkEmail = 'zk-email',\n TeeEncrypted = 'tee-encrypted',\n OnchainPublic = 'onchain-public',\n}\n\nexport function normalizeRecoveryMode(raw: string | undefined | null): EmailRecoveryMode | null {\n if (!raw) return null;\n const value = raw.trim().toLowerCase();\n if (value === EmailRecoveryModeHint.ZkEmail) return 'zk-email';\n if (value === EmailRecoveryModeHint.TeeEncrypted) return 'tee-encrypted';\n if (value === EmailRecoveryModeHint.OnchainPublic) return 'onchain-public';\n return null;\n}\n\nexport function extractRecoveryModeFromBody(emailBlob?: string): EmailRecoveryMode | null {\n if (!emailBlob) return null;\n\n const lines = emailBlob.split(/\\r?\\n/);\n const bodyStartIndex = lines.findIndex(line => line.trim() === '');\n if (bodyStartIndex === -1) return null;\n\n const bodyLines = lines.slice(bodyStartIndex + 1);\n const firstNonEmptyBodyLine = bodyLines.find(line => line.trim() !== '');\n if (!firstNonEmptyBodyLine) return null;\n\n const candidate = firstNonEmptyBodyLine.trim();\n const normalized = normalizeRecoveryMode(candidate);\n if (normalized) return normalized;\n\n const lower = candidate.toLowerCase();\n if (lower.includes(EmailRecoveryModeHint.ZkEmail)) return 'zk-email';\n if (lower.includes(EmailRecoveryModeHint.TeeEncrypted)) return 'tee-encrypted';\n if (lower.includes(EmailRecoveryModeHint.OnchainPublic)) return 'onchain-public';\n\n return null;\n}\n\ntype HeaderValue = string | string[] | undefined;\ntype HeadersLike = Headers | Record<string, HeaderValue> | undefined;\n\nexport type RecoverEmailParseResult =\n | { ok: true; accountId: string; emailBlob: string; explicitMode?: string }\n | { ok: false; status: number; code: string; message: string };\n\nfunction getHeader(headers: HeadersLike, name: string): string | undefined {\n if (!headers) return undefined;\n\n const maybeHeaders = headers as any;\n if (typeof maybeHeaders.get === 'function') {\n const v = maybeHeaders.get(name);\n return (typeof v === 'string') ? v : undefined;\n }\n\n const record = headers as Record<string, HeaderValue>;\n const v = record[name.toLowerCase()] ?? record[name];\n if (Array.isArray(v)) return (typeof v[0] === 'string') ? v[0] : undefined;\n return (typeof v === 'string') ? v : undefined;\n}\n\nfunction parseExplicitMode(body: unknown, headers?: HeadersLike): string | undefined {\n const modeFromBody =\n (typeof (body as any)?.explicitMode === 'string' ? String((body as any).explicitMode) : '') ||\n (typeof (body as any)?.explicit_mode === 'string' ? String((body as any).explicit_mode) : '');\n const modeFromHeader = getHeader(headers, 'x-email-recovery-mode') || getHeader(headers, 'x-recovery-mode') || '';\n const raw = (modeFromBody || modeFromHeader).trim();\n return raw ? raw : undefined;\n}\n\nexport function parseRecoverEmailRequest(body: unknown, opts: { headers?: HeadersLike } = {}): RecoverEmailParseResult {\n const explicitMode = parseExplicitMode(body, opts.headers);\n\n const normalized = normalizeForwardableEmailPayload(body);\n if (!normalized.ok) {\n return { ok: false, status: 400, code: normalized.code, message: normalized.message };\n }\n\n const payload = normalized.payload;\n const emailBlob = payload.raw || '';\n const emailHeaders = payload.headers || {};\n\n const subjectHeader = emailHeaders['subject'];\n const parsedAccountId = parseAccountIdFromSubject(subjectHeader || emailBlob);\n const headerAccountId = String(emailHeaders['x-near-account-id'] || emailHeaders['x-account-id'] || '').trim();\n const accountId = (parsedAccountId || headerAccountId || '').trim();\n\n if (!accountId) {\n return { ok: false, status: 400, code: 'missing_account', message: 'x-near-account-id header is required' };\n }\n if (!emailBlob) {\n return { ok: false, status: 400, code: 'missing_email', message: 'raw email blob is required' };\n }\n\n return { ok: true, accountId, emailBlob, explicitMode };\n}\n\nconst EMAIL_ADDRESS_REGEX =\n /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)/;\n\nexport function canonicalizeEmail(input: string): string {\n const raw = String(input || '').trim();\n if (!raw) return '';\n\n // Handle cases where a full header line is passed in (e.g. \"From: ...\").\n const withoutHeaderName = raw.replace(/^[a-z0-9-]+\\s*:\\s*/i, '').trim();\n\n // Prefer the common \"Name <email@domain>\" format when present, but still\n // validate/extract the actual address via regex.\n const angleMatch = withoutHeaderName.match(/<([^>]+)>/);\n const candidates = [\n angleMatch?.[1],\n withoutHeaderName,\n ].filter((v): v is string => typeof v === 'string' && v.length > 0);\n\n for (const candidate of candidates) {\n const cleaned = candidate.replace(/^mailto:\\s*/i, '');\n const match = cleaned.match(EMAIL_ADDRESS_REGEX);\n if (match?.[1]) {\n return match[1].trim().toLowerCase();\n }\n }\n\n return withoutHeaderName.toLowerCase();\n}\n\nexport function parseHeaderValue(rawEmail: string, name: string): string | undefined {\n try {\n const raw = String(rawEmail || '');\n if (!raw) return undefined;\n\n const lines = raw.split(/\\r?\\n/);\n const headerLines: string[] = [];\n\n // Only consider the header section (until the first blank line).\n for (const line of lines) {\n if (line.trim() === '') break;\n\n // RFC822 header folding: lines starting with whitespace continue previous header.\n if (/^\\s/.test(line) && headerLines.length > 0) {\n headerLines[headerLines.length - 1] += ` ${line.trim()}`;\n continue;\n }\n\n headerLines.push(line);\n }\n\n const headerName = name.trim();\n if (!headerName) return undefined;\n\n const re = new RegExp(`^${headerName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\s*:`, 'i');\n const found = headerLines.find((l) => re.test(l));\n if (!found) return undefined;\n\n const idx = found.indexOf(':');\n const value = idx >= 0 ? found.slice(idx + 1).trim() : '';\n return value || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function parseRecoverSubjectBindings(\n rawEmail: string\n): { requestId: string; accountId: string; newPublicKey: string } | null {\n // Accept either a full RFC822 email or a bare Subject value.\n let subjectText = (parseHeaderValue(rawEmail, 'subject') || String(rawEmail || '')).trim();\n if (!subjectText) return null;\n\n // Strip common reply/forward prefixes.\n subjectText = subjectText.replace(/^(re|fwd):\\s*/i, '').trim();\n if (!subjectText) return null;\n\n // Strict format:\n // \"recover-<request_id> <accountId> ed25519:<pk>\"\n const match = subjectText.match(\n /^recover-([A-Za-z0-9]{6})\\s+([^\\s]+)\\s+ed25519:([^\\s]+)\\s*$/i\n );\n if (!match) return null;\n\n const [, requestId, accountId, newPublicKey] = match;\n return { requestId, accountId, newPublicKey };\n}\n"],"mappings":";AAGA,IAAY,0EAAL;AACL;AACA;AACA;;;AAGF,SAAgB,sBAAsB,KAA0D;AAC9F,KAAI,CAAC,IAAK,QAAO;CACjB,MAAM,QAAQ,IAAI,OAAO;AACzB,KAAI,UAAU,sBAAsB,QAAS,QAAO;AACpD,KAAI,UAAU,sBAAsB,aAAc,QAAO;AACzD,KAAI,UAAU,sBAAsB,cAAe,QAAO;AAC1D,QAAO;;AAGT,SAAgB,4BAA4B,WAA8C;AACxF,KAAI,CAAC,UAAW,QAAO;CAEvB,MAAM,QAAQ,UAAU,MAAM;CAC9B,MAAM,iBAAiB,MAAM,WAAU,SAAQ,KAAK,WAAW;AAC/D,KAAI,mBAAmB,GAAI,QAAO;CAElC,MAAM,YAAY,MAAM,MAAM,iBAAiB;CAC/C,MAAM,wBAAwB,UAAU,MAAK,SAAQ,KAAK,WAAW;AACrE,KAAI,CAAC,sBAAuB,QAAO;CAEnC,MAAM,YAAY,sBAAsB;CACxC,MAAM,aAAa,sBAAsB;AACzC,KAAI,WAAY,QAAO;CAEvB,MAAM,QAAQ,UAAU;AACxB,KAAI,MAAM,SAAS,sBAAsB,SAAU,QAAO;AAC1D,KAAI,MAAM,SAAS,sBAAsB,cAAe,QAAO;AAC/D,KAAI,MAAM,SAAS,sBAAsB,eAAgB,QAAO;AAEhE,QAAO;;AA6DT,MAAM,sBACJ;AAEF,SAAgB,kBAAkB,OAAuB;CACvD,MAAM,MAAM,OAAO,SAAS,IAAI;AAChC,KAAI,CAAC,IAAK,QAAO;CAGjB,MAAM,oBAAoB,IAAI,QAAQ,uBAAuB,IAAI;CAIjE,MAAM,aAAa,kBAAkB,MAAM;CAC3C,MAAM,aAAa,CACjB,aAAa,IACb,mBACA,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS;AAEjE,MAAK,MAAM,aAAa,YAAY;EAClC,MAAM,UAAU,UAAU,QAAQ,gBAAgB;EAClD,MAAM,QAAQ,QAAQ,MAAM;AAC5B,MAAI,QAAQ,GACV,QAAO,MAAM,GAAG,OAAO;;AAI3B,QAAO,kBAAkB;;AAG3B,SAAgB,iBAAiB,UAAkB,MAAkC;AACnF,KAAI;EACF,MAAM,MAAM,OAAO,YAAY;AAC/B,MAAI,CAAC,IAAK,QAAO;EAEjB,MAAM,QAAQ,IAAI,MAAM;EACxB,MAAMA,cAAwB;AAG9B,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,WAAW,GAAI;AAGxB,OAAI,MAAM,KAAK,SAAS,YAAY,SAAS,GAAG;AAC9C,gBAAY,YAAY,SAAS,MAAM,IAAI,KAAK;AAChD;;AAGF,eAAY,KAAK;;EAGnB,MAAM,aAAa,KAAK;AACxB,MAAI,CAAC,WAAY,QAAO;EAExB,MAAM,KAAK,IAAI,OAAO,IAAI,WAAW,QAAQ,uBAAuB,QAAQ,QAAQ;EACpF,MAAM,QAAQ,YAAY,MAAM,MAAM,GAAG,KAAK;AAC9C,MAAI,CAAC,MAAO,QAAO;EAEnB,MAAM,MAAM,MAAM,QAAQ;EAC1B,MAAM,QAAQ,OAAO,IAAI,MAAM,MAAM,MAAM,GAAG,SAAS;AACvD,SAAO,SAAS;SACV;AACN,SAAO;;;AAIX,SAAgB,4BACd,UACuE;CAEvE,IAAI,eAAe,iBAAiB,UAAU,cAAc,OAAO,YAAY,KAAK;AACpF,KAAI,CAAC,YAAa,QAAO;AAGzB,eAAc,YAAY,QAAQ,kBAAkB,IAAI;AACxD,KAAI,CAAC,YAAa,QAAO;CAIzB,MAAM,QAAQ,YAAY,MACxB;AAEF,KAAI,CAAC,MAAO,QAAO;CAEnB,MAAM,GAAG,WAAW,WAAW,gBAAgB;AAC/C,QAAO;EAAE;EAAW;EAAW"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ZkEmailProverClient } from "./zkEmail/proverClient.js";
|
|
2
2
|
import { buildForwardablePayloadFromRawEmail, extractZkEmailBindingsFromPayload, generateZkEmailProofFromPayload, normalizeForwardableEmailPayload, parseAccountIdFromSubject } from "./zkEmail/index.js";
|
|
3
3
|
import { extractRecoveryModeFromBody, normalizeRecoveryMode } from "./emailParsers.js";
|
|
4
|
-
import { deriveOutlayerStaticKeyFromSeedHex, encryptEmailForOutlayer } from "./emailEncryptor.js";
|
|
4
|
+
import { deriveOutlayerStaticKeyFromSeedHex, encryptEmailForOutlayer, hashRecoveryEmailForAccount } from "./emailEncryptor.js";
|
|
5
5
|
import { buildEncryptedEmailRecoveryActions, buildOnchainEmailRecoveryActions, buildZkEmailRecoveryActions, getOutlayerEncryptionPublicKey, sendEmailRecoveryTransaction } from "./rpcCalls.js";
|
|
6
6
|
import { mapZkEmailRecoveryError, prepareZkEmailRecovery } from "./zkEmail/recovery.js";
|
|
7
7
|
import { normalizeLogger } from "../core/logger.js";
|
|
@@ -16,7 +16,7 @@ import { decryptEmailForOutlayerTestOnly, deriveTestX25519KeypairFromSeed } from
|
|
|
16
16
|
* - Encrypting raw RFC822 emails with encryptEmailForOutlayer, binding an AEAD context
|
|
17
17
|
* `{ account_id, network_id, payer_account_id }`,
|
|
18
18
|
* - Calling the per-account EmailRecoverer contract with:
|
|
19
|
-
* - `verify_encrypted_email_and_recover(encrypted_email_blob, aead_context)` for DKIM/TEE,
|
|
19
|
+
* - `verify_encrypted_email_and_recover(encrypted_email_blob, aead_context, expected_hashed_email, expected_new_public_key)` for DKIM/TEE,
|
|
20
20
|
* - `verify_zkemail_and_recover` for zk-email recovery,
|
|
21
21
|
* - Performing legacy plaintext on-chain verification via `verify_email_onchain_and_recover`
|
|
22
22
|
* for backwards compatibility only.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["e: unknown","e: any","error: any"],"sources":["../../../../src/server/email-recovery/index.ts"],"sourcesContent":["import type { ActionArgsWasm } from '../../core/types/actions';\nimport { ActionType, validateActionArgsWasm } from '../../core/types/actions';\nimport { parseContractExecutionError } from '../core/errors';\nimport { generateZkEmailProofFromPayload, type ZkEmailProverClientOptions } from './zkEmail';\nimport { extractRecoveryModeFromBody, normalizeRecoveryMode } from './emailParsers';\nimport { encryptEmailForOutlayer } from './emailEncryptor';\nimport { buildEncryptedEmailRecoveryActions, buildOnchainEmailRecoveryActions, buildZkEmailRecoveryActions, sendEmailRecoveryTransaction, getOutlayerEncryptionPublicKey } from './rpcCalls';\nimport { ZkEmailProverClient } from './zkEmail/proverClient';\nimport { mapZkEmailRecoveryError, prepareZkEmailRecovery } from './zkEmail/recovery';\nimport { normalizeLogger, type NormalizedLogger } from '../core/logger';\nimport type {\n EmailRecoveryDispatchRequest,\n EmailRecoveryMode,\n EmailRecoveryRequest,\n EmailRecoveryResult,\n EmailRecoveryServiceDeps,\n} from './types';\n\nexport * from './emailEncryptor';\nexport * from './zkEmail';\nexport * from './zkEmail/recovery';\nexport * from './testHelpers';\nexport * from './types';\n\n/**\n * EmailRecoveryService encapsulates email recovery logic for the relayer.\n *\n * It currently orchestrates:\n * - Fetching and caching the Outlayer X25519 public key from the global EmailDKIMVerifier,\n * - Encrypting raw RFC822 emails with encryptEmailForOutlayer, binding an AEAD context\n * `{ account_id, network_id, payer_account_id }`,\n * - Calling the per-account EmailRecoverer contract with:\n * - `verify_encrypted_email_and_recover(encrypted_email_blob, aead_context)` for DKIM/TEE,\n * - `verify_zkemail_and_recover` for zk-email recovery,\n * - Performing legacy plaintext on-chain verification via `verify_email_onchain_and_recover`\n * for backwards compatibility only.\n */\nexport class EmailRecoveryService {\n private readonly deps: EmailRecoveryServiceDeps;\n private readonly logger: NormalizedLogger;\n private cachedOutlayerPk: Uint8Array | null = null;\n private zkEmailProverClient: ZkEmailProverClient | null = null;\n private zkEmailProverClientKey: string | null = null;\n\n constructor(deps: EmailRecoveryServiceDeps) {\n this.deps = deps;\n this.logger = normalizeLogger(deps.logger);\n }\n\n /**\n * Lightweight view of zk-email prover wiring for health/readiness endpoints.\n * This does not perform any network calls.\n */\n getZkEmailProverBaseUrl(): string | null {\n const baseUrl = String(this.deps.zkEmailProver?.baseUrl || '').trim().replace(/\\/+$/, '');\n return baseUrl ? baseUrl : null;\n }\n\n /**\n * Readiness check for zk-email prover.\n *\n * Returns `healthy: null` when zk-email prover is not configured.\n * Does not log; callers (routers) may decide how/when to log.\n */\n async checkZkEmailProverHealth(): Promise<{\n configured: boolean;\n baseUrl: string | null;\n healthy: boolean | null;\n errorCode?: string;\n message?: string;\n proverCauseCode?: string;\n proverCauseMessage?: string;\n }> {\n const baseUrl = this.getZkEmailProverBaseUrl();\n const opts = this.deps.zkEmailProver;\n if (!baseUrl || !opts) {\n return { configured: false, baseUrl: null, healthy: null };\n }\n\n try {\n const client = this.getZkEmailProverClient({ ...opts, baseUrl });\n await client.healthz();\n return { configured: true, baseUrl, healthy: true };\n } catch (e: unknown) {\n const mapped = mapZkEmailRecoveryError(e);\n return {\n configured: true,\n baseUrl,\n healthy: false,\n errorCode: mapped.errorCode,\n message: mapped.message,\n proverCauseCode: mapped.proverCauseCode,\n proverCauseMessage: mapped.proverCauseMessage,\n };\n }\n }\n\n private getZkEmailProverClient(opts: ZkEmailProverClientOptions): ZkEmailProverClient {\n const baseUrl = String(opts.baseUrl || '').replace(/\\/+$/, '');\n const timeoutMs = opts.timeoutMs ?? 60_000;\n const healthCheck = opts.healthCheck;\n const key = `${baseUrl}|${timeoutMs}|${healthCheck?.enabled ?? 'default'}|${healthCheck?.ttlMs ?? 'default'}|${healthCheck?.timeoutMs ?? 'default'}`;\n\n if (this.zkEmailProverClient && this.zkEmailProverClientKey === key) {\n return this.zkEmailProverClient;\n }\n\n const client = new ZkEmailProverClient(opts);\n this.zkEmailProverClient = client;\n this.zkEmailProverClientKey = key;\n return client;\n }\n\n private async getOutlayerEmailDkimPublicKey(): Promise<Uint8Array> {\n if (this.cachedOutlayerPk) {\n return this.cachedOutlayerPk;\n }\n const pk = await getOutlayerEncryptionPublicKey(this.deps);\n this.cachedOutlayerPk = pk;\n return pk;\n }\n\n /**\n * Determine recovery mode (zk-email | encrypted | onchain-public) from:\n * - explicit override (for programmatic callers),\n * - body markers inside the raw email,\n * falling back to tee-private for backwards compatibility.\n */\n private determineRecoveryMode(input: {\n explicitMode?: string;\n emailBlob?: string;\n }): EmailRecoveryMode {\n return (\n normalizeRecoveryMode(input.explicitMode) ??\n extractRecoveryModeFromBody(input.emailBlob) ??\n 'tee-encrypted'\n );\n }\n\n /**\n * Top-level dispatcher for email recovery modes.\n *\n * Usage from HTTP routes:\n * - Pass the full raw RFC822 email as `emailBlob` (including headers + body).\n * - Optionally include an explicit `explicitMode` override (`'zk-email' | 'tee-encrypted' | 'onchain-public'`).\n * - Otherwise, the first non-empty body line is parsed as a mode hint:\n * - `\"zk-email\"` → zk-email prover + per-account `verify_zkemail_and_recover`.\n * - `\"tee-encrypted\"` (or legacy `\"encrypted\"`) → per-account EmailRecoverer encrypted path (`verify_encrypted_email_and_recover`).\n * - `\"onchain-public\"` → currently routed to the same per-account encrypted path for backwards compatibility.\n * - If no hint is found, the mode defaults to `'tee-encrypted'`.\n */\n async requestEmailRecovery(request: EmailRecoveryDispatchRequest): Promise<EmailRecoveryResult> {\n const mode = this.determineRecoveryMode({\n explicitMode: request.explicitMode,\n emailBlob: request.emailBlob,\n });\n this.logger.debug('[email-recovery] requestEmailRecovery mode selected', {\n mode,\n accountId: request.accountId,\n });\n\n switch (mode) {\n case 'tee-encrypted':\n return this.verifyEncryptedEmailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n case 'zk-email':\n return this.verifyZkemailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n case 'onchain-public':\n // Use the same encrypted/TEE path via per-account EmailRecoverer.\n return this.verifyEncryptedEmailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n default:\n // Fallback to the TEE-encrypted path for forwards compatibility.\n return this.verifyEncryptedEmailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n }\n }\n\n /**\n * Helper for encrypted DKIM-based email recovery:\n * - Encrypts the raw email blob for the Outlayer worker.\n * - Calls the per-account EmailRecoverer contract's\n * `verify_encrypted_email_and_recover` entrypoint on the user's account.\n *\n * The per-account EmailRecoverer then delegates to the global\n * EmailDKIMVerifier (TEE path), which stores a VerificationResult keyed by\n * request_id. The frontend polls EmailDKIMVerifier::get_verification_result(request_id)\n * to observe success/failure.\n */\n\t async verifyEncryptedEmailAndRecover(request: EmailRecoveryRequest): Promise<EmailRecoveryResult> {\n\t const accountId = (request.accountId || '').trim();\n\t const emailBlob = request.emailBlob;\n\n\t if (!accountId) {\n\t const errMsg = 'accountId is required';\n\t return { success: false, error: errMsg, message: errMsg };\n\t }\n\t if (!emailBlob || typeof emailBlob !== 'string') {\n\t const errMsg = 'emailBlob (raw email) is required';\n\t return { success: false, error: errMsg, message: errMsg };\n\t }\n\n\t const { ensureSignerAndRelayerAccount } = this.deps;\n\n\t try {\n\t await ensureSignerAndRelayerAccount();\n\t } catch (e: any) {\n\t const msg = e?.message || 'Failed to initialize relayer account';\n\t return { success: false, error: msg, message: msg };\n\t }\n\n\t\t const recipientPk = await this.getOutlayerEmailDkimPublicKey();\n\t\t this.logger.debug('[email-recovery] encrypted using Outlayer public key', {\n\t\t accountId,\n\t\t outlayerPkLen: recipientPk.length,\n\t\t });\n\n\t const { actions, receiverId } = await buildEncryptedEmailRecoveryActions(this.deps, {\n\t accountId,\n\t emailBlob,\n\t recipientPk,\n\t encrypt: async ({ emailRaw, aeadContext, recipientPk: pk }) => {\n\t const { envelope } = await encryptEmailForOutlayer({\n\t emailRaw,\n\t aeadContext,\n\t recipientPk: pk,\n\t });\n\n\t\t this.logger.debug('[email-recovery] encrypted email envelope metadata', {\n\t\t accountId,\n\t\t aeadContextLen: aeadContext.length,\n\t\t envelope: {\n\t\t version: envelope.version,\n\t\t ephemeral_pub_len: envelope.ephemeral_pub?.length ?? 0,\n\t\t nonce_len: envelope.nonce?.length ?? 0,\n\t\t ciphertext_len: envelope.ciphertext?.length ?? 0,\n\t\t },\n\t\t });\n\n\t return { envelope };\n\t },\n\t });\n\n\t return sendEmailRecoveryTransaction(this.deps, {\n\t receiverId,\n\t actions,\n\t label: `Encrypted email verification requested for ${accountId}`,\n\t });\n\t }\n\n /**\n * Legacy helper for plaintext/on-chain DKIM email verification + account recovery.\n * This path is deprecated in favor of the encrypted TEE path via\n * `verifyEncryptedEmailAndRecover` and is no longer used by\n * `requestEmailRecovery`.\n */\n\t async verifyEmailOnchainAndRecover(request: EmailRecoveryRequest): Promise<EmailRecoveryResult> {\n const accountId = (request.accountId || '').trim();\n const emailBlob = request.emailBlob;\n\n if (!accountId) {\n let errMsg = 'accountId is required';\n return { success: false, error: errMsg, message: errMsg };\n }\n if (!emailBlob || typeof emailBlob !== 'string') {\n let errMsg = 'emailBlob (raw email) is required';\n return { success: false, error: errMsg, message: errMsg };\n }\n\n\t const { ensureSignerAndRelayerAccount } = this.deps;\n\n try {\n await ensureSignerAndRelayerAccount();\n } catch (e: any) {\n const msg = e?.message || 'Failed to initialize relayer account';\n return { success: false, error: msg, message: msg };\n }\n\n\t const { actions, receiverId } = await buildOnchainEmailRecoveryActions(this.deps, {\n\t accountId,\n\t emailBlob,\n\t });\n\n\t return sendEmailRecoveryTransaction(this.deps, {\n\t receiverId,\n\t actions,\n\t label: `On-chain email verification requested for ${accountId}`,\n\t });\n }\n\n /**\n * Helper for zk-email recovery:\n * - Calls external zk-email prover with the raw email blob to obtain (proof, publicInputs).\n * - Extracts subject/header bindings (account_id, new_public_key, from_email, timestamp).\n * - Calls the per-account EmailRecoverer contract with verify_zkemail_and_recover.\n */\n\t async verifyZkemailAndRecover(request: EmailRecoveryRequest): Promise<EmailRecoveryResult> {\n\t const accountId = (request.accountId || '').trim();\n\t const emailBlob = request.emailBlob;\n\n if (!accountId) {\n return {\n success: false,\n error: 'zkemail_missing_account_id',\n message: 'accountId is required',\n };\n }\n if (!emailBlob || typeof emailBlob !== 'string') {\n return {\n success: false,\n error: 'zkemail_missing_email_blob',\n message: 'emailBlob (raw email) is required',\n };\n }\n\n\t const { ensureSignerAndRelayerAccount, zkEmailProver } = this.deps;\n\n if (!zkEmailProver || !zkEmailProver.baseUrl) {\n this.logger.warn('[email-recovery] zk-email missing prover configuration', { accountId });\n return {\n success: false,\n error: 'zkemail_prover_not_configured',\n message: 'zk-email prover configuration is missing',\n };\n }\n\n const prepared = prepareZkEmailRecovery(emailBlob, accountId);\n if (!prepared.ok) {\n const log = {\n accountId,\n requestId: prepared.requestId,\n proverBaseUrl: zkEmailProver.baseUrl,\n errorCode: prepared.errorCode,\n errorMessage: prepared.message,\n accountIdSubject: prepared.subjectAccountId,\n };\n if (prepared.errorCode === 'zkemail_account_mismatch') {\n this.logger.warn('[email-recovery] zk-email account mismatch', log);\n } else {\n this.logger.warn('[email-recovery] zk-email recovery rejected', log);\n }\n return { success: false, error: prepared.errorCode, message: prepared.message };\n }\n\n const { payload, bindings } = prepared.prepared;\n\n try {\n await ensureSignerAndRelayerAccount();\n } catch (e: any) {\n const msg = e?.message || 'Failed to initialize relayer account';\n this.logger.error('[email-recovery] zk-email ensureSignerAndRelayerAccount failed', {\n accountId,\n requestId: bindings.requestId,\n error: msg,\n });\n return { success: false, error: 'zkemail_relayer_init_failed', message: msg };\n }\n\n\t try {\n\t const proverClient = this.getZkEmailProverClient(zkEmailProver);\n\t const proofResult = await generateZkEmailProofFromPayload(payload, proverClient);\n\n\t const contractArgs = {\n\t proof: proofResult.proof,\n\t public_inputs: proofResult.publicInputs,\n\t account_id: bindings.accountId,\n\t new_public_key: bindings.newPublicKey,\n\t from_email: bindings.fromEmail,\n\t timestamp: bindings.timestamp,\n\t };\n\n\t const { actions, receiverId } = await buildZkEmailRecoveryActions(this.deps, {\n\t accountId,\n\t contractArgs,\n\t });\n\n\t return sendEmailRecoveryTransaction(this.deps, {\n\t receiverId,\n\t actions,\n\t label: `ZK-email recovery requested for ${accountId}`,\n\t });\n\t\t } catch (error: any) {\n const mapped = mapZkEmailRecoveryError(error);\n\n\t\t this.logger.error('[email-recovery] zk-email recovery error', {\n\t\t accountId,\n\t requestId: bindings.requestId,\n\t\t errorCode: mapped.errorCode,\n\t\t errorMessage: mapped.message,\n\t proverBaseUrl: zkEmailProver.baseUrl,\n\t proverCauseCode: mapped.proverCauseCode,\n\t proverCauseMessage: mapped.proverCauseMessage,\n\t\t });\n\n\t return {\n\t success: false,\n\t error: mapped.errorCode,\n\t message: mapped.message,\n\t };\n\t }\n\t }\n\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["e: unknown","e: any","error: any"],"sources":["../../../../src/server/email-recovery/index.ts"],"sourcesContent":["import type { ActionArgsWasm } from '../../core/types/actions';\nimport { ActionType, validateActionArgsWasm } from '../../core/types/actions';\nimport { parseContractExecutionError } from '../core/errors';\nimport { generateZkEmailProofFromPayload, type ZkEmailProverClientOptions } from './zkEmail';\nimport { extractRecoveryModeFromBody, normalizeRecoveryMode } from './emailParsers';\nimport { encryptEmailForOutlayer } from './emailEncryptor';\nimport { buildEncryptedEmailRecoveryActions, buildOnchainEmailRecoveryActions, buildZkEmailRecoveryActions, sendEmailRecoveryTransaction, getOutlayerEncryptionPublicKey } from './rpcCalls';\nimport { ZkEmailProverClient } from './zkEmail/proverClient';\nimport { mapZkEmailRecoveryError, prepareZkEmailRecovery } from './zkEmail/recovery';\nimport { normalizeLogger, type NormalizedLogger } from '../core/logger';\nimport type {\n EmailRecoveryDispatchRequest,\n EmailRecoveryMode,\n EmailRecoveryRequest,\n EmailRecoveryResult,\n EmailRecoveryServiceDeps,\n} from './types';\n\nexport * from './emailEncryptor';\nexport * from './zkEmail';\nexport * from './zkEmail/recovery';\nexport * from './testHelpers';\nexport * from './types';\n\n/**\n * EmailRecoveryService encapsulates email recovery logic for the relayer.\n *\n * It currently orchestrates:\n * - Fetching and caching the Outlayer X25519 public key from the global EmailDKIMVerifier,\n * - Encrypting raw RFC822 emails with encryptEmailForOutlayer, binding an AEAD context\n * `{ account_id, network_id, payer_account_id }`,\n * - Calling the per-account EmailRecoverer contract with:\n * - `verify_encrypted_email_and_recover(encrypted_email_blob, aead_context, expected_hashed_email, expected_new_public_key)` for DKIM/TEE,\n * - `verify_zkemail_and_recover` for zk-email recovery,\n * - Performing legacy plaintext on-chain verification via `verify_email_onchain_and_recover`\n * for backwards compatibility only.\n */\nexport class EmailRecoveryService {\n private readonly deps: EmailRecoveryServiceDeps;\n private readonly logger: NormalizedLogger;\n private cachedOutlayerPk: Uint8Array | null = null;\n private zkEmailProverClient: ZkEmailProverClient | null = null;\n private zkEmailProverClientKey: string | null = null;\n\n constructor(deps: EmailRecoveryServiceDeps) {\n this.deps = deps;\n this.logger = normalizeLogger(deps.logger);\n }\n\n /**\n * Lightweight view of zk-email prover wiring for health/readiness endpoints.\n * This does not perform any network calls.\n */\n getZkEmailProverBaseUrl(): string | null {\n const baseUrl = String(this.deps.zkEmailProver?.baseUrl || '').trim().replace(/\\/+$/, '');\n return baseUrl ? baseUrl : null;\n }\n\n /**\n * Readiness check for zk-email prover.\n *\n * Returns `healthy: null` when zk-email prover is not configured.\n * Does not log; callers (routers) may decide how/when to log.\n */\n async checkZkEmailProverHealth(): Promise<{\n configured: boolean;\n baseUrl: string | null;\n healthy: boolean | null;\n errorCode?: string;\n message?: string;\n proverCauseCode?: string;\n proverCauseMessage?: string;\n }> {\n const baseUrl = this.getZkEmailProverBaseUrl();\n const opts = this.deps.zkEmailProver;\n if (!baseUrl || !opts) {\n return { configured: false, baseUrl: null, healthy: null };\n }\n\n try {\n const client = this.getZkEmailProverClient({ ...opts, baseUrl });\n await client.healthz();\n return { configured: true, baseUrl, healthy: true };\n } catch (e: unknown) {\n const mapped = mapZkEmailRecoveryError(e);\n return {\n configured: true,\n baseUrl,\n healthy: false,\n errorCode: mapped.errorCode,\n message: mapped.message,\n proverCauseCode: mapped.proverCauseCode,\n proverCauseMessage: mapped.proverCauseMessage,\n };\n }\n }\n\n private getZkEmailProverClient(opts: ZkEmailProverClientOptions): ZkEmailProverClient {\n const baseUrl = String(opts.baseUrl || '').replace(/\\/+$/, '');\n const timeoutMs = opts.timeoutMs ?? 60_000;\n const healthCheck = opts.healthCheck;\n const key = `${baseUrl}|${timeoutMs}|${healthCheck?.enabled ?? 'default'}|${healthCheck?.ttlMs ?? 'default'}|${healthCheck?.timeoutMs ?? 'default'}`;\n\n if (this.zkEmailProverClient && this.zkEmailProverClientKey === key) {\n return this.zkEmailProverClient;\n }\n\n const client = new ZkEmailProverClient(opts);\n this.zkEmailProverClient = client;\n this.zkEmailProverClientKey = key;\n return client;\n }\n\n private async getOutlayerEmailDkimPublicKey(): Promise<Uint8Array> {\n if (this.cachedOutlayerPk) {\n return this.cachedOutlayerPk;\n }\n const pk = await getOutlayerEncryptionPublicKey(this.deps);\n this.cachedOutlayerPk = pk;\n return pk;\n }\n\n /**\n * Determine recovery mode (zk-email | encrypted | onchain-public) from:\n * - explicit override (for programmatic callers),\n * - body markers inside the raw email,\n * falling back to tee-private for backwards compatibility.\n */\n private determineRecoveryMode(input: {\n explicitMode?: string;\n emailBlob?: string;\n }): EmailRecoveryMode {\n return (\n normalizeRecoveryMode(input.explicitMode) ??\n extractRecoveryModeFromBody(input.emailBlob) ??\n 'tee-encrypted'\n );\n }\n\n /**\n * Top-level dispatcher for email recovery modes.\n *\n * Usage from HTTP routes:\n * - Pass the full raw RFC822 email as `emailBlob` (including headers + body).\n * - Optionally include an explicit `explicitMode` override (`'zk-email' | 'tee-encrypted' | 'onchain-public'`).\n * - Otherwise, the first non-empty body line is parsed as a mode hint:\n * - `\"zk-email\"` → zk-email prover + per-account `verify_zkemail_and_recover`.\n * - `\"tee-encrypted\"` (or legacy `\"encrypted\"`) → per-account EmailRecoverer encrypted path (`verify_encrypted_email_and_recover`).\n * - `\"onchain-public\"` → currently routed to the same per-account encrypted path for backwards compatibility.\n * - If no hint is found, the mode defaults to `'tee-encrypted'`.\n */\n async requestEmailRecovery(request: EmailRecoveryDispatchRequest): Promise<EmailRecoveryResult> {\n const mode = this.determineRecoveryMode({\n explicitMode: request.explicitMode,\n emailBlob: request.emailBlob,\n });\n this.logger.debug('[email-recovery] requestEmailRecovery mode selected', {\n mode,\n accountId: request.accountId,\n });\n\n switch (mode) {\n case 'tee-encrypted':\n return this.verifyEncryptedEmailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n case 'zk-email':\n return this.verifyZkemailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n case 'onchain-public':\n // Use the same encrypted/TEE path via per-account EmailRecoverer.\n return this.verifyEncryptedEmailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n default:\n // Fallback to the TEE-encrypted path for forwards compatibility.\n return this.verifyEncryptedEmailAndRecover({\n accountId: request.accountId,\n emailBlob: request.emailBlob,\n });\n }\n }\n\n /**\n * Helper for encrypted DKIM-based email recovery:\n * - Encrypts the raw email blob for the Outlayer worker.\n * - Calls the per-account EmailRecoverer contract's\n * `verify_encrypted_email_and_recover` entrypoint on the user's account.\n *\n * The per-account EmailRecoverer then delegates to the global\n * EmailDKIMVerifier (TEE path), which stores a VerificationResult keyed by\n * request_id. The frontend polls EmailDKIMVerifier::get_verification_result(request_id)\n * to observe success/failure.\n */\n\t async verifyEncryptedEmailAndRecover(request: EmailRecoveryRequest): Promise<EmailRecoveryResult> {\n\t const accountId = (request.accountId || '').trim();\n\t const emailBlob = request.emailBlob;\n\n\t if (!accountId) {\n\t const errMsg = 'accountId is required';\n\t return { success: false, error: errMsg, message: errMsg };\n\t }\n\t if (!emailBlob || typeof emailBlob !== 'string') {\n\t const errMsg = 'emailBlob (raw email) is required';\n\t return { success: false, error: errMsg, message: errMsg };\n\t }\n\n\t const { ensureSignerAndRelayerAccount } = this.deps;\n\n\t try {\n\t await ensureSignerAndRelayerAccount();\n\t } catch (e: any) {\n\t const msg = e?.message || 'Failed to initialize relayer account';\n\t return { success: false, error: msg, message: msg };\n\t }\n\n\t\t const recipientPk = await this.getOutlayerEmailDkimPublicKey();\n\t\t this.logger.debug('[email-recovery] encrypted using Outlayer public key', {\n\t\t accountId,\n\t\t outlayerPkLen: recipientPk.length,\n\t\t });\n\n\t const { actions, receiverId } = await buildEncryptedEmailRecoveryActions(this.deps, {\n\t accountId,\n\t emailBlob,\n\t recipientPk,\n\t encrypt: async ({ emailRaw, aeadContext, recipientPk: pk }) => {\n\t const { envelope } = await encryptEmailForOutlayer({\n\t emailRaw,\n\t aeadContext,\n\t recipientPk: pk,\n\t });\n\n\t\t this.logger.debug('[email-recovery] encrypted email envelope metadata', {\n\t\t accountId,\n\t\t aeadContextLen: aeadContext.length,\n\t\t envelope: {\n\t\t version: envelope.version,\n\t\t ephemeral_pub_len: envelope.ephemeral_pub?.length ?? 0,\n\t\t nonce_len: envelope.nonce?.length ?? 0,\n\t\t ciphertext_len: envelope.ciphertext?.length ?? 0,\n\t\t },\n\t\t });\n\n\t return { envelope };\n\t },\n\t });\n\n\t return sendEmailRecoveryTransaction(this.deps, {\n\t receiverId,\n\t actions,\n\t label: `Encrypted email verification requested for ${accountId}`,\n\t });\n\t }\n\n /**\n * Legacy helper for plaintext/on-chain DKIM email verification + account recovery.\n * This path is deprecated in favor of the encrypted TEE path via\n * `verifyEncryptedEmailAndRecover` and is no longer used by\n * `requestEmailRecovery`.\n */\n\t async verifyEmailOnchainAndRecover(request: EmailRecoveryRequest): Promise<EmailRecoveryResult> {\n const accountId = (request.accountId || '').trim();\n const emailBlob = request.emailBlob;\n\n if (!accountId) {\n let errMsg = 'accountId is required';\n return { success: false, error: errMsg, message: errMsg };\n }\n if (!emailBlob || typeof emailBlob !== 'string') {\n let errMsg = 'emailBlob (raw email) is required';\n return { success: false, error: errMsg, message: errMsg };\n }\n\n\t const { ensureSignerAndRelayerAccount } = this.deps;\n\n try {\n await ensureSignerAndRelayerAccount();\n } catch (e: any) {\n const msg = e?.message || 'Failed to initialize relayer account';\n return { success: false, error: msg, message: msg };\n }\n\n\t const { actions, receiverId } = await buildOnchainEmailRecoveryActions(this.deps, {\n\t accountId,\n\t emailBlob,\n\t });\n\n\t return sendEmailRecoveryTransaction(this.deps, {\n\t receiverId,\n\t actions,\n\t label: `On-chain email verification requested for ${accountId}`,\n\t });\n }\n\n /**\n * Helper for zk-email recovery:\n * - Calls external zk-email prover with the raw email blob to obtain (proof, publicInputs).\n * - Extracts subject/header bindings (account_id, new_public_key, from_email, timestamp).\n * - Calls the per-account EmailRecoverer contract with verify_zkemail_and_recover.\n */\n\t async verifyZkemailAndRecover(request: EmailRecoveryRequest): Promise<EmailRecoveryResult> {\n\t const accountId = (request.accountId || '').trim();\n\t const emailBlob = request.emailBlob;\n\n if (!accountId) {\n return {\n success: false,\n error: 'zkemail_missing_account_id',\n message: 'accountId is required',\n };\n }\n if (!emailBlob || typeof emailBlob !== 'string') {\n return {\n success: false,\n error: 'zkemail_missing_email_blob',\n message: 'emailBlob (raw email) is required',\n };\n }\n\n\t const { ensureSignerAndRelayerAccount, zkEmailProver } = this.deps;\n\n if (!zkEmailProver || !zkEmailProver.baseUrl) {\n this.logger.warn('[email-recovery] zk-email missing prover configuration', { accountId });\n return {\n success: false,\n error: 'zkemail_prover_not_configured',\n message: 'zk-email prover configuration is missing',\n };\n }\n\n const prepared = prepareZkEmailRecovery(emailBlob, accountId);\n if (!prepared.ok) {\n const log = {\n accountId,\n requestId: prepared.requestId,\n proverBaseUrl: zkEmailProver.baseUrl,\n errorCode: prepared.errorCode,\n errorMessage: prepared.message,\n accountIdSubject: prepared.subjectAccountId,\n };\n if (prepared.errorCode === 'zkemail_account_mismatch') {\n this.logger.warn('[email-recovery] zk-email account mismatch', log);\n } else {\n this.logger.warn('[email-recovery] zk-email recovery rejected', log);\n }\n return { success: false, error: prepared.errorCode, message: prepared.message };\n }\n\n const { payload, bindings } = prepared.prepared;\n\n try {\n await ensureSignerAndRelayerAccount();\n } catch (e: any) {\n const msg = e?.message || 'Failed to initialize relayer account';\n this.logger.error('[email-recovery] zk-email ensureSignerAndRelayerAccount failed', {\n accountId,\n requestId: bindings.requestId,\n error: msg,\n });\n return { success: false, error: 'zkemail_relayer_init_failed', message: msg };\n }\n\n\t try {\n\t const proverClient = this.getZkEmailProverClient(zkEmailProver);\n\t const proofResult = await generateZkEmailProofFromPayload(payload, proverClient);\n\n\t const contractArgs = {\n\t proof: proofResult.proof,\n\t public_inputs: proofResult.publicInputs,\n\t account_id: bindings.accountId,\n\t new_public_key: bindings.newPublicKey,\n\t from_email: bindings.fromEmail,\n\t timestamp: bindings.timestamp,\n\t };\n\n\t const { actions, receiverId } = await buildZkEmailRecoveryActions(this.deps, {\n\t accountId,\n\t contractArgs,\n\t });\n\n\t return sendEmailRecoveryTransaction(this.deps, {\n\t receiverId,\n\t actions,\n\t label: `ZK-email recovery requested for ${accountId}`,\n\t });\n\t\t } catch (error: any) {\n const mapped = mapZkEmailRecoveryError(error);\n\n\t\t this.logger.error('[email-recovery] zk-email recovery error', {\n\t\t accountId,\n\t requestId: bindings.requestId,\n\t\t errorCode: mapped.errorCode,\n\t\t errorMessage: mapped.message,\n\t proverBaseUrl: zkEmailProver.baseUrl,\n\t proverCauseCode: mapped.proverCauseCode,\n\t proverCauseMessage: mapped.proverCauseMessage,\n\t\t });\n\n\t return {\n\t success: false,\n\t error: mapped.errorCode,\n\t message: mapped.message,\n\t };\n\t }\n\t }\n\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ActionType, validateActionArgsWasm } from "../sdk/src/core/types/actions.js";
|
|
2
2
|
import { parseContractExecutionError } from "../core/errors.js";
|
|
3
|
+
import { parseHeaderValue, parseRecoverSubjectBindings } from "./emailParsers.js";
|
|
4
|
+
import { hashRecoveryEmailForAccount } from "./emailEncryptor.js";
|
|
3
5
|
|
|
4
6
|
//#region src/server/email-recovery/rpcCalls.ts
|
|
5
7
|
async function getOutlayerEncryptionPublicKey(deps) {
|
|
@@ -33,9 +35,20 @@ async function buildEncryptedEmailRecoveryActions(deps, input) {
|
|
|
33
35
|
aeadContext,
|
|
34
36
|
recipientPk
|
|
35
37
|
});
|
|
38
|
+
const bindings = parseRecoverSubjectBindings(emailBlob);
|
|
39
|
+
if (!bindings) throw new Error("Encrypted email recovery requires Subject: recover-<request_id> <accountId> ed25519:<new_public_key>");
|
|
40
|
+
if (bindings.accountId !== accountId) throw new Error(`Encrypted email recovery subject accountId mismatch (expected "${accountId}", got "${bindings.accountId}")`);
|
|
41
|
+
const fromHeader = parseHeaderValue(emailBlob, "from");
|
|
42
|
+
if (!fromHeader) throw new Error("Encrypted email recovery requires a From: header");
|
|
43
|
+
const expectedHashedEmail = hashRecoveryEmailForAccount({
|
|
44
|
+
recoveryEmail: fromHeader,
|
|
45
|
+
accountId
|
|
46
|
+
});
|
|
36
47
|
const contractArgs = {
|
|
37
48
|
encrypted_email_blob: envelope,
|
|
38
|
-
aead_context: aeadContext
|
|
49
|
+
aead_context: aeadContext,
|
|
50
|
+
expected_hashed_email: expectedHashedEmail,
|
|
51
|
+
expected_new_public_key: bindings.newPublicKey
|
|
39
52
|
};
|
|
40
53
|
const actions = [{
|
|
41
54
|
action_type: ActionType.FunctionCall,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpcCalls.js","names":["bytes: Uint8Array","aeadContext: EmailEncryptionContext","actions: ActionArgsWasm[]","error: any"],"sources":["../../../../src/server/email-recovery/rpcCalls.ts"],"sourcesContent":["import type { ActionArgsWasm } from '../../core/types/actions';\nimport { ActionType, validateActionArgsWasm } from '../../core/types/actions';\nimport { parseContractExecutionError } from '../core/errors';\nimport type
|
|
1
|
+
{"version":3,"file":"rpcCalls.js","names":["bytes: Uint8Array","aeadContext: EmailEncryptionContext","actions: ActionArgsWasm[]","error: any"],"sources":["../../../../src/server/email-recovery/rpcCalls.ts"],"sourcesContent":["import type { ActionArgsWasm } from '../../core/types/actions';\nimport { ActionType, validateActionArgsWasm } from '../../core/types/actions';\nimport { parseContractExecutionError } from '../core/errors';\nimport { hashRecoveryEmailForAccount, type EmailEncryptionContext } from './emailEncryptor';\nimport { parseHeaderValue, parseRecoverSubjectBindings } from './emailParsers';\nimport type { EmailRecoveryResult, EmailRecoveryServiceDeps, EmailRecoveryRequest } from './types';\n\nexport async function getOutlayerEncryptionPublicKey(\n deps: Pick<EmailRecoveryServiceDeps, 'nearClient' | 'emailDkimVerifierContract'>,\n): Promise<Uint8Array> {\n const { nearClient, emailDkimVerifierContract } = deps;\n\n const result = await nearClient.view<{}, unknown>({\n account: emailDkimVerifierContract,\n method: 'get_outlayer_encryption_public_key',\n args: {},\n });\n\n if (typeof result !== 'string' || !result) {\n throw new Error('Outlayer encryption public key is not configured on EmailDkimVerifier');\n }\n\n let bytes: Uint8Array;\n try {\n const decoded = typeof Buffer !== 'undefined'\n ? Buffer.from(result, 'base64')\n : Uint8Array.from(atob(result), c => c.charCodeAt(0));\n bytes = decoded instanceof Uint8Array ? decoded : new Uint8Array(decoded);\n } catch (e) {\n throw new Error(`Failed to decode Outlayer email DKIM public key: ${(e as Error).message}`);\n }\n\n if (bytes.length !== 32) {\n throw new Error(`Outlayer email DKIM public key must be 32 bytes, got ${bytes.length}`);\n }\n\n return bytes;\n}\n\nexport async function buildEncryptedEmailRecoveryActions(\n deps: EmailRecoveryServiceDeps,\n input: {\n accountId: string;\n emailBlob: string;\n recipientPk: Uint8Array;\n encrypt: (args: {\n emailRaw: string;\n aeadContext: EmailEncryptionContext;\n recipientPk: Uint8Array;\n }) => Promise<{ envelope: { version: number; ephemeral_pub: string; nonce: string; ciphertext: string } }>;\n },\n): Promise<{ actions: ActionArgsWasm[]; receiverId: string }> {\n const {\n relayerAccountId,\n networkId,\n } = deps;\n const { accountId, emailBlob, recipientPk, encrypt } = input;\n\n const aeadContext: EmailEncryptionContext = {\n account_id: accountId,\n network_id: networkId,\n payer_account_id: relayerAccountId,\n };\n\n const { envelope } = await encrypt({\n emailRaw: emailBlob,\n aeadContext,\n recipientPk,\n });\n\n const bindings = parseRecoverSubjectBindings(emailBlob);\n if (!bindings) {\n throw new Error('Encrypted email recovery requires Subject: recover-<request_id> <accountId> ed25519:<new_public_key>');\n }\n if (bindings.accountId !== accountId) {\n throw new Error(`Encrypted email recovery subject accountId mismatch (expected \"${accountId}\", got \"${bindings.accountId}\")`);\n }\n\n const fromHeader = parseHeaderValue(emailBlob, 'from');\n if (!fromHeader) {\n throw new Error('Encrypted email recovery requires a From: header');\n }\n const expectedHashedEmail = hashRecoveryEmailForAccount({ recoveryEmail: fromHeader, accountId });\n\n const contractArgs = {\n encrypted_email_blob: envelope,\n aead_context: aeadContext,\n expected_hashed_email: expectedHashedEmail,\n expected_new_public_key: bindings.newPublicKey,\n };\n\n const actions: ActionArgsWasm[] = [\n {\n action_type: ActionType.FunctionCall,\n method_name: 'verify_encrypted_email_and_recover',\n args: JSON.stringify(contractArgs),\n gas: '300000000000000',\n deposit: '10000000000000000000000',\n },\n ];\n actions.forEach(validateActionArgsWasm);\n\n return {\n actions,\n receiverId: accountId,\n };\n}\n\nexport async function buildZkEmailRecoveryActions(\n deps: EmailRecoveryServiceDeps,\n input: {\n accountId: string;\n contractArgs: {\n proof: unknown;\n public_inputs: string[];\n account_id: string;\n new_public_key: string;\n from_email: string;\n timestamp: string;\n };\n },\n): Promise<{ actions: ActionArgsWasm[]; receiverId: string }> {\n const { accountId, contractArgs } = input;\n\n const actions: ActionArgsWasm[] = [\n {\n action_type: ActionType.FunctionCall,\n method_name: 'verify_zkemail_and_recover',\n args: JSON.stringify(contractArgs),\n gas: '300000000000000',\n deposit: '10000000000000000000000',\n },\n ];\n actions.forEach(validateActionArgsWasm);\n\n return {\n actions,\n receiverId: accountId,\n };\n}\n\nexport async function buildOnchainEmailRecoveryActions(\n _deps: EmailRecoveryServiceDeps,\n input: { accountId: string; emailBlob: string },\n): Promise<{ actions: ActionArgsWasm[]; receiverId: string }> {\n const { accountId, emailBlob } = input;\n\n const actions: ActionArgsWasm[] = [\n {\n action_type: ActionType.FunctionCall,\n method_name: 'verify_email_onchain_and_recover',\n args: JSON.stringify({\n email_blob: emailBlob,\n }),\n gas: '300000000000000',\n deposit: '10000000000000000000000',\n },\n ];\n actions.forEach(validateActionArgsWasm);\n\n return {\n actions,\n receiverId: accountId,\n };\n}\n\nexport async function sendEmailRecoveryTransaction(\n deps: EmailRecoveryServiceDeps,\n args: {\n receiverId: string;\n actions: ActionArgsWasm[];\n label: string;\n },\n): Promise<EmailRecoveryResult> {\n const {\n relayerAccountId,\n relayerPrivateKey,\n nearClient,\n queueTransaction,\n fetchTxContext,\n signWithPrivateKey,\n getRelayerPublicKey,\n } = deps;\n\n const { receiverId, actions, label } = args;\n\n return queueTransaction(async () => {\n try {\n const relayerPublicKey = getRelayerPublicKey();\n const { nextNonce, blockHash } = await fetchTxContext(relayerAccountId, relayerPublicKey);\n\n const signed = await signWithPrivateKey({\n nearPrivateKey: relayerPrivateKey,\n signerAccountId: relayerAccountId,\n receiverId,\n nonce: nextNonce,\n blockHash,\n actions,\n });\n\n const result = await nearClient.sendTransaction(signed);\n\n const contractError = parseContractExecutionError(result, receiverId);\n if (contractError) {\n return {\n success: false,\n error: contractError,\n message: contractError,\n };\n }\n\n return {\n success: true,\n transactionHash: result.transaction.hash,\n message: label,\n };\n } catch (error: any) {\n const msg = error?.message || 'Unknown email recovery error';\n return {\n success: false,\n error: msg,\n message: msg,\n };\n }\n }, args.label);\n}\n"],"mappings":"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"}
|
package/dist/esm/server/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AUTH_SERVICE_CONFIG_DEFAULTS, createAuthServiceConfig, parseBool, requireEnvVar, validateConfigs } from "./core/config.js";
|
|
2
2
|
import { ZkEmailProverClient } from "./email-recovery/zkEmail/proverClient.js";
|
|
3
3
|
import { buildForwardablePayloadFromRawEmail, extractZkEmailBindingsFromPayload, generateZkEmailProofFromPayload, normalizeForwardableEmailPayload, parseAccountIdFromSubject } from "./email-recovery/zkEmail/index.js";
|
|
4
|
-
import { deriveOutlayerStaticKeyFromSeedHex, encryptEmailForOutlayer } from "./email-recovery/emailEncryptor.js";
|
|
4
|
+
import { deriveOutlayerStaticKeyFromSeedHex, encryptEmailForOutlayer, hashRecoveryEmailForAccount } from "./email-recovery/emailEncryptor.js";
|
|
5
5
|
import { mapZkEmailRecoveryError, prepareZkEmailRecovery } from "./email-recovery/zkEmail/recovery.js";
|
|
6
6
|
import { decryptEmailForOutlayerTestOnly, deriveTestX25519KeypairFromSeed } from "./email-recovery/testHelpers.js";
|
|
7
7
|
import { EmailRecoveryService } from "./email-recovery/index.js";
|
|
@@ -12,4 +12,4 @@ import { SessionService, buildCorsOrigins, parseCsvList } from "./core/SessionSe
|
|
|
12
12
|
import { handleVerifyAuthenticationResponse, verifyAuthenticationMiddleware } from "./core/verifyAuthenticationHandler.js";
|
|
13
13
|
import { handleAddGraceKey, handleApplyServerLock, handleGetShamirKeyInfo, handleListGraceKeys, handleRemoveGraceKey, handleRemoveServerLock } from "./core/shamirHandlers.js";
|
|
14
14
|
|
|
15
|
-
export { AUTH_SERVICE_CONFIG_DEFAULTS, AuthService, EmailRecoveryService, SHAMIR_P_B64U, SessionService, Shamir3PassUtils, ShamirService, ZkEmailProverClient, buildCorsOrigins, buildForwardablePayloadFromRawEmail, createAuthServiceConfig, decryptEmailForOutlayerTestOnly, deriveOutlayerStaticKeyFromSeedHex, deriveTestX25519KeypairFromSeed, encryptEmailForOutlayer, extractZkEmailBindingsFromPayload, generateZkEmailProofFromPayload, getShamirPB64uFromWasm, handleAddGraceKey, handleApplyServerLock, handleGetShamirKeyInfo, handleListGraceKeys, handleRemoveGraceKey, handleRemoveServerLock, handleVerifyAuthenticationResponse, mapZkEmailRecoveryError, normalizeForwardableEmailPayload, parseAccountIdFromSubject, parseBool, parseCsvList, prepareZkEmailRecovery, requireEnvVar, validateConfigs, verifyAuthenticationMiddleware };
|
|
15
|
+
export { AUTH_SERVICE_CONFIG_DEFAULTS, AuthService, EmailRecoveryService, SHAMIR_P_B64U, SessionService, Shamir3PassUtils, ShamirService, ZkEmailProverClient, buildCorsOrigins, buildForwardablePayloadFromRawEmail, createAuthServiceConfig, decryptEmailForOutlayerTestOnly, deriveOutlayerStaticKeyFromSeedHex, deriveTestX25519KeypairFromSeed, encryptEmailForOutlayer, extractZkEmailBindingsFromPayload, generateZkEmailProofFromPayload, getShamirPB64uFromWasm, handleAddGraceKey, handleApplyServerLock, handleGetShamirKeyInfo, handleListGraceKeys, handleRemoveGraceKey, handleRemoveServerLock, handleVerifyAuthenticationResponse, hashRecoveryEmailForAccount, mapZkEmailRecoveryError, normalizeForwardableEmailPayload, parseAccountIdFromSubject, parseBool, parseCsvList, prepareZkEmailRecovery, requireEnvVar, validateConfigs, verifyAuthenticationMiddleware };
|