@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,6 +1,6 @@
|
|
|
1
1
|
import { ERROR_MESSAGES, getIntentDigest, getNearAccountId, getRegisterAccountPayload, isSerializedRegistrationCredential, isUserCancelledSecureConfirm, serializeRegistrationCredentialWithPRF, toError } from "./requestHelpers-aUKhXiEl.js";
|
|
2
2
|
import "./validation-DhPPUba7.js";
|
|
3
|
-
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-
|
|
3
|
+
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-Yga6W0en.js";
|
|
4
4
|
import "./css-loader-BrMMlG4X.js";
|
|
5
5
|
import "./lit-events-BKobq01K.js";
|
|
6
6
|
import "./tx-tree-themes-i3It4IYY.js";
|
|
@@ -130,4 +130,4 @@ async function handleRegistrationFlow(ctx, request, worker, opts) {
|
|
|
130
130
|
|
|
131
131
|
//#endregion
|
|
132
132
|
export { handleRegistrationFlow };
|
|
133
|
-
//# sourceMappingURL=registration-
|
|
133
|
+
//# sourceMappingURL=registration-bKEg9Zr2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registration-
|
|
1
|
+
{"version":3,"file":"registration-bKEg9Zr2.js","names":["uiVrfChallenge: VRFChallenge","credential: PublicKeyCredential | undefined","e: unknown","serialized: WebAuthnRegistrationCredential","err: unknown"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n TransactionSummary,\n RegistrationSecureConfirmRequest,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport type { WebAuthnRegistrationCredential } from '../../../../types/webauthn';\nimport {\n getNearAccountId,\n getIntentDigest,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getRegisterAccountPayload,\n} from './index';\nimport { isSerializedRegistrationCredential, serializeRegistrationCredentialWithPRF } from '../../../credentialsHelpers';\nimport { toError } from '../../../../../utils/errors';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nexport async function handleRegistrationFlow(\n ctx: VrfWorkerManagerContext,\n request: RegistrationSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n\n console.debug('[RegistrationFlow] start', {\n nearAccountId,\n uiMode: confirmationConfig?.uiMode,\n behavior: confirmationConfig?.behavior,\n theme: confirmationConfig?.theme,\n intentDigest: transactionSummary?.intentDigest,\n });\n\n // 1) NEAR context\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: 1, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n const transactionContext = nearRpc.transactionContext as TransactionContext;\n session.setReservedNonces(nearRpc.reservedNonces);\n\n // 2) Initial VRF challenge via bootstrap\n const rpId = adapters.vrf.getRpId();\n const bootstrap = await adapters.vrf.generateVrfKeypairBootstrap({\n vrfInputData: {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n saveInMemory: true,\n sessionId: request.requestId,\n });\n let uiVrfChallenge: VRFChallenge = bootstrap.vrfChallenge;\n console.debug('[RegistrationFlow] VRF bootstrap ok', { blockHeight: uiVrfChallenge.blockHeight });\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallenge });\n if (!confirmed) {\n console.debug('[RegistrationFlow] user cancelled');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) JIT refresh VRF (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n console.debug('[RegistrationFlow] VRF JIT refresh ok', { blockHeight: uiVrfChallenge.blockHeight });\n } catch (e) {\n console.debug('[RegistrationFlow] VRF JIT refresh skipped', e);\n }\n\n // 5) Collect registration credentials (with duplicate retry)\n let credential: PublicKeyCredential | undefined;\n let deviceNumber = request.payload?.deviceNumber;\n\n const tryCreate = async (dn?: number): Promise<PublicKeyCredential> => {\n console.debug('[RegistrationFlow] navigator.credentials.create start', { deviceNumber: dn });\n return await adapters.webauthn.createRegistrationCredential({\n nearAccountId,\n challenge: uiVrfChallenge,\n deviceNumber: dn,\n });\n };\n\n try {\n try {\n credential = await tryCreate(deviceNumber);\n console.debug('[RegistrationFlow] credentials.create ok');\n } catch (e: unknown) {\n const err = toError(e);\n const name = String(err?.name || '');\n const msg = String(err?.message || '');\n const isDuplicate = name === 'InvalidStateError' || /excluded|already\\s*registered/i.test(msg);\n if (isDuplicate) {\n const nextDeviceNumber = (deviceNumber !== undefined && Number.isFinite(deviceNumber)) ? (deviceNumber + 1) : 2;\n console.debug('[RegistrationFlow] duplicate credential, retry with next deviceNumber', { nextDeviceNumber });\n credential = await tryCreate(nextDeviceNumber);\n getRegisterAccountPayload(request).deviceNumber = nextDeviceNumber;\n } else {\n console.error('[RegistrationFlow] credentials.create failed (non-duplicate)', { name, msg });\n throw err;\n }\n }\n\n // We require registration credentials to include dual PRF outputs (first + second)\n // so VRF/NEAR key derivation can happen inside the workers without passing PRF outputs\n // as separate main-thread values.\n const serialized: WebAuthnRegistrationCredential = isSerializedRegistrationCredential(credential as unknown)\n ? (credential as unknown as WebAuthnRegistrationCredential)\n : serializeRegistrationCredentialWithPRF({\n credential: credential! as PublicKeyCredential,\n firstPrfOutput: true,\n secondPrfOutput: true,\n });\n\n // 6) Respond + close\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serialized,\n // PRF outputs are embedded in serialized credential; VRF worker extracts and sends via MessagePort\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n\n } catch (err: unknown) {\n const cancelled = isUserCancelledSecureConfirm(err);\n const msg = String((toError(err))?.message || err || '');\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n\n const isPrfBrowserUnsupported =\n /WebAuthn PRF output is missing from navigator\\.credentials\\.create\\(\\)/i.test(msg)\n || /does not fully support the WebAuthn PRF extension during registration/i.test(msg)\n || /roaming hardware authenticators .* not supported in this flow/i.test(msg);\n\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isPrfBrowserUnsupported ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ import "./tx-confirmer-wrapper-lHNgz9i4.js";
|
|
|
11
11
|
import { init_errors, toError } from "./errors-D9ar28Dr.js";
|
|
12
12
|
import { init_credentialsHelpers, isSerializedRegistrationCredential, serializeRegistrationCredentialWithPRF } from "./WebAuthnFallbacks-Bl4BTsNt.js";
|
|
13
13
|
import { ERROR_MESSAGES, getIntentDigest, getNearAccountId, getRegisterAccountPayload, isUserCancelledSecureConfirm } from "./requestHelpers-Dh1hEYL9.js";
|
|
14
|
-
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-
|
|
14
|
+
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-DIRR8_Z9.js";
|
|
15
15
|
|
|
16
16
|
//#region src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.ts
|
|
17
17
|
init_credentialsHelpers();
|
|
@@ -13,7 +13,7 @@ import "./WebAuthnFallbacks-Bl4BTsNt.js";
|
|
|
13
13
|
import { ERROR_MESSAGES, SecureConfirmationType, getIntentDigest, getNearAccountId, getSignTransactionPayload, getTxCount, init_accountIds, isUserCancelledSecureConfirm, toAccountId } from "./requestHelpers-Dh1hEYL9.js";
|
|
14
14
|
import { PASSKEY_MANAGER_DEFAULT_CONFIGS, init_defaultConfigs } from "./defaultConfigs-DpslkAQd.js";
|
|
15
15
|
import { getLastLoggedInDeviceNumber, init_getDeviceNumber } from "./getDeviceNumber-zsOHT_Um.js";
|
|
16
|
-
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-
|
|
16
|
+
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-DIRR8_Z9.js";
|
|
17
17
|
|
|
18
18
|
//#region src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.ts
|
|
19
19
|
init_accountIds();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ERROR_MESSAGES, SecureConfirmationType, getIntentDigest, getNearAccountId, getSignTransactionPayload, getTxCount, isUserCancelledSecureConfirm, toAccountId, toError } from "./requestHelpers-aUKhXiEl.js";
|
|
2
2
|
import "./validation-DhPPUba7.js";
|
|
3
3
|
import { PASSKEY_MANAGER_DEFAULT_CONFIGS, getLastLoggedInDeviceNumber } from "./getDeviceNumber-fXizNGQl.js";
|
|
4
|
-
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-
|
|
4
|
+
import { createConfirmSession, createConfirmTxFlowAdapters } from "./createAdapters-Yga6W0en.js";
|
|
5
5
|
import "./css-loader-BrMMlG4X.js";
|
|
6
6
|
import "./lit-events-BKobq01K.js";
|
|
7
7
|
import "./tx-tree-themes-i3It4IYY.js";
|
|
@@ -163,4 +163,4 @@ async function handleTransactionSigningFlow(ctx, request, worker, opts) {
|
|
|
163
163
|
|
|
164
164
|
//#endregion
|
|
165
165
|
export { handleTransactionSigningFlow };
|
|
166
|
-
//# sourceMappingURL=transactions-
|
|
166
|
+
//# sourceMappingURL=transactions-bqaAwL4k.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactions-BIqKZeR0.js","names":["uiVrfChallenge: VRFChallenge | undefined","uiVrfChallengeForUi: Partial<VRFChallenge> | undefined","err: unknown","contractId: string | undefined","nearRpcUrl: string | undefined"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n SecureConfirmationType,\n TransactionSummary,\n SigningSecureConfirmRequest,\n SigningAuthMode,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport {\n getNearAccountId,\n getIntentDigest,\n getTxCount,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getSignTransactionPayload,\n} from './index';\nimport { toAccountId } from '../../../../types/accountIds';\nimport { getLastLoggedInDeviceNumber } from '../../../SignerWorkerManager/getDeviceNumber';\nimport { toError } from '../../../../../utils/errors';\nimport { PASSKEY_MANAGER_DEFAULT_CONFIGS } from '../../../../defaultConfigs';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nfunction getSigningAuthMode(request: SigningSecureConfirmRequest): SigningAuthMode {\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n return getSignTransactionPayload(request).signingAuthMode ?? 'webauthn';\n }\n if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const p = request.payload as any;\n return (p?.signingAuthMode as SigningAuthMode | undefined) ?? 'webauthn';\n }\n return 'webauthn';\n}\n\nexport async function handleTransactionSigningFlow(\n ctx: VrfWorkerManagerContext,\n request: SigningSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n const signingAuthMode = getSigningAuthMode(request);\n const usesNeeded = getTxCount(request);\n\n // 1) NEAR context + nonce reservation\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: usesNeeded, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n // eslint-disable-next-line no-console\n console.error('[SigningFlow] fetchNearContext failed', { error: nearRpc.error, details: nearRpc.details });\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n session.setReservedNonces(nearRpc.reservedNonces);\n let transactionContext = nearRpc.transactionContext as TransactionContext;\n\n // 2) Security context shown in the confirmer (rpId + block height).\n // For warmSession signing we still want to show this context even though\n // we won't collect a WebAuthn credential.\n const rpId = adapters.vrf.getRpId();\n let uiVrfChallenge: VRFChallenge | undefined;\n let uiVrfChallengeForUi: Partial<VRFChallenge> | undefined = rpId\n ? {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n }\n : undefined;\n\n // Initial VRF challenge (only needed for WebAuthn credential collection)\n if (signingAuthMode === 'webauthn') {\n uiVrfChallenge = await adapters.vrf.generateVrfChallengeForSession(\n {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n request.requestId,\n );\n uiVrfChallengeForUi = uiVrfChallenge;\n }\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallengeForUi });\n if (!confirmed) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) Warm session: dispense WrapKeySeed and skip WebAuthn\n if (signingAuthMode === 'warmSession') {\n try {\n await adapters.vrf.dispenseSessionKey({ sessionId: request.requestId, uses: usesNeeded });\n } catch (err: unknown) {\n const msg = String((toError(err))?.message || err || '');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: msg || 'Failed to dispense warm session key',\n });\n }\n\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n transactionContext,\n });\n return;\n }\n\n // 5) JIT refresh VRF + ctx (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n transactionContext = refreshed.transactionContext;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n } catch (e) {\n console.debug('[SigningFlow] VRF JIT refresh skipped', e);\n }\n\n // 6) Collect authentication credential\n try {\n if (!uiVrfChallenge) {\n throw new Error('Missing vrfChallenge for WebAuthn signing flow');\n }\n const serializedCredential = await adapters.webauthn.collectAuthenticationCredentialWithPRF({\n nearAccountId,\n vrfChallenge: uiVrfChallenge,\n });\n\n // 5c) Derive WrapKeySeed inside the VRF worker and deliver it to the signer worker via\n // the reserved WrapKeySeed MessagePort. Main thread only sees wrapKeySalt metadata.\n let contractId: string | undefined;\n let nearRpcUrl: string | undefined;\n try {\n // Ensure VRF session is active and bound to the same account we are signing for.\n const vrfStatus = await adapters.vrf.checkVrfStatus();\n if (!vrfStatus.active) {\n throw new Error('VRF keypair not active in memory. VRF session may have expired or was not properly initialized. Please refresh and try again.');\n }\n if (!vrfStatus.nearAccountId || String(vrfStatus.nearAccountId) !== String(toAccountId(nearAccountId))) {\n throw new Error('VRF session is active but bound to a different account than the one being signed. Please log in again on this device.');\n }\n\n const deviceNumber = await getLastLoggedInDeviceNumber(toAccountId(nearAccountId), ctx.indexedDB.clientDB);\n const encryptedKeyData = await ctx.indexedDB.nearKeysDB.getEncryptedKey(nearAccountId, deviceNumber);\n // For v2+ vaults, wrapKeySalt is the canonical salt.\n const wrapKeySalt = encryptedKeyData?.wrapKeySalt || '';\n if (!wrapKeySalt) {\n throw new Error('Missing wrapKeySalt in vault; re-register to upgrade vault format.');\n }\n\n // Extract contract verification context when available.\n // - SIGN_TRANSACTION: use per-request rpcCall (already normalized by caller).\n // - SIGN_NEP413_MESSAGE: allow per-request override; fall back to PASSKEY_MANAGER_DEFAULT_CONFIGS.\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n const payload = getSignTransactionPayload(request);\n contractId = payload?.rpcCall?.contractId;\n nearRpcUrl = payload?.rpcCall?.nearRpcUrl;\n } else if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const payload = request.payload as any;\n contractId = payload?.contractId\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.contractId;\n nearRpcUrl = payload?.nearRpcUrl\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.nearRpcUrl;\n }\n\n await adapters.vrf.mintSessionKeysAndSendToSigner({\n sessionId: request.requestId,\n wrapKeySalt,\n contractId,\n nearRpcUrl,\n credential: serializedCredential,\n });\n\t } catch (err) {\n\t console.error('[SigningFlow] WrapKeySeed derivation failed:', err);\n\t throw err; // Don't silently ignore - propagate the error\n\t }\n\n // 6) Respond; keep nonces reserved for worker to use\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serializedCredential,\n // prfOutput intentionally omitted to keep signer PRF-free\n // WrapKeySeed travels only over the dedicated VRF→Signer MessagePort; do not echo in the main-thread envelope\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n } catch (err: unknown) {\n // Treat TouchID/FaceID cancellation and related errors as a negative decision\n const cancelled = isUserCancelledSecureConfirm(err);\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n const msg = String((toError(err))?.message || err || '');\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n // Ensure UI is closed and nonces released, then rethrow\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n const isWrongPasskeyError = /multiple passkeys \\(devicenumbers\\) for account/i.test(msg);\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isWrongPasskeyError ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transactions-bqaAwL4k.js","names":["uiVrfChallenge: VRFChallenge | undefined","uiVrfChallengeForUi: Partial<VRFChallenge> | undefined","err: unknown","contractId: string | undefined","nearRpcUrl: string | undefined"],"sources":["../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../../';\nimport type { ConfirmationConfig } from '../../../../types/signer-worker';\nimport {\n SecureConfirmationType,\n TransactionSummary,\n SigningSecureConfirmRequest,\n SigningAuthMode,\n} from '../types';\nimport { VRFChallenge, TransactionContext } from '../../../../types';\nimport {\n getNearAccountId,\n getIntentDigest,\n getTxCount,\n isUserCancelledSecureConfirm,\n ERROR_MESSAGES,\n getSignTransactionPayload,\n} from './index';\nimport { toAccountId } from '../../../../types/accountIds';\nimport { getLastLoggedInDeviceNumber } from '../../../SignerWorkerManager/getDeviceNumber';\nimport { toError } from '../../../../../utils/errors';\nimport { PASSKEY_MANAGER_DEFAULT_CONFIGS } from '../../../../defaultConfigs';\nimport { createConfirmSession } from '../adapters/session';\nimport { createConfirmTxFlowAdapters } from '../adapters/createAdapters';\n\nfunction getSigningAuthMode(request: SigningSecureConfirmRequest): SigningAuthMode {\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n return getSignTransactionPayload(request).signingAuthMode ?? 'webauthn';\n }\n if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const p = request.payload as any;\n return (p?.signingAuthMode as SigningAuthMode | undefined) ?? 'webauthn';\n }\n return 'webauthn';\n}\n\nexport async function handleTransactionSigningFlow(\n ctx: VrfWorkerManagerContext,\n request: SigningSecureConfirmRequest,\n worker: Worker,\n opts: { confirmationConfig: ConfirmationConfig; transactionSummary: TransactionSummary },\n): Promise<void> {\n const { confirmationConfig, transactionSummary } = opts;\n const adapters = createConfirmTxFlowAdapters(ctx);\n const session = createConfirmSession({\n adapters,\n worker,\n request,\n confirmationConfig,\n transactionSummary,\n });\n const nearAccountId = getNearAccountId(request);\n const signingAuthMode = getSigningAuthMode(request);\n const usesNeeded = getTxCount(request);\n\n // 1) NEAR context + nonce reservation\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: usesNeeded, reserveNonces: true });\n if (nearRpc.error && !nearRpc.transactionContext) {\n // eslint-disable-next-line no-console\n console.error('[SigningFlow] fetchNearContext failed', { error: nearRpc.error, details: nearRpc.details });\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}`,\n });\n }\n session.setReservedNonces(nearRpc.reservedNonces);\n let transactionContext = nearRpc.transactionContext as TransactionContext;\n\n // 2) Security context shown in the confirmer (rpId + block height).\n // For warmSession signing we still want to show this context even though\n // we won't collect a WebAuthn credential.\n const rpId = adapters.vrf.getRpId();\n let uiVrfChallenge: VRFChallenge | undefined;\n let uiVrfChallengeForUi: Partial<VRFChallenge> | undefined = rpId\n ? {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n }\n : undefined;\n\n // Initial VRF challenge (only needed for WebAuthn credential collection)\n if (signingAuthMode === 'webauthn') {\n uiVrfChallenge = await adapters.vrf.generateVrfChallengeForSession(\n {\n userId: nearAccountId,\n rpId,\n blockHeight: transactionContext.txBlockHeight,\n blockHash: transactionContext.txBlockHash,\n },\n request.requestId,\n );\n uiVrfChallengeForUi = uiVrfChallenge;\n }\n\n // 3) UI confirm\n const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallengeForUi });\n if (!confirmed) {\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: uiError,\n });\n }\n\n // 4) Warm session: dispense WrapKeySeed and skip WebAuthn\n if (signingAuthMode === 'warmSession') {\n try {\n await adapters.vrf.dispenseSessionKey({ sessionId: request.requestId, uses: usesNeeded });\n } catch (err: unknown) {\n const msg = String((toError(err))?.message || err || '');\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: msg || 'Failed to dispense warm session key',\n });\n }\n\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n transactionContext,\n });\n return;\n }\n\n // 5) JIT refresh VRF + ctx (best-effort)\n try {\n const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);\n uiVrfChallenge = refreshed.vrfChallenge;\n transactionContext = refreshed.transactionContext;\n session.updateUI({ vrfChallenge: uiVrfChallenge });\n } catch (e) {\n console.debug('[SigningFlow] VRF JIT refresh skipped', e);\n }\n\n // 6) Collect authentication credential\n try {\n if (!uiVrfChallenge) {\n throw new Error('Missing vrfChallenge for WebAuthn signing flow');\n }\n const serializedCredential = await adapters.webauthn.collectAuthenticationCredentialWithPRF({\n nearAccountId,\n vrfChallenge: uiVrfChallenge,\n });\n\n // 5c) Derive WrapKeySeed inside the VRF worker and deliver it to the signer worker via\n // the reserved WrapKeySeed MessagePort. Main thread only sees wrapKeySalt metadata.\n let contractId: string | undefined;\n let nearRpcUrl: string | undefined;\n try {\n // Ensure VRF session is active and bound to the same account we are signing for.\n const vrfStatus = await adapters.vrf.checkVrfStatus();\n if (!vrfStatus.active) {\n throw new Error('VRF keypair not active in memory. VRF session may have expired or was not properly initialized. Please refresh and try again.');\n }\n if (!vrfStatus.nearAccountId || String(vrfStatus.nearAccountId) !== String(toAccountId(nearAccountId))) {\n throw new Error('VRF session is active but bound to a different account than the one being signed. Please log in again on this device.');\n }\n\n const deviceNumber = await getLastLoggedInDeviceNumber(toAccountId(nearAccountId), ctx.indexedDB.clientDB);\n const encryptedKeyData = await ctx.indexedDB.nearKeysDB.getEncryptedKey(nearAccountId, deviceNumber);\n // For v2+ vaults, wrapKeySalt is the canonical salt.\n const wrapKeySalt = encryptedKeyData?.wrapKeySalt || '';\n if (!wrapKeySalt) {\n throw new Error('Missing wrapKeySalt in vault; re-register to upgrade vault format.');\n }\n\n // Extract contract verification context when available.\n // - SIGN_TRANSACTION: use per-request rpcCall (already normalized by caller).\n // - SIGN_NEP413_MESSAGE: allow per-request override; fall back to PASSKEY_MANAGER_DEFAULT_CONFIGS.\n if (request.type === SecureConfirmationType.SIGN_TRANSACTION) {\n const payload = getSignTransactionPayload(request);\n contractId = payload?.rpcCall?.contractId;\n nearRpcUrl = payload?.rpcCall?.nearRpcUrl;\n } else if (request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE) {\n const payload = request.payload as any;\n contractId = payload?.contractId\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.contractId;\n nearRpcUrl = payload?.nearRpcUrl\n || PASSKEY_MANAGER_DEFAULT_CONFIGS.nearRpcUrl;\n }\n\n await adapters.vrf.mintSessionKeysAndSendToSigner({\n sessionId: request.requestId,\n wrapKeySalt,\n contractId,\n nearRpcUrl,\n credential: serializedCredential,\n });\n\t } catch (err) {\n\t console.error('[SigningFlow] WrapKeySeed derivation failed:', err);\n\t throw err; // Don't silently ignore - propagate the error\n\t }\n\n // 6) Respond; keep nonces reserved for worker to use\n session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: true,\n credential: serializedCredential,\n // prfOutput intentionally omitted to keep signer PRF-free\n // WrapKeySeed travels only over the dedicated VRF→Signer MessagePort; do not echo in the main-thread envelope\n vrfChallenge: uiVrfChallenge,\n transactionContext,\n });\n } catch (err: unknown) {\n // Treat TouchID/FaceID cancellation and related errors as a negative decision\n const cancelled = isUserCancelledSecureConfirm(err);\n // For missing PRF outputs, surface the error to caller (defensive path tests expect a throw)\n const msg = String((toError(err))?.message || err || '');\n if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) {\n // Ensure UI is closed and nonces released, then rethrow\n return session.cleanupAndRethrow(err);\n }\n if (cancelled) {\n window.parent?.postMessage({ type: 'WALLET_UI_CLOSED' }, '*');\n }\n const isWrongPasskeyError = /multiple passkeys \\(devicenumbers\\) for account/i.test(msg);\n return session.confirmAndCloseModal({\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: cancelled\n ? ERROR_MESSAGES.cancelled\n : (isWrongPasskeyError ? msg : ERROR_MESSAGES.collectCredentialsFailed),\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import "./asset-base-K63RlTrt.js";
|
|
|
6
6
|
import "./tx-tree-themes-BND0SU2h.js";
|
|
7
7
|
import { CONFIRM_UI_ELEMENT_SELECTORS, W3A_TX_BUTTON_HOST_ID, W3A_TX_BUTTON_ID, defineTag } from "./tags-C2Wlhqjd.js";
|
|
8
8
|
import { WalletIframeDomEvents, computeUiIntentDigestFromTxs, orderActionForDigest } from "./txDigest-CxjhSCgm.js";
|
|
9
|
-
import { base64UrlDecode } from "./base64-DBPGuXh4.js";
|
|
9
|
+
import { base64Decode, base64UrlDecode, init_base64 } from "./base64-DBPGuXh4.js";
|
|
10
10
|
import { ActionType, init_actions, toActionArgsWasm, validateActionArgsWasm } from "./actions-O1FD5Bq8.js";
|
|
11
11
|
import { ensureKnownW3aElement } from "./ensure-defined-CHInSx7l.js";
|
|
12
12
|
import { base58Encode, errorMessage, esm_default, getNearShortErrorMessage, getUserFriendlyErrorMessage, init_base58, init_encoders, init_errors, init_esm, isTouchIdCancellationError, toError } from "./errors-D9ar28Dr.js";
|
|
@@ -2226,6 +2226,7 @@ init_utils();
|
|
|
2226
2226
|
init_encoders();
|
|
2227
2227
|
init_base58();
|
|
2228
2228
|
init_esm();
|
|
2229
|
+
init_base64();
|
|
2229
2230
|
/**
|
|
2230
2231
|
* Control messages exchanged between worker shims and the main thread.
|
|
2231
2232
|
*
|
|
@@ -3271,42 +3272,42 @@ async function importFlow(label, loader) {
|
|
|
3271
3272
|
}
|
|
3272
3273
|
const HANDLERS = {
|
|
3273
3274
|
[SecureConfirmationType.DECRYPT_PRIVATE_KEY_WITH_PRF]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
|
|
3274
|
-
const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-
|
|
3275
|
+
const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-BHScJasw.js"));
|
|
3275
3276
|
await handleLocalOnlyFlow(ctx, request, worker, {
|
|
3276
3277
|
confirmationConfig,
|
|
3277
3278
|
transactionSummary
|
|
3278
3279
|
});
|
|
3279
3280
|
},
|
|
3280
3281
|
[SecureConfirmationType.SHOW_SECURE_PRIVATE_KEY_UI]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
|
|
3281
|
-
const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-
|
|
3282
|
+
const { handleLocalOnlyFlow } = await importFlow("localOnly", () => import("./localOnly-BHScJasw.js"));
|
|
3282
3283
|
await handleLocalOnlyFlow(ctx, request, worker, {
|
|
3283
3284
|
confirmationConfig,
|
|
3284
3285
|
transactionSummary
|
|
3285
3286
|
});
|
|
3286
3287
|
},
|
|
3287
3288
|
[SecureConfirmationType.REGISTER_ACCOUNT]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
|
|
3288
|
-
const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-
|
|
3289
|
+
const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-lDD60Ytt.js"));
|
|
3289
3290
|
await handleRegistrationFlow(ctx, request, worker, {
|
|
3290
3291
|
confirmationConfig,
|
|
3291
3292
|
transactionSummary
|
|
3292
3293
|
});
|
|
3293
3294
|
},
|
|
3294
3295
|
[SecureConfirmationType.LINK_DEVICE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
|
|
3295
|
-
const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-
|
|
3296
|
+
const { handleRegistrationFlow } = await importFlow("registration", () => import("./registration-lDD60Ytt.js"));
|
|
3296
3297
|
await handleRegistrationFlow(ctx, request, worker, {
|
|
3297
3298
|
confirmationConfig,
|
|
3298
3299
|
transactionSummary
|
|
3299
3300
|
});
|
|
3300
3301
|
},
|
|
3301
3302
|
[SecureConfirmationType.SIGN_TRANSACTION]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
|
|
3302
|
-
const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-
|
|
3303
|
+
const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-BalIhtJ9.js"));
|
|
3303
3304
|
await handleTransactionSigningFlow(ctx, request, worker, {
|
|
3304
3305
|
confirmationConfig,
|
|
3305
3306
|
transactionSummary
|
|
3306
3307
|
});
|
|
3307
3308
|
},
|
|
3308
3309
|
[SecureConfirmationType.SIGN_NEP413_MESSAGE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {
|
|
3309
|
-
const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-
|
|
3310
|
+
const { handleTransactionSigningFlow } = await importFlow("transactions", () => import("./transactions-BalIhtJ9.js"));
|
|
3310
3311
|
await handleTransactionSigningFlow(ctx, request, worker, {
|
|
3311
3312
|
confirmationConfig,
|
|
3312
3313
|
transactionSummary
|
|
@@ -6385,6 +6386,29 @@ var WebAuthnManager = class {
|
|
|
6385
6386
|
async extractCosePublicKey(attestationObjectBase64url) {
|
|
6386
6387
|
return await this.signerWorkerManager.extractCosePublicKey(attestationObjectBase64url);
|
|
6387
6388
|
}
|
|
6389
|
+
/**
|
|
6390
|
+
* Helper to ensure the local `lastUser` pointer is consistent with the latest DB updates.
|
|
6391
|
+
* This fixes issues where a recovery or registration might have updated the user record
|
|
6392
|
+
* but failed to update the `lastUser` pointer (e.g. due to previous bugs or interruptions),
|
|
6393
|
+
* preventing the strict `ensureCurrentPasskey` check from passing.
|
|
6394
|
+
*/
|
|
6395
|
+
async autoHealLastUserPointer(nearAccountId) {
|
|
6396
|
+
try {
|
|
6397
|
+
const lastUser = await this.getLastUser();
|
|
6398
|
+
if (lastUser && lastUser.nearAccountId === nearAccountId) {
|
|
6399
|
+
const freshest = await IndexedDBManager.clientDB.getLastDBUpdatedUser(nearAccountId);
|
|
6400
|
+
if (freshest && freshest.deviceNumber !== lastUser.deviceNumber) {
|
|
6401
|
+
console.log(`[WebAuthnManager] Auto-healing lastUser pointer from device ${lastUser.deviceNumber} to ${freshest.deviceNumber}`);
|
|
6402
|
+
await this.setLastUser(nearAccountId, freshest.deviceNumber);
|
|
6403
|
+
}
|
|
6404
|
+
} else {
|
|
6405
|
+
const freshest = await IndexedDBManager.clientDB.getLastDBUpdatedUser(nearAccountId);
|
|
6406
|
+
if (freshest) await this.setLastUser(nearAccountId, freshest.deviceNumber);
|
|
6407
|
+
}
|
|
6408
|
+
} catch (e) {
|
|
6409
|
+
console.warn("[WebAuthnManager] Auto-heal pointer failed (non-fatal):", e);
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6388
6412
|
/** Worker-driven export: two-phase V2 (collect PRF → decrypt → show UI) */
|
|
6389
6413
|
async exportNearKeypairWithUIWorkerDriven(nearAccountId, options) {
|
|
6390
6414
|
await this.withSigningSession({
|
|
@@ -10014,6 +10038,28 @@ var init_emailRecoveryPendingStore = __esm({ "src/core/EmailRecovery/emailRecove
|
|
|
10014
10038
|
|
|
10015
10039
|
//#endregion
|
|
10016
10040
|
//#region src/core/EmailRecovery/index.ts
|
|
10041
|
+
function getTxSuccessValueBase64(outcome) {
|
|
10042
|
+
const status = outcome.status;
|
|
10043
|
+
if (!status || typeof status !== "object") return null;
|
|
10044
|
+
if (!("SuccessValue" in status)) return null;
|
|
10045
|
+
const value = status.SuccessValue;
|
|
10046
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
10047
|
+
}
|
|
10048
|
+
function parseLinkDeviceRegisterUserResponse(outcome) {
|
|
10049
|
+
try {
|
|
10050
|
+
const successValueB64 = getTxSuccessValueBase64(outcome);
|
|
10051
|
+
if (!successValueB64) return null;
|
|
10052
|
+
const bytes = base64Decode(successValueB64);
|
|
10053
|
+
const text = new TextDecoder().decode(bytes);
|
|
10054
|
+
if (!text.trim()) return null;
|
|
10055
|
+
const parsed = JSON.parse(text);
|
|
10056
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
10057
|
+
const candidate = parsed;
|
|
10058
|
+
return typeof candidate.verified === "boolean" ? candidate : null;
|
|
10059
|
+
} catch {
|
|
10060
|
+
return null;
|
|
10061
|
+
}
|
|
10062
|
+
}
|
|
10017
10063
|
async function hashRecoveryEmails(emails, accountId) {
|
|
10018
10064
|
const encoder = new TextEncoder();
|
|
10019
10065
|
const salt = (accountId || "").trim().toLowerCase();
|
|
@@ -10085,6 +10131,27 @@ var init_EmailRecovery = __esm({ "src/core/EmailRecovery/index.ts": (() => {
|
|
|
10085
10131
|
};
|
|
10086
10132
|
}) });
|
|
10087
10133
|
|
|
10134
|
+
//#endregion
|
|
10135
|
+
//#region src/core/types/emailRecovery.ts
|
|
10136
|
+
var EmailRecoveryErrorCode, EmailRecoveryError;
|
|
10137
|
+
var init_emailRecovery$1 = __esm({ "src/core/types/emailRecovery.ts": (() => {
|
|
10138
|
+
EmailRecoveryErrorCode = /* @__PURE__ */ function(EmailRecoveryErrorCode$1) {
|
|
10139
|
+
EmailRecoveryErrorCode$1["REGISTRATION_NOT_VERIFIED"] = "EMAIL_RECOVERY_REGISTRATION_NOT_VERIFIED";
|
|
10140
|
+
EmailRecoveryErrorCode$1["VRF_CHALLENGE_EXPIRED"] = "EMAIL_RECOVERY_VRF_CHALLENGE_EXPIRED";
|
|
10141
|
+
return EmailRecoveryErrorCode$1;
|
|
10142
|
+
}({});
|
|
10143
|
+
EmailRecoveryError = class extends Error {
|
|
10144
|
+
code;
|
|
10145
|
+
context;
|
|
10146
|
+
constructor(message, code, context) {
|
|
10147
|
+
super(message);
|
|
10148
|
+
this.name = "EmailRecoveryError";
|
|
10149
|
+
this.code = code;
|
|
10150
|
+
this.context = context;
|
|
10151
|
+
}
|
|
10152
|
+
};
|
|
10153
|
+
}) });
|
|
10154
|
+
|
|
10088
10155
|
//#endregion
|
|
10089
10156
|
//#region src/core/TatchiPasskey/emailRecovery.ts
|
|
10090
10157
|
var emailRecovery_exports = {};
|
|
@@ -10124,6 +10191,7 @@ var EmailRecoveryFlow;
|
|
|
10124
10191
|
var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (() => {
|
|
10125
10192
|
init_IndexedDBManager();
|
|
10126
10193
|
init_validation$1();
|
|
10194
|
+
init_errors();
|
|
10127
10195
|
init_accountIds();
|
|
10128
10196
|
init_sdkSentEvents();
|
|
10129
10197
|
init_vrf_worker();
|
|
@@ -10131,6 +10199,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10131
10199
|
init_getDeviceNumber();
|
|
10132
10200
|
init_login();
|
|
10133
10201
|
init_EmailRecovery();
|
|
10202
|
+
init_emailRecovery$1();
|
|
10134
10203
|
EmailRecoveryFlow = class {
|
|
10135
10204
|
context;
|
|
10136
10205
|
options;
|
|
@@ -10158,8 +10227,9 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10158
10227
|
emit(event) {
|
|
10159
10228
|
this.options?.onEvent?.(event);
|
|
10160
10229
|
}
|
|
10161
|
-
emitError(step,
|
|
10162
|
-
const err$1 = new Error(
|
|
10230
|
+
emitError(step, messageOrError) {
|
|
10231
|
+
const err$1 = typeof messageOrError === "string" ? new Error(messageOrError) : messageOrError;
|
|
10232
|
+
const message = err$1.message || (typeof messageOrError === "string" ? messageOrError : "Unknown error");
|
|
10163
10233
|
this.phase = EmailRecoveryPhase.ERROR;
|
|
10164
10234
|
this.error = err$1;
|
|
10165
10235
|
this.emit({
|
|
@@ -10218,8 +10288,8 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10218
10288
|
const accountView = await this.context.nearClient.viewAccount(nearAccountId);
|
|
10219
10289
|
const available = this.computeAvailableBalance(accountView);
|
|
10220
10290
|
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.`);
|
|
10221
|
-
} catch (
|
|
10222
|
-
await this.fail(1,
|
|
10291
|
+
} catch (err$1) {
|
|
10292
|
+
await this.fail(1, errorMessage(err$1) || "Failed to fetch account balance for recovery");
|
|
10223
10293
|
}
|
|
10224
10294
|
}
|
|
10225
10295
|
async getCanonicalRecoveryEmailOrFail(recoveryEmail) {
|
|
@@ -10231,7 +10301,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10231
10301
|
try {
|
|
10232
10302
|
const { syncAuthenticatorsContractCall: syncAuthenticatorsContractCall$1 } = await import("./rpcCalls-BQrJMTdg.js");
|
|
10233
10303
|
const authenticators = await syncAuthenticatorsContractCall$1(this.context.nearClient, this.context.configs.contractId, nearAccountId);
|
|
10234
|
-
const numbers = authenticators.map((
|
|
10304
|
+
const numbers = authenticators.map(({ authenticator }) => authenticator.deviceNumber).filter((n) => typeof n === "number" && Number.isFinite(n));
|
|
10235
10305
|
const max = numbers.length > 0 ? Math.max(...numbers) : 0;
|
|
10236
10306
|
return max + 1;
|
|
10237
10307
|
} catch {
|
|
@@ -10479,7 +10549,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10479
10549
|
nearPublicKey: rec.nearPublicKey
|
|
10480
10550
|
};
|
|
10481
10551
|
} catch (e) {
|
|
10482
|
-
const err$1 = this.emitError(2, e
|
|
10552
|
+
const err$1 = this.emitError(2, errorMessage(e) || "Email recovery TouchID/derivation failed");
|
|
10483
10553
|
await this.options?.afterCall?.(false);
|
|
10484
10554
|
throw err$1;
|
|
10485
10555
|
}
|
|
@@ -10649,7 +10719,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10649
10719
|
accountId
|
|
10650
10720
|
};
|
|
10651
10721
|
}
|
|
10652
|
-
async
|
|
10722
|
+
async signNewDevice2RegistrationTx(rec, accountId) {
|
|
10653
10723
|
const vrfChallenge = rec.vrfChallenge;
|
|
10654
10724
|
if (!vrfChallenge) return this.fail(5, "Missing VRF challenge for email recovery registration");
|
|
10655
10725
|
const registrationResult = await this.context.webAuthnManager.signDevice2RegistrationWithStoredKey({
|
|
@@ -10663,47 +10733,56 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10663
10733
|
return registrationResult.signedTransaction;
|
|
10664
10734
|
}
|
|
10665
10735
|
async broadcastRegistrationTxAndWaitFinal(rec, signedTx) {
|
|
10736
|
+
let txResult;
|
|
10666
10737
|
try {
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
step: 5,
|
|
10672
|
-
phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
10673
|
-
status: EmailRecoveryStatus.PROGRESS,
|
|
10674
|
-
message: "Registration transaction confirmed",
|
|
10675
|
-
data: {
|
|
10676
|
-
accountId: rec.accountId,
|
|
10677
|
-
nearPublicKey: rec.nearPublicKey,
|
|
10678
|
-
transactionHash: txHash
|
|
10679
|
-
}
|
|
10680
|
-
});
|
|
10681
|
-
return txHash;
|
|
10682
|
-
} catch {}
|
|
10683
|
-
} catch (e) {
|
|
10684
|
-
const msg = String(e?.message || "");
|
|
10685
|
-
await this.fail(5, msg || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)");
|
|
10738
|
+
txResult = await this.context.nearClient.sendTransaction(signedTx, DEFAULT_WAIT_STATUS.linkDeviceRegistration);
|
|
10739
|
+
} catch (err$1) {
|
|
10740
|
+
const msg = errorMessage(err$1) || "Failed to broadcast email recovery registration transaction (insufficient funds or RPC error)";
|
|
10741
|
+
throw new Error(msg);
|
|
10686
10742
|
}
|
|
10687
|
-
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10743
|
+
const txHash = this.getTxHash(txResult);
|
|
10744
|
+
const linkDeviceResult = parseLinkDeviceRegisterUserResponse(txResult);
|
|
10745
|
+
if (linkDeviceResult?.verified === false) {
|
|
10746
|
+
const logs = this.extractNearExecutionLogs(txResult);
|
|
10747
|
+
const isStaleChallenge = logs.some((log) => /StaleChallenge|freshness validation failed/i.test(log));
|
|
10748
|
+
const txHint = txHash ? ` (tx: ${txHash})` : "";
|
|
10749
|
+
const code = isStaleChallenge ? EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED : EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED;
|
|
10750
|
+
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}.`;
|
|
10751
|
+
throw new EmailRecoveryError(message, code, {
|
|
10752
|
+
accountId: rec.accountId,
|
|
10753
|
+
nearPublicKey: rec.nearPublicKey,
|
|
10754
|
+
transactionHash: txHash,
|
|
10755
|
+
logs,
|
|
10756
|
+
result: linkDeviceResult
|
|
10701
10757
|
});
|
|
10702
|
-
return true;
|
|
10703
|
-
} catch (err$1) {
|
|
10704
|
-
console.warn("[EmailRecoveryFlow] Failed to store recovery user record:", err$1);
|
|
10705
|
-
return false;
|
|
10706
10758
|
}
|
|
10759
|
+
if (txHash) this.emit({
|
|
10760
|
+
step: 5,
|
|
10761
|
+
phase: EmailRecoveryPhase.STEP_5_FINALIZING_REGISTRATION,
|
|
10762
|
+
status: EmailRecoveryStatus.PROGRESS,
|
|
10763
|
+
message: "Registration transaction confirmed",
|
|
10764
|
+
data: {
|
|
10765
|
+
accountId: rec.accountId,
|
|
10766
|
+
nearPublicKey: rec.nearPublicKey,
|
|
10767
|
+
transactionHash: txHash
|
|
10768
|
+
}
|
|
10769
|
+
});
|
|
10770
|
+
return txHash;
|
|
10771
|
+
}
|
|
10772
|
+
getTxHash(outcome) {
|
|
10773
|
+
const txUnknown = outcome.transaction;
|
|
10774
|
+
if (txUnknown && typeof txUnknown === "object") {
|
|
10775
|
+
const hash = txUnknown.hash;
|
|
10776
|
+
if (typeof hash === "string" && hash.length > 0) return hash;
|
|
10777
|
+
}
|
|
10778
|
+
const fallback = outcome.transaction_hash;
|
|
10779
|
+
return typeof fallback === "string" && fallback.length > 0 ? fallback : void 0;
|
|
10780
|
+
}
|
|
10781
|
+
extractNearExecutionLogs(outcome) {
|
|
10782
|
+
const logs = [];
|
|
10783
|
+
for (const entry of outcome.transaction_outcome.outcome.logs) logs.push(String(entry));
|
|
10784
|
+
for (const receipt of outcome.receipts_outcome) for (const entry of receipt.outcome.logs) logs.push(String(entry));
|
|
10785
|
+
return logs;
|
|
10707
10786
|
}
|
|
10708
10787
|
mapAuthenticatorsFromContract(authenticators) {
|
|
10709
10788
|
return authenticators.map(({ authenticator }) => ({
|
|
@@ -10739,7 +10818,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10739
10818
|
}
|
|
10740
10819
|
async updateNonceBestEffort(nonceManager, signedTx) {
|
|
10741
10820
|
try {
|
|
10742
|
-
const txNonce = signedTx.transaction
|
|
10821
|
+
const txNonce = signedTx.transaction.nonce;
|
|
10743
10822
|
if (txNonce != null) await nonceManager.updateNonceFromBlockchain(this.context.nearClient, String(txNonce));
|
|
10744
10823
|
} catch {}
|
|
10745
10824
|
}
|
|
@@ -10762,6 +10841,10 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10762
10841
|
};
|
|
10763
10842
|
await webAuthnManager.storeUserData(payload);
|
|
10764
10843
|
}
|
|
10844
|
+
/**
|
|
10845
|
+
* Explicitly persist the authenticator from the recovery record into the local cache.
|
|
10846
|
+
* This ensures the key is available immediately, bridging the gap before RPC sync sees it.
|
|
10847
|
+
*/
|
|
10765
10848
|
async persistAuthenticatorBestEffort(rec, accountId) {
|
|
10766
10849
|
try {
|
|
10767
10850
|
const { webAuthnManager } = this.context;
|
|
@@ -10778,7 +10861,10 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10778
10861
|
syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10779
10862
|
vrfPublicKey: rec.vrfPublicKey
|
|
10780
10863
|
});
|
|
10781
|
-
|
|
10864
|
+
console.log("[EmailRecoveryFlow] Locally persisted recovered authenticator for immediate use.");
|
|
10865
|
+
} catch (e) {
|
|
10866
|
+
console.error("[EmailRecoveryFlow] Failed to locally persist authenticator (critical for immediate export):", e);
|
|
10867
|
+
}
|
|
10782
10868
|
}
|
|
10783
10869
|
async markCompleteAndClearPending(rec) {
|
|
10784
10870
|
rec.status = "complete";
|
|
@@ -10848,7 +10934,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10848
10934
|
} catch (err$1) {
|
|
10849
10935
|
return {
|
|
10850
10936
|
success: false,
|
|
10851
|
-
reason: err$1
|
|
10937
|
+
reason: errorMessage(err$1) || String(err$1)
|
|
10852
10938
|
};
|
|
10853
10939
|
}
|
|
10854
10940
|
}
|
|
@@ -10876,18 +10962,14 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10876
10962
|
});
|
|
10877
10963
|
try {
|
|
10878
10964
|
const { nonceManager, accountId } = this.initializeNonceManager(rec);
|
|
10879
|
-
const signedTx = await this.
|
|
10965
|
+
const signedTx = await this.signNewDevice2RegistrationTx(rec, accountId);
|
|
10880
10966
|
const txHash = await this.broadcastRegistrationTxAndWaitFinal(rec, signedTx);
|
|
10881
|
-
if (txHash)
|
|
10882
|
-
const storedUser = await this.persistRecoveredUserRecordBestEffort(rec, accountId);
|
|
10883
|
-
if (storedUser) {
|
|
10884
|
-
const syncedAuthenticators = await this.syncAuthenticatorsBestEffort(accountId);
|
|
10885
|
-
if (syncedAuthenticators) await this.setLastUserBestEffort(accountId, rec.deviceNumber);
|
|
10886
|
-
}
|
|
10887
|
-
}
|
|
10888
|
-
await this.updateNonceBestEffort(nonceManager, signedTx);
|
|
10967
|
+
if (!txHash) console.warn("[EmailRecoveryFlow] Registration transaction confirmed without hash; continuing local persistence");
|
|
10889
10968
|
await this.persistRecoveredUserData(rec, accountId);
|
|
10969
|
+
await this.syncAuthenticatorsBestEffort(accountId);
|
|
10890
10970
|
await this.persistAuthenticatorBestEffort(rec, accountId);
|
|
10971
|
+
await this.setLastUserBestEffort(accountId, rec.deviceNumber);
|
|
10972
|
+
await this.updateNonceBestEffort(nonceManager, signedTx);
|
|
10891
10973
|
this.emitAutoLoginEvent(EmailRecoveryStatus.PROGRESS, "Attempting auto-login with recovered device...", { autoLogin: "progress" });
|
|
10892
10974
|
const autoLoginResult = await this.attemptAutoLogin(rec);
|
|
10893
10975
|
if (autoLoginResult.success) this.emitAutoLoginEvent(EmailRecoveryStatus.SUCCESS, `Welcome ${accountId}`, { autoLogin: "success" });
|
|
@@ -10908,7 +10990,10 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10908
10990
|
}
|
|
10909
10991
|
});
|
|
10910
10992
|
} catch (e) {
|
|
10911
|
-
|
|
10993
|
+
rec.status = "error";
|
|
10994
|
+
await this.savePending(rec).catch(() => {});
|
|
10995
|
+
const original = e instanceof Error ? e : new Error(errorMessage(e) || "Email recovery finalization failed");
|
|
10996
|
+
const err$1 = this.emitError(5, original);
|
|
10912
10997
|
await this.options?.afterCall?.(false);
|
|
10913
10998
|
throw err$1;
|
|
10914
10999
|
}
|
|
@@ -10930,7 +11015,7 @@ var init_emailRecovery = __esm({ "src/core/TatchiPasskey/emailRecovery.ts": (()
|
|
|
10930
11015
|
};
|
|
10931
11016
|
return this.handleAutoLoginFailure(touchIdResult.reason || "Auto-login failed");
|
|
10932
11017
|
} catch (err$1) {
|
|
10933
|
-
return this.handleAutoLoginFailure(err$1
|
|
11018
|
+
return this.handleAutoLoginFailure(errorMessage(err$1) || String(err$1), err$1);
|
|
10934
11019
|
}
|
|
10935
11020
|
}
|
|
10936
11021
|
};
|
|
Binary file
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import type { AccountId } from '../types/accountIds';
|
|
2
2
|
import { type RecoveryEmailRecord } from '../IndexedDBManager';
|
|
3
|
+
import type { FinalExecutionOutcome } from '@near-js/types';
|
|
3
4
|
export { EmailRecoveryPendingStore, type PendingStore } from './emailRecoveryPendingStore';
|
|
4
5
|
export type RecoveryEmailEntry = {
|
|
5
6
|
hashHex: string;
|
|
6
7
|
email: string;
|
|
7
8
|
};
|
|
8
9
|
export { type RecoveryEmailRecord };
|
|
10
|
+
export type LinkDeviceRegisterUserResponse = {
|
|
11
|
+
verified?: boolean;
|
|
12
|
+
registration_info?: unknown;
|
|
13
|
+
registrationInfo?: unknown;
|
|
14
|
+
error?: unknown;
|
|
15
|
+
};
|
|
16
|
+
export declare function parseLinkDeviceRegisterUserResponse(outcome: FinalExecutionOutcome): LinkDeviceRegisterUserResponse | null;
|
|
9
17
|
export declare const canonicalizeEmail: (email: string) => string;
|
|
10
18
|
export declare const bytesToHex: (bytes: number[] | Uint8Array) => string;
|
|
11
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/EmailRecovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3F,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,OAAO,EAAE,KAAK,mBAAmB,EAAE,CAAC;AAEpC,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MA2BjD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,GAAG,UAAU,KAAG,MAKzD,CAAC;AA4BF;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACvG,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B,CAAC,CAqBD;AAED,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAErG"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/EmailRecovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,yBAAyB,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3F,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,OAAO,EAAE,KAAK,mBAAmB,EAAE,CAAC;AAEpC,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAUF,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,qBAAqB,GAC7B,8BAA8B,GAAG,IAAI,CAgBvC;AAED,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MA2BjD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,GAAG,UAAU,KAAG,MAKzD,CAAC;AA4BF;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACvG,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B,CAAC,CAqBD;AAED,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAErG"}
|
|
@@ -105,14 +105,19 @@ export declare class EmailRecoveryFlow {
|
|
|
105
105
|
}): Promise<void>;
|
|
106
106
|
private pollUntilAddKey;
|
|
107
107
|
private initializeNonceManager;
|
|
108
|
-
private
|
|
108
|
+
private signNewDevice2RegistrationTx;
|
|
109
109
|
private broadcastRegistrationTxAndWaitFinal;
|
|
110
|
-
private
|
|
110
|
+
private getTxHash;
|
|
111
|
+
private extractNearExecutionLogs;
|
|
111
112
|
private mapAuthenticatorsFromContract;
|
|
112
113
|
private syncAuthenticatorsBestEffort;
|
|
113
114
|
private setLastUserBestEffort;
|
|
114
115
|
private updateNonceBestEffort;
|
|
115
116
|
private persistRecoveredUserData;
|
|
117
|
+
/**
|
|
118
|
+
* Explicitly persist the authenticator from the recovery record into the local cache.
|
|
119
|
+
* This ensures the key is available immediately, bridging the gap before RPC sync sees it.
|
|
120
|
+
*/
|
|
116
121
|
private persistAuthenticatorBestEffort;
|
|
117
122
|
private markCompleteAndClearPending;
|
|
118
123
|
private assertVrfActiveForAccount;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emailRecovery.d.ts","sourceRoot":"","sources":["../../../../../src/core/TatchiPasskey/emailRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"emailRecovery.d.ts","sourceRoot":"","sources":["../../../../../src/core/TatchiPasskey/emailRecovery.ts"],"names":[],"mappings":"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"}
|