@tatchi-xyz/sdk 0.20.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/TatchiPasskey/emailRecovery.js +67 -45
- 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/react/components/AccountMenuButton/{LinkedDevicesModal-BCrFe5p3.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CRJrtxDb.css → ProfileDropdown-BG_6hcim.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css → TouchIcon-C-RcGfr5.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.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 +254 -140
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CL4gsszN.css → ShowQRCode-CB0UCQ_h.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CL4gsszN.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 +1 -0
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +67 -45
- 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/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/TatchiPasskey/emailRecovery.js +67 -45
- 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/react/components/AccountMenuButton/{LinkedDevicesModal-BCrFe5p3.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CRJrtxDb.css → ProfileDropdown-BG_6hcim.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css → TouchIcon-C-RcGfr5.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.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 +254 -140
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/components/{ShowQRCode-CL4gsszN.css → ShowQRCode-CB0UCQ_h.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-CL4gsszN.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 +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +67 -45
- 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/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 +549 -557
- 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/TatchiPasskey/emailRecovery.d.ts +5 -4
- 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/tatchi.d.ts +0 -4
- package/dist/types/src/core/types/tatchi.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,13 +1,24 @@
|
|
|
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
3
|
import { EmailRecoveryErrorCode, init_emailRecovery } from "../../../sdk/src/core/types/emailRecovery.js";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx
|
|
8
|
-
|
|
9
|
-
init_accountIds();
|
|
8
|
+
init_sdkSentEvents();
|
|
10
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
|
+
}
|
|
11
22
|
function getEmailRecoveryErrorCode(err) {
|
|
12
23
|
const code = err?.code;
|
|
13
24
|
if (typeof code !== "string") return null;
|
|
@@ -15,6 +26,11 @@ function getEmailRecoveryErrorCode(err) {
|
|
|
15
26
|
}
|
|
16
27
|
function getEmailRecoveryUiError(err) {
|
|
17
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
|
+
};
|
|
18
34
|
const code = getEmailRecoveryErrorCode(err);
|
|
19
35
|
switch (code) {
|
|
20
36
|
case EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED: return {
|
|
@@ -31,6 +47,19 @@ function getEmailRecoveryUiError(err) {
|
|
|
31
47
|
};
|
|
32
48
|
}
|
|
33
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
|
+
}
|
|
34
63
|
const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {
|
|
35
64
|
const mountedRef = React.useRef(true);
|
|
36
65
|
const mailtoAttemptTimerRef = React.useRef(null);
|
|
@@ -47,7 +76,6 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
47
76
|
}, []);
|
|
48
77
|
const [isBusy, setIsBusy] = React.useState(false);
|
|
49
78
|
const [accountIdInput, setAccountIdInput] = React.useState("");
|
|
50
|
-
const [recoveryEmailInput, setRecoveryEmailInput] = React.useState("");
|
|
51
79
|
const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState(null);
|
|
52
80
|
const [pendingNearPublicKey, setPendingNearPublicKey] = React.useState(null);
|
|
53
81
|
const [mailtoUiState, setMailtoUiState] = React.useState("ready");
|
|
@@ -59,9 +87,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
59
87
|
const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);
|
|
60
88
|
const [accountInfoError, setAccountInfoError] = React.useState(null);
|
|
61
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");
|
|
62
93
|
const [explorerToast, setExplorerToast] = React.useState(null);
|
|
63
94
|
const lastPrefilledAccountIdRef = React.useRef("");
|
|
64
|
-
const lastPrefilledRecoveryEmailRef = React.useRef("");
|
|
65
95
|
React.useEffect(() => {
|
|
66
96
|
const next = (accountId || "").trim();
|
|
67
97
|
if (!next) return;
|
|
@@ -82,6 +112,9 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
82
112
|
setAccountInfo(null);
|
|
83
113
|
setAccountInfoError(null);
|
|
84
114
|
setLocalRecoveryEmails([]);
|
|
115
|
+
setRecoveryEmailRecords([]);
|
|
116
|
+
setRecoveryEmailInput("");
|
|
117
|
+
setRecoveryEmailMatchStatus("empty");
|
|
85
118
|
setExplorerToast(null);
|
|
86
119
|
if (mailtoAttemptTimerRef.current != null) {
|
|
87
120
|
window.clearTimeout(mailtoAttemptTimerRef.current);
|
|
@@ -105,14 +138,16 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
105
138
|
const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);
|
|
106
139
|
const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);
|
|
107
140
|
const safeSetLocalRecoveryEmails = React.useMemo(() => safeSet(setLocalRecoveryEmails), []);
|
|
141
|
+
const safeSetRecoveryEmailRecords = React.useMemo(() => safeSet(setRecoveryEmailRecords), []);
|
|
142
|
+
const safeSetRecoveryEmailMatchStatus = React.useMemo(() => safeSet(setRecoveryEmailMatchStatus), []);
|
|
108
143
|
const safeSetExplorerToast = React.useMemo(() => safeSet(setExplorerToast), []);
|
|
109
144
|
const safeSetMailtoUiState = React.useMemo(() => safeSet(setMailtoUiState), []);
|
|
110
145
|
const onEvent = React.useCallback((ev) => {
|
|
111
146
|
if (cancelRequestedRef.current) return;
|
|
112
147
|
safeSetStatusText(ev?.message || null);
|
|
113
148
|
emailRecoveryOptions?.onEvent?.(ev);
|
|
114
|
-
const data = ev
|
|
115
|
-
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"];
|
|
116
151
|
const txHash = typeof rawTxHash === "string" ? rawTxHash.trim() : "";
|
|
117
152
|
if (txHash) {
|
|
118
153
|
const base = String(tatchiPasskey.configs?.nearExplorerUrl || "https://testnet.nearblocks.io").replace(/\/$/, "");
|
|
@@ -122,13 +157,13 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
122
157
|
transactionHash: txHash
|
|
123
158
|
});
|
|
124
159
|
}
|
|
125
|
-
const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;
|
|
160
|
+
const elapsedRaw = data?.["elapsedMs"] ?? data?.["elapsed_ms"];
|
|
126
161
|
if (elapsedRaw == null) safeSetPollingElapsedMs(null);
|
|
127
162
|
const elapsed = elapsedRaw == null ? NaN : Number(elapsedRaw);
|
|
128
163
|
if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);
|
|
129
|
-
if (ev
|
|
130
|
-
const raw =
|
|
131
|
-
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");
|
|
132
167
|
safeSetCanRestart(false);
|
|
133
168
|
}
|
|
134
169
|
}, [
|
|
@@ -150,6 +185,16 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
150
185
|
accountId: normalized
|
|
151
186
|
});
|
|
152
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]);
|
|
153
198
|
const launchMailto = React.useCallback((rawMailtoUrl) => {
|
|
154
199
|
const url = String(rawMailtoUrl || "").trim();
|
|
155
200
|
if (!url) return;
|
|
@@ -195,40 +240,9 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
195
240
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
196
241
|
};
|
|
197
242
|
}, [mailtoUiState, safeSetMailtoUiState]);
|
|
198
|
-
const fetchLocalRecoveryEmailsFromIndexedDB = React.useCallback(async (rawAccountId) => {
|
|
199
|
-
const normalized = (rawAccountId || "").trim();
|
|
200
|
-
if (!normalized) {
|
|
201
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId");
|
|
202
|
-
return [];
|
|
203
|
-
}
|
|
204
|
-
try {
|
|
205
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB", { accountId: normalized });
|
|
206
|
-
const records = await IndexedDBManager.getRecoveryEmails(toAccountId(normalized));
|
|
207
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records", {
|
|
208
|
-
accountId: normalized,
|
|
209
|
-
count: Array.isArray(records) ? records.length : 0,
|
|
210
|
-
records
|
|
211
|
-
});
|
|
212
|
-
if (!Array.isArray(records) || records.length === 0) return [];
|
|
213
|
-
const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));
|
|
214
|
-
const emails = sorted.map((r) => String(r?.email || "").trim().toLowerCase()).filter((e) => !!e && e.includes("@"));
|
|
215
|
-
const uniq = Array.from(new Set(emails));
|
|
216
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails", {
|
|
217
|
-
accountId: normalized,
|
|
218
|
-
emails: uniq
|
|
219
|
-
});
|
|
220
|
-
return uniq;
|
|
221
|
-
} catch (err) {
|
|
222
|
-
console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB", {
|
|
223
|
-
accountId: normalized,
|
|
224
|
-
error: err instanceof Error ? err.message : String(err)
|
|
225
|
-
});
|
|
226
|
-
return [];
|
|
227
|
-
}
|
|
228
|
-
}, []);
|
|
229
243
|
const deriveEmailsFromRecoveryRecords = React.useCallback((records) => {
|
|
230
|
-
if (
|
|
231
|
-
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("@"));
|
|
232
246
|
return Array.from(new Set(emails));
|
|
233
247
|
}, []);
|
|
234
248
|
React.useEffect(() => {
|
|
@@ -246,27 +260,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
246
260
|
const handle = window.setTimeout(() => {
|
|
247
261
|
(async () => {
|
|
248
262
|
try {
|
|
249
|
-
const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;
|
|
250
|
-
let localEmails = [];
|
|
251
|
-
if (!isWalletIframeMode) {
|
|
252
|
-
localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);
|
|
253
|
-
if (!cancelled) console.log("[EmailRecoverySlide] local saved emails (IndexedDB)", {
|
|
254
|
-
accountId: normalized,
|
|
255
|
-
localEmails
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
263
|
const records = await tatchiPasskey.getRecoveryEmails(normalized);
|
|
259
|
-
const resolvedEmails =
|
|
264
|
+
const resolvedEmails = deriveEmailsFromRecoveryRecords(records);
|
|
260
265
|
if (!cancelled) {
|
|
261
266
|
safeSetLocalRecoveryEmails(resolvedEmails);
|
|
262
|
-
|
|
263
|
-
accountId: normalized,
|
|
264
|
-
emails: resolvedEmails
|
|
265
|
-
});
|
|
266
|
-
if (resolvedEmails.length === 1 && (recoveryEmailInput.trim() === "" || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)) {
|
|
267
|
-
lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];
|
|
268
|
-
setRecoveryEmailInput(resolvedEmails[0]);
|
|
269
|
-
}
|
|
267
|
+
safeSetRecoveryEmailRecords(records);
|
|
270
268
|
}
|
|
271
269
|
const info = records ? { emailsCount: Array.isArray(records) ? records.length : 0 } : null;
|
|
272
270
|
if (cancelled) return;
|
|
@@ -274,7 +272,10 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
274
272
|
} catch (err) {
|
|
275
273
|
if (cancelled) return;
|
|
276
274
|
safeSetAccountInfo(null);
|
|
277
|
-
|
|
275
|
+
const msg = err instanceof Error ? err.message : "";
|
|
276
|
+
safeSetAccountInfoError(msg || "Failed to load email recovery settings for this account");
|
|
277
|
+
safeSetLocalRecoveryEmails([]);
|
|
278
|
+
safeSetRecoveryEmailRecords([]);
|
|
278
279
|
} finally {
|
|
279
280
|
if (!cancelled) safeSetAccountInfoLoading(false);
|
|
280
281
|
}
|
|
@@ -287,25 +288,100 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
287
288
|
}, [
|
|
288
289
|
accountIdInput,
|
|
289
290
|
deriveEmailsFromRecoveryRecords,
|
|
290
|
-
fetchLocalRecoveryEmailsFromIndexedDB,
|
|
291
|
-
recoveryEmailInput,
|
|
292
291
|
safeSetAccountInfo,
|
|
293
292
|
safeSetAccountInfoError,
|
|
294
293
|
safeSetAccountInfoLoading,
|
|
295
294
|
safeSetLocalRecoveryEmails,
|
|
295
|
+
safeSetRecoveryEmailRecords,
|
|
296
296
|
tatchiPasskey
|
|
297
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
|
+
]);
|
|
298
342
|
const handleStart = React.useCallback(async () => {
|
|
299
343
|
const normalizedAccountId = (accountIdInput || "").trim();
|
|
300
344
|
if (!normalizedAccountId) {
|
|
301
345
|
safeSetErrorText("Enter an account ID.");
|
|
302
346
|
return;
|
|
303
347
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
safeSetErrorText("Enter the recovery email to send from.");
|
|
348
|
+
if (accountInfoLoading) {
|
|
349
|
+
safeSetErrorText("Checking recovery email settings…");
|
|
307
350
|
return;
|
|
308
351
|
}
|
|
352
|
+
if (accountInfoError) {
|
|
353
|
+
safeSetErrorText(accountInfoError);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (!accountInfo) {
|
|
357
|
+
safeSetErrorText("Failed to load email recovery settings for this account.");
|
|
358
|
+
return;
|
|
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
|
+
}
|
|
309
385
|
safeSetIsBusy(true);
|
|
310
386
|
cancelRequestedRef.current = false;
|
|
311
387
|
safeSetErrorText(null);
|
|
@@ -319,7 +395,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
319
395
|
try {
|
|
320
396
|
const result = await tatchiPasskey.startEmailRecovery({
|
|
321
397
|
accountId: normalizedAccountId,
|
|
322
|
-
recoveryEmail:
|
|
398
|
+
...recoveryEmail ? { recoveryEmail } : {},
|
|
323
399
|
options: {
|
|
324
400
|
onEvent,
|
|
325
401
|
onError: (err) => {
|
|
@@ -327,8 +403,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
327
403
|
safeSetErrorText(err?.message || "Failed to start email recovery");
|
|
328
404
|
didForwardError = true;
|
|
329
405
|
emailRecoveryOptions?.onError?.(err);
|
|
330
|
-
}
|
|
331
|
-
afterCall: async () => {}
|
|
406
|
+
}
|
|
332
407
|
}
|
|
333
408
|
});
|
|
334
409
|
safeSetPendingMailtoUrl(result.mailtoUrl);
|
|
@@ -345,10 +420,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
345
420
|
const uiError = getEmailRecoveryUiError(err);
|
|
346
421
|
safeSetErrorText(uiError.message || "Failed to finalize email recovery");
|
|
347
422
|
safeSetCanRestart(uiError.canRestart);
|
|
423
|
+
const txHash = getEmailRecoveryErrorTxHash(err);
|
|
424
|
+
if (txHash) showExplorerTxToast(txHash);
|
|
348
425
|
didForwardError = true;
|
|
349
426
|
emailRecoveryOptions?.onError?.(err);
|
|
350
|
-
}
|
|
351
|
-
afterCall: async () => {}
|
|
427
|
+
}
|
|
352
428
|
}
|
|
353
429
|
});
|
|
354
430
|
showExplorerToast(normalizedAccountId);
|
|
@@ -379,6 +455,8 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
379
455
|
const uiError = getEmailRecoveryUiError(err);
|
|
380
456
|
safeSetErrorText(uiError.message || "Failed to start email recovery");
|
|
381
457
|
safeSetCanRestart(uiError.canRestart);
|
|
458
|
+
const txHash = getEmailRecoveryErrorTxHash(err);
|
|
459
|
+
if (txHash) showExplorerTxToast(txHash);
|
|
382
460
|
if (!didForwardError && err instanceof Error) emailRecoveryOptions?.onError?.(err);
|
|
383
461
|
} finally {
|
|
384
462
|
safeSetIsBusy(false);
|
|
@@ -386,9 +464,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
386
464
|
}, [
|
|
387
465
|
accountIdInput,
|
|
388
466
|
emailRecoveryOptions,
|
|
389
|
-
recoveryEmailInput,
|
|
390
467
|
onEvent,
|
|
391
468
|
refreshLoginState,
|
|
469
|
+
accountInfo,
|
|
470
|
+
accountInfoError,
|
|
471
|
+
accountInfoLoading,
|
|
472
|
+
recoveryEmailConfirmationRequired,
|
|
473
|
+
recoveryEmailInput,
|
|
474
|
+
recoveryEmailRecords,
|
|
392
475
|
showExplorerToast,
|
|
393
476
|
safeSetErrorText,
|
|
394
477
|
safeSetIsBusy,
|
|
@@ -397,6 +480,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
397
480
|
safeSetStatusText,
|
|
398
481
|
safeSetMailtoUiState,
|
|
399
482
|
attemptOpenMailtoAuto,
|
|
483
|
+
showExplorerTxToast,
|
|
400
484
|
tatchiPasskey
|
|
401
485
|
]);
|
|
402
486
|
const handleRestart = React.useCallback(async () => {
|
|
@@ -433,8 +517,27 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
433
517
|
safeSetStatusText,
|
|
434
518
|
tatchiPasskey
|
|
435
519
|
]);
|
|
436
|
-
const summaryLine = accountInfoLoading ? "Checking if account has recovery emails configured
|
|
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";
|
|
437
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;
|
|
438
541
|
return /* @__PURE__ */ jsxs("div", {
|
|
439
542
|
className: "w3a-email-recovery-slide",
|
|
440
543
|
children: [
|
|
@@ -444,73 +547,84 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
444
547
|
}),
|
|
445
548
|
/* @__PURE__ */ jsx("div", {
|
|
446
549
|
className: "w3a-email-recovery-help",
|
|
447
|
-
children: "Send a
|
|
550
|
+
children: "Send a special email to recover your account. This email must be sent from the designated email recovery address."
|
|
448
551
|
}),
|
|
449
|
-
/* @__PURE__ */ jsx("div", {
|
|
450
|
-
className: "w3a-email-recovery-
|
|
552
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("div", {
|
|
553
|
+
className: "w3a-input-pill w3a-email-recovery-input-pill",
|
|
451
554
|
children: /* @__PURE__ */ jsx("div", {
|
|
452
|
-
className: "w3a-input-
|
|
453
|
-
children: /* @__PURE__ */ jsx("
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
inputMode: "text",
|
|
465
|
-
disabled: isBusy
|
|
466
|
-
})
|
|
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
|
|
467
567
|
})
|
|
468
568
|
})
|
|
469
|
-
}),
|
|
470
|
-
/* @__PURE__ */
|
|
569
|
+
}) }),
|
|
570
|
+
/* @__PURE__ */ jsxs("div", {
|
|
471
571
|
className: "w3a-email-recovery-summary",
|
|
472
572
|
"aria-live": "polite",
|
|
473
|
-
children:
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
className: "w3a-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
})
|
|
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."
|
|
494
626
|
})
|
|
495
|
-
|
|
496
|
-
}),
|
|
497
|
-
localRecoveryEmails.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
498
|
-
className: "w3a-email-recovery-summary",
|
|
499
|
-
"aria-live": "polite",
|
|
500
|
-
children: [/* @__PURE__ */ jsx("div", { children: "Saved on this device:" }), /* @__PURE__ */ jsx("div", {
|
|
501
|
-
className: "w3a-email-recovery-saved-emails",
|
|
502
|
-
children: localRecoveryEmails.map((email) => /* @__PURE__ */ jsx("button", {
|
|
503
|
-
type: "button",
|
|
504
|
-
className: "w3a-email-recovery-email-chip",
|
|
505
|
-
onClick: () => setRecoveryEmailInput(email),
|
|
506
|
-
disabled: isBusy,
|
|
507
|
-
children: email
|
|
508
|
-
}, email))
|
|
509
|
-
})]
|
|
510
|
-
}),
|
|
511
|
-
localRecoveryEmails.length > 0 && /* @__PURE__ */ jsx("datalist", {
|
|
512
|
-
id: "w3a-email-recovery-saved-emails",
|
|
513
|
-
children: localRecoveryEmails.map((email) => /* @__PURE__ */ jsx("option", { value: email }, email))
|
|
627
|
+
]
|
|
514
628
|
}),
|
|
515
629
|
/* @__PURE__ */ jsxs("div", {
|
|
516
630
|
className: "w3a-email-recovery-actions",
|
|
@@ -518,8 +632,8 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
518
632
|
(!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ jsx("button", {
|
|
519
633
|
onClick: handleStart,
|
|
520
634
|
className: "w3a-link-device-btn w3a-link-device-btn-primary",
|
|
521
|
-
disabled:
|
|
522
|
-
children: noRecoveryEmailsConfigured ? "No recovery emails configured" : isBusy ? "Working…" : "Start Email Recovery"
|
|
635
|
+
disabled: startDisabled,
|
|
636
|
+
children: accountInfoLoading ? "Checking recovery emails…" : noRecoveryEmailsConfigured ? "No recovery emails configured" : disableStartForRecoveryEmailMismatch ? "Confirm recovery email" : isBusy ? "Working…" : "Start Email Recovery"
|
|
523
637
|
}),
|
|
524
638
|
pendingMailtoUrl && /* @__PURE__ */ jsxs("button", {
|
|
525
639
|
type: "button",
|
|
@@ -553,13 +667,13 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
553
667
|
"s)."
|
|
554
668
|
]
|
|
555
669
|
}),
|
|
556
|
-
explorerToast && /* @__PURE__ */
|
|
670
|
+
explorerToast && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("br", {}), /* @__PURE__ */ jsx("a", {
|
|
557
671
|
className: "w3a-email-recovery-link",
|
|
558
672
|
href: explorerToast.url,
|
|
559
673
|
target: "_blank",
|
|
560
674
|
rel: "noopener noreferrer",
|
|
561
675
|
children: "View on explorer"
|
|
562
|
-
}) })
|
|
676
|
+
})] })
|
|
563
677
|
]
|
|
564
678
|
})
|
|
565
679
|
]
|