@tatchi-xyz/sdk 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/EmailRecovery/index.js +25 -0
- package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js +135 -77
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/index.js +2 -1
- package/dist/cjs/core/TatchiPasskey/index.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/cjs/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/cjs/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/cjs/core/WalletIframe/client/router.js +1 -1
- package/dist/cjs/core/WalletIframe/client/router.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/cjs/core/defaultConfigs.js +3 -7
- package/dist/cjs/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/core/nearCrypto.js +29 -5
- package/dist/cjs/core/nearCrypto.js.map +1 -1
- package/dist/cjs/core/rpcCalls.js +56 -26
- package/dist/cjs/core/rpcCalls.js.map +1 -1
- package/dist/cjs/core/types/emailRecovery.js +33 -0
- package/dist/cjs/core/types/emailRecovery.js.map +1 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-BG_6hcim.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-C-RcGfr5.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/client.js +30 -8
- package/dist/cjs/react/components/PasskeyAuthMenu/client.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +22 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +354 -154
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CB0UCQ_h.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
- package/dist/cjs/react/context/useSDKFlowRuntime.js +183 -0
- package/dist/cjs/react/context/useSDKFlowRuntime.js.map +1 -0
- package/dist/cjs/react/context/useTatchiContextValue.js +24 -15
- package/dist/cjs/react/context/useTatchiContextValue.js.map +1 -1
- package/dist/cjs/react/context/useTatchiWithSdkFlow.js +96 -0
- package/dist/cjs/react/context/useTatchiWithSdkFlow.js.map +1 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +26 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +135 -77
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js +2 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js +1 -1
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/defaultConfigs.js +3 -7
- package/dist/cjs/react/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/nearCrypto.js +29 -5
- package/dist/cjs/react/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/rpcCalls.js +56 -26
- package/dist/cjs/react/sdk/src/core/rpcCalls.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/types/emailRecovery.js +33 -0
- package/dist/cjs/react/sdk/src/core/types/emailRecovery.js.map +1 -0
- package/dist/cjs/server/email-recovery/emailParsers.js +2 -1
- package/dist/cjs/server/email-recovery/emailParsers.js.map +1 -1
- package/dist/cjs/server/email-recovery/index.js +6 -6
- package/dist/cjs/server/email-recovery/index.js.map +1 -1
- package/dist/cjs/server/email-recovery/rpcCalls.js +22 -3
- package/dist/cjs/server/email-recovery/rpcCalls.js.map +1 -1
- package/dist/cjs/server/router/cloudflare.js +8 -3
- 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 +2 -4
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/server/sdk/src/core/nearCrypto.js +26 -7
- package/dist/cjs/server/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/esm/core/EmailRecovery/index.js +25 -1
- package/dist/esm/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/emailRecovery.js +136 -78
- package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/index.js +2 -1
- package/dist/esm/core/TatchiPasskey/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/esm/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/esm/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/esm/core/WalletIframe/client/router.js +1 -1
- package/dist/esm/core/WalletIframe/client/router.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/esm/core/defaultConfigs.js +3 -7
- package/dist/esm/core/defaultConfigs.js.map +1 -1
- package/dist/esm/core/nearCrypto.js +24 -6
- package/dist/esm/core/nearCrypto.js.map +1 -1
- package/dist/esm/core/rpcCalls.js +56 -26
- package/dist/esm/core/rpcCalls.js.map +1 -1
- package/dist/esm/core/types/emailRecovery.js +26 -0
- package/dist/esm/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-BG_6hcim.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-C-RcGfr5.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
- package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/client.js +30 -8
- package/dist/esm/react/components/PasskeyAuthMenu/client.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +20 -0
- package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
- package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
- package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +354 -154
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CB0UCQ_h.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
- package/dist/esm/react/context/useSDKFlowRuntime.js +181 -0
- package/dist/esm/react/context/useSDKFlowRuntime.js.map +1 -0
- package/dist/esm/react/context/useTatchiContextValue.js +25 -16
- package/dist/esm/react/context/useTatchiContextValue.js.map +1 -1
- package/dist/esm/react/context/useTatchiWithSdkFlow.js +94 -0
- package/dist/esm/react/context/useTatchiWithSdkFlow.js.map +1 -0
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +25 -1
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -78
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js +1 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/esm/react/sdk/src/core/defaultConfigs.js +3 -7
- package/dist/esm/react/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/react/sdk/src/core/nearCrypto.js +24 -6
- package/dist/esm/react/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/esm/react/sdk/src/core/rpcCalls.js +56 -26
- package/dist/esm/react/sdk/src/core/rpcCalls.js.map +1 -1
- package/dist/esm/react/sdk/src/core/types/emailRecovery.js +26 -0
- package/dist/esm/react/sdk/src/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/react/styles/styles.css +58 -3
- package/dist/esm/sdk/{defaultConfigs-DpslkAQd.js → defaultConfigs-CfQDV-ya.js} +3 -7
- package/dist/esm/sdk/{getDeviceNumber-fXizNGQl.js → getDeviceNumber-BpernPnM.js} +4 -8
- package/dist/esm/sdk/getDeviceNumber-BpernPnM.js.map +1 -0
- package/dist/esm/sdk/offline-export-app.js +23 -6
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{router-DuGYOd3G.js → router-BWtacLJg.js} +1 -1
- package/dist/esm/sdk/{rpcCalls-BQrJMTdg.js → rpcCalls-CYGJSCgm.js} +3 -3
- package/dist/esm/sdk/{rpcCalls-YVeUVMk2.js → rpcCalls-DZZSa-sk.js} +57 -27
- package/dist/esm/sdk/{transactions-bqaAwL4k.js → transactions-Cn9xTWlK.js} +2 -2
- package/dist/esm/sdk/{transactions-bqaAwL4k.js.map → transactions-Cn9xTWlK.js.map} +1 -1
- package/dist/esm/sdk/{transactions-BalIhtJ9.js → transactions-DfdwDQCn.js} +1 -1
- package/dist/esm/sdk/wallet-iframe-host.js +660 -590
- package/dist/esm/server/email-recovery/emailParsers.js +3 -1
- package/dist/esm/server/email-recovery/emailParsers.js.map +1 -1
- package/dist/esm/server/email-recovery/index.js +6 -6
- package/dist/esm/server/email-recovery/index.js.map +1 -1
- package/dist/esm/server/email-recovery/rpcCalls.js +22 -3
- package/dist/esm/server/email-recovery/rpcCalls.js.map +1 -1
- package/dist/esm/server/router/cloudflare.js +8 -3
- 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 +2 -4
- package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/server/sdk/src/core/nearCrypto.js +26 -8
- package/dist/esm/server/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts +8 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +8 -5
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/index.d.ts +1 -1
- package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/scanDevice.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts +1 -1
- package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/client/router.d.ts +1 -1
- package/dist/types/src/core/WalletIframe/client/router.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/shared/messages.d.ts +1 -1
- package/dist/types/src/core/WalletIframe/shared/messages.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts +2 -1
- package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts.map +1 -1
- package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
- package/dist/types/src/core/nearCrypto.d.ts +14 -0
- package/dist/types/src/core/nearCrypto.d.ts.map +1 -1
- package/dist/types/src/core/rpcCalls.d.ts +11 -8
- package/dist/types/src/core/rpcCalls.d.ts.map +1 -1
- package/dist/types/src/core/types/emailRecovery.d.ts +10 -0
- package/dist/types/src/core/types/emailRecovery.d.ts.map +1 -0
- package/dist/types/src/core/types/index.d.ts +1 -0
- package/dist/types/src/core/types/index.d.ts.map +1 -1
- package/dist/types/src/core/types/tatchi.d.ts +0 -4
- package/dist/types/src/core/types/tatchi.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/adapters/tatchi.d.ts +2 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/client.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts +10 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts.map +1 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts +8 -3
- package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts +2 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/types/src/react/context/useSDKFlowRuntime.d.ts +10 -0
- package/dist/types/src/react/context/useSDKFlowRuntime.d.ts.map +1 -0
- package/dist/types/src/react/context/useTatchiContextValue.d.ts.map +1 -1
- package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts +9 -0
- package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts.map +1 -0
- package/dist/types/src/react/types.d.ts +31 -0
- package/dist/types/src/react/types.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/emailParsers.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/index.d.ts +5 -6
- package/dist/types/src/server/email-recovery/index.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/rpcCalls.d.ts +1 -0
- package/dist/types/src/server/email-recovery/rpcCalls.d.ts.map +1 -1
- package/dist/types/src/server/router/cloudflare-adaptor.d.ts.map +1 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/package.json +1 -1
- package/dist/esm/sdk/getDeviceNumber-fXizNGQl.js.map +0 -1
|
@@ -1,11 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { EmailRecoveryPhase, EmailRecoveryStatus, init_sdkSentEvents } from "../../../sdk/src/core/types/sdkSentEvents.js";
|
|
2
|
+
import { bytesToHex, canonicalizeEmail, init_EmailRecovery } from "../../../sdk/src/core/EmailRecovery/index.js";
|
|
3
|
+
import { EmailRecoveryErrorCode, init_emailRecovery } from "../../../sdk/src/core/types/emailRecovery.js";
|
|
3
4
|
import React from "react";
|
|
4
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
|
|
6
7
|
//#region src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
init_sdkSentEvents();
|
|
9
|
+
init_emailRecovery();
|
|
10
|
+
init_EmailRecovery();
|
|
11
|
+
async function hashRecoveryEmailForAccountHex(args) {
|
|
12
|
+
const salt = String(args.accountId || "").trim().toLowerCase();
|
|
13
|
+
if (!salt) return null;
|
|
14
|
+
const canonical = canonicalizeEmail(String(args.recoveryEmail || ""));
|
|
15
|
+
if (!canonical || !canonical.includes("@")) return null;
|
|
16
|
+
if (typeof crypto === "undefined" || !crypto.subtle) return null;
|
|
17
|
+
const input = `${canonical}|${salt}`;
|
|
18
|
+
const bytes = new TextEncoder().encode(input);
|
|
19
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
20
|
+
return bytesToHex(new Uint8Array(digest));
|
|
21
|
+
}
|
|
22
|
+
function getEmailRecoveryErrorCode(err) {
|
|
23
|
+
const code = err?.code;
|
|
24
|
+
if (typeof code !== "string") return null;
|
|
25
|
+
return Object.values(EmailRecoveryErrorCode).includes(code) ? code : null;
|
|
26
|
+
}
|
|
27
|
+
function getEmailRecoveryUiError(err) {
|
|
28
|
+
const fallback = err instanceof Error ? err.message : String(err || "");
|
|
29
|
+
const normalizedFallback = fallback.trim().toLowerCase();
|
|
30
|
+
if (normalizedFallback.includes("recovery email is required")) return {
|
|
31
|
+
message: fallback || "Recovery email is required for email-based account recovery. Make sure you send the email from your configured recovery email address.",
|
|
32
|
+
canRestart: true
|
|
33
|
+
};
|
|
34
|
+
const code = getEmailRecoveryErrorCode(err);
|
|
35
|
+
switch (code) {
|
|
36
|
+
case EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED: return {
|
|
37
|
+
message: fallback || "Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again.",
|
|
38
|
+
canRestart: true
|
|
39
|
+
};
|
|
40
|
+
case EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED: return {
|
|
41
|
+
message: fallback || "Registration did not verify on-chain. Please restart email recovery and try again.",
|
|
42
|
+
canRestart: true
|
|
43
|
+
};
|
|
44
|
+
default: return {
|
|
45
|
+
message: fallback || "Email recovery failed",
|
|
46
|
+
canRestart: false
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function getEmailRecoveryErrorTxHash(err) {
|
|
51
|
+
const carrier = err;
|
|
52
|
+
const ctx = carrier?.context && typeof carrier.context === "object" ? carrier.context : null;
|
|
53
|
+
const details = carrier?.details && typeof carrier.details === "object" ? carrier.details : null;
|
|
54
|
+
const source = ctx ?? details;
|
|
55
|
+
if (!source) return null;
|
|
56
|
+
const txHash = source.transactionHash;
|
|
57
|
+
return typeof txHash === "string" && txHash.trim().length > 0 ? txHash.trim() : null;
|
|
58
|
+
}
|
|
59
|
+
function asRecord(value) {
|
|
60
|
+
if (!value || typeof value !== "object") return null;
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
9
63
|
const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {
|
|
10
64
|
const mountedRef = React.useRef(true);
|
|
11
65
|
const mailtoAttemptTimerRef = React.useRef(null);
|
|
@@ -22,19 +76,22 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
22
76
|
}, []);
|
|
23
77
|
const [isBusy, setIsBusy] = React.useState(false);
|
|
24
78
|
const [accountIdInput, setAccountIdInput] = React.useState("");
|
|
25
|
-
const [recoveryEmailInput, setRecoveryEmailInput] = React.useState("");
|
|
26
79
|
const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState(null);
|
|
80
|
+
const [pendingNearPublicKey, setPendingNearPublicKey] = React.useState(null);
|
|
27
81
|
const [mailtoUiState, setMailtoUiState] = React.useState("ready");
|
|
28
82
|
const [statusText, setStatusText] = React.useState(null);
|
|
29
83
|
const [pollingElapsedMs, setPollingElapsedMs] = React.useState(null);
|
|
30
84
|
const [errorText, setErrorText] = React.useState(null);
|
|
85
|
+
const [canRestart, setCanRestart] = React.useState(false);
|
|
31
86
|
const [accountInfo, setAccountInfo] = React.useState(null);
|
|
32
87
|
const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);
|
|
33
88
|
const [accountInfoError, setAccountInfoError] = React.useState(null);
|
|
34
89
|
const [localRecoveryEmails, setLocalRecoveryEmails] = React.useState([]);
|
|
90
|
+
const [recoveryEmailRecords, setRecoveryEmailRecords] = React.useState([]);
|
|
91
|
+
const [recoveryEmailInput, setRecoveryEmailInput] = React.useState("");
|
|
92
|
+
const [recoveryEmailMatchStatus, setRecoveryEmailMatchStatus] = React.useState("empty");
|
|
35
93
|
const [explorerToast, setExplorerToast] = React.useState(null);
|
|
36
94
|
const lastPrefilledAccountIdRef = React.useRef("");
|
|
37
|
-
const lastPrefilledRecoveryEmailRef = React.useRef("");
|
|
38
95
|
React.useEffect(() => {
|
|
39
96
|
const next = (accountId || "").trim();
|
|
40
97
|
if (!next) return;
|
|
@@ -45,14 +102,19 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
45
102
|
}, [accountId]);
|
|
46
103
|
React.useEffect(() => {
|
|
47
104
|
setPendingMailtoUrl(null);
|
|
105
|
+
setPendingNearPublicKey(null);
|
|
48
106
|
setMailtoUiState("ready");
|
|
49
107
|
cancelRequestedRef.current = false;
|
|
50
108
|
setStatusText(null);
|
|
51
109
|
setPollingElapsedMs(null);
|
|
52
110
|
setErrorText(null);
|
|
111
|
+
setCanRestart(false);
|
|
53
112
|
setAccountInfo(null);
|
|
54
113
|
setAccountInfoError(null);
|
|
55
114
|
setLocalRecoveryEmails([]);
|
|
115
|
+
setRecoveryEmailRecords([]);
|
|
116
|
+
setRecoveryEmailInput("");
|
|
117
|
+
setRecoveryEmailMatchStatus("empty");
|
|
56
118
|
setExplorerToast(null);
|
|
57
119
|
if (mailtoAttemptTimerRef.current != null) {
|
|
58
120
|
window.clearTimeout(mailtoAttemptTimerRef.current);
|
|
@@ -66,22 +128,26 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
66
128
|
};
|
|
67
129
|
};
|
|
68
130
|
const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);
|
|
131
|
+
const safeSetPendingNearPublicKey = React.useMemo(() => safeSet(setPendingNearPublicKey), []);
|
|
69
132
|
const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);
|
|
70
133
|
const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);
|
|
71
134
|
const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);
|
|
72
135
|
const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);
|
|
136
|
+
const safeSetCanRestart = React.useMemo(() => safeSet(setCanRestart), []);
|
|
73
137
|
const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);
|
|
74
138
|
const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);
|
|
75
139
|
const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);
|
|
76
140
|
const safeSetLocalRecoveryEmails = React.useMemo(() => safeSet(setLocalRecoveryEmails), []);
|
|
141
|
+
const safeSetRecoveryEmailRecords = React.useMemo(() => safeSet(setRecoveryEmailRecords), []);
|
|
142
|
+
const safeSetRecoveryEmailMatchStatus = React.useMemo(() => safeSet(setRecoveryEmailMatchStatus), []);
|
|
77
143
|
const safeSetExplorerToast = React.useMemo(() => safeSet(setExplorerToast), []);
|
|
78
144
|
const safeSetMailtoUiState = React.useMemo(() => safeSet(setMailtoUiState), []);
|
|
79
145
|
const onEvent = React.useCallback((ev) => {
|
|
80
146
|
if (cancelRequestedRef.current) return;
|
|
81
147
|
safeSetStatusText(ev?.message || null);
|
|
82
148
|
emailRecoveryOptions?.onEvent?.(ev);
|
|
83
|
-
const data = ev
|
|
84
|
-
const rawTxHash = data?.transactionHash ?? data?.transaction_hash;
|
|
149
|
+
const data = "data" in ev ? asRecord(ev.data) : null;
|
|
150
|
+
const rawTxHash = data?.["transactionHash"] ?? data?.["transaction_hash"];
|
|
85
151
|
const txHash = typeof rawTxHash === "string" ? rawTxHash.trim() : "";
|
|
86
152
|
if (txHash) {
|
|
87
153
|
const base = String(tatchiPasskey.configs?.nearExplorerUrl || "https://testnet.nearblocks.io").replace(/\/$/, "");
|
|
@@ -91,16 +157,18 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
91
157
|
transactionHash: txHash
|
|
92
158
|
});
|
|
93
159
|
}
|
|
94
|
-
const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;
|
|
160
|
+
const elapsedRaw = data?.["elapsedMs"] ?? data?.["elapsed_ms"];
|
|
95
161
|
if (elapsedRaw == null) safeSetPollingElapsedMs(null);
|
|
96
162
|
const elapsed = elapsedRaw == null ? NaN : Number(elapsedRaw);
|
|
97
163
|
if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);
|
|
98
|
-
if (ev
|
|
99
|
-
const raw =
|
|
100
|
-
safeSetErrorText(
|
|
164
|
+
if (ev.phase === EmailRecoveryPhase.ERROR || ev.status === EmailRecoveryStatus.ERROR) {
|
|
165
|
+
const raw = "error" in ev ? ev.error : ev.message;
|
|
166
|
+
safeSetErrorText(raw || "Email recovery failed");
|
|
167
|
+
safeSetCanRestart(false);
|
|
101
168
|
}
|
|
102
169
|
}, [
|
|
103
170
|
emailRecoveryOptions,
|
|
171
|
+
safeSetCanRestart,
|
|
104
172
|
safeSetErrorText,
|
|
105
173
|
safeSetExplorerToast,
|
|
106
174
|
safeSetPollingElapsedMs,
|
|
@@ -117,6 +185,16 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
117
185
|
accountId: normalized
|
|
118
186
|
});
|
|
119
187
|
}, [safeSetExplorerToast, tatchiPasskey]);
|
|
188
|
+
const showExplorerTxToast = React.useCallback((txHash) => {
|
|
189
|
+
const normalized = (txHash || "").trim();
|
|
190
|
+
if (!normalized) return;
|
|
191
|
+
const base = String(tatchiPasskey.configs?.nearExplorerUrl || "https://testnet.nearblocks.io").replace(/\/$/, "");
|
|
192
|
+
const url = base.includes("nearblocks.io") ? `${base}/txns/${normalized}` : `${base}/transactions/${normalized}`;
|
|
193
|
+
safeSetExplorerToast({
|
|
194
|
+
url,
|
|
195
|
+
transactionHash: normalized
|
|
196
|
+
});
|
|
197
|
+
}, [safeSetExplorerToast, tatchiPasskey]);
|
|
120
198
|
const launchMailto = React.useCallback((rawMailtoUrl) => {
|
|
121
199
|
const url = String(rawMailtoUrl || "").trim();
|
|
122
200
|
if (!url) return;
|
|
@@ -162,40 +240,9 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
162
240
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
163
241
|
};
|
|
164
242
|
}, [mailtoUiState, safeSetMailtoUiState]);
|
|
165
|
-
const fetchLocalRecoveryEmailsFromIndexedDB = React.useCallback(async (rawAccountId) => {
|
|
166
|
-
const normalized = (rawAccountId || "").trim();
|
|
167
|
-
if (!normalized) {
|
|
168
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId");
|
|
169
|
-
return [];
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB", { accountId: normalized });
|
|
173
|
-
const records = await IndexedDBManager.getRecoveryEmails(toAccountId(normalized));
|
|
174
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records", {
|
|
175
|
-
accountId: normalized,
|
|
176
|
-
count: Array.isArray(records) ? records.length : 0,
|
|
177
|
-
records
|
|
178
|
-
});
|
|
179
|
-
if (!Array.isArray(records) || records.length === 0) return [];
|
|
180
|
-
const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));
|
|
181
|
-
const emails = sorted.map((r) => String(r?.email || "").trim().toLowerCase()).filter((e) => !!e && e.includes("@"));
|
|
182
|
-
const uniq = Array.from(new Set(emails));
|
|
183
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails", {
|
|
184
|
-
accountId: normalized,
|
|
185
|
-
emails: uniq
|
|
186
|
-
});
|
|
187
|
-
return uniq;
|
|
188
|
-
} catch (err) {
|
|
189
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB", {
|
|
190
|
-
accountId: normalized,
|
|
191
|
-
error: err instanceof Error ? err.message : String(err)
|
|
192
|
-
});
|
|
193
|
-
return [];
|
|
194
|
-
}
|
|
195
|
-
}, []);
|
|
196
243
|
const deriveEmailsFromRecoveryRecords = React.useCallback((records) => {
|
|
197
|
-
if (
|
|
198
|
-
const emails = records.map((r) =>
|
|
244
|
+
if (records.length === 0) return [];
|
|
245
|
+
const emails = records.map((r) => r.email.trim().toLowerCase()).filter((e) => e.length > 0 && e.includes("@"));
|
|
199
246
|
return Array.from(new Set(emails));
|
|
200
247
|
}, []);
|
|
201
248
|
React.useEffect(() => {
|
|
@@ -213,27 +260,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
213
260
|
const handle = window.setTimeout(() => {
|
|
214
261
|
(async () => {
|
|
215
262
|
try {
|
|
216
|
-
const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;
|
|
217
|
-
let localEmails = [];
|
|
218
|
-
if (!isWalletIframeMode) {
|
|
219
|
-
localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);
|
|
220
|
-
if (!cancelled) console.log("[EmailRecoverySlide] local saved emails (IndexedDB)", {
|
|
221
|
-
accountId: normalized,
|
|
222
|
-
localEmails
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
263
|
const records = await tatchiPasskey.getRecoveryEmails(normalized);
|
|
226
|
-
const resolvedEmails =
|
|
264
|
+
const resolvedEmails = deriveEmailsFromRecoveryRecords(records);
|
|
227
265
|
if (!cancelled) {
|
|
228
266
|
safeSetLocalRecoveryEmails(resolvedEmails);
|
|
229
|
-
|
|
230
|
-
accountId: normalized,
|
|
231
|
-
emails: resolvedEmails
|
|
232
|
-
});
|
|
233
|
-
if (resolvedEmails.length === 1 && (recoveryEmailInput.trim() === "" || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)) {
|
|
234
|
-
lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];
|
|
235
|
-
setRecoveryEmailInput(resolvedEmails[0]);
|
|
236
|
-
}
|
|
267
|
+
safeSetRecoveryEmailRecords(records);
|
|
237
268
|
}
|
|
238
269
|
const info = records ? { emailsCount: Array.isArray(records) ? records.length : 0 } : null;
|
|
239
270
|
if (cancelled) return;
|
|
@@ -241,7 +272,10 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
241
272
|
} catch (err) {
|
|
242
273
|
if (cancelled) return;
|
|
243
274
|
safeSetAccountInfo(null);
|
|
244
|
-
|
|
275
|
+
const msg = err instanceof Error ? err.message : "";
|
|
276
|
+
safeSetAccountInfoError(msg || "Failed to load email recovery settings for this account");
|
|
277
|
+
safeSetLocalRecoveryEmails([]);
|
|
278
|
+
safeSetRecoveryEmailRecords([]);
|
|
245
279
|
} finally {
|
|
246
280
|
if (!cancelled) safeSetAccountInfoLoading(false);
|
|
247
281
|
}
|
|
@@ -254,37 +288,114 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
254
288
|
}, [
|
|
255
289
|
accountIdInput,
|
|
256
290
|
deriveEmailsFromRecoveryRecords,
|
|
257
|
-
fetchLocalRecoveryEmailsFromIndexedDB,
|
|
258
|
-
recoveryEmailInput,
|
|
259
291
|
safeSetAccountInfo,
|
|
260
292
|
safeSetAccountInfoError,
|
|
261
293
|
safeSetAccountInfoLoading,
|
|
262
294
|
safeSetLocalRecoveryEmails,
|
|
295
|
+
safeSetRecoveryEmailRecords,
|
|
263
296
|
tatchiPasskey
|
|
264
297
|
]);
|
|
298
|
+
const recoveryEmailConfirmationRequired = !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount > 0 && localRecoveryEmails.length === 0;
|
|
299
|
+
React.useEffect(() => {
|
|
300
|
+
const normalizedAccountId = (accountIdInput || "").trim();
|
|
301
|
+
const rawEmail = (recoveryEmailInput || "").trim();
|
|
302
|
+
if (!rawEmail || !normalizedAccountId) {
|
|
303
|
+
safeSetRecoveryEmailMatchStatus("empty");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (!Array.isArray(recoveryEmailRecords) || recoveryEmailRecords.length === 0) {
|
|
307
|
+
safeSetRecoveryEmailMatchStatus("checking");
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
let cancelled = false;
|
|
311
|
+
safeSetRecoveryEmailMatchStatus("checking");
|
|
312
|
+
const handle = window.setTimeout(() => {
|
|
313
|
+
(async () => {
|
|
314
|
+
try {
|
|
315
|
+
const hashHex = await hashRecoveryEmailForAccountHex({
|
|
316
|
+
recoveryEmail: rawEmail,
|
|
317
|
+
accountId: normalizedAccountId
|
|
318
|
+
});
|
|
319
|
+
if (cancelled) return;
|
|
320
|
+
if (!hashHex) {
|
|
321
|
+
safeSetRecoveryEmailMatchStatus("invalid");
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const normalizedHashHex = hashHex.toLowerCase();
|
|
325
|
+
const matches = recoveryEmailRecords.some((rec) => String(rec.hashHex || "").toLowerCase() === normalizedHashHex);
|
|
326
|
+
safeSetRecoveryEmailMatchStatus(matches ? "match" : "mismatch");
|
|
327
|
+
} catch {
|
|
328
|
+
if (!cancelled) safeSetRecoveryEmailMatchStatus("invalid");
|
|
329
|
+
}
|
|
330
|
+
})();
|
|
331
|
+
}, 250);
|
|
332
|
+
return () => {
|
|
333
|
+
cancelled = true;
|
|
334
|
+
window.clearTimeout(handle);
|
|
335
|
+
};
|
|
336
|
+
}, [
|
|
337
|
+
accountIdInput,
|
|
338
|
+
recoveryEmailInput,
|
|
339
|
+
recoveryEmailRecords,
|
|
340
|
+
safeSetRecoveryEmailMatchStatus
|
|
341
|
+
]);
|
|
265
342
|
const handleStart = React.useCallback(async () => {
|
|
266
343
|
const normalizedAccountId = (accountIdInput || "").trim();
|
|
267
344
|
if (!normalizedAccountId) {
|
|
268
345
|
safeSetErrorText("Enter an account ID.");
|
|
269
346
|
return;
|
|
270
347
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
348
|
+
if (accountInfoLoading) {
|
|
349
|
+
safeSetErrorText("Checking recovery email settings…");
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (accountInfoError) {
|
|
353
|
+
safeSetErrorText(accountInfoError);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (!accountInfo) {
|
|
357
|
+
safeSetErrorText("Failed to load email recovery settings for this account.");
|
|
274
358
|
return;
|
|
275
359
|
}
|
|
360
|
+
if (accountInfo.emailsCount === 0) {
|
|
361
|
+
safeSetErrorText("No recovery emails are configured for this account.");
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const recoveryEmail = recoveryEmailInput.trim();
|
|
365
|
+
if (recoveryEmailConfirmationRequired) {
|
|
366
|
+
if (!recoveryEmail) {
|
|
367
|
+
safeSetErrorText("Enter the recovery email address you will send from.");
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const hashHex = await hashRecoveryEmailForAccountHex({
|
|
371
|
+
recoveryEmail,
|
|
372
|
+
accountId: normalizedAccountId
|
|
373
|
+
}).catch(() => null);
|
|
374
|
+
if (!hashHex) {
|
|
375
|
+
safeSetErrorText("Enter a valid recovery email address.");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const normalizedHashHex = hashHex.toLowerCase();
|
|
379
|
+
const matches = recoveryEmailRecords.some((rec) => String(rec.hashHex || "").toLowerCase() === normalizedHashHex);
|
|
380
|
+
if (!matches) {
|
|
381
|
+
safeSetErrorText("That email is not configured for recovery on this account. Please use your configured recovery email address.");
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
276
385
|
safeSetIsBusy(true);
|
|
277
386
|
cancelRequestedRef.current = false;
|
|
278
387
|
safeSetErrorText(null);
|
|
388
|
+
safeSetCanRestart(false);
|
|
279
389
|
safeSetStatusText(null);
|
|
280
390
|
safeSetPollingElapsedMs(null);
|
|
281
391
|
safeSetPendingMailtoUrl(null);
|
|
392
|
+
safeSetPendingNearPublicKey(null);
|
|
282
393
|
safeSetMailtoUiState("ready");
|
|
283
394
|
let didForwardError = false;
|
|
284
395
|
try {
|
|
285
396
|
const result = await tatchiPasskey.startEmailRecovery({
|
|
286
397
|
accountId: normalizedAccountId,
|
|
287
|
-
recoveryEmail:
|
|
398
|
+
...recoveryEmail ? { recoveryEmail } : {},
|
|
288
399
|
options: {
|
|
289
400
|
onEvent,
|
|
290
401
|
onError: (err) => {
|
|
@@ -292,11 +403,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
292
403
|
safeSetErrorText(err?.message || "Failed to start email recovery");
|
|
293
404
|
didForwardError = true;
|
|
294
405
|
emailRecoveryOptions?.onError?.(err);
|
|
295
|
-
}
|
|
296
|
-
afterCall: async () => {}
|
|
406
|
+
}
|
|
297
407
|
}
|
|
298
408
|
});
|
|
299
409
|
safeSetPendingMailtoUrl(result.mailtoUrl);
|
|
410
|
+
safeSetPendingNearPublicKey(result.nearPublicKey);
|
|
300
411
|
safeSetStatusText("Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…");
|
|
301
412
|
attemptOpenMailtoAuto(result.mailtoUrl);
|
|
302
413
|
const finalizePromise = tatchiPasskey.finalizeEmailRecovery({
|
|
@@ -306,11 +417,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
306
417
|
onEvent,
|
|
307
418
|
onError: (err) => {
|
|
308
419
|
if (cancelRequestedRef.current) return;
|
|
309
|
-
|
|
420
|
+
const uiError = getEmailRecoveryUiError(err);
|
|
421
|
+
safeSetErrorText(uiError.message || "Failed to finalize email recovery");
|
|
422
|
+
safeSetCanRestart(uiError.canRestart);
|
|
423
|
+
const txHash = getEmailRecoveryErrorTxHash(err);
|
|
424
|
+
if (txHash) showExplorerTxToast(txHash);
|
|
310
425
|
didForwardError = true;
|
|
311
426
|
emailRecoveryOptions?.onError?.(err);
|
|
312
|
-
}
|
|
313
|
-
afterCall: async () => {}
|
|
427
|
+
}
|
|
314
428
|
}
|
|
315
429
|
});
|
|
316
430
|
showExplorerToast(normalizedAccountId);
|
|
@@ -333,10 +447,16 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
333
447
|
safeSetStatusText(null);
|
|
334
448
|
safeSetPollingElapsedMs(null);
|
|
335
449
|
safeSetPendingMailtoUrl(null);
|
|
450
|
+
safeSetPendingNearPublicKey(null);
|
|
336
451
|
safeSetMailtoUiState("ready");
|
|
452
|
+
safeSetCanRestart(false);
|
|
337
453
|
return;
|
|
338
454
|
}
|
|
339
|
-
|
|
455
|
+
const uiError = getEmailRecoveryUiError(err);
|
|
456
|
+
safeSetErrorText(uiError.message || "Failed to start email recovery");
|
|
457
|
+
safeSetCanRestart(uiError.canRestart);
|
|
458
|
+
const txHash = getEmailRecoveryErrorTxHash(err);
|
|
459
|
+
if (txHash) showExplorerTxToast(txHash);
|
|
340
460
|
if (!didForwardError && err instanceof Error) emailRecoveryOptions?.onError?.(err);
|
|
341
461
|
} finally {
|
|
342
462
|
safeSetIsBusy(false);
|
|
@@ -344,9 +464,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
344
464
|
}, [
|
|
345
465
|
accountIdInput,
|
|
346
466
|
emailRecoveryOptions,
|
|
347
|
-
recoveryEmailInput,
|
|
348
467
|
onEvent,
|
|
349
468
|
refreshLoginState,
|
|
469
|
+
accountInfo,
|
|
470
|
+
accountInfoError,
|
|
471
|
+
accountInfoLoading,
|
|
472
|
+
recoveryEmailConfirmationRequired,
|
|
473
|
+
recoveryEmailInput,
|
|
474
|
+
recoveryEmailRecords,
|
|
350
475
|
showExplorerToast,
|
|
351
476
|
safeSetErrorText,
|
|
352
477
|
safeSetIsBusy,
|
|
@@ -355,10 +480,64 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
355
480
|
safeSetStatusText,
|
|
356
481
|
safeSetMailtoUiState,
|
|
357
482
|
attemptOpenMailtoAuto,
|
|
483
|
+
showExplorerTxToast,
|
|
358
484
|
tatchiPasskey
|
|
359
485
|
]);
|
|
360
|
-
const
|
|
486
|
+
const handleRestart = React.useCallback(async () => {
|
|
487
|
+
const normalizedAccountId = (accountIdInput || "").trim();
|
|
488
|
+
if (!normalizedAccountId) return;
|
|
489
|
+
safeSetIsBusy(true);
|
|
490
|
+
try {
|
|
491
|
+
cancelRequestedRef.current = true;
|
|
492
|
+
await tatchiPasskey.cancelEmailRecovery({
|
|
493
|
+
accountId: normalizedAccountId,
|
|
494
|
+
nearPublicKey: pendingNearPublicKey || void 0
|
|
495
|
+
}).catch(() => {});
|
|
496
|
+
safeSetErrorText(null);
|
|
497
|
+
safeSetStatusText(null);
|
|
498
|
+
safeSetPollingElapsedMs(null);
|
|
499
|
+
safeSetPendingMailtoUrl(null);
|
|
500
|
+
safeSetPendingNearPublicKey(null);
|
|
501
|
+
safeSetMailtoUiState("ready");
|
|
502
|
+
safeSetCanRestart(false);
|
|
503
|
+
} finally {
|
|
504
|
+
cancelRequestedRef.current = false;
|
|
505
|
+
safeSetIsBusy(false);
|
|
506
|
+
}
|
|
507
|
+
}, [
|
|
508
|
+
accountIdInput,
|
|
509
|
+
pendingNearPublicKey,
|
|
510
|
+
safeSetCanRestart,
|
|
511
|
+
safeSetErrorText,
|
|
512
|
+
safeSetIsBusy,
|
|
513
|
+
safeSetMailtoUiState,
|
|
514
|
+
safeSetPendingMailtoUrl,
|
|
515
|
+
safeSetPendingNearPublicKey,
|
|
516
|
+
safeSetPollingElapsedMs,
|
|
517
|
+
safeSetStatusText,
|
|
518
|
+
tatchiPasskey
|
|
519
|
+
]);
|
|
520
|
+
const summaryLine = accountInfoLoading ? /* @__PURE__ */ jsxs(Fragment, { children: ["Checking if account has recovery emails configured", /* @__PURE__ */ jsxs("span", {
|
|
521
|
+
className: "w3a-ellipsis",
|
|
522
|
+
"aria-hidden": "true",
|
|
523
|
+
children: [
|
|
524
|
+
/* @__PURE__ */ jsx("span", {
|
|
525
|
+
className: "w3a-ellipsis-dot",
|
|
526
|
+
children: "."
|
|
527
|
+
}),
|
|
528
|
+
/* @__PURE__ */ jsx("span", {
|
|
529
|
+
className: "w3a-ellipsis-dot",
|
|
530
|
+
children: "."
|
|
531
|
+
}),
|
|
532
|
+
/* @__PURE__ */ jsx("span", {
|
|
533
|
+
className: "w3a-ellipsis-dot",
|
|
534
|
+
children: "."
|
|
535
|
+
})
|
|
536
|
+
]
|
|
537
|
+
})] }) : accountInfo && !accountInfoError ? `Recovery emails configured: ${accountInfo.emailsCount}` : "\xA0";
|
|
361
538
|
const noRecoveryEmailsConfigured = !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;
|
|
539
|
+
const disableStartForRecoveryEmailMismatch = recoveryEmailConfirmationRequired && (recoveryEmailMatchStatus === "empty" || recoveryEmailMatchStatus === "checking" || recoveryEmailMatchStatus === "invalid" || recoveryEmailMatchStatus === "mismatch");
|
|
540
|
+
const startDisabled = isBusy || accountInfoLoading || !!accountInfoError || !accountInfo || noRecoveryEmailsConfigured || disableStartForRecoveryEmailMismatch;
|
|
362
541
|
return /* @__PURE__ */ jsxs("div", {
|
|
363
542
|
className: "w3a-email-recovery-slide",
|
|
364
543
|
children: [
|
|
@@ -368,92 +547,113 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
368
547
|
}),
|
|
369
548
|
/* @__PURE__ */ jsx("div", {
|
|
370
549
|
className: "w3a-email-recovery-help",
|
|
371
|
-
children: "Send a special
|
|
550
|
+
children: "Send a special email to recover your account. This email must be sent from the designated email recovery address."
|
|
372
551
|
}),
|
|
373
|
-
/* @__PURE__ */ jsx("div", {
|
|
374
|
-
className: "w3a-email-recovery-
|
|
552
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("div", {
|
|
553
|
+
className: "w3a-input-pill w3a-email-recovery-input-pill",
|
|
375
554
|
children: /* @__PURE__ */ jsx("div", {
|
|
376
|
-
className: "w3a-input-
|
|
377
|
-
children: /* @__PURE__ */ jsx("
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
inputMode: "text",
|
|
389
|
-
disabled: isBusy
|
|
390
|
-
})
|
|
555
|
+
className: "w3a-input-wrap",
|
|
556
|
+
children: /* @__PURE__ */ jsx("input", {
|
|
557
|
+
type: "text",
|
|
558
|
+
value: accountIdInput,
|
|
559
|
+
onChange: (e) => setAccountIdInput(e.target.value),
|
|
560
|
+
placeholder: "NEAR account ID (e.g. alice.testnet)",
|
|
561
|
+
className: "w3a-input",
|
|
562
|
+
autoCapitalize: "none",
|
|
563
|
+
autoCorrect: "off",
|
|
564
|
+
spellCheck: false,
|
|
565
|
+
inputMode: "text",
|
|
566
|
+
disabled: isBusy
|
|
391
567
|
})
|
|
392
568
|
})
|
|
393
|
-
}),
|
|
394
|
-
/* @__PURE__ */
|
|
569
|
+
}) }),
|
|
570
|
+
/* @__PURE__ */ jsxs("div", {
|
|
395
571
|
className: "w3a-email-recovery-summary",
|
|
396
572
|
"aria-live": "polite",
|
|
397
|
-
children:
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
className: "w3a-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
})
|
|
573
|
+
children: [
|
|
574
|
+
/* @__PURE__ */ jsx("div", { children: summaryLine }),
|
|
575
|
+
!!accountInfoError && /* @__PURE__ */ jsx("div", {
|
|
576
|
+
className: "w3a-email-recovery-warning",
|
|
577
|
+
children: accountInfoError
|
|
578
|
+
}),
|
|
579
|
+
localRecoveryEmails.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
580
|
+
className: "w3a-email-recovery-saved-emails",
|
|
581
|
+
role: "list",
|
|
582
|
+
"aria-label": "Recovery emails",
|
|
583
|
+
children: localRecoveryEmails.map((email) => /* @__PURE__ */ jsx("span", {
|
|
584
|
+
className: "w3a-email-recovery-email-chip w3a-email-recovery-email-chip-static",
|
|
585
|
+
role: "listitem",
|
|
586
|
+
children: email
|
|
587
|
+
}, email))
|
|
588
|
+
}),
|
|
589
|
+
recoveryEmailConfirmationRequired && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
590
|
+
/* @__PURE__ */ jsx("div", {
|
|
591
|
+
className: "w3a-email-recovery-warning",
|
|
592
|
+
children: "This device can’t display your configured recovery email address. Enter the email you will send from to confirm it matches what’s configured for this account."
|
|
593
|
+
}),
|
|
594
|
+
/* @__PURE__ */ jsx("div", {
|
|
595
|
+
className: "w3a-input-pill w3a-email-recovery-input-pill",
|
|
596
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
597
|
+
className: "w3a-input-wrap",
|
|
598
|
+
children: /* @__PURE__ */ jsx("input", {
|
|
599
|
+
type: "email",
|
|
600
|
+
value: recoveryEmailInput,
|
|
601
|
+
onChange: (e) => setRecoveryEmailInput(e.target.value),
|
|
602
|
+
placeholder: "Recovery email address (sender)",
|
|
603
|
+
className: "w3a-input",
|
|
604
|
+
autoCapitalize: "none",
|
|
605
|
+
autoCorrect: "off",
|
|
606
|
+
spellCheck: false,
|
|
607
|
+
inputMode: "email",
|
|
608
|
+
disabled: isBusy
|
|
609
|
+
})
|
|
610
|
+
})
|
|
611
|
+
}),
|
|
612
|
+
recoveryEmailMatchStatus === "checking" && /* @__PURE__ */ jsx("div", { children: "Checking recovery email…" }),
|
|
613
|
+
recoveryEmailMatchStatus === "invalid" && /* @__PURE__ */ jsx("div", {
|
|
614
|
+
className: "w3a-email-recovery-warning",
|
|
615
|
+
children: "Enter a valid email address."
|
|
616
|
+
}),
|
|
617
|
+
recoveryEmailMatchStatus === "mismatch" && /* @__PURE__ */ jsx("div", {
|
|
618
|
+
className: "w3a-email-recovery-warning",
|
|
619
|
+
children: "That email is not configured for recovery on this account."
|
|
620
|
+
}),
|
|
621
|
+
recoveryEmailMatchStatus === "match" && /* @__PURE__ */ jsx("div", { children: "Recovery email verified for this account." })
|
|
622
|
+
] }),
|
|
623
|
+
!!accountIdInput.trim() && !noRecoveryEmailsConfigured && /* @__PURE__ */ jsx("div", {
|
|
624
|
+
className: "w3a-email-recovery-from-warning",
|
|
625
|
+
children: recoveryEmailInput.trim() ? `Check that you are sending the recovery email from ${recoveryEmailInput.trim()}.` : "Check that you are sending the recovery email from your designated recovery email."
|
|
418
626
|
})
|
|
419
|
-
|
|
420
|
-
}),
|
|
421
|
-
localRecoveryEmails.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
422
|
-
className: "w3a-email-recovery-summary",
|
|
423
|
-
"aria-live": "polite",
|
|
424
|
-
children: [/* @__PURE__ */ jsx("div", { children: "Saved on this device:" }), /* @__PURE__ */ jsx("div", {
|
|
425
|
-
className: "w3a-email-recovery-saved-emails",
|
|
426
|
-
children: localRecoveryEmails.map((email) => /* @__PURE__ */ jsx("button", {
|
|
427
|
-
type: "button",
|
|
428
|
-
className: "w3a-email-recovery-email-chip",
|
|
429
|
-
onClick: () => setRecoveryEmailInput(email),
|
|
430
|
-
disabled: isBusy,
|
|
431
|
-
children: email
|
|
432
|
-
}, email))
|
|
433
|
-
})]
|
|
434
|
-
}),
|
|
435
|
-
localRecoveryEmails.length > 0 && /* @__PURE__ */ jsx("datalist", {
|
|
436
|
-
id: "w3a-email-recovery-saved-emails",
|
|
437
|
-
children: localRecoveryEmails.map((email) => /* @__PURE__ */ jsx("option", { value: email }, email))
|
|
627
|
+
]
|
|
438
628
|
}),
|
|
439
629
|
/* @__PURE__ */ jsxs("div", {
|
|
440
630
|
className: "w3a-email-recovery-actions",
|
|
441
|
-
children: [
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
"
|
|
455
|
-
|
|
456
|
-
|
|
631
|
+
children: [
|
|
632
|
+
(!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ jsx("button", {
|
|
633
|
+
onClick: handleStart,
|
|
634
|
+
className: "w3a-link-device-btn w3a-link-device-btn-primary",
|
|
635
|
+
disabled: startDisabled,
|
|
636
|
+
children: accountInfoLoading ? "Checking recovery emails…" : noRecoveryEmailsConfigured ? "No recovery emails configured" : disableStartForRecoveryEmailMismatch ? "Confirm recovery email" : isBusy ? "Working…" : "Start Email Recovery"
|
|
637
|
+
}),
|
|
638
|
+
pendingMailtoUrl && /* @__PURE__ */ jsxs("button", {
|
|
639
|
+
type: "button",
|
|
640
|
+
onClick: () => attemptOpenMailtoFromUserGesture(pendingMailtoUrl),
|
|
641
|
+
className: "w3a-link-device-btn w3a-link-device-btn-primary",
|
|
642
|
+
disabled: mailtoUiState === "opening",
|
|
643
|
+
"aria-busy": mailtoUiState === "opening",
|
|
644
|
+
children: [mailtoUiState === "opening" && /* @__PURE__ */ jsx("span", {
|
|
645
|
+
className: "w3a-spinner",
|
|
646
|
+
"aria-hidden": "true"
|
|
647
|
+
}), mailtoUiState === "opening" ? "Opening email…" : "Open recovery email draft"]
|
|
648
|
+
}),
|
|
649
|
+
errorText && canRestart && /* @__PURE__ */ jsx("button", {
|
|
650
|
+
type: "button",
|
|
651
|
+
onClick: handleRestart,
|
|
652
|
+
className: "w3a-link-device-btn",
|
|
653
|
+
disabled: isBusy,
|
|
654
|
+
children: "Restart email recovery"
|
|
655
|
+
})
|
|
656
|
+
]
|
|
457
657
|
}),
|
|
458
658
|
(errorText || statusText || explorerToast) && /* @__PURE__ */ jsxs("div", {
|
|
459
659
|
className: `w3a-email-recovery-status${errorText ? " is-error" : ""}`,
|