@tatchi-xyz/sdk 0.18.0 → 0.20.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 +80 -60
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/index.js +23 -0
- package/dist/cjs/core/WebAuthnManager/index.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-BCrFe5p3.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +25 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +80 -60
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js +23 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.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/esm/core/EmailRecovery/index.js +25 -1
- package/dist/esm/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/emailRecovery.js +81 -61
- package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/index.js +23 -0
- package/dist/esm/core/WebAuthnManager/index.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-BCrFe5p3.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
- 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 +81 -61
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js +23 -0
- package/dist/esm/react/sdk/src/core/WebAuthnManager/index.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/sdk/{createAdapters-qVGD6i0g.js → createAdapters-DIRR8_Z9.js} +1 -1
- package/dist/esm/sdk/{createAdapters-BumKM2ft.js → createAdapters-Yga6W0en.js} +2 -2
- package/dist/esm/sdk/{createAdapters-BumKM2ft.js.map → createAdapters-Yga6W0en.js.map} +1 -1
- package/dist/esm/sdk/{localOnly-pXMTqh1m.js → localOnly-BHScJasw.js} +2 -2
- package/dist/esm/sdk/{localOnly-Byi3AK7A.js → localOnly-VevCI7H0.js} +3 -3
- package/dist/esm/sdk/{localOnly-Byi3AK7A.js.map → localOnly-VevCI7H0.js.map} +1 -1
- package/dist/esm/sdk/offline-export-app.js +29 -6
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{registration-CBiS4Ua_.js → registration-bKEg9Zr2.js} +2 -2
- package/dist/esm/sdk/{registration-CBiS4Ua_.js.map → registration-bKEg9Zr2.js.map} +1 -1
- package/dist/esm/sdk/{registration-DLPLsGCz.js → registration-lDD60Ytt.js} +1 -1
- package/dist/esm/sdk/{transactions-Bk-VavcV.js → transactions-BalIhtJ9.js} +1 -1
- package/dist/esm/sdk/{transactions-BIqKZeR0.js → transactions-bqaAwL4k.js} +2 -2
- package/dist/esm/sdk/{transactions-BIqKZeR0.js.map → transactions-bqaAwL4k.js.map} +1 -1
- package/dist/esm/sdk/wallet-iframe-host.js +150 -65
- 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 +7 -2
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts +7 -0
- package/dist/types/src/core/WebAuthnManager/index.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/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/package.json +1 -1
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.js');
|
|
2
2
|
const require_accountIds = require('../types/accountIds.js');
|
|
3
3
|
const require_index = require('../IndexedDBManager/index.js');
|
|
4
|
+
const require_base64 = require('../../utils/base64.js');
|
|
4
5
|
const require_emailRecoveryPendingStore = require('./emailRecoveryPendingStore.js');
|
|
5
6
|
|
|
6
7
|
//#region src/core/EmailRecovery/index.ts
|
|
8
|
+
function getTxSuccessValueBase64(outcome) {
|
|
9
|
+
const status = outcome.status;
|
|
10
|
+
if (!status || typeof status !== "object") return null;
|
|
11
|
+
if (!("SuccessValue" in status)) return null;
|
|
12
|
+
const value = status.SuccessValue;
|
|
13
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
14
|
+
}
|
|
15
|
+
function parseLinkDeviceRegisterUserResponse(outcome) {
|
|
16
|
+
try {
|
|
17
|
+
const successValueB64 = getTxSuccessValueBase64(outcome);
|
|
18
|
+
if (!successValueB64) return null;
|
|
19
|
+
const bytes = require_base64.base64Decode(successValueB64);
|
|
20
|
+
const text = new TextDecoder().decode(bytes);
|
|
21
|
+
if (!text.trim()) return null;
|
|
22
|
+
const parsed = JSON.parse(text);
|
|
23
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
24
|
+
const candidate = parsed;
|
|
25
|
+
return typeof candidate.verified === "boolean" ? candidate : null;
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
7
30
|
async function hashRecoveryEmails(emails, accountId) {
|
|
8
31
|
const encoder = new TextEncoder();
|
|
9
32
|
const salt = (accountId || "").trim().toLowerCase();
|
|
@@ -54,6 +77,7 @@ var canonicalizeEmail, bytesToHex;
|
|
|
54
77
|
var init_EmailRecovery = require_rolldown_runtime.__esm({ "src/core/EmailRecovery/index.ts": (() => {
|
|
55
78
|
require_accountIds.init_accountIds();
|
|
56
79
|
require_index.init_IndexedDBManager();
|
|
80
|
+
require_base64.init_base64();
|
|
57
81
|
require_emailRecoveryPendingStore.init_emailRecoveryPendingStore();
|
|
58
82
|
canonicalizeEmail = (email) => {
|
|
59
83
|
const raw = String(email || "").trim();
|
|
@@ -85,5 +109,6 @@ Object.defineProperty(exports, 'init_EmailRecovery', {
|
|
|
85
109
|
return init_EmailRecovery;
|
|
86
110
|
}
|
|
87
111
|
});
|
|
112
|
+
exports.parseLinkDeviceRegisterUserResponse = parseLinkDeviceRegisterUserResponse;
|
|
88
113
|
exports.prepareRecoveryEmails = prepareRecoveryEmails;
|
|
89
114
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["hashed: number[][]","toAccountId","pairs: RecoveryEmailEntry[]","IndexedDBManager"],"sources":["../../../../src/core/EmailRecovery/index.ts"],"sourcesContent":["import type { AccountId } from '../types/accountIds';\nimport { toAccountId } from '../types/accountIds';\nimport { IndexedDBManager, type RecoveryEmailRecord } from '../IndexedDBManager';\nexport { EmailRecoveryPendingStore, type PendingStore } from './emailRecoveryPendingStore';\n\nexport type RecoveryEmailEntry = {\n hashHex: string;\n email: string;\n};\n\nexport { type RecoveryEmailRecord };\n\nexport const canonicalizeEmail = (email: string): string => {\n const raw = String(email || '').trim();\n if (!raw) return '';\n\n // Handle cases where a full header line is passed in (e.g. \"From: ...\").\n const withoutHeaderName = raw.replace(/^[a-z0-9-]+\\s*:\\s*/i, '').trim();\n\n const emailRegex =\n /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)/;\n\n // Prefer the common \"Name <email@domain>\" format when present, but still\n // validate/extract the actual address via regex.\n const angleMatch = withoutHeaderName.match(/<([^>]+)>/);\n const candidates = [\n angleMatch?.[1],\n withoutHeaderName,\n ].filter((v): v is string => typeof v === 'string' && v.length > 0);\n\n for (const candidate of candidates) {\n const cleaned = candidate.replace(/^mailto:\\s*/i, '');\n const match = cleaned.match(emailRegex);\n if (match?.[1]) {\n return match[1].trim().toLowerCase();\n }\n }\n\n return withoutHeaderName.toLowerCase();\n};\n\nexport const bytesToHex = (bytes: number[] | Uint8Array): string => {\n const arr = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);\n return `0x${Array.from(arr)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')}`;\n};\n\nasync function hashRecoveryEmails(emails: string[], accountId: AccountId): Promise<number[][]> {\n const encoder = new TextEncoder();\n const salt = (accountId || '').trim().toLowerCase();\n const normalized = (emails || [])\n .map(e => e.trim())\n .filter(e => e.length > 0);\n\n const hashed: number[][] = [];\n\n for (const email of normalized) {\n try {\n const canonicalEmail = canonicalizeEmail(email);\n const input = `${canonicalEmail}|${salt}`;\n const data = encoder.encode(input);\n const digest = await crypto.subtle.digest('SHA-256', data);\n const bytes = new Uint8Array(digest);\n hashed.push(Array.from(bytes));\n } catch {\n const bytes = encoder.encode(email.toLowerCase());\n hashed.push(Array.from(bytes));\n }\n }\n\n return hashed;\n}\n\n/**\n * Canonicalize and hash recovery emails for an account, and persist the mapping\n * (hashHex → canonical email) in IndexedDB on a best-effort basis.\n */\nexport async function prepareRecoveryEmails(nearAccountId: AccountId, recoveryEmails: string[]): Promise<{\n hashes: number[][];\n pairs: RecoveryEmailEntry[];\n}> {\n const accountId = toAccountId(nearAccountId);\n\n const trimmedEmails = (recoveryEmails || []).map(e => e.trim()).filter(e => e.length > 0);\n const canonicalEmails = trimmedEmails.map(canonicalizeEmail);\n const recoveryEmailHashes = await hashRecoveryEmails(recoveryEmails, accountId);\n\n const pairs: RecoveryEmailEntry[] = recoveryEmailHashes.map((hashBytes, idx) => ({\n hashHex: bytesToHex(hashBytes),\n email: canonicalEmails[idx],\n }));\n\n void (async () => {\n try {\n await IndexedDBManager.upsertRecoveryEmails(accountId, pairs);\n } catch (error) {\n console.warn('[EmailRecovery] Failed to persist local recovery emails', error);\n }\n })();\n\n return { hashes: recoveryEmailHashes, pairs };\n}\n\nexport async function getLocalRecoveryEmails(nearAccountId: AccountId): Promise<RecoveryEmailRecord[]> {\n return IndexedDBManager.getRecoveryEmails(nearAccountId);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":["base64Decode","hashed: number[][]","toAccountId","pairs: RecoveryEmailEntry[]","IndexedDBManager"],"sources":["../../../../src/core/EmailRecovery/index.ts"],"sourcesContent":["import type { AccountId } from '../types/accountIds';\nimport { toAccountId } from '../types/accountIds';\nimport { IndexedDBManager, type RecoveryEmailRecord } from '../IndexedDBManager';\nimport type { FinalExecutionOutcome } from '@near-js/types';\nimport { base64Decode } from '../../utils/base64';\nexport { EmailRecoveryPendingStore, type PendingStore } from './emailRecoveryPendingStore';\n\nexport type RecoveryEmailEntry = {\n hashHex: string;\n email: string;\n};\n\nexport { type RecoveryEmailRecord };\n\nexport type LinkDeviceRegisterUserResponse = {\n verified?: boolean;\n registration_info?: unknown;\n registrationInfo?: unknown;\n error?: unknown;\n};\n\nfunction getTxSuccessValueBase64(outcome: FinalExecutionOutcome): string | null {\n const status = outcome.status;\n if (!status || typeof status !== 'object') return null;\n if (!('SuccessValue' in status)) return null;\n const value = status.SuccessValue;\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nexport function parseLinkDeviceRegisterUserResponse(\n outcome: FinalExecutionOutcome\n): LinkDeviceRegisterUserResponse | null {\n try {\n const successValueB64 = getTxSuccessValueBase64(outcome);\n if (!successValueB64) return null;\n\n const bytes = base64Decode(successValueB64);\n const text = new TextDecoder().decode(bytes);\n if (!text.trim()) return null;\n\n const parsed = JSON.parse(text) as unknown;\n if (!parsed || typeof parsed !== 'object') return null;\n const candidate = parsed as LinkDeviceRegisterUserResponse;\n return typeof candidate.verified === 'boolean' ? candidate : null;\n } catch {\n return null;\n }\n}\n\nexport const canonicalizeEmail = (email: string): string => {\n const raw = String(email || '').trim();\n if (!raw) return '';\n\n // Handle cases where a full header line is passed in (e.g. \"From: ...\").\n const withoutHeaderName = raw.replace(/^[a-z0-9-]+\\s*:\\s*/i, '').trim();\n\n const emailRegex =\n /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)/;\n\n // Prefer the common \"Name <email@domain>\" format when present, but still\n // validate/extract the actual address via regex.\n const angleMatch = withoutHeaderName.match(/<([^>]+)>/);\n const candidates = [\n angleMatch?.[1],\n withoutHeaderName,\n ].filter((v): v is string => typeof v === 'string' && v.length > 0);\n\n for (const candidate of candidates) {\n const cleaned = candidate.replace(/^mailto:\\s*/i, '');\n const match = cleaned.match(emailRegex);\n if (match?.[1]) {\n return match[1].trim().toLowerCase();\n }\n }\n\n return withoutHeaderName.toLowerCase();\n};\n\nexport const bytesToHex = (bytes: number[] | Uint8Array): string => {\n const arr = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);\n return `0x${Array.from(arr)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')}`;\n};\n\nasync function hashRecoveryEmails(emails: string[], accountId: AccountId): Promise<number[][]> {\n const encoder = new TextEncoder();\n const salt = (accountId || '').trim().toLowerCase();\n const normalized = (emails || [])\n .map(e => e.trim())\n .filter(e => e.length > 0);\n\n const hashed: number[][] = [];\n\n for (const email of normalized) {\n try {\n const canonicalEmail = canonicalizeEmail(email);\n const input = `${canonicalEmail}|${salt}`;\n const data = encoder.encode(input);\n const digest = await crypto.subtle.digest('SHA-256', data);\n const bytes = new Uint8Array(digest);\n hashed.push(Array.from(bytes));\n } catch {\n const bytes = encoder.encode(email.toLowerCase());\n hashed.push(Array.from(bytes));\n }\n }\n\n return hashed;\n}\n\n/**\n * Canonicalize and hash recovery emails for an account, and persist the mapping\n * (hashHex → canonical email) in IndexedDB on a best-effort basis.\n */\nexport async function prepareRecoveryEmails(nearAccountId: AccountId, recoveryEmails: string[]): Promise<{\n hashes: number[][];\n pairs: RecoveryEmailEntry[];\n}> {\n const accountId = toAccountId(nearAccountId);\n\n const trimmedEmails = (recoveryEmails || []).map(e => e.trim()).filter(e => e.length > 0);\n const canonicalEmails = trimmedEmails.map(canonicalizeEmail);\n const recoveryEmailHashes = await hashRecoveryEmails(recoveryEmails, accountId);\n\n const pairs: RecoveryEmailEntry[] = recoveryEmailHashes.map((hashBytes, idx) => ({\n hashHex: bytesToHex(hashBytes),\n email: canonicalEmails[idx],\n }));\n\n void (async () => {\n try {\n await IndexedDBManager.upsertRecoveryEmails(accountId, pairs);\n } catch (error) {\n console.warn('[EmailRecovery] Failed to persist local recovery emails', error);\n }\n })();\n\n return { hashes: recoveryEmailHashes, pairs };\n}\n\nexport async function getLocalRecoveryEmails(nearAccountId: AccountId): Promise<RecoveryEmailRecord[]> {\n return IndexedDBManager.getRecoveryEmails(nearAccountId);\n}\n"],"mappings":";;;;;;;AAqBA,SAAS,wBAAwB,SAA+C;CAC9E,MAAM,SAAS,QAAQ;AACvB,KAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,KAAI,EAAE,kBAAkB,QAAS,QAAO;CACxC,MAAM,QAAQ,OAAO;AACrB,QAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;;AAGjE,SAAgB,oCACd,SACuC;AACvC,KAAI;EACF,MAAM,kBAAkB,wBAAwB;AAChD,MAAI,CAAC,gBAAiB,QAAO;EAE7B,MAAM,QAAQA,4BAAa;EAC3B,MAAM,OAAO,IAAI,cAAc,OAAO;AACtC,MAAI,CAAC,KAAK,OAAQ,QAAO;EAEzB,MAAM,SAAS,KAAK,MAAM;AAC1B,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;EAClD,MAAM,YAAY;AAClB,SAAO,OAAO,UAAU,aAAa,YAAY,YAAY;SACvD;AACN,SAAO;;;AAwCX,eAAe,mBAAmB,QAAkB,WAA2C;CAC7F,MAAM,UAAU,IAAI;CACpB,MAAM,QAAQ,aAAa,IAAI,OAAO;CACtC,MAAM,cAAc,UAAU,IAC3B,KAAI,MAAK,EAAE,QACX,QAAO,MAAK,EAAE,SAAS;CAE1B,MAAMC,SAAqB;AAE3B,MAAK,MAAM,SAAS,WAClB,KAAI;EACF,MAAM,iBAAiB,kBAAkB;EACzC,MAAM,QAAQ,GAAG,eAAe,GAAG;EACnC,MAAM,OAAO,QAAQ,OAAO;EAC5B,MAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW;EACrD,MAAM,QAAQ,IAAI,WAAW;AAC7B,SAAO,KAAK,MAAM,KAAK;SACjB;EACN,MAAM,QAAQ,QAAQ,OAAO,MAAM;AACnC,SAAO,KAAK,MAAM,KAAK;;AAI3B,QAAO;;;;;;AAOT,eAAsB,sBAAsB,eAA0B,gBAGnE;CACD,MAAM,YAAYC,+BAAY;CAE9B,MAAM,iBAAiB,kBAAkB,IAAI,KAAI,MAAK,EAAE,QAAQ,QAAO,MAAK,EAAE,SAAS;CACvF,MAAM,kBAAkB,cAAc,IAAI;CAC1C,MAAM,sBAAsB,MAAM,mBAAmB,gBAAgB;CAErE,MAAMC,QAA8B,oBAAoB,KAAK,WAAW,SAAS;EAC/E,SAAS,WAAW;EACpB,OAAO,gBAAgB;;AAGzB,EAAM,YAAY;AAChB,MAAI;AACF,SAAMC,+BAAiB,qBAAqB,WAAW;WAChD,OAAO;AACd,WAAQ,KAAK,2DAA2D;;;AAI5E,QAAO;EAAE,QAAQ;EAAqB;;;AAGxC,eAAsB,uBAAuB,eAA0D;AACrG,QAAOA,+BAAiB,kBAAkB;;;;;;;;CA7F/B,qBAAqB,UAA0B;EAC1D,MAAM,MAAM,OAAO,SAAS,IAAI;AAChC,MAAI,CAAC,IAAK,QAAO;EAGjB,MAAM,oBAAoB,IAAI,QAAQ,uBAAuB,IAAI;EAEjE,MAAM,aACJ;EAIF,MAAM,aAAa,kBAAkB,MAAM;EAC3C,MAAM,aAAa,CACjB,aAAa,IACb,mBACA,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS;AAEjE,OAAK,MAAM,aAAa,YAAY;GAClC,MAAM,UAAU,UAAU,QAAQ,gBAAgB;GAClD,MAAM,QAAQ,QAAQ,MAAM;AAC5B,OAAI,QAAQ,GACV,QAAO,MAAM,GAAG,OAAO;;AAI3B,SAAO,kBAAkB;;CAGd,cAAc,UAAyC;EAClE,MAAM,MAAM,iBAAiB,aAAa,QAAQ,WAAW,KAAK;AAClE,SAAO,KAAK,MAAM,KAAK,KACpB,KAAI,MAAK,EAAE,SAAS,IAAI,SAAS,GAAG,MACpC,KAAK"}
|
|
@@ -3,12 +3,14 @@ const require_validation = require('../../utils/validation.js');
|
|
|
3
3
|
const require_accountIds = require('../types/accountIds.js');
|
|
4
4
|
const require_index = require('../IndexedDBManager/index.js');
|
|
5
5
|
const require_vrf_worker = require('../types/vrf-worker.js');
|
|
6
|
+
const require_errors = require('../../utils/errors.js');
|
|
6
7
|
const require_sdkSentEvents = require('../types/sdkSentEvents.js');
|
|
7
8
|
const require_rpc = require('../types/rpc.js');
|
|
8
9
|
const require_getDeviceNumber = require('../WebAuthnManager/SignerWorkerManager/getDeviceNumber.js');
|
|
9
10
|
const require_login = require('./login.js');
|
|
10
11
|
const require_emailRecoveryPendingStore = require('../EmailRecovery/emailRecoveryPendingStore.js');
|
|
11
12
|
const require_index$1 = require('../EmailRecovery/index.js');
|
|
13
|
+
const require_emailRecovery = require('../types/emailRecovery.js');
|
|
12
14
|
|
|
13
15
|
//#region src/core/TatchiPasskey/emailRecovery.ts
|
|
14
16
|
var emailRecovery_exports = {};
|
|
@@ -48,6 +50,7 @@ var EmailRecoveryFlow;
|
|
|
48
50
|
var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasskey/emailRecovery.ts": (() => {
|
|
49
51
|
require_index.init_IndexedDBManager();
|
|
50
52
|
require_validation.init_validation();
|
|
53
|
+
require_errors.init_errors();
|
|
51
54
|
require_accountIds.init_accountIds();
|
|
52
55
|
require_sdkSentEvents.init_sdkSentEvents();
|
|
53
56
|
require_vrf_worker.init_vrf_worker();
|
|
@@ -55,6 +58,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
55
58
|
require_getDeviceNumber.init_getDeviceNumber();
|
|
56
59
|
require_login.init_login();
|
|
57
60
|
require_index$1.init_EmailRecovery();
|
|
61
|
+
require_emailRecovery.init_emailRecovery();
|
|
58
62
|
EmailRecoveryFlow = class {
|
|
59
63
|
context;
|
|
60
64
|
options;
|
|
@@ -82,8 +86,9 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
82
86
|
emit(event) {
|
|
83
87
|
this.options?.onEvent?.(event);
|
|
84
88
|
}
|
|
85
|
-
emitError(step,
|
|
86
|
-
const err = new Error(
|
|
89
|
+
emitError(step, messageOrError) {
|
|
90
|
+
const err = typeof messageOrError === "string" ? new Error(messageOrError) : messageOrError;
|
|
91
|
+
const message = err.message || (typeof messageOrError === "string" ? messageOrError : "Unknown error");
|
|
87
92
|
this.phase = require_sdkSentEvents.EmailRecoveryPhase.ERROR;
|
|
88
93
|
this.error = err;
|
|
89
94
|
this.emit({
|
|
@@ -142,8 +147,8 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
142
147
|
const accountView = await this.context.nearClient.viewAccount(nearAccountId);
|
|
143
148
|
const available = this.computeAvailableBalance(accountView);
|
|
144
149
|
if (available < BigInt(minBalanceYocto)) await this.fail(1, `This account does not have enough NEAR to finalize recovery. Available: ${available.toString()} yocto; required: ${String(minBalanceYocto)}. Please top up and try again.`);
|
|
145
|
-
} catch (
|
|
146
|
-
await this.fail(1,
|
|
150
|
+
} catch (err) {
|
|
151
|
+
await this.fail(1, require_errors.errorMessage(err) || "Failed to fetch account balance for recovery");
|
|
147
152
|
}
|
|
148
153
|
}
|
|
149
154
|
async getCanonicalRecoveryEmailOrFail(recoveryEmail) {
|
|
@@ -155,7 +160,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
155
160
|
try {
|
|
156
161
|
const { syncAuthenticatorsContractCall } = await Promise.resolve().then(() => require("../rpcCalls.js"));
|
|
157
162
|
const authenticators = await syncAuthenticatorsContractCall(this.context.nearClient, this.context.configs.contractId, nearAccountId);
|
|
158
|
-
const numbers = authenticators.map((
|
|
163
|
+
const numbers = authenticators.map(({ authenticator }) => authenticator.deviceNumber).filter((n) => typeof n === "number" && Number.isFinite(n));
|
|
159
164
|
const max = numbers.length > 0 ? Math.max(...numbers) : 0;
|
|
160
165
|
return max + 1;
|
|
161
166
|
} catch {
|
|
@@ -234,11 +239,11 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
234
239
|
success: false
|
|
235
240
|
};
|
|
236
241
|
if (!result.verified) {
|
|
237
|
-
const errorMessage = result.error_message || result.error_code || "Email verification failed on relayer/contract";
|
|
242
|
+
const errorMessage$1 = result.error_message || result.error_code || "Email verification failed on relayer/contract";
|
|
238
243
|
return {
|
|
239
244
|
completed: true,
|
|
240
245
|
success: false,
|
|
241
|
-
errorMessage,
|
|
246
|
+
errorMessage: errorMessage$1,
|
|
242
247
|
transactionHash: result.transaction_hash
|
|
243
248
|
};
|
|
244
249
|
}
|
|
@@ -403,7 +408,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
403
408
|
nearPublicKey: rec.nearPublicKey
|
|
404
409
|
};
|
|
405
410
|
} catch (e) {
|
|
406
|
-
const err = this.emitError(2, e
|
|
411
|
+
const err = this.emitError(2, require_errors.errorMessage(e) || "Email recovery TouchID/derivation failed");
|
|
407
412
|
await this.options?.afterCall?.(false);
|
|
408
413
|
throw err;
|
|
409
414
|
}
|
|
@@ -573,7 +578,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
573
578
|
accountId
|
|
574
579
|
};
|
|
575
580
|
}
|
|
576
|
-
async
|
|
581
|
+
async signNewDevice2RegistrationTx(rec, accountId) {
|
|
577
582
|
const vrfChallenge = rec.vrfChallenge;
|
|
578
583
|
if (!vrfChallenge) return this.fail(5, "Missing VRF challenge for email recovery registration");
|
|
579
584
|
const registrationResult = await this.context.webAuthnManager.signDevice2RegistrationWithStoredKey({
|
|
@@ -587,47 +592,56 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
587
592
|
return registrationResult.signedTransaction;
|
|
588
593
|
}
|
|
589
594
|
async broadcastRegistrationTxAndWaitFinal(rec, signedTx) {
|
|
595
|
+
let txResult;
|
|
590
596
|
try {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
step: 5,
|
|
596
|
-
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
597
|
-
status: require_sdkSentEvents.EmailRecoveryStatus.PROGRESS,
|
|
598
|
-
message: "Registration transaction confirmed",
|
|
599
|
-
data: {
|
|
600
|
-
accountId: rec.accountId,
|
|
601
|
-
nearPublicKey: rec.nearPublicKey,
|
|
602
|
-
transactionHash: txHash
|
|
603
|
-
}
|
|
604
|
-
});
|
|
605
|
-
return txHash;
|
|
606
|
-
} catch {}
|
|
607
|
-
} catch (e) {
|
|
608
|
-
const msg = String(e?.message || "");
|
|
609
|
-
await this.fail(5, msg || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)");
|
|
597
|
+
txResult = await this.context.nearClient.sendTransaction(signedTx, require_rpc.DEFAULT_WAIT_STATUS.linkDeviceRegistration);
|
|
598
|
+
} catch (err) {
|
|
599
|
+
const msg = require_errors.errorMessage(err) || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)";
|
|
600
|
+
throw new Error(msg);
|
|
610
601
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
602
|
+
const txHash = this.getTxHash(txResult);
|
|
603
|
+
const linkDeviceResult = require_index$1.parseLinkDeviceRegisterUserResponse(txResult);
|
|
604
|
+
if (linkDeviceResult?.verified === false) {
|
|
605
|
+
const logs = this.extractNearExecutionLogs(txResult);
|
|
606
|
+
const isStaleChallenge = logs.some((log) => /StaleChallenge|freshness validation failed/i.test(log));
|
|
607
|
+
const txHint = txHash ? ` (tx: ${txHash})` : "";
|
|
608
|
+
const code = isStaleChallenge ? require_emailRecovery.EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED : require_emailRecovery.EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED;
|
|
609
|
+
const message = isStaleChallenge ? `Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again${txHint}.` : `Registration did not verify on-chain. Please try again${txHint}.`;
|
|
610
|
+
throw new require_emailRecovery.EmailRecoveryError(message, code, {
|
|
611
|
+
accountId: rec.accountId,
|
|
612
|
+
nearPublicKey: rec.nearPublicKey,
|
|
613
|
+
transactionHash: txHash,
|
|
614
|
+
logs,
|
|
615
|
+
result: linkDeviceResult
|
|
625
616
|
});
|
|
626
|
-
return true;
|
|
627
|
-
} catch (err) {
|
|
628
|
-
console.warn("[EmailRecoveryFlow] Failed to store recovery user record:", err);
|
|
629
|
-
return false;
|
|
630
617
|
}
|
|
618
|
+
if (txHash) this.emit({
|
|
619
|
+
step: 5,
|
|
620
|
+
phase: require_sdkSentEvents.EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
621
|
+
status: require_sdkSentEvents.EmailRecoveryStatus.PROGRESS,
|
|
622
|
+
message: "Registration transaction confirmed",
|
|
623
|
+
data: {
|
|
624
|
+
accountId: rec.accountId,
|
|
625
|
+
nearPublicKey: rec.nearPublicKey,
|
|
626
|
+
transactionHash: txHash
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
return txHash;
|
|
630
|
+
}
|
|
631
|
+
getTxHash(outcome) {
|
|
632
|
+
const txUnknown = outcome.transaction;
|
|
633
|
+
if (txUnknown && typeof txUnknown === "object") {
|
|
634
|
+
const hash = txUnknown.hash;
|
|
635
|
+
if (typeof hash === "string" && hash.length > 0) return hash;
|
|
636
|
+
}
|
|
637
|
+
const fallback = outcome.transaction_hash;
|
|
638
|
+
return typeof fallback === "string" && fallback.length > 0 ? fallback : void 0;
|
|
639
|
+
}
|
|
640
|
+
extractNearExecutionLogs(outcome) {
|
|
641
|
+
const logs = [];
|
|
642
|
+
for (const entry of outcome.transaction_outcome.outcome.logs) logs.push(String(entry));
|
|
643
|
+
for (const receipt of outcome.receipts_outcome) for (const entry of receipt.outcome.logs) logs.push(String(entry));
|
|
644
|
+
return logs;
|
|
631
645
|
}
|
|
632
646
|
mapAuthenticatorsFromContract(authenticators) {
|
|
633
647
|
return authenticators.map(({ authenticator }) => ({
|
|
@@ -663,7 +677,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
663
677
|
}
|
|
664
678
|
async updateNonceBestEffort(nonceManager, signedTx) {
|
|
665
679
|
try {
|
|
666
|
-
const txNonce = signedTx.transaction
|
|
680
|
+
const txNonce = signedTx.transaction.nonce;
|
|
667
681
|
if (txNonce != null) await nonceManager.updateNonceFromBlockchain(this.context.nearClient, String(txNonce));
|
|
668
682
|
} catch {}
|
|
669
683
|
}
|
|
@@ -686,6 +700,10 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
686
700
|
};
|
|
687
701
|
await webAuthnManager.storeUserData(payload);
|
|
688
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Explicitly persist the authenticator from the recovery record into the local cache.
|
|
705
|
+
* This ensures the key is available immediately, bridging the gap before RPC sync sees it.
|
|
706
|
+
*/
|
|
689
707
|
async persistAuthenticatorBestEffort(rec, accountId) {
|
|
690
708
|
try {
|
|
691
709
|
const { webAuthnManager } = this.context;
|
|
@@ -702,7 +720,10 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
702
720
|
syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
703
721
|
vrfPublicKey: rec.vrfPublicKey
|
|
704
722
|
});
|
|
705
|
-
|
|
723
|
+
console.log("[EmailRecoveryFlow] Locally persisted recovered authenticator for immediate use.");
|
|
724
|
+
} catch (e) {
|
|
725
|
+
console.error("[EmailRecoveryFlow] Failed to locally persist authenticator (critical for immediate export):", e);
|
|
726
|
+
}
|
|
706
727
|
}
|
|
707
728
|
async markCompleteAndClearPending(rec) {
|
|
708
729
|
rec.status = "complete";
|
|
@@ -772,7 +793,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
772
793
|
} catch (err) {
|
|
773
794
|
return {
|
|
774
795
|
success: false,
|
|
775
|
-
reason: err
|
|
796
|
+
reason: require_errors.errorMessage(err) || String(err)
|
|
776
797
|
};
|
|
777
798
|
}
|
|
778
799
|
}
|
|
@@ -800,18 +821,14 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
800
821
|
});
|
|
801
822
|
try {
|
|
802
823
|
const { nonceManager, accountId } = this.initializeNonceManager(rec);
|
|
803
|
-
const signedTx = await this.
|
|
824
|
+
const signedTx = await this.signNewDevice2RegistrationTx(rec, accountId);
|
|
804
825
|
const txHash = await this.broadcastRegistrationTxAndWaitFinal(rec, signedTx);
|
|
805
|
-
if (txHash)
|
|
806
|
-
const storedUser = await this.persistRecoveredUserRecordBestEffort(rec, accountId);
|
|
807
|
-
if (storedUser) {
|
|
808
|
-
const syncedAuthenticators = await this.syncAuthenticatorsBestEffort(accountId);
|
|
809
|
-
if (syncedAuthenticators) await this.setLastUserBestEffort(accountId, rec.deviceNumber);
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
await this.updateNonceBestEffort(nonceManager, signedTx);
|
|
826
|
+
if (!txHash) console.warn("[EmailRecoveryFlow] Registration transaction confirmed without hash; continuing local persistence");
|
|
813
827
|
await this.persistRecoveredUserData(rec, accountId);
|
|
828
|
+
await this.syncAuthenticatorsBestEffort(accountId);
|
|
814
829
|
await this.persistAuthenticatorBestEffort(rec, accountId);
|
|
830
|
+
await this.setLastUserBestEffort(accountId, rec.deviceNumber);
|
|
831
|
+
await this.updateNonceBestEffort(nonceManager, signedTx);
|
|
815
832
|
this.emitAutoLoginEvent(require_sdkSentEvents.EmailRecoveryStatus.PROGRESS, "Attempting auto-login with recovered device...", { autoLogin: "progress" });
|
|
816
833
|
const autoLoginResult = await this.attemptAutoLogin(rec);
|
|
817
834
|
if (autoLoginResult.success) this.emitAutoLoginEvent(require_sdkSentEvents.EmailRecoveryStatus.SUCCESS, `Welcome ${accountId}`, { autoLogin: "success" });
|
|
@@ -832,7 +849,10 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
832
849
|
}
|
|
833
850
|
});
|
|
834
851
|
} catch (e) {
|
|
835
|
-
|
|
852
|
+
rec.status = "error";
|
|
853
|
+
await this.savePending(rec).catch(() => {});
|
|
854
|
+
const original = e instanceof Error ? e : new Error(require_errors.errorMessage(e) || "Email recovery finalization failed");
|
|
855
|
+
const err = this.emitError(5, original);
|
|
836
856
|
await this.options?.afterCall?.(false);
|
|
837
857
|
throw err;
|
|
838
858
|
}
|
|
@@ -854,7 +874,7 @@ var init_emailRecovery = require_rolldown_runtime.__esm({ "src/core/TatchiPasske
|
|
|
854
874
|
};
|
|
855
875
|
return this.handleAutoLoginFailure(touchIdResult.reason || "Auto-login failed");
|
|
856
876
|
} catch (err) {
|
|
857
|
-
return this.handleAutoLoginFailure(err
|
|
877
|
+
return this.handleAutoLoginFailure(require_errors.errorMessage(err) || String(err), err);
|
|
858
878
|
}
|
|
859
879
|
}
|
|
860
880
|
};
|