@tatchi-xyz/sdk 0.16.0 → 0.18.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/emailRecoveryPendingStore.js +69 -0
- package/dist/cjs/core/EmailRecovery/emailRecoveryPendingStore.js.map +1 -0
- package/dist/cjs/core/EmailRecovery/index.js +32 -13
- 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 +557 -377
- 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 +26 -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/relay.js +23 -1
- package/dist/cjs/core/TatchiPasskey/relay.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 +3 -0
- package/dist/cjs/core/WalletIframe/client/IframeTransport.js.map +1 -1
- package/dist/cjs/core/WalletIframe/client/router.js +15 -2
- 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/rpcCalls.js +8 -0
- package/dist/cjs/core/rpcCalls.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/index.js +6 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-STvIsylA.css → LinkedDevicesModal-CSSowiHP.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-STvIsylA.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-iARgUwK1.css → ProfileDropdown-CEPMZ1gY.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-iARgUwK1.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css → Web3AuthProfileButton-DopOg7Xc.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css.map → Web3AuthProfileButton-DopOg7Xc.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css → TouchIcon-BQWentvJ.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css.map → TouchIcon-BQWentvJ.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css → PasskeyAuthMenu-DwrzWMYx.css} +14 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css.map → PasskeyAuthMenu-DwrzWMYx.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-CCN4h6Uv.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-DCnR__fx.css.map → ShowQRCode-CCN4h6Uv.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/useQRCamera.js +1 -0
- package/dist/cjs/react/hooks/useQRCamera.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/EmailRecovery/emailRecoveryPendingStore.js +69 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/emailRecoveryPendingStore.js.map +1 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +32 -13
- 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 +557 -377
- 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 +26 -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/relay.js +23 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/relay.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 +3 -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 +15 -2
- 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/rpcCalls.js +8 -0
- package/dist/cjs/react/sdk/src/core/rpcCalls.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/emailRecoveryPendingStore.js +63 -0
- package/dist/esm/core/EmailRecovery/emailRecoveryPendingStore.js.map +1 -0
- package/dist/esm/core/EmailRecovery/index.js +28 -14
- 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 +557 -377
- 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 +28 -2
- 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/relay.js +23 -1
- package/dist/esm/core/TatchiPasskey/relay.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 +4 -1
- package/dist/esm/core/WalletIframe/client/IframeTransport.js.map +1 -1
- package/dist/esm/core/WalletIframe/client/router.js +16 -3
- 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/rpcCalls.js +8 -1
- package/dist/esm/core/rpcCalls.js.map +1 -1
- package/dist/esm/core/types/vrf-worker.js +6 -2
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-STvIsylA.css → LinkedDevicesModal-CSSowiHP.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-STvIsylA.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-iARgUwK1.css → ProfileDropdown-CEPMZ1gY.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-iARgUwK1.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css → Web3AuthProfileButton-DopOg7Xc.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css.map → Web3AuthProfileButton-DopOg7Xc.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css → TouchIcon-BQWentvJ.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css.map → TouchIcon-BQWentvJ.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css → PasskeyAuthMenu-DwrzWMYx.css} +14 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css.map → PasskeyAuthMenu-DwrzWMYx.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-CCN4h6Uv.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-DCnR__fx.css.map → ShowQRCode-CCN4h6Uv.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/useQRCamera.js +2 -1
- package/dist/esm/react/hooks/useQRCamera.js.map +1 -1
- package/dist/esm/react/sdk/src/core/EmailRecovery/emailRecoveryPendingStore.js +63 -0
- package/dist/esm/react/sdk/src/core/EmailRecovery/emailRecoveryPendingStore.js.map +1 -0
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +28 -14
- 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 +557 -377
- 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 +28 -2
- 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/relay.js +23 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/relay.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 +4 -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 +16 -3
- 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/rpcCalls.js +8 -1
- package/dist/esm/react/sdk/src/core/rpcCalls.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-DuGYOd3G.js} +19 -4
- package/dist/esm/sdk/{rpcCalls-fLObBbbz.js → rpcCalls-BQrJMTdg.js} +3 -3
- package/dist/esm/sdk/{rpcCalls-CAU5XYEF.js → rpcCalls-YVeUVMk2.js} +9 -2
- 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 +782 -447
- 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/emailRecoveryPendingStore.d.ts +25 -0
- package/dist/types/src/core/EmailRecovery/emailRecoveryPendingStore.d.ts.map +1 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts +1 -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 +45 -5
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/index.d.ts +10 -2
- package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/relay.d.ts +2 -1
- package/dist/types/src/core/TatchiPasskey/relay.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/router.d.ts +7 -3
- 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/core/rpcCalls.d.ts +9 -0
- package/dist/types/src/core/rpcCalls.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passkeyClientDB.js","names":["DB_CONFIG: PasskeyClientDBConfig","err: any","entry: AppStateEntry<T>","wrongPasskeyError: string | undefined","userData: ClientUserData","lastUserState: LastUserAccountIdState","fixed: ClientUserData","clientAuth: ClientAuthenticatorData","rec: DerivedAddressRecord","rec: RecoveryEmailRecord"],"sources":["../../../../../../../src/core/IndexedDBManager/passkeyClientDB.ts"],"sourcesContent":["import { openDB, type IDBPDatabase } from 'idb';\nimport { type ValidationResult, validateNearAccountId } from '../../utils/validation';\nimport type { AccountId } from '../types/accountIds';\nimport { toAccountId } from '../types/accountIds';\nimport { ConfirmationConfig, DEFAULT_CONFIRMATION_CONFIG } from '../types/signer-worker'\n\n\nexport interface ClientUserData {\n // Primary key - now uses AccountId + deviceNumber for unique identification\n nearAccountId: AccountId;\n deviceNumber: number; // Device number for multi-device support (1-indexed)\n version?: number;\n\n // User metadata\n registeredAt?: number;\n lastLogin?: number;\n lastUpdated?: number;\n\n // WebAuthn/Passkey data (merged from WebAuthnManager)\n clientNearPublicKey: string;\n passkeyCredential: {\n id: string;\n rawId: string;\n };\n\n // VRF credentials for stateless authentication\n encryptedVrfKeypair: {\n encryptedVrfDataB64u: string;\n chacha20NonceB64u: string;\n };\n // Server-assisted auto-login (VRF key session): Shamir 3-pass fields\n // Stores relayer-blinded KEK and the VRF ciphertext; server never sees plaintext VRF or KEK\n serverEncryptedVrfKeypair?: {\n ciphertextVrfB64u: string;\n kek_s_b64u: string;\n // Metadata for proactive refresh\n serverKeyId: string;\n updatedAt?: number;\n };\n\n // User preferences\n preferences?: UserPreferences;\n}\n\nexport type StoreUserDataInput = Omit<ClientUserData, 'deviceNumber' | 'lastLogin' | 'registeredAt'>\n & {\n deviceNumber?: number;\n serverEncryptedVrfKeypair?: ClientUserData['serverEncryptedVrfKeypair'];\n version?: number;\n };\n\nexport interface UserPreferences {\n useRelayer: boolean;\n useNetwork: 'testnet' | 'mainnet';\n confirmationConfig: ConfirmationConfig;\n // User preferences can be extended here as needed\n}\n\n// Authenticator cache\nexport interface ClientAuthenticatorData {\n credentialId: string;\n credentialPublicKey: Uint8Array;\n transports?: string[]; // AuthenticatorTransport[]\n name?: string;\n nearAccountId: AccountId; // FK reference using AccountId\n deviceNumber: number; // Device number for this authenticator (1-indexed)\n registered: string; // ISO date string\n syncedAt: string; // When this cache entry was last synced with contract\n vrfPublicKey: string; // Base64-encoded VRF public key (1:1 relationship on client)\n}\n\ninterface AppStateEntry<T = unknown> {\n key: string;\n value: T;\n}\n\n// Internal helper: legacy user records may be missing deviceNumber.\ntype ClientUserDataWithOptionalDevice =\n | ClientUserData\n | (Omit<ClientUserData, 'deviceNumber'> & { deviceNumber?: number });\n\n// Special type for lastUserAccountId app state entry\nexport interface LastUserAccountIdState {\n accountId: AccountId;\n deviceNumber: number;\n}\n\ninterface PasskeyClientDBConfig {\n dbName: string;\n dbVersion: number;\n userStore: string;\n appStateStore: string;\n authenticatorStore: string;\n derivedAddressStore: string;\n recoveryEmailStore: string;\n}\n\n// === CONSTANTS ===\nconst DB_CONFIG: PasskeyClientDBConfig = {\n dbName: 'PasskeyClientDB',\n dbVersion: 15, // v15: add recoveryEmails store\n userStore: 'users',\n appStateStore: 'appState',\n authenticatorStore: 'authenticators',\n derivedAddressStore: 'derivedAddresses',\n recoveryEmailStore: 'recoveryEmails'\n} as const;\n\nexport interface IndexedDBEvent {\n type: 'user-updated' | 'preferences-updated' | 'user-deleted';\n accountId: AccountId;\n data?: Record<string, unknown>;\n}\n\n// Persisted mapping of derived (e.g., EVM) addresses tied to an account\n/**\n * Persisted mapping of derived (e.g., EVM/Solana/Zcash) addresses tied to an account.\n *\n * Notes on multi-chain support:\n * - The composite primary key is [nearAccountId, contractId, path]. To support\n * different chains and chain IDs, encode them in the `path` string, e.g.:\n * - EVM: `evm:<chainId>:<derivationPath>` → `evm:84532:ethereum-1`\n * - Solana: `solana:<derivationPath>`\n * - Zcash: `zcash:<derivationPath>`\n * - Additional descriptive fields like `namespace` and `chainRef` are optional metadata\n * and are not part of the key.\n */\nexport interface DerivedAddressRecord {\n nearAccountId: AccountId;\n contractId: string; // MPC/Derivation contract on NEAR\n path: string; // Composite path (may include namespace/chainId); see docs above\n address: string; // Derived address (e.g., 0x...)\n updatedAt: number;\n // Optional metadata (not used in the key)\n namespace?: string; // e.g., 'evm', 'solana', 'zcash'\n chainRef?: string; // e.g., chainId '84532' or a named network slug\n}\n\n/**\n * Persisted mapping of recovery email hashes to canonical email addresses for an account.\n *\n * Notes:\n * - Composite primary key is [nearAccountId, hashHex].\n * - `hashHex` is the 0x-prefixed hex encoding of the 32-byte hash:\n * SHA256(canonical_email || \"|\" || account_id)\n * - `email` is the canonical form: \"local@domain\", lowercased.\n */\nexport interface RecoveryEmailRecord {\n nearAccountId: AccountId;\n hashHex: string;\n email: string;\n addedAt: number;\n}\n\nexport class PasskeyClientDBManager {\n private config: PasskeyClientDBConfig;\n private db: IDBPDatabase | null = null;\n private disabled = false;\n private eventListeners: Set<(event: IndexedDBEvent) => void> = new Set();\n\n constructor(config: PasskeyClientDBConfig = DB_CONFIG) {\n this.config = config;\n }\n\n getDbName(): string {\n return this.config.dbName;\n }\n\n setDbName(dbName: string): void {\n const next = String(dbName || '').trim();\n if (!next || next === this.config.dbName) return;\n try { (this.db as any)?.close?.(); } catch {}\n this.db = null;\n this.config = { ...this.config, dbName: next };\n }\n\n isDisabled(): boolean {\n return this.disabled;\n }\n\n setDisabled(disabled: boolean): void {\n const next = !!disabled;\n if (next === this.disabled) return;\n this.disabled = next;\n if (next) {\n try { (this.db as any)?.close?.(); } catch {}\n this.db = null;\n }\n }\n\n // === EVENT SYSTEM ===\n\n onChange(listener: (event: IndexedDBEvent) => void): () => void {\n this.eventListeners.add(listener);\n return () => {\n this.eventListeners.delete(listener);\n };\n }\n\n private emitEvent(event: IndexedDBEvent): void {\n this.eventListeners.forEach(listener => {\n try {\n listener(event);\n } catch (error) {\n console.warn('[IndexedDBManager]: Error in event listener:', error);\n }\n });\n }\n\n private async getDB(): Promise<IDBPDatabase> {\n if (this.disabled) {\n throw new Error('[PasskeyClientDBManager] IndexedDB is disabled in this environment.');\n }\n if (this.db) {\n return this.db;\n }\n\n try {\n this.db = await openDB(this.config.dbName, this.config.dbVersion, {\n upgrade: (db, oldVersion, _newVersion, _transaction): void => {\n // Create stores if they don't exist\n if (!db.objectStoreNames.contains(DB_CONFIG.userStore)) {\n // Users table: composite key of [nearAccountId, deviceNumber]\n const userStore = db.createObjectStore(DB_CONFIG.userStore, { keyPath: ['nearAccountId', 'deviceNumber'] });\n userStore.createIndex('nearAccountId', 'nearAccountId', { unique: false });\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.appStateStore)) {\n db.createObjectStore(DB_CONFIG.appStateStore, { keyPath: 'key' });\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.authenticatorStore)) {\n // Authenticators table: composite key of [nearAccountId, deviceNumber, credentialId]\n const authStore = db.createObjectStore(DB_CONFIG.authenticatorStore, { keyPath: ['nearAccountId', 'deviceNumber', 'credentialId'] });\n authStore.createIndex('nearAccountId', 'nearAccountId', { unique: false });\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.derivedAddressStore)) {\n // Derived addresses: composite key of [nearAccountId, contractId, path]\n const dStore = db.createObjectStore(DB_CONFIG.derivedAddressStore, { keyPath: ['nearAccountId', 'contractId', 'path'] });\n try { dStore.createIndex('nearAccountId', 'nearAccountId', { unique: false }); } catch {}\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.recoveryEmailStore)) {\n // Recovery emails: composite key of [nearAccountId, hashHex]\n const rStore = db.createObjectStore(DB_CONFIG.recoveryEmailStore, { keyPath: ['nearAccountId', 'hashHex'] });\n try { rStore.createIndex('nearAccountId', 'nearAccountId', { unique: false }); } catch {}\n }\n },\n blocked() {\n console.warn('PasskeyClientDB connection is blocked.');\n },\n blocking() {\n console.warn('PasskeyClientDB connection is blocking another connection.');\n },\n terminated: () => {\n console.warn('PasskeyClientDB connection has been terminated.');\n this.db = null;\n },\n });\n\n // Post-open migrations (non-blocking)\n try { await this.runMigrationsIfNeeded(this.db); } catch {}\n\n } catch (err: any) {\n const msg = String(err?.message || '');\n if (err?.name === 'VersionError' || /less than the existing version/i.test(msg)) {\n // Mixed-version contexts (host/app) — open without version to adopt existing DB\n try {\n console.warn('PasskeyClientDB: opening existing DB without version due to VersionError');\n this.db = await openDB(this.config.dbName);\n } catch (e) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n\n return this.db;\n }\n\n private async runMigrationsIfNeeded(_db: IDBPDatabase): Promise<void> {\n return;\n }\n\n // === APP STATE METHODS ===\n\n async getAppState<T = unknown>(key: string): Promise<T | undefined> {\n const db = await this.getDB();\n const result = await db.get(DB_CONFIG.appStateStore, key);\n return result?.value as T | undefined;\n }\n\n async setAppState<T = unknown>(key: string, value: T): Promise<void> {\n const db = await this.getDB();\n const entry: AppStateEntry<T> = { key, value };\n await db.put(DB_CONFIG.appStateStore, entry);\n }\n\n // === ACCOUNT ID VALIDATION AND UTILITIES ===\n\n /**\n * Validate that a NEAR account ID is in the expected format\n * Supports both <username>.<relayerAccountId> and <username>.testnet formats\n */\n validateNearAccountId(nearAccountId: AccountId): ValidationResult {\n return validateNearAccountId(nearAccountId);\n }\n\n /**\n * Extract username from NEAR account ID\n */\n extractUsername(nearAccountId: AccountId): string {\n const validation = validateNearAccountId(nearAccountId);\n if (!validation.valid) {\n throw new Error(`Invalid NEAR account ID: ${validation.error}`);\n }\n return nearAccountId.split('.')[0];\n }\n\n /**\n * Generate a NEAR account ID from a username and domain\n * @param username - The username to use for the account ID\n * @param domain - The domain to use for the account ID\n * @returns The generated NEAR account ID\n */\n generateNearAccountId(username: string, domain: string): string {\n const sanitizedName = username\n .toLowerCase()\n .replace(/[^a-z0-9_\\\\-]/g, '')\n .substring(0, 32);\n return `${sanitizedName}.${domain}`;\n }\n\n // === USER MANAGEMENT METHODS ===\n\n async getUser(nearAccountId: AccountId, deviceNumber?: number): Promise<ClientUserData | null> {\n if (!nearAccountId) return null;\n\n const validation = this.validateNearAccountId(nearAccountId);\n if (!validation.valid) {\n console.warn(`Invalid account ID format: ${nearAccountId}`);\n return null;\n }\n\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n\n if (typeof deviceNumber === 'number') {\n const rec = await db.get(DB_CONFIG.userStore, [accountId, deviceNumber]);\n if (!rec) return null;\n return await this.normalizeUserDeviceNumber(rec as ClientUserDataWithOptionalDevice, deviceNumber);\n }\n\n const index = db.transaction(DB_CONFIG.userStore).store.index('nearAccountId');\n const results = await index.getAll(accountId);\n if (results.length === 0) {\n return null;\n }\n\n if (results.length > 1) {\n console.warn(\n `Multiple passkeys found for account ${accountId}, deviceNumber not provided; ` +\n 'defaulting to last logged-in user.'\n );\n console.log('defaulting to last used user deviceNumber');\n const lastUserState = await this.getAppState<LastUserAccountIdState>('lastUserAccountId').catch(() => null);\n if (lastUserState && toAccountId(lastUserState.accountId) === accountId) {\n const keyed = await db.get(DB_CONFIG.userStore, [accountId, lastUserState.deviceNumber]);\n if (keyed) {\n return await this.normalizeUserDeviceNumber(\n keyed as ClientUserDataWithOptionalDevice,\n lastUserState.deviceNumber\n );\n }\n }\n }\n\n const first = results[0] as ClientUserDataWithOptionalDevice;\n if (!first) return null;\n return await this.normalizeUserDeviceNumber(first, 1);\n }\n\n /**\n * Get the current/last user\n * This is maintained via app state and updated whenever a user is stored or updated\n */\n async getLastUser(): Promise<ClientUserData | null> {\n const lastUserState = await this.getAppState<LastUserAccountIdState>('lastUserAccountId');\n if (!lastUserState) return null;\n const db = await this.getDB();\n const accountId = toAccountId(lastUserState.accountId);\n // Prefer exact device match using composite primary key\n const record = await db.get(DB_CONFIG.userStore, [accountId, lastUserState.deviceNumber]);\n if (record) return record as ClientUserData;\n // Fallback: return any user for account\n return this.getUser(accountId);\n }\n\n /** Get user record by composite key (nearAccountId, deviceNumber) */\n async getUserByDevice(nearAccountId: AccountId, deviceNumber: number): Promise<ClientUserData | null> {\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n const rec = await db.get(DB_CONFIG.userStore, [accountId, deviceNumber]);\n return rec as ClientUserData || null;\n }\n\n /**\n * Get the most recently updated user record for a given account.\n * Useful when deviceNumber is unknown but we need the freshest key for the account.\n */\n /**\n * Get the most recently updated user record for a given account.\n * Useful when deviceNumber is unknown but we need the freshest key for the account.\n */\n async getLastDBUpdatedUser(nearAccountId: AccountId): Promise<ClientUserData | null> {\n const db = await this.getDB();\n try {\n const idx = db.transaction(DB_CONFIG.userStore).store.index('nearAccountId');\n const all = await idx.getAll(toAccountId(nearAccountId));\n if (Array.isArray(all) && all.length > 0) {\n const latest = (all as ClientUserData[]).reduce((a, b) =>\n (a.lastUpdated ?? 0) >= (b.lastUpdated ?? 0) ? a : b\n );\n return latest;\n }\n } catch {\n // fall through\n }\n return null;\n }\n\n async hasPasskeyCredential(nearAccountId: AccountId): Promise<boolean> {\n const authenticators = await this.getAuthenticatorsByUser(nearAccountId);\n return !!authenticators[0]?.credentialId;\n }\n\n /**\n * Ensure the current passkey selection is aligned with the last logged-in device.\n *\n * - When multiple authenticators exist for an account and no deviceNumber is specified,\n * this helper prefers authenticators whose deviceNumber matches the last logged-in user.\n * - Optionally validates that a selected credential (by rawId) also matches the last-user device.\n *\n * @param nearAccountId - Account ID for which the operation is being performed\n * @param authenticators - All authenticators stored for the account\n * @param selectedCredentialRawId - Optional rawId of the credential chosen by WebAuthn\n * @returns filtered authenticators for allowCredentials, plus optional wrongPasskeyError\n */\n async ensureCurrentPasskey(\n nearAccountId: AccountId,\n authenticators: ClientAuthenticatorData[],\n selectedCredentialRawId?: string,\n ): Promise<{\n authenticatorsForPrompt: ClientAuthenticatorData[];\n wrongPasskeyError?: string;\n }> {\n let authenticatorsForPrompt = authenticators;\n let wrongPasskeyError: string | undefined;\n\n if (authenticators.length > 1) {\n const accountIdNormalized = toAccountId(nearAccountId);\n const lastUser = await this.getLastUser().catch(() => null);\n const expectedAccountId = lastUser?.nearAccountId;\n const expectedDeviceNumber = lastUser?.deviceNumber;\n\n if (\n expectedAccountId &&\n expectedDeviceNumber &&\n expectedAccountId === accountIdNormalized\n ) {\n // For the prompt, prefer authenticators that match the last-user deviceNumber.\n const filtered = authenticators.filter(a => a.deviceNumber === expectedDeviceNumber);\n if (filtered.length > 0) {\n authenticatorsForPrompt = filtered;\n }\n\n // If a credential was already chosen, verify it matches the last-user deviceNumber.\n if (selectedCredentialRawId) {\n const matched = authenticators.find(a => a.credentialId === selectedCredentialRawId);\n if (matched && matched.deviceNumber !== expectedDeviceNumber) {\n wrongPasskeyError =\n `You have multiple passkeys (deviceNumbers) for account ${accountIdNormalized}, ` +\n 'but used a passkey from a different device. Please use the passkey for the most recently logged-in device.';\n }\n }\n }\n }\n\n return { authenticatorsForPrompt, wrongPasskeyError };\n }\n\n /**\n * Register a new user with the given NEAR account ID\n * @param nearAccountId - Full NEAR account ID (e.g., \"username.testnet\" or \"username.relayer.testnet\")\n * @param additionalData - Additional user data to store\n */\n async registerUser(storeUserData: StoreUserDataInput): Promise<ClientUserData> {\n\n const validation = this.validateNearAccountId(storeUserData.nearAccountId);\n if (!validation.valid) {\n throw new Error(`Cannot register user with invalid account ID: ${validation.error}`);\n }\n\n const now = Date.now();\n\n const userData: ClientUserData = {\n nearAccountId: toAccountId(storeUserData.nearAccountId),\n deviceNumber: storeUserData.deviceNumber || 1, // Default to device 1 (1-indexed)\n version: storeUserData.version || 2,\n registeredAt: now,\n lastLogin: now,\n lastUpdated: now,\n clientNearPublicKey: storeUserData.clientNearPublicKey,\n passkeyCredential: storeUserData.passkeyCredential,\n preferences: {\n useRelayer: false,\n useNetwork: 'testnet',\n confirmationConfig: DEFAULT_CONFIRMATION_CONFIG,\n // Default preferences can be set here\n },\n encryptedVrfKeypair: storeUserData.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: storeUserData.serverEncryptedVrfKeypair,\n };\n\n await this.storeUser(userData);\n return userData;\n }\n\n async updateUser(nearAccountId: AccountId, updates: Partial<ClientUserData>): Promise<void> {\n const user = await this.getUser(nearAccountId);\n if (user) {\n const updatedUser = {\n ...user,\n ...updates,\n lastUpdated: Date.now()\n };\n await this.storeUser(updatedUser); // This will update the app state lastUserAccountId\n\n // Emit event for user updates\n this.emitEvent({\n type: 'user-updated',\n accountId: nearAccountId,\n data: { updates, updatedUser }\n });\n }\n }\n\n async updateLastLogin(nearAccountId: AccountId): Promise<void> {\n await this.updateUser(nearAccountId, { lastLogin: Date.now() });\n }\n\n /**\n * Set the last logged-in user\n * @param nearAccountId - The account ID of the user\n * @param deviceNumber - The device number (defaults to 1)\n */\n async setLastUser(nearAccountId: AccountId, deviceNumber: number = 1): Promise<void> {\n const lastUserState: LastUserAccountIdState = {\n accountId: nearAccountId,\n deviceNumber,\n };\n await this.setAppState('lastUserAccountId', lastUserState);\n }\n\n async updatePreferences(\n nearAccountId: AccountId,\n preferences: Partial<UserPreferences>\n ): Promise<void> {\n const user = await this.getUser(nearAccountId);\n if (user) {\n const updatedPreferences = {\n ...user.preferences,\n ...preferences\n } as UserPreferences;\n await this.updateUser(nearAccountId, { preferences: updatedPreferences });\n\n // Emit event for preference changes\n this.emitEvent({\n type: 'preferences-updated',\n accountId: nearAccountId,\n data: { preferences: updatedPreferences }\n });\n }\n }\n\n private async normalizeUserDeviceNumber(\n user: ClientUserDataWithOptionalDevice,\n defaultDeviceNumber: number\n ): Promise<ClientUserData> {\n const hasValidDevice =\n typeof user.deviceNumber === 'number' && Number.isFinite(user.deviceNumber);\n if (hasValidDevice) {\n return user as ClientUserData;\n }\n\n const deviceNumber = defaultDeviceNumber;\n const fixed: ClientUserData = {\n ...(user as Omit<ClientUserData, 'deviceNumber'>),\n deviceNumber,\n };\n await this.storeUser(fixed);\n return fixed;\n }\n\n private async storeUser(userData: ClientUserData): Promise<void> {\n const validation = this.validateNearAccountId(userData.nearAccountId);\n if (!validation.valid) {\n throw new Error(`Cannot store user with invalid account ID: ${validation.error}`);\n }\n\n const db = await this.getDB();\n await db.put(DB_CONFIG.userStore, userData);\n\n // Update lastUserAccountId with new format including device info\n const lastUserState: LastUserAccountIdState = {\n accountId: userData.nearAccountId,\n deviceNumber: userData.deviceNumber,\n };\n\n await this.setAppState('lastUserAccountId', lastUserState);\n }\n\n /**\n * Store WebAuthn user data (compatibility with WebAuthnManager)\n * @param userData - User data with nearAccountId as primary identifier\n */\n async storeWebAuthnUserData(userData: {\n nearAccountId: AccountId;\n deviceNumber?: number; // Device number for multi-device support (1-indexed)\n clientNearPublicKey: string;\n lastUpdated?: number;\n version?: number;\n passkeyCredential: {\n id: string;\n rawId: string;\n };\n encryptedVrfKeypair: {\n encryptedVrfDataB64u: string;\n chacha20NonceB64u: string;\n };\n serverEncryptedVrfKeypair?: {\n ciphertextVrfB64u: string;\n kek_s_b64u: string;\n serverKeyId: string;\n updatedAt?: number;\n };\n }): Promise<void> {\n\n if (userData.deviceNumber === undefined) {\n console.warn(\"WARNING: deviceNumber is undefined in storeWebAuthnUserData, will default to 1\");\n }\n const validation = this.validateNearAccountId(userData.nearAccountId);\n if (!validation.valid) {\n throw new Error(`Cannot store WebAuthn data for invalid account ID: ${validation.error}`);\n }\n\n // Get existing user data or create new\n let existingUser = await this.getUser(userData.nearAccountId);\n if (!existingUser) {\n const deviceNumberToUse = userData.deviceNumber || 1;\n existingUser = await this.registerUser({\n nearAccountId: userData.nearAccountId,\n deviceNumber: deviceNumberToUse, // Use provided device number or default to 1\n clientNearPublicKey: userData.clientNearPublicKey,\n passkeyCredential: userData.passkeyCredential,\n encryptedVrfKeypair: userData.encryptedVrfKeypair,\n version: userData.version || 2,\n serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair,\n });\n }\n\n // Update with WebAuthn-specific data (including VRF credentials)\n const finalDeviceNumber = userData.deviceNumber || existingUser.deviceNumber;\n\n await this.updateUser(userData.nearAccountId, {\n clientNearPublicKey: userData.clientNearPublicKey,\n encryptedVrfKeypair: userData.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair,\n version: userData.version || existingUser.version,\n deviceNumber: finalDeviceNumber, // Use provided device number or keep existing\n lastUpdated: userData.lastUpdated || Date.now()\n });\n }\n\n async getAllUsers(): Promise<ClientUserData[]> {\n const db = await this.getDB();\n return db.getAll(DB_CONFIG.userStore);\n }\n\n async deleteUser(nearAccountId: AccountId): Promise<void> {\n const db = await this.getDB();\n await db.delete(DB_CONFIG.userStore, nearAccountId);\n // Also clean up related authenticators\n await this.clearAuthenticatorsForUser(nearAccountId);\n }\n\n async clearAllUsers(): Promise<void> {\n const db = await this.getDB();\n await db.clear(DB_CONFIG.userStore);\n }\n\n async clearAllAppState(): Promise<void> {\n const db = await this.getDB();\n await db.clear(DB_CONFIG.appStateStore);\n }\n\n /**\n * Store authenticator data for a user\n */\n async storeAuthenticator(authenticatorData: ClientAuthenticatorData): Promise<void> {\n const db = await this.getDB();\n await db.put(DB_CONFIG.authenticatorStore, authenticatorData);\n }\n\n /**\n * Get all authenticators for a user (optionally for a specific device)\n */\n async getAuthenticatorsByUser(nearAccountId: AccountId): Promise<ClientAuthenticatorData[]> {\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readonly');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n const accountId = toAccountId(nearAccountId);\n\n // Get all authenticators for this account across all devices\n const index = store.index('nearAccountId');\n return await index.getAll(accountId);\n }\n\n /**\n * Get a specific authenticator by credential ID\n */\n async getAuthenticatorByCredentialId(\n nearAccountId: AccountId,\n credentialId: string\n ): Promise<ClientAuthenticatorData | null> {\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readonly');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n const accountId = toAccountId(nearAccountId);\n\n // Primary key is [nearAccountId, deviceNumber, credentialId], so we cannot\n // look up by [nearAccountId, credentialId] directly. Use the nearAccountId\n // index and filter by credentialId.\n const index = store.index('nearAccountId');\n const all = await index.getAll(accountId);\n const match = all.find((auth: any) => auth.credentialId === credentialId) || null;\n return match;\n }\n\n /**\n * Clear all authenticators for a user\n */\n async clearAuthenticatorsForUser(nearAccountId: AccountId): Promise<void> {\n const authenticators = await this.getAuthenticatorsByUser(nearAccountId);\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readwrite');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n\n for (const auth of authenticators) {\n // Composite PK is [nearAccountId, deviceNumber, credentialId]\n await store.delete([nearAccountId, auth.deviceNumber, auth.credentialId]);\n }\n }\n\n /**\n * Sync authenticators from contract data\n */\n async syncAuthenticatorsFromContract(\n nearAccountId: AccountId,\n contractAuthenticators: Array<{\n credentialId: string;\n credentialPublicKey: Uint8Array;\n transports?: string[];\n name?: string;\n registered: string;\n vrfPublicKey: string;\n deviceNumber?: number; // Device number from contract\n }>\n ): Promise<void> {\n // Clear existing cache for this user\n await this.clearAuthenticatorsForUser(nearAccountId);\n\n // Add all contract authenticators to cache\n const syncedAt = new Date().toISOString();\n for (const auth of contractAuthenticators) {\n // Fix transport processing: filter out undefined values and provide fallback\n const rawTransports = auth.transports || [];\n const validTransports = rawTransports.filter((transport: any) =>\n transport !== undefined && transport !== null && typeof transport === 'string'\n );\n\n // If no valid transports, default to 'internal' for platform authenticators\n const transports = validTransports.length > 0 ? validTransports : ['internal'];\n\n const clientAuth: ClientAuthenticatorData = {\n credentialId: auth.credentialId,\n credentialPublicKey: auth.credentialPublicKey,\n transports,\n name: auth.name,\n nearAccountId: toAccountId(nearAccountId),\n deviceNumber: auth.deviceNumber || 1, // Default to device 1 (1-indexed)\n registered: auth.registered,\n syncedAt: syncedAt,\n vrfPublicKey: auth.vrfPublicKey,\n };\n await this.storeAuthenticator(clientAuth);\n }\n }\n\n // === ATOMIC OPERATIONS AND ROLLBACK METHODS ===\n\n /**\n * Delete all authenticators for a user\n */\n async deleteAllAuthenticatorsForUser(nearAccountId: AccountId): Promise<void> {\n const authenticators = await this.getAuthenticatorsByUser(nearAccountId);\n\n if (authenticators.length === 0) {\n console.warn(`No authenticators found for user ${nearAccountId}`);\n return;\n }\n\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readwrite');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n\n for (const auth of authenticators) {\n // Composite PK is [nearAccountId, deviceNumber, credentialId]\n await store.delete([nearAccountId, auth.deviceNumber, auth.credentialId]);\n }\n\n console.debug(`Deleted ${authenticators.length} authenticators for user ${nearAccountId}`);\n }\n\n /**\n * Get user's confirmation config from IndexedDB\n * @param nearAccountId - The user's account ID\n * @returns ConfirmationConfig or undefined\n */\n async getConfirmationConfig(nearAccountId: AccountId): Promise<ConfirmationConfig> {\n const user = await this.getUser(nearAccountId);\n return user?.preferences?.confirmationConfig || DEFAULT_CONFIRMATION_CONFIG;\n }\n\n /**\n * Get user's theme preference from IndexedDB\n * @param nearAccountId - The user's account ID\n * @returns 'dark' | 'light' | null\n */\n async getTheme(nearAccountId: AccountId): Promise<'dark' | 'light' | null> {\n const user = await this.getUser(nearAccountId);\n return user?.preferences?.confirmationConfig.theme || null;\n }\n\n /**\n * Set user's theme preference in IndexedDB\n * @param nearAccountId - The user's account ID\n * @param theme - The theme to set ('dark' | 'light')\n */\n async setTheme(nearAccountId: AccountId, theme: 'dark' | 'light'): Promise<void> {\n const existingConfig = await this.getConfirmationConfig(nearAccountId);\n const confirmationConfig = { ...existingConfig, theme };\n await this.updatePreferences(nearAccountId, { confirmationConfig });\n }\n\n /**\n * Get user's theme with fallback to 'dark'\n * @param nearAccountId - The user's account ID\n * @returns 'dark' | 'light'\n */\n async getThemeOrDefault(nearAccountId: AccountId): Promise<'dark' | 'light'> {\n const theme = await this.getTheme(nearAccountId);\n return theme || 'dark';\n }\n\n /**\n * Toggle between dark and light theme for a user\n * @param nearAccountId - The user's account ID\n * @returns The new theme that was set\n */\n async toggleTheme(nearAccountId: AccountId): Promise<'dark' | 'light'> {\n const currentTheme = await this.getThemeOrDefault(nearAccountId);\n const newTheme = currentTheme === 'dark' ? 'light' : 'dark';\n await this.setTheme(nearAccountId, newTheme);\n return newTheme;\n }\n\n // === DERIVED ADDRESS METHODS ===\n\n /**\n * Store a derived address for a given NEAR account + contract + path\n */\n async setDerivedAddress(nearAccountId: AccountId, args: { contractId: string; path: string; address: string }): Promise<void> {\n if (!nearAccountId || !args?.contractId || !args?.path || !args?.address) return;\n const validation = this.validateNearAccountId(nearAccountId);\n if (!validation.valid) return;\n const rec: DerivedAddressRecord = {\n nearAccountId: toAccountId(nearAccountId),\n contractId: String(args.contractId),\n path: String(args.path),\n address: String(args.address),\n updatedAt: Date.now(),\n };\n const db = await this.getDB();\n await db.put(DB_CONFIG.derivedAddressStore, rec);\n }\n\n /**\n * Fetch a derived address record; returns null if not found\n */\n async getDerivedAddressRecord(nearAccountId: AccountId, args: { contractId: string; path: string }): Promise<DerivedAddressRecord | null> {\n if (!nearAccountId || !args?.contractId || !args?.path) return null;\n const db = await this.getDB();\n const rec = await db.get(DB_CONFIG.derivedAddressStore, [toAccountId(nearAccountId), String(args.contractId), String(args.path)]);\n return (rec as DerivedAddressRecord) || null;\n }\n\n /**\n * Get only the derived address string; returns null if not set\n */\n async getDerivedAddress(nearAccountId: AccountId, args: { contractId: string; path: string }): Promise<string | null> {\n const rec = await this.getDerivedAddressRecord(nearAccountId, args);\n return rec?.address || null;\n }\n\n // === RECOVERY EMAIL METHODS ===\n\n /**\n * Upsert recovery email records for an account.\n * Merges by hashHex, preferring the most recent email.\n */\n async upsertRecoveryEmails(\n nearAccountId: AccountId,\n entries: Array<{ hashHex: string; email: string }>\n ): Promise<void> {\n if (!nearAccountId || !entries?.length) return;\n const validation = this.validateNearAccountId(nearAccountId);\n if (!validation.valid) return;\n\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n const now = Date.now();\n\n for (const entry of entries) {\n const hashHex = String(entry?.hashHex || '').trim();\n const email = String(entry?.email || '').trim();\n if (!hashHex || !email) continue;\n\n const rec: RecoveryEmailRecord = {\n nearAccountId: accountId,\n hashHex,\n email,\n addedAt: now,\n };\n await db.put(DB_CONFIG.recoveryEmailStore, rec);\n }\n }\n\n /**\n * Fetch all recovery email records for an account.\n */\n async getRecoveryEmails(nearAccountId: AccountId): Promise<RecoveryEmailRecord[]> {\n if (!nearAccountId) return [];\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n const tx = db.transaction(DB_CONFIG.recoveryEmailStore, 'readonly');\n const store = tx.objectStore(DB_CONFIG.recoveryEmailStore);\n const index = store.index('nearAccountId');\n const result = await index.getAll(accountId);\n return (result as RecoveryEmailRecord[]) || [];\n }\n\n /**\n * Atomic operation wrapper for multiple IndexedDB operations\n * Either all operations succeed or all are rolled back\n */\n async atomicOperation<T>(operation: (db: IDBPDatabase) => Promise<T>): Promise<T> {\n const db = await this.getDB();\n try {\n const result = await operation(db);\n return result;\n } catch (error) {\n console.error('Atomic operation failed:', error);\n throw error;\n }\n }\n\n /**\n * Complete rollback of user registration data\n * Deletes user, authenticators, and WebAuthn data atomically\n */\n async rollbackUserRegistration(nearAccountId: AccountId): Promise<void> {\n console.debug(`Rolling back registration data for ${nearAccountId}`);\n\n await this.atomicOperation(async (db) => {\n // Delete all authenticators for this user\n await this.deleteAllAuthenticatorsForUser(nearAccountId);\n\n // Delete user record\n await db.delete(DB_CONFIG.userStore, nearAccountId);\n\n // Clear from app state if this was the last user\n const lastUserAccount = await this.getAppState<string>('lastUserAccountId');\n if (lastUserAccount === nearAccountId) {\n await this.setAppState('lastUserAccountId', null);\n }\n\n console.debug(`Rolled back all registration data for ${nearAccountId}`);\n return true;\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"passkeyClientDB.js","names":["DB_CONFIG: PasskeyClientDBConfig","err: any","entry: AppStateEntry<T>","userData: ClientUserData","lastUserState: LastUserAccountIdState","fixed: ClientUserData","updatedUser: ClientUserData","clientAuth: ClientAuthenticatorData","rec: DerivedAddressRecord","rec: RecoveryEmailRecord"],"sources":["../../../../../../../src/core/IndexedDBManager/passkeyClientDB.ts"],"sourcesContent":["import { openDB, type IDBPDatabase } from 'idb';\nimport { type ValidationResult, validateNearAccountId } from '../../utils/validation';\nimport type { AccountId } from '../types/accountIds';\nimport { toAccountId } from '../types/accountIds';\nimport { ConfirmationConfig, DEFAULT_CONFIRMATION_CONFIG } from '../types/signer-worker'\n\n\nexport interface ClientUserData {\n // Primary key - now uses AccountId + deviceNumber for unique identification\n nearAccountId: AccountId;\n deviceNumber: number; // Device number for multi-device support (1-indexed)\n version?: number;\n\n // User metadata\n registeredAt?: number;\n lastLogin?: number;\n lastUpdated?: number;\n\n // WebAuthn/Passkey data (merged from WebAuthnManager)\n clientNearPublicKey: string;\n passkeyCredential: {\n id: string;\n rawId: string;\n };\n\n // VRF credentials for stateless authentication\n encryptedVrfKeypair: {\n encryptedVrfDataB64u: string;\n chacha20NonceB64u: string;\n };\n // Server-assisted auto-login (VRF key session): Shamir 3-pass fields\n // Stores relayer-blinded KEK and the VRF ciphertext; server never sees plaintext VRF or KEK\n serverEncryptedVrfKeypair?: {\n ciphertextVrfB64u: string;\n kek_s_b64u: string;\n // Metadata for proactive refresh\n serverKeyId: string;\n updatedAt?: number;\n };\n\n // User preferences\n preferences?: UserPreferences;\n}\n\nexport type StoreUserDataInput = Omit<ClientUserData, 'deviceNumber' | 'lastLogin' | 'registeredAt'>\n & {\n deviceNumber?: number;\n serverEncryptedVrfKeypair?: ClientUserData['serverEncryptedVrfKeypair'];\n version?: number;\n };\n\nexport type StoreWebAuthnUserDataInput = {\n nearAccountId: AccountId;\n deviceNumber: number;\n clientNearPublicKey: string;\n lastUpdated?: number;\n version?: number;\n passkeyCredential: ClientUserData['passkeyCredential'];\n encryptedVrfKeypair: ClientUserData['encryptedVrfKeypair'];\n serverEncryptedVrfKeypair?: ClientUserData['serverEncryptedVrfKeypair'];\n};\n\nexport interface UserPreferences {\n useRelayer: boolean;\n useNetwork: 'testnet' | 'mainnet';\n confirmationConfig: ConfirmationConfig;\n // User preferences can be extended here as needed\n}\n\n// Authenticator cache\nexport interface ClientAuthenticatorData {\n credentialId: string;\n credentialPublicKey: Uint8Array;\n transports?: string[]; // AuthenticatorTransport[]\n name?: string;\n nearAccountId: AccountId; // FK reference using AccountId\n deviceNumber: number; // Device number for this authenticator (1-indexed)\n registered: string; // ISO date string\n syncedAt: string; // When this cache entry was last synced with contract\n vrfPublicKey: string; // Base64-encoded VRF public key (1:1 relationship on client)\n}\n\ninterface AppStateEntry<T = unknown> {\n key: string;\n value: T;\n}\n\n// Internal helper: legacy user records may be missing deviceNumber.\ntype ClientUserDataWithOptionalDevice =\n | ClientUserData\n | (Omit<ClientUserData, 'deviceNumber'> & { deviceNumber?: number });\n\n// Special type for lastUserAccountId app state entry\nexport interface LastUserAccountIdState {\n accountId: AccountId;\n deviceNumber: number;\n}\n\ninterface PasskeyClientDBConfig {\n dbName: string;\n dbVersion: number;\n userStore: string;\n appStateStore: string;\n authenticatorStore: string;\n derivedAddressStore: string;\n recoveryEmailStore: string;\n}\n\n// === CONSTANTS ===\nconst DB_CONFIG: PasskeyClientDBConfig = {\n dbName: 'PasskeyClientDB',\n dbVersion: 15, // v15: add recoveryEmails store\n userStore: 'users',\n appStateStore: 'appState',\n authenticatorStore: 'authenticators',\n derivedAddressStore: 'derivedAddresses',\n recoveryEmailStore: 'recoveryEmails'\n} as const;\n\nexport interface IndexedDBEvent {\n type: 'user-updated' | 'preferences-updated' | 'user-deleted';\n accountId: AccountId;\n data?: Record<string, unknown>;\n}\n\n// Persisted mapping of derived (e.g., EVM) addresses tied to an account\n/**\n * Persisted mapping of derived (e.g., EVM/Solana/Zcash) addresses tied to an account.\n *\n * Notes on multi-chain support:\n * - The composite primary key is [nearAccountId, contractId, path]. To support\n * different chains and chain IDs, encode them in the `path` string, e.g.:\n * - EVM: `evm:<chainId>:<derivationPath>` → `evm:84532:ethereum-1`\n * - Solana: `solana:<derivationPath>`\n * - Zcash: `zcash:<derivationPath>`\n * - Additional descriptive fields like `namespace` and `chainRef` are optional metadata\n * and are not part of the key.\n */\nexport interface DerivedAddressRecord {\n nearAccountId: AccountId;\n contractId: string; // MPC/Derivation contract on NEAR\n path: string; // Composite path (may include namespace/chainId); see docs above\n address: string; // Derived address (e.g., 0x...)\n updatedAt: number;\n // Optional metadata (not used in the key)\n namespace?: string; // e.g., 'evm', 'solana', 'zcash'\n chainRef?: string; // e.g., chainId '84532' or a named network slug\n}\n\n/**\n * Persisted mapping of recovery email hashes to canonical email addresses for an account.\n *\n * Notes:\n * - Composite primary key is [nearAccountId, hashHex].\n * - `hashHex` is the 0x-prefixed hex encoding of the 32-byte hash:\n * SHA256(canonical_email || \"|\" || account_id)\n * - `email` is the canonical form: \"local@domain\", lowercased.\n */\nexport interface RecoveryEmailRecord {\n nearAccountId: AccountId;\n hashHex: string;\n email: string;\n addedAt: number;\n}\n\nexport class PasskeyClientDBManager {\n private config: PasskeyClientDBConfig;\n private db: IDBPDatabase | null = null;\n private disabled = false;\n private eventListeners: Set<(event: IndexedDBEvent) => void> = new Set();\n\n constructor(config: PasskeyClientDBConfig = DB_CONFIG) {\n this.config = config;\n }\n\n getDbName(): string {\n return this.config.dbName;\n }\n\n setDbName(dbName: string): void {\n const next = String(dbName || '').trim();\n if (!next || next === this.config.dbName) return;\n try { (this.db as any)?.close?.(); } catch {}\n this.db = null;\n this.config = { ...this.config, dbName: next };\n }\n\n isDisabled(): boolean {\n return this.disabled;\n }\n\n setDisabled(disabled: boolean): void {\n const next = !!disabled;\n if (next === this.disabled) return;\n this.disabled = next;\n if (next) {\n try { (this.db as any)?.close?.(); } catch {}\n this.db = null;\n }\n }\n\n // === EVENT SYSTEM ===\n\n onChange(listener: (event: IndexedDBEvent) => void): () => void {\n this.eventListeners.add(listener);\n return () => {\n this.eventListeners.delete(listener);\n };\n }\n\n private emitEvent(event: IndexedDBEvent): void {\n this.eventListeners.forEach(listener => {\n try {\n listener(event);\n } catch (error) {\n console.warn('[IndexedDBManager]: Error in event listener:', error);\n }\n });\n }\n\n private async getDB(): Promise<IDBPDatabase> {\n if (this.disabled) {\n throw new Error('[PasskeyClientDBManager] IndexedDB is disabled in this environment.');\n }\n if (this.db) {\n return this.db;\n }\n\n try {\n this.db = await openDB(this.config.dbName, this.config.dbVersion, {\n upgrade: (db, oldVersion, _newVersion, _transaction): void => {\n // Create stores if they don't exist\n if (!db.objectStoreNames.contains(DB_CONFIG.userStore)) {\n // Users table: composite key of [nearAccountId, deviceNumber]\n const userStore = db.createObjectStore(DB_CONFIG.userStore, { keyPath: ['nearAccountId', 'deviceNumber'] });\n userStore.createIndex('nearAccountId', 'nearAccountId', { unique: false });\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.appStateStore)) {\n db.createObjectStore(DB_CONFIG.appStateStore, { keyPath: 'key' });\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.authenticatorStore)) {\n // Authenticators table: composite key of [nearAccountId, deviceNumber, credentialId]\n const authStore = db.createObjectStore(DB_CONFIG.authenticatorStore, { keyPath: ['nearAccountId', 'deviceNumber', 'credentialId'] });\n authStore.createIndex('nearAccountId', 'nearAccountId', { unique: false });\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.derivedAddressStore)) {\n // Derived addresses: composite key of [nearAccountId, contractId, path]\n const dStore = db.createObjectStore(DB_CONFIG.derivedAddressStore, { keyPath: ['nearAccountId', 'contractId', 'path'] });\n try { dStore.createIndex('nearAccountId', 'nearAccountId', { unique: false }); } catch {}\n }\n if (!db.objectStoreNames.contains(DB_CONFIG.recoveryEmailStore)) {\n // Recovery emails: composite key of [nearAccountId, hashHex]\n const rStore = db.createObjectStore(DB_CONFIG.recoveryEmailStore, { keyPath: ['nearAccountId', 'hashHex'] });\n try { rStore.createIndex('nearAccountId', 'nearAccountId', { unique: false }); } catch {}\n }\n },\n blocked() {\n console.warn('PasskeyClientDB connection is blocked.');\n },\n blocking() {\n console.warn('PasskeyClientDB connection is blocking another connection.');\n },\n terminated: () => {\n console.warn('PasskeyClientDB connection has been terminated.');\n this.db = null;\n },\n });\n\n // Post-open migrations (non-blocking)\n try { await this.runMigrationsIfNeeded(this.db); } catch {}\n\n } catch (err: any) {\n const msg = String(err?.message || '');\n if (err?.name === 'VersionError' || /less than the existing version/i.test(msg)) {\n // Mixed-version contexts (host/app) — open without version to adopt existing DB\n try {\n console.warn('PasskeyClientDB: opening existing DB without version due to VersionError');\n this.db = await openDB(this.config.dbName);\n } catch (e) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n\n return this.db;\n }\n\n private async runMigrationsIfNeeded(_db: IDBPDatabase): Promise<void> {\n return;\n }\n\n // === APP STATE METHODS ===\n\n async getAppState<T = unknown>(key: string): Promise<T | undefined> {\n const db = await this.getDB();\n const result = await db.get(DB_CONFIG.appStateStore, key);\n return result?.value as T | undefined;\n }\n\n async setAppState<T = unknown>(key: string, value: T): Promise<void> {\n const db = await this.getDB();\n const entry: AppStateEntry<T> = { key, value };\n await db.put(DB_CONFIG.appStateStore, entry);\n }\n\n // === ACCOUNT ID VALIDATION AND UTILITIES ===\n\n /**\n * Validate that a NEAR account ID is in the expected format\n * Supports both <username>.<relayerAccountId> and <username>.testnet formats\n */\n validateNearAccountId(nearAccountId: AccountId): ValidationResult {\n return validateNearAccountId(nearAccountId);\n }\n\n /**\n * Extract username from NEAR account ID\n */\n extractUsername(nearAccountId: AccountId): string {\n const validation = validateNearAccountId(nearAccountId);\n if (!validation.valid) {\n throw new Error(`Invalid NEAR account ID: ${validation.error}`);\n }\n return nearAccountId.split('.')[0];\n }\n\n /**\n * Generate a NEAR account ID from a username and domain\n * @param username - The username to use for the account ID\n * @param domain - The domain to use for the account ID\n * @returns The generated NEAR account ID\n */\n generateNearAccountId(username: string, domain: string): string {\n const sanitizedName = username\n .toLowerCase()\n .replace(/[^a-z0-9_\\\\-]/g, '')\n .substring(0, 32);\n return `${sanitizedName}.${domain}`;\n }\n\n // === USER MANAGEMENT METHODS ===\n\n async getUser(nearAccountId: AccountId, deviceNumber?: number): Promise<ClientUserData | null> {\n if (!nearAccountId) return null;\n\n const validation = this.validateNearAccountId(nearAccountId);\n if (!validation.valid) {\n console.warn(`Invalid account ID format: ${nearAccountId}`);\n return null;\n }\n\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n\n if (typeof deviceNumber === 'number') {\n const rec = await db.get(DB_CONFIG.userStore, [accountId, deviceNumber]);\n if (!rec) return null;\n return await this.normalizeUserDeviceNumber(rec as ClientUserDataWithOptionalDevice, deviceNumber);\n }\n\n const index = db.transaction(DB_CONFIG.userStore).store.index('nearAccountId');\n const results = await index.getAll(accountId);\n if (results.length === 0) {\n return null;\n }\n\n if (results.length > 1) {\n console.warn(\n `Multiple passkeys found for account ${accountId}, deviceNumber not provided; ` +\n 'defaulting to last logged-in user.'\n );\n console.log('defaulting to last used user deviceNumber');\n const lastUserState = await this.getAppState<LastUserAccountIdState>('lastUserAccountId').catch(() => null);\n if (lastUserState && toAccountId(lastUserState.accountId) === accountId) {\n const keyed = await db.get(DB_CONFIG.userStore, [accountId, lastUserState.deviceNumber]);\n if (keyed) {\n return await this.normalizeUserDeviceNumber(\n keyed as ClientUserDataWithOptionalDevice,\n lastUserState.deviceNumber\n );\n }\n }\n }\n\n const first = results[0] as ClientUserDataWithOptionalDevice;\n if (!first) return null;\n return await this.normalizeUserDeviceNumber(first, 1);\n }\n\n /**\n * Get the current/last user\n * This is maintained via app state and updated whenever a user is stored or updated\n */\n async getLastUser(): Promise<ClientUserData | null> {\n const lastUserState = await this.getAppState<LastUserAccountIdState>('lastUserAccountId');\n if (!lastUserState) return null;\n const db = await this.getDB();\n const accountId = toAccountId(lastUserState.accountId);\n // Prefer exact device match using composite primary key\n const record = await db.get(DB_CONFIG.userStore, [accountId, lastUserState.deviceNumber]);\n if (record) return record as ClientUserData;\n // Fallback: return any user for account\n return this.getUser(accountId);\n }\n\n /** Get user record by composite key (nearAccountId, deviceNumber) */\n async getUserByDevice(nearAccountId: AccountId, deviceNumber: number): Promise<ClientUserData | null> {\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n const rec = await db.get(DB_CONFIG.userStore, [accountId, deviceNumber]);\n return rec as ClientUserData || null;\n }\n\n /**\n * Get the most recently updated user record for a given account.\n * Useful when deviceNumber is unknown but we need the freshest key for the account.\n */\n /**\n * Get the most recently updated user record for a given account.\n * Useful when deviceNumber is unknown but we need the freshest key for the account.\n */\n async getLastDBUpdatedUser(nearAccountId: AccountId): Promise<ClientUserData | null> {\n const db = await this.getDB();\n try {\n const idx = db.transaction(DB_CONFIG.userStore).store.index('nearAccountId');\n const all = await idx.getAll(toAccountId(nearAccountId));\n if (Array.isArray(all) && all.length > 0) {\n const latest = (all as ClientUserData[]).reduce((a, b) =>\n (a.lastUpdated ?? 0) >= (b.lastUpdated ?? 0) ? a : b\n );\n return latest;\n }\n } catch {\n // fall through\n }\n return null;\n }\n\n async hasPasskeyCredential(nearAccountId: AccountId): Promise<boolean> {\n const authenticators = await this.getAuthenticatorsByUser(nearAccountId);\n return !!authenticators[0]?.credentialId;\n }\n\n /**\n * Ensure the current passkey selection is aligned with the last logged-in device.\n *\n * - When multiple authenticators exist for an account and no deviceNumber is specified,\n * this helper prefers authenticators whose deviceNumber matches the last logged-in user.\n * - Optionally validates that a selected credential (by rawId) also matches the last-user device.\n *\n * @param nearAccountId - Account ID for which the operation is being performed\n * @param authenticators - All authenticators stored for the account\n * @param selectedCredentialRawId - Optional rawId of the credential chosen by WebAuthn\n * @returns filtered authenticators for allowCredentials, plus optional wrongPasskeyError\n */\n async ensureCurrentPasskey(\n nearAccountId: AccountId,\n authenticators: ClientAuthenticatorData[],\n selectedCredentialRawId?: string,\n ): Promise<{\n authenticatorsForPrompt: ClientAuthenticatorData[];\n wrongPasskeyError?: string;\n }> {\n if (authenticators.length <= 1) {\n return { authenticatorsForPrompt: authenticators };\n }\n\n const accountIdNormalized = toAccountId(nearAccountId);\n const lastUser = await this.getLastUser().catch(() => null);\n if (!lastUser || lastUser.nearAccountId !== accountIdNormalized) {\n return { authenticatorsForPrompt: authenticators };\n }\n\n const expectedDeviceNumber = lastUser.deviceNumber;\n const byDeviceNumber = authenticators.filter(a => a.deviceNumber === expectedDeviceNumber);\n\n // Prefer the credentialId for the last-user deviceNumber; use the stored last-user rawId\n // only when it matches an authenticator for that device (or when we have no device match).\n let expectedCredentialId = lastUser.passkeyCredential.rawId;\n if (byDeviceNumber.length > 0 && !byDeviceNumber.some(a => a.credentialId === expectedCredentialId)) {\n expectedCredentialId = byDeviceNumber[0].credentialId;\n }\n\n // Preference: restrict allowCredentials to the last-user credentialId.\n // Fallback: if the local authenticator cache is missing that entry, prefer the last-user deviceNumber.\n const byCredentialId = authenticators.filter(a => a.credentialId === expectedCredentialId);\n const authenticatorsForPrompt =\n byCredentialId.length > 0\n ? byCredentialId\n : (byDeviceNumber.length > 0 ? byDeviceNumber : authenticators);\n\n const wrongPasskeyError =\n selectedCredentialRawId && selectedCredentialRawId !== expectedCredentialId\n ? (\n `You have multiple passkeys (deviceNumbers) for account ${accountIdNormalized}, ` +\n 'but used a different passkey than the most recently logged-in one. Please use the passkey for the most recently logged-in device.'\n )\n : undefined;\n\n return { authenticatorsForPrompt, wrongPasskeyError };\n }\n\n /**\n * Register a new user with the given NEAR account ID\n * @param nearAccountId - Full NEAR account ID (e.g., \"username.testnet\" or \"username.relayer.testnet\")\n * @param additionalData - Additional user data to store\n */\n async registerUser(storeUserData: StoreUserDataInput): Promise<ClientUserData> {\n\n const validation = this.validateNearAccountId(storeUserData.nearAccountId);\n if (!validation.valid) {\n throw new Error(`Cannot register user with invalid account ID: ${validation.error}`);\n }\n\n const now = Date.now();\n\n const userData: ClientUserData = {\n nearAccountId: toAccountId(storeUserData.nearAccountId),\n deviceNumber: storeUserData.deviceNumber || 1, // Default to device 1 (1-indexed)\n version: storeUserData.version || 2,\n registeredAt: now,\n lastLogin: now,\n lastUpdated: now,\n clientNearPublicKey: storeUserData.clientNearPublicKey,\n passkeyCredential: storeUserData.passkeyCredential,\n preferences: {\n useRelayer: false,\n useNetwork: 'testnet',\n confirmationConfig: DEFAULT_CONFIRMATION_CONFIG,\n // Default preferences can be set here\n },\n encryptedVrfKeypair: storeUserData.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: storeUserData.serverEncryptedVrfKeypair,\n };\n\n await this.storeUser(userData);\n return userData;\n }\n\n async updateUser(nearAccountId: AccountId, updates: Partial<ClientUserData>): Promise<void> {\n const user = await this.getUser(nearAccountId);\n if (user) {\n const updatedUser = {\n ...user,\n ...updates,\n lastUpdated: Date.now()\n };\n await this.storeUser(updatedUser); // This will update the app state lastUserAccountId\n\n // Emit event for user updates\n this.emitEvent({\n type: 'user-updated',\n accountId: nearAccountId,\n data: { updates, updatedUser }\n });\n }\n }\n\n async updateLastLogin(nearAccountId: AccountId): Promise<void> {\n await this.updateUser(nearAccountId, { lastLogin: Date.now() });\n }\n\n /**\n * Set the last logged-in user\n * @param nearAccountId - The account ID of the user\n * @param deviceNumber - The device number (defaults to 1)\n */\n async setLastUser(nearAccountId: AccountId, deviceNumber: number = 1): Promise<void> {\n const lastUserState: LastUserAccountIdState = {\n accountId: nearAccountId,\n deviceNumber,\n };\n await this.setAppState('lastUserAccountId', lastUserState);\n }\n\n async updatePreferences(\n nearAccountId: AccountId,\n preferences: Partial<UserPreferences>\n ): Promise<void> {\n const user = await this.getUser(nearAccountId);\n if (user) {\n const updatedPreferences = {\n ...user.preferences,\n ...preferences\n } as UserPreferences;\n await this.updateUser(nearAccountId, { preferences: updatedPreferences });\n\n // Emit event for preference changes\n this.emitEvent({\n type: 'preferences-updated',\n accountId: nearAccountId,\n data: { preferences: updatedPreferences }\n });\n }\n }\n\n private async normalizeUserDeviceNumber(\n user: ClientUserDataWithOptionalDevice,\n defaultDeviceNumber: number\n ): Promise<ClientUserData> {\n const hasValidDevice =\n typeof user.deviceNumber === 'number' && Number.isFinite(user.deviceNumber);\n if (hasValidDevice) {\n return user as ClientUserData;\n }\n\n const deviceNumber = defaultDeviceNumber;\n const fixed: ClientUserData = {\n ...(user as Omit<ClientUserData, 'deviceNumber'>),\n deviceNumber,\n };\n await this.storeUser(fixed);\n return fixed;\n }\n\n private async storeUser(userData: ClientUserData): Promise<void> {\n const validation = this.validateNearAccountId(userData.nearAccountId);\n if (!validation.valid) {\n throw new Error(`Cannot store user with invalid account ID: ${validation.error}`);\n }\n\n const db = await this.getDB();\n await db.put(DB_CONFIG.userStore, userData);\n\n // Update lastUserAccountId with new format including device info\n const lastUserState: LastUserAccountIdState = {\n accountId: userData.nearAccountId,\n deviceNumber: userData.deviceNumber,\n };\n\n await this.setAppState('lastUserAccountId', lastUserState);\n }\n\n /**\n * Store WebAuthn user data (compatibility with WebAuthnManager)\n * @param userData - User data with nearAccountId as primary identifier\n */\n async storeWebAuthnUserData(userData: StoreWebAuthnUserDataInput): Promise<void> {\n const validation = this.validateNearAccountId(userData.nearAccountId);\n if (!validation.valid) {\n throw new Error(`Cannot store WebAuthn data for invalid account ID: ${validation.error}`);\n }\n\n const accountId = toAccountId(userData.nearAccountId);\n const deviceNumber = userData.deviceNumber;\n let user = await this.getUser(accountId, deviceNumber);\n\n if (!user) {\n user = await this.registerUser({\n nearAccountId: accountId,\n deviceNumber,\n clientNearPublicKey: userData.clientNearPublicKey,\n passkeyCredential: userData.passkeyCredential,\n encryptedVrfKeypair: userData.encryptedVrfKeypair,\n version: userData.version || 2,\n serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair,\n });\n }\n\n const updatedUser: ClientUserData = {\n ...user,\n clientNearPublicKey: userData.clientNearPublicKey,\n passkeyCredential: userData.passkeyCredential,\n encryptedVrfKeypair: userData.encryptedVrfKeypair,\n serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair ?? user.serverEncryptedVrfKeypair,\n version: userData.version ?? user.version,\n lastUpdated: userData.lastUpdated ?? Date.now(),\n };\n\n await this.storeUser(updatedUser);\n this.emitEvent({\n type: 'user-updated',\n accountId,\n data: { updatedUser }\n });\n }\n\n async getAllUsers(): Promise<ClientUserData[]> {\n const db = await this.getDB();\n return db.getAll(DB_CONFIG.userStore);\n }\n\n async deleteUser(nearAccountId: AccountId): Promise<void> {\n const db = await this.getDB();\n await db.delete(DB_CONFIG.userStore, nearAccountId);\n // Also clean up related authenticators\n await this.clearAuthenticatorsForUser(nearAccountId);\n }\n\n async clearAllUsers(): Promise<void> {\n const db = await this.getDB();\n await db.clear(DB_CONFIG.userStore);\n }\n\n async clearAllAppState(): Promise<void> {\n const db = await this.getDB();\n await db.clear(DB_CONFIG.appStateStore);\n }\n\n /**\n * Store authenticator data for a user\n */\n async storeAuthenticator(authenticatorData: ClientAuthenticatorData): Promise<void> {\n const db = await this.getDB();\n await db.put(DB_CONFIG.authenticatorStore, authenticatorData);\n }\n\n /**\n * Get all authenticators for a user (optionally for a specific device)\n */\n async getAuthenticatorsByUser(nearAccountId: AccountId): Promise<ClientAuthenticatorData[]> {\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readonly');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n const accountId = toAccountId(nearAccountId);\n\n // Get all authenticators for this account across all devices\n const index = store.index('nearAccountId');\n return await index.getAll(accountId);\n }\n\n /**\n * Get a specific authenticator by credential ID\n */\n async getAuthenticatorByCredentialId(\n nearAccountId: AccountId,\n credentialId: string\n ): Promise<ClientAuthenticatorData | null> {\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readonly');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n const accountId = toAccountId(nearAccountId);\n\n // Primary key is [nearAccountId, deviceNumber, credentialId], so we cannot\n // look up by [nearAccountId, credentialId] directly. Use the nearAccountId\n // index and filter by credentialId.\n const index = store.index('nearAccountId');\n const all = await index.getAll(accountId);\n const match = all.find((auth: any) => auth.credentialId === credentialId) || null;\n return match;\n }\n\n /**\n * Clear all authenticators for a user\n */\n async clearAuthenticatorsForUser(nearAccountId: AccountId): Promise<void> {\n const authenticators = await this.getAuthenticatorsByUser(nearAccountId);\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readwrite');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n\n for (const auth of authenticators) {\n // Composite PK is [nearAccountId, deviceNumber, credentialId]\n await store.delete([nearAccountId, auth.deviceNumber, auth.credentialId]);\n }\n }\n\n /**\n * Sync authenticators from contract data\n */\n async syncAuthenticatorsFromContract(\n nearAccountId: AccountId,\n contractAuthenticators: Array<{\n credentialId: string;\n credentialPublicKey: Uint8Array;\n transports?: string[];\n name?: string;\n registered: string;\n vrfPublicKey: string;\n deviceNumber?: number; // Device number from contract\n }>\n ): Promise<void> {\n // Clear existing cache for this user\n await this.clearAuthenticatorsForUser(nearAccountId);\n\n // Add all contract authenticators to cache\n const syncedAt = new Date().toISOString();\n for (const auth of contractAuthenticators) {\n // Fix transport processing: filter out undefined values and provide fallback\n const rawTransports = auth.transports || [];\n const validTransports = rawTransports.filter((transport: any) =>\n transport !== undefined && transport !== null && typeof transport === 'string'\n );\n\n // If no valid transports, default to 'internal' for platform authenticators\n const transports = validTransports.length > 0 ? validTransports : ['internal'];\n\n const clientAuth: ClientAuthenticatorData = {\n credentialId: auth.credentialId,\n credentialPublicKey: auth.credentialPublicKey,\n transports,\n name: auth.name,\n nearAccountId: toAccountId(nearAccountId),\n deviceNumber: auth.deviceNumber || 1, // Default to device 1 (1-indexed)\n registered: auth.registered,\n syncedAt: syncedAt,\n vrfPublicKey: auth.vrfPublicKey,\n };\n await this.storeAuthenticator(clientAuth);\n }\n }\n\n // === ATOMIC OPERATIONS AND ROLLBACK METHODS ===\n\n /**\n * Delete all authenticators for a user\n */\n async deleteAllAuthenticatorsForUser(nearAccountId: AccountId): Promise<void> {\n const authenticators = await this.getAuthenticatorsByUser(nearAccountId);\n\n if (authenticators.length === 0) {\n console.warn(`No authenticators found for user ${nearAccountId}`);\n return;\n }\n\n const db = await this.getDB();\n const tx = db.transaction(DB_CONFIG.authenticatorStore, 'readwrite');\n const store = tx.objectStore(DB_CONFIG.authenticatorStore);\n\n for (const auth of authenticators) {\n // Composite PK is [nearAccountId, deviceNumber, credentialId]\n await store.delete([nearAccountId, auth.deviceNumber, auth.credentialId]);\n }\n\n console.debug(`Deleted ${authenticators.length} authenticators for user ${nearAccountId}`);\n }\n\n /**\n * Get user's confirmation config from IndexedDB\n * @param nearAccountId - The user's account ID\n * @returns ConfirmationConfig or undefined\n */\n async getConfirmationConfig(nearAccountId: AccountId): Promise<ConfirmationConfig> {\n const user = await this.getUser(nearAccountId);\n return user?.preferences?.confirmationConfig || DEFAULT_CONFIRMATION_CONFIG;\n }\n\n /**\n * Get user's theme preference from IndexedDB\n * @param nearAccountId - The user's account ID\n * @returns 'dark' | 'light' | null\n */\n async getTheme(nearAccountId: AccountId): Promise<'dark' | 'light' | null> {\n const user = await this.getUser(nearAccountId);\n return user?.preferences?.confirmationConfig.theme || null;\n }\n\n /**\n * Set user's theme preference in IndexedDB\n * @param nearAccountId - The user's account ID\n * @param theme - The theme to set ('dark' | 'light')\n */\n async setTheme(nearAccountId: AccountId, theme: 'dark' | 'light'): Promise<void> {\n const existingConfig = await this.getConfirmationConfig(nearAccountId);\n const confirmationConfig = { ...existingConfig, theme };\n await this.updatePreferences(nearAccountId, { confirmationConfig });\n }\n\n /**\n * Get user's theme with fallback to 'dark'\n * @param nearAccountId - The user's account ID\n * @returns 'dark' | 'light'\n */\n async getThemeOrDefault(nearAccountId: AccountId): Promise<'dark' | 'light'> {\n const theme = await this.getTheme(nearAccountId);\n return theme || 'dark';\n }\n\n /**\n * Toggle between dark and light theme for a user\n * @param nearAccountId - The user's account ID\n * @returns The new theme that was set\n */\n async toggleTheme(nearAccountId: AccountId): Promise<'dark' | 'light'> {\n const currentTheme = await this.getThemeOrDefault(nearAccountId);\n const newTheme = currentTheme === 'dark' ? 'light' : 'dark';\n await this.setTheme(nearAccountId, newTheme);\n return newTheme;\n }\n\n // === DERIVED ADDRESS METHODS ===\n\n /**\n * Store a derived address for a given NEAR account + contract + path\n */\n async setDerivedAddress(nearAccountId: AccountId, args: { contractId: string; path: string; address: string }): Promise<void> {\n if (!nearAccountId || !args?.contractId || !args?.path || !args?.address) return;\n const validation = this.validateNearAccountId(nearAccountId);\n if (!validation.valid) return;\n const rec: DerivedAddressRecord = {\n nearAccountId: toAccountId(nearAccountId),\n contractId: String(args.contractId),\n path: String(args.path),\n address: String(args.address),\n updatedAt: Date.now(),\n };\n const db = await this.getDB();\n await db.put(DB_CONFIG.derivedAddressStore, rec);\n }\n\n /**\n * Fetch a derived address record; returns null if not found\n */\n async getDerivedAddressRecord(nearAccountId: AccountId, args: { contractId: string; path: string }): Promise<DerivedAddressRecord | null> {\n if (!nearAccountId || !args?.contractId || !args?.path) return null;\n const db = await this.getDB();\n const rec = await db.get(DB_CONFIG.derivedAddressStore, [toAccountId(nearAccountId), String(args.contractId), String(args.path)]);\n return (rec as DerivedAddressRecord) || null;\n }\n\n /**\n * Get only the derived address string; returns null if not set\n */\n async getDerivedAddress(nearAccountId: AccountId, args: { contractId: string; path: string }): Promise<string | null> {\n const rec = await this.getDerivedAddressRecord(nearAccountId, args);\n return rec?.address || null;\n }\n\n // === RECOVERY EMAIL METHODS ===\n\n /**\n * Upsert recovery email records for an account.\n * Merges by hashHex, preferring the most recent email.\n */\n async upsertRecoveryEmails(\n nearAccountId: AccountId,\n entries: Array<{ hashHex: string; email: string }>\n ): Promise<void> {\n if (!nearAccountId || !entries?.length) return;\n const validation = this.validateNearAccountId(nearAccountId);\n if (!validation.valid) return;\n\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n const now = Date.now();\n\n for (const entry of entries) {\n const hashHex = String(entry?.hashHex || '').trim();\n const email = String(entry?.email || '').trim();\n if (!hashHex || !email) continue;\n\n const rec: RecoveryEmailRecord = {\n nearAccountId: accountId,\n hashHex,\n email,\n addedAt: now,\n };\n await db.put(DB_CONFIG.recoveryEmailStore, rec);\n }\n }\n\n /**\n * Fetch all recovery email records for an account.\n */\n async getRecoveryEmails(nearAccountId: AccountId): Promise<RecoveryEmailRecord[]> {\n if (!nearAccountId) return [];\n const db = await this.getDB();\n const accountId = toAccountId(nearAccountId);\n const tx = db.transaction(DB_CONFIG.recoveryEmailStore, 'readonly');\n const store = tx.objectStore(DB_CONFIG.recoveryEmailStore);\n const index = store.index('nearAccountId');\n const result = await index.getAll(accountId);\n return (result as RecoveryEmailRecord[]) || [];\n }\n\n /**\n * Atomic operation wrapper for multiple IndexedDB operations\n * Either all operations succeed or all are rolled back\n */\n async atomicOperation<T>(operation: (db: IDBPDatabase) => Promise<T>): Promise<T> {\n const db = await this.getDB();\n try {\n const result = await operation(db);\n return result;\n } catch (error) {\n console.error('Atomic operation failed:', error);\n throw error;\n }\n }\n\n /**\n * Complete rollback of user registration data\n * Deletes user, authenticators, and WebAuthn data atomically\n */\n async rollbackUserRegistration(nearAccountId: AccountId): Promise<void> {\n console.debug(`Rolling back registration data for ${nearAccountId}`);\n\n await this.atomicOperation(async (db) => {\n // Delete all authenticators for this user\n await this.deleteAllAuthenticatorsForUser(nearAccountId);\n\n // Delete user record\n await db.delete(DB_CONFIG.userStore, nearAccountId);\n\n // Clear from app state if this was the last user\n const lastUserAccount = await this.getAppState<string>('lastUserAccountId');\n if (lastUserAccount === nearAccountId) {\n await this.setAppState('lastUserAccountId', null);\n }\n\n console.debug(`Rolled back all registration data for ${nearAccountId}`);\n return true;\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { init_validation, isFunction } from "./WalletIframe/validation.js";
|
|
2
2
|
import { base64Decode, base64Encode } from "../utils/base64.js";
|
|
3
3
|
import { errorMessage, init_errors } from "../utils/errors.js";
|
|
4
|
-
import "../utils/index.js";
|
|
4
|
+
import { init_utils } from "../utils/index.js";
|
|
5
5
|
import { DEFAULT_WAIT_STATUS, init_rpc } from "./types/rpc.js";
|
|
6
6
|
import { NearRpcError } from "./NearRpcError.js";
|
|
7
7
|
|
|
8
8
|
//#region src/core/NearClient.ts
|
|
9
|
+
init_utils();
|
|
9
10
|
init_errors();
|
|
10
11
|
init_rpc();
|
|
11
12
|
init_validation();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NearClient.js","names":["txPayload: EncodableSignedTx","lastError: unknown","err: unknown","params: Record<string, unknown>","fullAccessKeys: FullAccessKey[]","functionCallAccessKeys: FunctionCallAccessKey[]"],"sources":["../../../../../../src/core/NearClient.ts"],"sourcesContent":["/**\n * Minimal NEAR RPC client that replaces @near-js/providers\n * Only includes the methods actually used by TatchiPasskey\n *\n * If needed, we can just wrap @near-js if we require more complex\n * functionality and type definitions\n */\n\nimport type {\n FinalExecutionOutcome,\n QueryResponseKind,\n TxExecutionStatus,\n AccessKeyView,\n AccessKeyInfoView,\n AccessKeyList,\n FunctionCallPermissionView,\n AccountView,\n BlockResult,\n BlockReference,\n RpcQueryRequest,\n FinalityReference,\n} from \"@near-js/types\";\nimport { base64Encode, base64Decode } from \"../utils\";\nimport { errorMessage } from \"../utils/errors\";\nimport { NearRpcError } from \"./NearRpcError\";\nimport { DEFAULT_WAIT_STATUS, RpcResponse } from \"./types/rpc\";\nimport { isFunction } from './WalletIframe/validation';\nimport {\n WasmTransaction,\n WasmSignature,\n} from \"../wasm_signer_worker/pkg/wasm_signer_worker.js\";\n\n// re-export near-js types\nexport type { AccessKeyList } from \"@near-js/types\";\n\nexport interface ViewAccountParams {\n account: string;\n block_id?: string;\n}\n\nexport type FullAccessKey = Omit<AccessKeyInfoView, 'access_key'>\n & { access_key: Omit<AccessKeyView, 'permission'> & { permission: 'FullAccess' } }\n\nexport type FunctionCallAccessKey = Omit<AccessKeyInfoView, 'access_key'>\n & { access_key: Omit<AccessKeyView, 'permission'> & { permission: FunctionCallPermissionView } }\n\nexport interface ContractResult<T> extends QueryResponseKind {\n result?: T | string | number;\n logs: string[];\n}\n\nexport enum RpcCallType {\n Query = \"query\",\n View = \"view\",\n Send = \"send_tx\",\n Block = \"block\",\n Call = \"call_function\",\n}\n\nexport class SignedTransaction {\n transaction: WasmTransaction;\n signature: WasmSignature;\n borsh_bytes: number[];\n\n constructor(data: {\n transaction: WasmTransaction;\n signature: WasmSignature;\n borsh_bytes: number[]\n }) {\n this.transaction = data.transaction;\n this.signature = data.signature;\n this.borsh_bytes = data.borsh_bytes;\n }\n\n static fromPlain(input: { transaction: unknown; signature: unknown; borsh_bytes: number[] }): SignedTransaction {\n return new SignedTransaction({\n transaction: input.transaction as WasmTransaction,\n signature: input.signature as WasmSignature,\n borsh_bytes: input.borsh_bytes,\n });\n }\n\n encode(): ArrayBuffer {\n // If borsh_bytes are already available, use them\n return (new Uint8Array(this.borsh_bytes)).buffer;\n }\n\n base64Encode(): string {\n return base64Encode(this.encode());\n }\n\n static decode(bytes: Uint8Array): SignedTransaction {\n // This would need borsh deserialization\n throw new Error('SignedTransaction.decode(): borsh deserialization not implemented');\n }\n}\n\n/**\n * Serialize a signed transaction-like object to base64.\n * Accepts either our SignedTransaction instance or a plain object\n * with borsh bytes (borsh_bytes | borshBytes) from cross-origin RPC.\n *\n * Implementation notes / pitfalls:\n * - We always bind `this` correctly when calling .base64Encode() / .encode()\n * so methods defined on SignedTransaction can safely call this.encode().\n * - The underlying base64Encode() helper is implemented to avoid spreading large\n * Uint8Arrays into String.fromCharCode(...), which can overflow the JS call\n * stack for big WASM binaries or large transactions.\n * - As a fallback, we accept raw borsh bytes in multiple shapes to keep the\n * serializer resilient to different runtimes (plain objects, typed arrays, etc.).\n */\nexport type EncodableSignedTx =\n | SignedTransaction\n | {\n // Borsh bytes in various shapes from different runtimes\n borsh_bytes?: unknown;\n borshBytes?: unknown;\n // Optional helper methods from some callers\n encode?: () => ArrayBuffer;\n base64Encode?: () => string;\n };\n\nexport function toArrayBufferFromUnknownBytes(\n bytes: unknown\n): ArrayBuffer | SharedArrayBuffer | null {\n if (!bytes) return null;\n\n // Plain number[]\n if (Array.isArray(bytes)) {\n return new Uint8Array(bytes as number[]).buffer;\n }\n\n // Typed arrays / DataView\n if (ArrayBuffer.isView(bytes)) {\n const view = bytes as ArrayBufferView;\n return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);\n }\n\n // Raw ArrayBuffer\n if (bytes instanceof ArrayBuffer) {\n return bytes;\n }\n\n return null;\n}\n\nexport function encodeSignedTransactionBase64(signed: EncodableSignedTx): string {\n // Some call sites wrap the actual SignedTransaction in a { signedTransaction } envelope.\n // Normalize that here so the rest of the function always works with a concrete tx-like object.\n const maybeSigned = (signed as any)?.signedTransaction;\n const txPayload: EncodableSignedTx =\n maybeSigned && typeof maybeSigned === 'object'\n ? (maybeSigned as EncodableSignedTx)\n : signed;\n\n // 1) If the payload exposes a .base64Encode() helper (our SignedTransaction class),\n // use it directly. Bind `this` so the method can safely call this.encode().\n const maybeBase64 = (txPayload as { base64Encode?: unknown }).base64Encode;\n if (isFunction(maybeBase64)) {\n return (maybeBase64 as () => string).call(txPayload);\n }\n\n // 2) Otherwise, fall back to a generic encode() → ArrayBuffer method if present.\n const maybeEncode = (txPayload as { encode?: unknown }).encode;\n if (isFunction(maybeEncode)) {\n const buf = (maybeEncode as () => ArrayBuffer).call(txPayload);\n return base64Encode(buf);\n }\n\n // 3) Finally, accept raw borsh bytes in multiple shapes / field names.\n // This keeps the serializer resilient across runtimes that may not\n // hydrate SignedTransaction instances but still provide borsh_bytes/Bytes.\n const snakeBuf = toArrayBufferFromUnknownBytes(\n (txPayload as { borsh_bytes?: unknown }).borsh_bytes\n );\n if (snakeBuf) {\n return base64Encode(snakeBuf);\n }\n\n const camelBuf = toArrayBufferFromUnknownBytes(\n (txPayload as { borshBytes?: unknown }).borshBytes\n );\n if (camelBuf) {\n return base64Encode(camelBuf);\n }\n\n throw new Error('Invalid signed transaction payload: cannot serialize to base64');\n}\n\n/**\n * MinimalNearClient provides a simplified interface for NEAR protocol interactions\n */\nexport interface NearClient {\n viewAccessKey(accountId: string, publicKey: string, finalityQuery?: FinalityReference): Promise<AccessKeyView>;\n viewAccessKeyList(accountId: string, finalityQuery?: FinalityReference): Promise<AccessKeyList>;\n viewAccount(accountId: string): Promise<AccountView>;\n viewCode(accountId: string, finalityQuery?: FinalityReference): Promise<Uint8Array>;\n viewBlock(params: BlockReference): Promise<BlockResult>;\n sendTransaction(\n signedTransaction: SignedTransaction,\n waitUntil?: TxExecutionStatus\n ): Promise<FinalExecutionOutcome>;\n query<T extends QueryResponseKind>(params: RpcQueryRequest): Promise<T>;\n callFunction<A, T>(\n contractId: string,\n method: string,\n args: A,\n blockQuery?: BlockReference\n ): Promise<T>;\n view<A, T>(params: { account: string; method: string; args: A }): Promise<T>;\n getAccessKeys(params: ViewAccountParams): Promise<{\n fullAccessKeys: FullAccessKey[];\n functionCallAccessKeys: FunctionCallAccessKey[];\n }>;\n}\n\nexport class MinimalNearClient implements NearClient {\n private readonly rpcUrls: string[];\n\n constructor(rpcUrl: string | string[]) {\n this.rpcUrls = MinimalNearClient.normalizeRpcUrls(rpcUrl);\n }\n\n private static normalizeRpcUrls(input: string | string[]): string[] {\n const urls = Array.isArray(input)\n ? input\n : input\n .split(/[\\s,]+/)\n .map(url => url.trim())\n .filter(Boolean);\n\n const normalized = urls.map(url => {\n try {\n return new URL(url).toString();\n } catch (err) {\n const message = errorMessage(err) || `Invalid NEAR RPC URL: ${url}`;\n throw new Error(message);\n }\n });\n\n if (!normalized.length) {\n throw new Error('NEAR RPC URL cannot be empty');\n }\n\n return Array.from(new Set(normalized));\n }\n\n // ===========================\n // PRIVATE HELPER FUNCTIONS\n // ===========================\n\n /** Build a JSON-RPC 2.0 POST body (stringified). */\n private buildRequestBody<P>(method: string, params: P): string {\n return JSON.stringify({\n jsonrpc: '2.0',\n id: crypto.randomUUID(),\n method,\n params\n });\n }\n\n /** Perform a single POST to one endpoint and return parsed RpcResponse. */\n private async postOnce(url: string, requestBody: string): Promise<RpcResponse> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: requestBody\n });\n\n if (!response.ok) {\n throw new Error(`RPC request failed: ${response.status} ${response.statusText}`);\n }\n\n const text = await response.text();\n if (!text?.trim()) {\n throw new Error('Empty response from RPC server');\n }\n\n return JSON.parse(text) as RpcResponse;\n }\n\n /** Try each configured RPC endpoint in order and return the first successful RpcResponse. */\n private async requestWithFallback(requestBody: string): Promise<RpcResponse> {\n let lastError: unknown;\n for (const [index, url] of this.rpcUrls.entries()) {\n try {\n const result = await this.postOnce(url, requestBody);\n if (index > 0) console.warn(`[NearClient] RPC succeeded via fallback: ${url}`);\n return result;\n } catch (err) {\n lastError = err;\n const remaining = index < this.rpcUrls.length - 1;\n console.warn(`[NearClient] RPC call to ${url} failed${remaining ? ', trying next' : ''}: ${errorMessage(err) || 'RPC request failed'}`);\n if (!remaining) throw err instanceof Error ? err : new Error(String(err));\n }\n }\n throw new Error(errorMessage(lastError) || 'RPC request failed');\n }\n\n /** Validate and unwrap RpcResponse into the typed result with rich error forwarding. */\n private unwrapRpcResult<T>(rpc: RpcResponse, operationName: string): T {\n if (rpc.error) {\n throw NearRpcError.fromRpcResponse(operationName, rpc);\n }\n const result = rpc.result as any;\n // Some providers return a wrapped error in `result.error`\n if (result?.error) {\n const msg = typeof result.error === 'string' ? result.error : JSON.stringify(result.error);\n throw new NearRpcError({ message: `${operationName} Error: ${msg}`, short: 'RpcError', type: 'RpcError' });\n }\n return rpc.result as T;\n }\n\n /**\n * Execute RPC call with proper error handling and result extraction\n */\n private async makeRpcCall<P, T>(\n method: string,\n params: P,\n operationName: string\n ): Promise<T> {\n const requestBody = this.buildRequestBody(method, params);\n const rpc = await this.requestWithFallback(requestBody);\n return this.unwrapRpcResult<T>(rpc, operationName);\n }\n\n // ===========================\n // PUBLIC API METHODS\n // ===========================\n\n async query<T extends QueryResponseKind>(params: RpcQueryRequest): Promise<T> {\n return this.makeRpcCall<RpcQueryRequest, T>(RpcCallType.Query, params, 'Query');\n }\n\n async viewAccessKey(accountId: string, publicKey: string, finalityQuery?: FinalityReference): Promise<AccessKeyView> {\n const publicKeyStr = publicKey;\n const finality = finalityQuery?.finality || 'final';\n const params = {\n request_type: 'view_access_key',\n finality: finality,\n account_id: accountId,\n public_key: publicKeyStr\n };\n return this.makeRpcCall<typeof params, AccessKeyView>(\n RpcCallType.Query,\n params,\n 'View Access Key'\n );\n }\n\n async viewAccessKeyList(accountId: string, finalityQuery?: FinalityReference): Promise<AccessKeyList> {\n const finality = finalityQuery?.finality || 'final';\n const params = {\n request_type: 'view_access_key_list',\n finality: finality,\n account_id: accountId\n };\n return this.makeRpcCall<typeof params, AccessKeyList>(RpcCallType.Query, params, 'View Access Key List');\n }\n\n async viewAccount(accountId: string): Promise<AccountView> {\n const params = {\n request_type: 'view_account',\n finality: 'final',\n account_id: accountId\n };\n return this.makeRpcCall<typeof params, AccountView>(RpcCallType.Query, params, 'View Account');\n }\n\n async viewCode(accountId: string, finalityQuery?: FinalityReference): Promise<Uint8Array> {\n const finality = finalityQuery?.finality || 'final';\n const params = {\n request_type: 'view_code',\n finality,\n account_id: accountId\n };\n const result = await this.makeRpcCall<typeof params, any>(\n RpcCallType.Query,\n params,\n 'View Code'\n );\n const codeBase64 = result?.code_base64;\n if (typeof codeBase64 !== 'string' || !codeBase64.length) {\n throw new Error('Invalid View Code response: missing code_base64');\n }\n return base64Decode(codeBase64);\n }\n\n async viewBlock(params: BlockReference): Promise<BlockResult> {\n return this.makeRpcCall<BlockReference, BlockResult>(RpcCallType.Block, params, 'View Block');\n }\n\n async sendTransaction(\n signedTransaction: SignedTransaction,\n waitUntil: TxExecutionStatus = DEFAULT_WAIT_STATUS.executeAction\n ): Promise<FinalExecutionOutcome> {\n const params = {\n signed_tx_base64: encodeSignedTransactionBase64(signedTransaction),\n wait_until: waitUntil\n };\n\n // Retry on transient RPC errors commonly seen with shared/public nodes\n const maxAttempts = 5;\n let lastError: unknown = null;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const outcome = await this.makeRpcCall<typeof params, FinalExecutionOutcome>(RpcCallType.Send, params, 'Send Transaction');\n // near-api-js throws on Failure; replicate that for clearer UX\n const status = (outcome as any)?.status;\n if (status && typeof status === 'object' && 'Failure' in status) {\n const failure = (status as any).Failure;\n throw NearRpcError.fromOutcome('Send Transaction', outcome, failure);\n }\n return outcome;\n } catch (err: unknown) {\n lastError = err;\n const msg = errorMessage(err);\n const retryable = /server error|internal|temporar|timeout|too many requests|429|unavailable|bad gateway|gateway timeout/i.test(msg || '');\n if (!retryable || attempt === maxAttempts) {\n throw err;\n }\n // Exponential backoff with jitter (200–1200ms approx across attempts)\n const base = 200 * Math.pow(2, attempt - 1);\n const jitter = Math.floor(Math.random() * 150);\n await new Promise(r => setTimeout(r, base + jitter));\n }\n }\n // Should be unreachable\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n // legacy helpers removed in favor of NearRpcError\n\n async callFunction<A, T>(\n contractId: string,\n method: string,\n args: A,\n blockQuery?: BlockReference\n ): Promise<T> {\n const rpcParams = {\n request_type: 'call_function',\n finality: 'final',\n account_id: contractId,\n method_name: method,\n args_base64: base64Encode(new TextEncoder().encode(JSON.stringify(args)).buffer)\n };\n const result = await this.makeRpcCall<typeof rpcParams, ContractResult<T>>(\n RpcCallType.Query,\n rpcParams,\n 'View Function'\n );\n\n // Parse result bytes to string/JSON\n const resultBytes = result.result;\n\n if (!Array.isArray(resultBytes)) {\n // If result is not bytes array, it might already be parsed\n return result as unknown as T;\n }\n\n const resultString = String.fromCharCode(...resultBytes);\n\n if (!resultString.trim()) {\n return null as T;\n }\n\n try {\n const parsed = JSON.parse(resultString);\n return parsed as T;\n } catch (parseError) {\n console.warn('Failed to parse result as JSON, returning as string:', parseError);\n console.warn('Raw result string:', resultString);\n // Return the string value if it's not valid JSON\n const cleanString = resultString.replace(/^\"|\"$/g, ''); // Remove quotes\n return cleanString as T;\n }\n }\n\n async view<A, T>(params: { account: string; method: string; args: A }): Promise<T> {\n return this.callFunction<A, T>(params.account, params.method, params.args);\n }\n\n async getAccessKeys({ account, block_id }: ViewAccountParams): Promise<{\n fullAccessKeys: FullAccessKey[];\n functionCallAccessKeys: FunctionCallAccessKey[];\n }> {\n // Build RPC parameters similar to the official implementation\n const params: Record<string, unknown> = {\n request_type: 'view_access_key_list',\n account_id: account,\n finality: 'final'\n };\n\n // Add block_id if provided (for specific block queries)\n if (block_id) {\n params.block_id = block_id;\n delete params.finality; // block_id takes precedence over finality\n }\n\n // Make the RPC call directly to match the official implementation\n const accessKeyList = await this.makeRpcCall<typeof params, AccessKeyList>(\n RpcCallType.Query,\n params,\n 'View Access Key List'\n );\n\n // Separate full access keys and function call access keys\n const fullAccessKeys: FullAccessKey[] = [];\n const functionCallAccessKeys: FunctionCallAccessKey[] = [];\n\n // Process each access key (matching the official categorization logic)\n for (const key of accessKeyList.keys) {\n if (key.access_key.permission === 'FullAccess') {\n // Full Access Keys: Keys with FullAccess permission\n fullAccessKeys.push(key as FullAccessKey);\n } else if (key.access_key.permission && typeof key.access_key.permission === 'object' && 'FunctionCall' in key.access_key.permission) {\n // Function Call Keys: Keys with limited permissions for specific contract calls\n functionCallAccessKeys.push(key as FunctionCallAccessKey);\n }\n }\n\n return {\n fullAccessKeys,\n functionCallAccessKeys\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NearClient.js","names":["txPayload: EncodableSignedTx","lastError: unknown","err: unknown","params: Record<string, unknown>","fullAccessKeys: FullAccessKey[]","functionCallAccessKeys: FunctionCallAccessKey[]"],"sources":["../../../../../../src/core/NearClient.ts"],"sourcesContent":["/**\n * Minimal NEAR RPC client that replaces @near-js/providers\n * Only includes the methods actually used by TatchiPasskey\n *\n * If needed, we can just wrap @near-js if we require more complex\n * functionality and type definitions\n */\n\nimport type {\n FinalExecutionOutcome,\n QueryResponseKind,\n TxExecutionStatus,\n AccessKeyView,\n AccessKeyInfoView,\n AccessKeyList,\n FunctionCallPermissionView,\n AccountView,\n BlockResult,\n BlockReference,\n RpcQueryRequest,\n FinalityReference,\n} from \"@near-js/types\";\nimport { base64Encode, base64Decode } from \"../utils\";\nimport { errorMessage } from \"../utils/errors\";\nimport { NearRpcError } from \"./NearRpcError\";\nimport { DEFAULT_WAIT_STATUS, RpcResponse } from \"./types/rpc\";\nimport { isFunction } from './WalletIframe/validation';\nimport {\n WasmTransaction,\n WasmSignature,\n} from \"../wasm_signer_worker/pkg/wasm_signer_worker.js\";\n\n// re-export near-js types\nexport type { AccessKeyList } from \"@near-js/types\";\n\nexport interface ViewAccountParams {\n account: string;\n block_id?: string;\n}\n\nexport type FullAccessKey = Omit<AccessKeyInfoView, 'access_key'>\n & { access_key: Omit<AccessKeyView, 'permission'> & { permission: 'FullAccess' } }\n\nexport type FunctionCallAccessKey = Omit<AccessKeyInfoView, 'access_key'>\n & { access_key: Omit<AccessKeyView, 'permission'> & { permission: FunctionCallPermissionView } }\n\nexport interface ContractResult<T> extends QueryResponseKind {\n result?: T | string | number;\n logs: string[];\n}\n\nexport enum RpcCallType {\n Query = \"query\",\n View = \"view\",\n Send = \"send_tx\",\n Block = \"block\",\n Call = \"call_function\",\n}\n\nexport class SignedTransaction {\n transaction: WasmTransaction;\n signature: WasmSignature;\n borsh_bytes: number[];\n\n constructor(data: {\n transaction: WasmTransaction;\n signature: WasmSignature;\n borsh_bytes: number[]\n }) {\n this.transaction = data.transaction;\n this.signature = data.signature;\n this.borsh_bytes = data.borsh_bytes;\n }\n\n static fromPlain(input: { transaction: unknown; signature: unknown; borsh_bytes: number[] }): SignedTransaction {\n return new SignedTransaction({\n transaction: input.transaction as WasmTransaction,\n signature: input.signature as WasmSignature,\n borsh_bytes: input.borsh_bytes,\n });\n }\n\n encode(): ArrayBuffer {\n // If borsh_bytes are already available, use them\n return (new Uint8Array(this.borsh_bytes)).buffer;\n }\n\n base64Encode(): string {\n return base64Encode(this.encode());\n }\n\n static decode(bytes: Uint8Array): SignedTransaction {\n // This would need borsh deserialization\n throw new Error('SignedTransaction.decode(): borsh deserialization not implemented');\n }\n}\n\n/**\n * Serialize a signed transaction-like object to base64.\n * Accepts either our SignedTransaction instance or a plain object\n * with borsh bytes (borsh_bytes | borshBytes) from cross-origin RPC.\n *\n * Implementation notes / pitfalls:\n * - We always bind `this` correctly when calling .base64Encode() / .encode()\n * so methods defined on SignedTransaction can safely call this.encode().\n * - The underlying base64Encode() helper is implemented to avoid spreading large\n * Uint8Arrays into String.fromCharCode(...), which can overflow the JS call\n * stack for big WASM binaries or large transactions.\n * - As a fallback, we accept raw borsh bytes in multiple shapes to keep the\n * serializer resilient to different runtimes (plain objects, typed arrays, etc.).\n */\nexport type EncodableSignedTx =\n | SignedTransaction\n | {\n // Borsh bytes in various shapes from different runtimes\n borsh_bytes?: unknown;\n borshBytes?: unknown;\n // Optional helper methods from some callers\n encode?: () => ArrayBuffer;\n base64Encode?: () => string;\n };\n\nexport function toArrayBufferFromUnknownBytes(\n bytes: unknown\n): ArrayBuffer | SharedArrayBuffer | null {\n if (!bytes) return null;\n\n // Plain number[]\n if (Array.isArray(bytes)) {\n return new Uint8Array(bytes as number[]).buffer;\n }\n\n // Typed arrays / DataView\n if (ArrayBuffer.isView(bytes)) {\n const view = bytes as ArrayBufferView;\n return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);\n }\n\n // Raw ArrayBuffer\n if (bytes instanceof ArrayBuffer) {\n return bytes;\n }\n\n return null;\n}\n\nexport function encodeSignedTransactionBase64(signed: EncodableSignedTx): string {\n // Some call sites wrap the actual SignedTransaction in a { signedTransaction } envelope.\n // Normalize that here so the rest of the function always works with a concrete tx-like object.\n const maybeSigned = (signed as any)?.signedTransaction;\n const txPayload: EncodableSignedTx =\n maybeSigned && typeof maybeSigned === 'object'\n ? (maybeSigned as EncodableSignedTx)\n : signed;\n\n // 1) If the payload exposes a .base64Encode() helper (our SignedTransaction class),\n // use it directly. Bind `this` so the method can safely call this.encode().\n const maybeBase64 = (txPayload as { base64Encode?: unknown }).base64Encode;\n if (isFunction(maybeBase64)) {\n return (maybeBase64 as () => string).call(txPayload);\n }\n\n // 2) Otherwise, fall back to a generic encode() → ArrayBuffer method if present.\n const maybeEncode = (txPayload as { encode?: unknown }).encode;\n if (isFunction(maybeEncode)) {\n const buf = (maybeEncode as () => ArrayBuffer).call(txPayload);\n return base64Encode(buf);\n }\n\n // 3) Finally, accept raw borsh bytes in multiple shapes / field names.\n // This keeps the serializer resilient across runtimes that may not\n // hydrate SignedTransaction instances but still provide borsh_bytes/Bytes.\n const snakeBuf = toArrayBufferFromUnknownBytes(\n (txPayload as { borsh_bytes?: unknown }).borsh_bytes\n );\n if (snakeBuf) {\n return base64Encode(snakeBuf);\n }\n\n const camelBuf = toArrayBufferFromUnknownBytes(\n (txPayload as { borshBytes?: unknown }).borshBytes\n );\n if (camelBuf) {\n return base64Encode(camelBuf);\n }\n\n throw new Error('Invalid signed transaction payload: cannot serialize to base64');\n}\n\n/**\n * MinimalNearClient provides a simplified interface for NEAR protocol interactions\n */\nexport interface NearClient {\n viewAccessKey(accountId: string, publicKey: string, finalityQuery?: FinalityReference): Promise<AccessKeyView>;\n viewAccessKeyList(accountId: string, finalityQuery?: FinalityReference): Promise<AccessKeyList>;\n viewAccount(accountId: string): Promise<AccountView>;\n viewCode(accountId: string, finalityQuery?: FinalityReference): Promise<Uint8Array>;\n viewBlock(params: BlockReference): Promise<BlockResult>;\n sendTransaction(\n signedTransaction: SignedTransaction,\n waitUntil?: TxExecutionStatus\n ): Promise<FinalExecutionOutcome>;\n query<T extends QueryResponseKind>(params: RpcQueryRequest): Promise<T>;\n callFunction<A, T>(\n contractId: string,\n method: string,\n args: A,\n blockQuery?: BlockReference\n ): Promise<T>;\n view<A, T>(params: { account: string; method: string; args: A }): Promise<T>;\n getAccessKeys(params: ViewAccountParams): Promise<{\n fullAccessKeys: FullAccessKey[];\n functionCallAccessKeys: FunctionCallAccessKey[];\n }>;\n}\n\nexport class MinimalNearClient implements NearClient {\n private readonly rpcUrls: string[];\n\n constructor(rpcUrl: string | string[]) {\n this.rpcUrls = MinimalNearClient.normalizeRpcUrls(rpcUrl);\n }\n\n private static normalizeRpcUrls(input: string | string[]): string[] {\n const urls = Array.isArray(input)\n ? input\n : input\n .split(/[\\s,]+/)\n .map(url => url.trim())\n .filter(Boolean);\n\n const normalized = urls.map(url => {\n try {\n return new URL(url).toString();\n } catch (err) {\n const message = errorMessage(err) || `Invalid NEAR RPC URL: ${url}`;\n throw new Error(message);\n }\n });\n\n if (!normalized.length) {\n throw new Error('NEAR RPC URL cannot be empty');\n }\n\n return Array.from(new Set(normalized));\n }\n\n // ===========================\n // PRIVATE HELPER FUNCTIONS\n // ===========================\n\n /** Build a JSON-RPC 2.0 POST body (stringified). */\n private buildRequestBody<P>(method: string, params: P): string {\n return JSON.stringify({\n jsonrpc: '2.0',\n id: crypto.randomUUID(),\n method,\n params\n });\n }\n\n /** Perform a single POST to one endpoint and return parsed RpcResponse. */\n private async postOnce(url: string, requestBody: string): Promise<RpcResponse> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: requestBody\n });\n\n if (!response.ok) {\n throw new Error(`RPC request failed: ${response.status} ${response.statusText}`);\n }\n\n const text = await response.text();\n if (!text?.trim()) {\n throw new Error('Empty response from RPC server');\n }\n\n return JSON.parse(text) as RpcResponse;\n }\n\n /** Try each configured RPC endpoint in order and return the first successful RpcResponse. */\n private async requestWithFallback(requestBody: string): Promise<RpcResponse> {\n let lastError: unknown;\n for (const [index, url] of this.rpcUrls.entries()) {\n try {\n const result = await this.postOnce(url, requestBody);\n if (index > 0) console.warn(`[NearClient] RPC succeeded via fallback: ${url}`);\n return result;\n } catch (err) {\n lastError = err;\n const remaining = index < this.rpcUrls.length - 1;\n console.warn(`[NearClient] RPC call to ${url} failed${remaining ? ', trying next' : ''}: ${errorMessage(err) || 'RPC request failed'}`);\n if (!remaining) throw err instanceof Error ? err : new Error(String(err));\n }\n }\n throw new Error(errorMessage(lastError) || 'RPC request failed');\n }\n\n /** Validate and unwrap RpcResponse into the typed result with rich error forwarding. */\n private unwrapRpcResult<T>(rpc: RpcResponse, operationName: string): T {\n if (rpc.error) {\n throw NearRpcError.fromRpcResponse(operationName, rpc);\n }\n const result = rpc.result as any;\n // Some providers return a wrapped error in `result.error`\n if (result?.error) {\n const msg = typeof result.error === 'string' ? result.error : JSON.stringify(result.error);\n throw new NearRpcError({ message: `${operationName} Error: ${msg}`, short: 'RpcError', type: 'RpcError' });\n }\n return rpc.result as T;\n }\n\n /**\n * Execute RPC call with proper error handling and result extraction\n */\n private async makeRpcCall<P, T>(\n method: string,\n params: P,\n operationName: string\n ): Promise<T> {\n const requestBody = this.buildRequestBody(method, params);\n const rpc = await this.requestWithFallback(requestBody);\n return this.unwrapRpcResult<T>(rpc, operationName);\n }\n\n // ===========================\n // PUBLIC API METHODS\n // ===========================\n\n async query<T extends QueryResponseKind>(params: RpcQueryRequest): Promise<T> {\n return this.makeRpcCall<RpcQueryRequest, T>(RpcCallType.Query, params, 'Query');\n }\n\n async viewAccessKey(accountId: string, publicKey: string, finalityQuery?: FinalityReference): Promise<AccessKeyView> {\n const publicKeyStr = publicKey;\n const finality = finalityQuery?.finality || 'final';\n const params = {\n request_type: 'view_access_key',\n finality: finality,\n account_id: accountId,\n public_key: publicKeyStr\n };\n return this.makeRpcCall<typeof params, AccessKeyView>(\n RpcCallType.Query,\n params,\n 'View Access Key'\n );\n }\n\n async viewAccessKeyList(accountId: string, finalityQuery?: FinalityReference): Promise<AccessKeyList> {\n const finality = finalityQuery?.finality || 'final';\n const params = {\n request_type: 'view_access_key_list',\n finality: finality,\n account_id: accountId\n };\n return this.makeRpcCall<typeof params, AccessKeyList>(RpcCallType.Query, params, 'View Access Key List');\n }\n\n async viewAccount(accountId: string): Promise<AccountView> {\n const params = {\n request_type: 'view_account',\n finality: 'final',\n account_id: accountId\n };\n return this.makeRpcCall<typeof params, AccountView>(RpcCallType.Query, params, 'View Account');\n }\n\n async viewCode(accountId: string, finalityQuery?: FinalityReference): Promise<Uint8Array> {\n const finality = finalityQuery?.finality || 'final';\n const params = {\n request_type: 'view_code',\n finality,\n account_id: accountId\n };\n const result = await this.makeRpcCall<typeof params, any>(\n RpcCallType.Query,\n params,\n 'View Code'\n );\n const codeBase64 = result?.code_base64;\n if (typeof codeBase64 !== 'string' || !codeBase64.length) {\n throw new Error('Invalid View Code response: missing code_base64');\n }\n return base64Decode(codeBase64);\n }\n\n async viewBlock(params: BlockReference): Promise<BlockResult> {\n return this.makeRpcCall<BlockReference, BlockResult>(RpcCallType.Block, params, 'View Block');\n }\n\n async sendTransaction(\n signedTransaction: SignedTransaction,\n waitUntil: TxExecutionStatus = DEFAULT_WAIT_STATUS.executeAction\n ): Promise<FinalExecutionOutcome> {\n const params = {\n signed_tx_base64: encodeSignedTransactionBase64(signedTransaction),\n wait_until: waitUntil\n };\n\n // Retry on transient RPC errors commonly seen with shared/public nodes\n const maxAttempts = 5;\n let lastError: unknown = null;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const outcome = await this.makeRpcCall<typeof params, FinalExecutionOutcome>(RpcCallType.Send, params, 'Send Transaction');\n // near-api-js throws on Failure; replicate that for clearer UX\n const status = (outcome as any)?.status;\n if (status && typeof status === 'object' && 'Failure' in status) {\n const failure = (status as any).Failure;\n throw NearRpcError.fromOutcome('Send Transaction', outcome, failure);\n }\n return outcome;\n } catch (err: unknown) {\n lastError = err;\n const msg = errorMessage(err);\n const retryable = /server error|internal|temporar|timeout|too many requests|429|unavailable|bad gateway|gateway timeout/i.test(msg || '');\n if (!retryable || attempt === maxAttempts) {\n throw err;\n }\n // Exponential backoff with jitter (200–1200ms approx across attempts)\n const base = 200 * Math.pow(2, attempt - 1);\n const jitter = Math.floor(Math.random() * 150);\n await new Promise(r => setTimeout(r, base + jitter));\n }\n }\n // Should be unreachable\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n // legacy helpers removed in favor of NearRpcError\n\n async callFunction<A, T>(\n contractId: string,\n method: string,\n args: A,\n blockQuery?: BlockReference\n ): Promise<T> {\n const rpcParams = {\n request_type: 'call_function',\n finality: 'final',\n account_id: contractId,\n method_name: method,\n args_base64: base64Encode(new TextEncoder().encode(JSON.stringify(args)).buffer)\n };\n const result = await this.makeRpcCall<typeof rpcParams, ContractResult<T>>(\n RpcCallType.Query,\n rpcParams,\n 'View Function'\n );\n\n // Parse result bytes to string/JSON\n const resultBytes = result.result;\n\n if (!Array.isArray(resultBytes)) {\n // If result is not bytes array, it might already be parsed\n return result as unknown as T;\n }\n\n const resultString = String.fromCharCode(...resultBytes);\n\n if (!resultString.trim()) {\n return null as T;\n }\n\n try {\n const parsed = JSON.parse(resultString);\n return parsed as T;\n } catch (parseError) {\n console.warn('Failed to parse result as JSON, returning as string:', parseError);\n console.warn('Raw result string:', resultString);\n // Return the string value if it's not valid JSON\n const cleanString = resultString.replace(/^\"|\"$/g, ''); // Remove quotes\n return cleanString as T;\n }\n }\n\n async view<A, T>(params: { account: string; method: string; args: A }): Promise<T> {\n return this.callFunction<A, T>(params.account, params.method, params.args);\n }\n\n async getAccessKeys({ account, block_id }: ViewAccountParams): Promise<{\n fullAccessKeys: FullAccessKey[];\n functionCallAccessKeys: FunctionCallAccessKey[];\n }> {\n // Build RPC parameters similar to the official implementation\n const params: Record<string, unknown> = {\n request_type: 'view_access_key_list',\n account_id: account,\n finality: 'final'\n };\n\n // Add block_id if provided (for specific block queries)\n if (block_id) {\n params.block_id = block_id;\n delete params.finality; // block_id takes precedence over finality\n }\n\n // Make the RPC call directly to match the official implementation\n const accessKeyList = await this.makeRpcCall<typeof params, AccessKeyList>(\n RpcCallType.Query,\n params,\n 'View Access Key List'\n );\n\n // Separate full access keys and function call access keys\n const fullAccessKeys: FullAccessKey[] = [];\n const functionCallAccessKeys: FunctionCallAccessKey[] = [];\n\n // Process each access key (matching the official categorization logic)\n for (const key of accessKeyList.keys) {\n if (key.access_key.permission === 'FullAccess') {\n // Full Access Keys: Keys with FullAccess permission\n fullAccessKeys.push(key as FullAccessKey);\n } else if (key.access_key.permission && typeof key.access_key.permission === 'object' && 'FunctionCall' in key.access_key.permission) {\n // Function Call Keys: Keys with limited permissions for specific contract calls\n functionCallAccessKeys.push(key as FunctionCallAccessKey);\n }\n }\n\n return {\n fullAccessKeys,\n functionCallAccessKeys\n };\n }\n}\n"],"mappings":"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"}
|