@tatchi-xyz/sdk 0.31.0 → 0.32.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/README.md +2 -0
- package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/login.js +1 -1
- package/dist/cjs/core/TatchiPasskey/login.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/registration.js +107 -63
- package/dist/cjs/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/cjs/core/WalletIframe/client/on-events-progress-bus.js +1 -1
- package/dist/cjs/core/WalletIframe/client/on-events-progress-bus.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/index.js +3 -3
- package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/core/defaultConfigs.js +3 -1
- package/dist/cjs/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/core/types/sdkSentEvents.js +3 -2
- package/dist/cjs/core/types/sdkSentEvents.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/TransactionSettingsSection.js +3 -3
- package/dist/cjs/react/components/AccountMenuButton/TransactionSettingsSection.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-CRlobBrN.css → PasskeyAuthMenu-D2eRb2-S.css} +3 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/PasskeyAuthMenu-D2eRb2-S.css.map +1 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/preload.js +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/preload.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/shell.js +52 -13
- package/dist/cjs/react/components/PasskeyAuthMenu/shell.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/skeleton.js +4 -2
- package/dist/cjs/react/components/PasskeyAuthMenu/skeleton.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +5 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/context/useTatchiWithSdkFlow.js +1 -1
- package/dist/cjs/react/context/useTatchiWithSdkFlow.js.map +1 -1
- package/dist/cjs/react/index.js +1 -1
- package/dist/cjs/react/src/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/cjs/react/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/cjs/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/login.js +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/login.js.map +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/registration.js +107 -63
- package/dist/cjs/react/src/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/cjs/react/src/core/WalletIframe/client/on-events-progress-bus.js +1 -1
- package/dist/cjs/react/src/core/WalletIframe/client/on-events-progress-bus.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/index.js +3 -3
- package/dist/cjs/react/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/react/src/core/defaultConfigs.js +3 -1
- package/dist/cjs/react/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/react/src/core/types/sdkSentEvents.js +3 -2
- package/dist/cjs/react/src/core/types/sdkSentEvents.js.map +1 -1
- package/dist/cjs/server/core/AuthService.js +49 -6
- package/dist/cjs/server/core/AuthService.js.map +1 -1
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/esm/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/login.js +1 -1
- package/dist/esm/core/TatchiPasskey/login.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/registration.js +107 -63
- package/dist/esm/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/esm/core/WalletIframe/client/on-events-progress-bus.js +1 -1
- package/dist/esm/core/WalletIframe/client/on-events-progress-bus.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/index.js +3 -3
- package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/core/defaultConfigs.js +3 -1
- package/dist/esm/core/defaultConfigs.js.map +1 -1
- package/dist/esm/core/types/sdkSentEvents.js +3 -2
- package/dist/esm/core/types/sdkSentEvents.js.map +1 -1
- package/dist/esm/react/components/AccountMenuButton/TransactionSettingsSection.js +3 -3
- package/dist/esm/react/components/AccountMenuButton/TransactionSettingsSection.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-D2VHZ04W.css → PasskeyAuthMenu-qTHAv58Z.css} +3 -1
- package/dist/esm/react/components/PasskeyAuthMenu/PasskeyAuthMenu-qTHAv58Z.css.map +1 -0
- package/dist/esm/react/components/PasskeyAuthMenu/preload.js +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/preload.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/shell.js +52 -13
- package/dist/esm/react/components/PasskeyAuthMenu/shell.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/skeleton.js +4 -2
- package/dist/esm/react/components/PasskeyAuthMenu/skeleton.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +5 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/context/useTatchiWithSdkFlow.js +1 -1
- package/dist/esm/react/context/useTatchiWithSdkFlow.js.map +1 -1
- package/dist/esm/react/index.js +1 -1
- package/dist/esm/react/src/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/esm/react/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/esm/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/login.js +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/login.js.map +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/registration.js +107 -63
- package/dist/esm/react/src/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/esm/react/src/core/WalletIframe/client/on-events-progress-bus.js +1 -1
- package/dist/esm/react/src/core/WalletIframe/client/on-events-progress-bus.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/index.js +3 -3
- package/dist/esm/react/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/react/src/core/defaultConfigs.js +3 -1
- package/dist/esm/react/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/react/src/core/types/sdkSentEvents.js +3 -2
- package/dist/esm/react/src/core/types/sdkSentEvents.js.map +1 -1
- package/dist/esm/react/styles/styles.css +2 -0
- package/dist/esm/sdk/{EmailRecovery-Dl8b4ONg.js → EmailRecovery-Y7rurd4B.js} +3 -3
- package/dist/esm/sdk/{EmailRecovery-v9oNO2Tc.js → EmailRecovery-lsjLWApQ.js} +1 -1
- package/dist/esm/sdk/{IndexedDBManager-B1cUvdyY.js → IndexedDBManager-CmdN7smS.js} +3 -3
- package/dist/esm/sdk/{createAdapters-Dv7ZJPf1.js → createAdapters-4c8mBiD5.js} +2 -11
- package/dist/esm/sdk/{createAdapters-Dv7ZJPf1.js.map → createAdapters-4c8mBiD5.js.map} +1 -1
- package/dist/esm/sdk/{createAdapters-1Hmc1vVC.js → createAdapters-DF32SIZa.js} +1 -10
- package/dist/esm/sdk/{defaultConfigs-BmCU1_qI.js → defaultConfigs-BQqiXif-.js} +3 -1
- package/dist/esm/sdk/{delegateAction-DdkvFFKA.js → delegateAction-Bq5zkOvn.js} +1 -1
- package/dist/esm/sdk/{emailRecovery-4J-g9tlY.js → emailRecovery-B1hbE_sM.js} +6 -6
- package/dist/esm/sdk/{getDeviceNumber-f8bfPB9U.js → getDeviceNumber-WiNzKx1x.js} +4 -2
- package/dist/esm/sdk/{getDeviceNumber-f8bfPB9U.js.map → getDeviceNumber-WiNzKx1x.js.map} +1 -1
- package/dist/esm/sdk/{linkDevice-C98klpcE.js → linkDevice-CRPf5aW2.js} +5 -5
- package/dist/esm/sdk/{localOnly-40zxrBMm.js → localOnly-COpDBMkm.js} +2 -2
- package/dist/esm/sdk/{localOnly-40zxrBMm.js.map → localOnly-COpDBMkm.js.map} +1 -1
- package/dist/esm/sdk/{localOnly-BZPBj14l.js → localOnly-DQQuqgjJ.js} +1 -1
- package/dist/esm/sdk/{login-DnROv3eA.js → login-DUIWZHp_.js} +4 -4
- package/dist/esm/sdk/offline-export-app.js +32 -21
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{registration-BP9M3tE1.js → registration-BR2G9tz_.js} +59 -68
- package/dist/esm/sdk/{registration-MrAOC8Ub.js → registration-R70lvG_o.js} +60 -69
- package/dist/esm/sdk/registration-R70lvG_o.js.map +1 -0
- package/dist/esm/sdk/{relay-Dq9D7fhG.js → relay-BCEyWFew.js} +1 -1
- package/dist/esm/sdk/{router-BEGGuWaB.js → router-Cj2WexK-.js} +3 -3
- package/dist/esm/sdk/{rpcCalls-CMzj_Va_.js → rpcCalls-C1sp-Epo.js} +3 -3
- package/dist/esm/sdk/{rpcCalls-B44MZora.js → rpcCalls-VL4loDKP.js} +2 -2
- package/dist/esm/sdk/{scanDevice-Cp-r-Z2T.js → scanDevice-C0HcnZym.js} +5 -5
- package/dist/esm/sdk/{sdkSentEvents-CzAZBFjP.js → sdkSentEvents-BfkcI7EN.js} +3 -2
- package/dist/esm/sdk/{signNEP413-DsyWH_Jo.js → signNEP413-lj0swHsD.js} +1 -1
- package/dist/esm/sdk/{syncAccount-CqWCmBVb.js → syncAccount-DnQ9AstS.js} +5 -5
- package/dist/esm/sdk/{syncAccount-Dt5jJbEB.js → syncAccount-xh81Vppo.js} +3 -3
- package/dist/esm/sdk/{transactions-DAZrPW-6.js → transactions-Cg1TIUyK.js} +76 -77
- package/dist/esm/sdk/{transactions-CrjP8yPD.js → transactions-CxsklyCK.js} +77 -78
- package/dist/esm/sdk/transactions-CxsklyCK.js.map +1 -0
- package/dist/esm/sdk/wallet-iframe-host.js +160 -105
- package/dist/esm/server/core/AuthService.js +49 -6
- package/dist/esm/server/core/AuthService.js.map +1 -1
- package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/__tests__/setup/bootstrap.d.ts.map +1 -1
- package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts +1 -1
- package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/faucets/createAccountRelayServer.d.ts +6 -6
- package/dist/types/src/core/TatchiPasskey/faucets/createAccountRelayServer.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/registration.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.d.ts +0 -5
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
- package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
- package/dist/types/src/core/types/sdkSentEvents.d.ts +18 -7
- package/dist/types/src/core/types/sdkSentEvents.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/preload.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/shell.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/skeleton.d.ts +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/skeleton.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/types/src/server/core/AuthService.d.ts.map +1 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/package.json +4 -4
- package/dist/cjs/react/components/PasskeyAuthMenu/PasskeyAuthMenu-CRlobBrN.css.map +0 -1
- package/dist/esm/react/components/PasskeyAuthMenu/PasskeyAuthMenu-D2VHZ04W.css.map +0 -1
- package/dist/esm/sdk/registration-MrAOC8Ub.js.map +0 -1
- package/dist/esm/sdk/transactions-CrjP8yPD.js.map +0 -1
package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js
CHANGED
|
@@ -26,91 +26,91 @@ async function handleTransactionSigningFlow(ctx, request, worker, opts) {
|
|
|
26
26
|
transactionSummary
|
|
27
27
|
});
|
|
28
28
|
const nearAccountId = getNearAccountId(request);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (!nearRpc.transactionContext) {
|
|
43
|
-
console.error("[SigningFlow] fetchNearContext failed", {
|
|
44
|
-
error: nearRpc.error,
|
|
45
|
-
details: nearRpc.details
|
|
46
|
-
});
|
|
47
|
-
return session.confirmAndCloseModal({
|
|
48
|
-
requestId: request.requestId,
|
|
49
|
-
intentDigest: getIntentDigest(request),
|
|
50
|
-
confirmed: false,
|
|
51
|
-
error: nearRpc.details ? `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}` : ERROR_MESSAGES.nearRpcFailed
|
|
29
|
+
try {
|
|
30
|
+
const signingAuthMode = getSigningAuthMode(request);
|
|
31
|
+
const usesNeeded = getTxCount(request);
|
|
32
|
+
const vrfIntentDigestB64u = request.type === SecureConfirmationType.SIGN_TRANSACTION ? getIntentDigest(request) : request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE ? await computeUiIntentDigestFromNep413({
|
|
33
|
+
nearAccountId,
|
|
34
|
+
recipient: request.payload.recipient,
|
|
35
|
+
message: request.payload.message
|
|
36
|
+
}) : void 0;
|
|
37
|
+
const sessionPolicyDigest32 = request.payload.sessionPolicyDigest32;
|
|
38
|
+
const nearRpc = await adapters.near.fetchNearContext({
|
|
39
|
+
nearAccountId,
|
|
40
|
+
txCount: usesNeeded,
|
|
41
|
+
reserveNonces: true
|
|
52
42
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
let uiVrfChallenge;
|
|
58
|
-
let uiVrfChallengeForUi = rpId ? {
|
|
59
|
-
userId: nearAccountId,
|
|
60
|
-
rpId,
|
|
61
|
-
blockHeight: transactionContext.txBlockHeight,
|
|
62
|
-
blockHash: transactionContext.txBlockHash
|
|
63
|
-
} : void 0;
|
|
64
|
-
if (signingAuthMode === "webauthn") {
|
|
65
|
-
uiVrfChallenge = await adapters.vrf.generateVrfChallengeForSession({
|
|
66
|
-
userId: nearAccountId,
|
|
67
|
-
rpId,
|
|
68
|
-
blockHeight: transactionContext.txBlockHeight,
|
|
69
|
-
blockHash: transactionContext.txBlockHash,
|
|
70
|
-
...vrfIntentDigestB64u ? { intentDigest: vrfIntentDigestB64u } : {},
|
|
71
|
-
...sessionPolicyDigest32 ? { sessionPolicyDigest32 } : {}
|
|
72
|
-
}, request.requestId);
|
|
73
|
-
uiVrfChallengeForUi = uiVrfChallenge;
|
|
74
|
-
}
|
|
75
|
-
const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallengeForUi });
|
|
76
|
-
if (!confirmed) return session.confirmAndCloseModal({
|
|
77
|
-
requestId: request.requestId,
|
|
78
|
-
intentDigest: getIntentDigest(request),
|
|
79
|
-
confirmed: false,
|
|
80
|
-
error: uiError
|
|
81
|
-
});
|
|
82
|
-
if (signingAuthMode === "warmSession") {
|
|
83
|
-
try {
|
|
84
|
-
await adapters.vrf.dispenseSessionKey({
|
|
85
|
-
sessionId: request.requestId,
|
|
86
|
-
uses: usesNeeded
|
|
43
|
+
if (!nearRpc.transactionContext) {
|
|
44
|
+
console.error("[SigningFlow] fetchNearContext failed", {
|
|
45
|
+
error: nearRpc.error,
|
|
46
|
+
details: nearRpc.details
|
|
87
47
|
});
|
|
88
|
-
} catch (err) {
|
|
89
|
-
const msg = String(toError(err)?.message || err || "");
|
|
90
48
|
return session.confirmAndCloseModal({
|
|
91
49
|
requestId: request.requestId,
|
|
92
50
|
intentDigest: getIntentDigest(request),
|
|
93
51
|
confirmed: false,
|
|
94
|
-
error:
|
|
52
|
+
error: nearRpc.details ? `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}` : ERROR_MESSAGES.nearRpcFailed
|
|
95
53
|
});
|
|
96
54
|
}
|
|
97
|
-
session.
|
|
55
|
+
session.setReservedNonces(nearRpc.reservedNonces);
|
|
56
|
+
let transactionContext = nearRpc.transactionContext;
|
|
57
|
+
const rpId = adapters.vrf.getRpId();
|
|
58
|
+
let uiVrfChallenge;
|
|
59
|
+
let uiVrfChallengeForUi = rpId ? {
|
|
60
|
+
userId: nearAccountId,
|
|
61
|
+
rpId,
|
|
62
|
+
blockHeight: transactionContext.txBlockHeight,
|
|
63
|
+
blockHash: transactionContext.txBlockHash
|
|
64
|
+
} : void 0;
|
|
65
|
+
if (signingAuthMode === "webauthn") {
|
|
66
|
+
uiVrfChallenge = await adapters.vrf.generateVrfChallengeForSession({
|
|
67
|
+
userId: nearAccountId,
|
|
68
|
+
rpId,
|
|
69
|
+
blockHeight: transactionContext.txBlockHeight,
|
|
70
|
+
blockHash: transactionContext.txBlockHash,
|
|
71
|
+
...vrfIntentDigestB64u ? { intentDigest: vrfIntentDigestB64u } : {},
|
|
72
|
+
...sessionPolicyDigest32 ? { sessionPolicyDigest32 } : {}
|
|
73
|
+
}, request.requestId);
|
|
74
|
+
uiVrfChallengeForUi = uiVrfChallenge;
|
|
75
|
+
}
|
|
76
|
+
const { confirmed, error: uiError } = await session.promptUser({ vrfChallenge: uiVrfChallengeForUi });
|
|
77
|
+
if (!confirmed) return session.confirmAndCloseModal({
|
|
98
78
|
requestId: request.requestId,
|
|
99
79
|
intentDigest: getIntentDigest(request),
|
|
100
|
-
confirmed:
|
|
101
|
-
|
|
80
|
+
confirmed: false,
|
|
81
|
+
error: uiError
|
|
102
82
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
83
|
+
if (signingAuthMode === "warmSession") {
|
|
84
|
+
try {
|
|
85
|
+
await adapters.vrf.dispenseSessionKey({
|
|
86
|
+
sessionId: request.requestId,
|
|
87
|
+
uses: usesNeeded
|
|
88
|
+
});
|
|
89
|
+
} catch (err) {
|
|
90
|
+
const msg = String(toError(err)?.message || err || "");
|
|
91
|
+
return session.confirmAndCloseModal({
|
|
92
|
+
requestId: request.requestId,
|
|
93
|
+
intentDigest: getIntentDigest(request),
|
|
94
|
+
confirmed: false,
|
|
95
|
+
error: msg || "Failed to dispense warm session key"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
session.confirmAndCloseModal({
|
|
99
|
+
requestId: request.requestId,
|
|
100
|
+
intentDigest: getIntentDigest(request),
|
|
101
|
+
confirmed: true,
|
|
102
|
+
transactionContext
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const refreshed = await adapters.vrf.maybeRefreshVrfChallenge(request, nearAccountId);
|
|
108
|
+
uiVrfChallenge = refreshed.vrfChallenge;
|
|
109
|
+
transactionContext = refreshed.transactionContext;
|
|
110
|
+
session.updateUI({ vrfChallenge: uiVrfChallenge });
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.debug("[SigningFlow] VRF JIT refresh skipped", e);
|
|
113
|
+
}
|
|
114
114
|
if (!uiVrfChallenge) throw new Error("Missing vrfChallenge for WebAuthn signing flow");
|
|
115
115
|
const serializedCredential = await adapters.webauthn.collectAuthenticationCredentialWithPRF({
|
|
116
116
|
nearAccountId,
|
|
@@ -158,7 +158,6 @@ async function handleTransactionSigningFlow(ctx, request, worker, opts) {
|
|
|
158
158
|
} catch (err) {
|
|
159
159
|
const cancelled = isUserCancelledSecureConfirm(err);
|
|
160
160
|
const msg = String(toError(err)?.message || err || "");
|
|
161
|
-
if (/Missing PRF result/i.test(msg) || /Missing PRF results/i.test(msg)) return session.cleanupAndRethrow(err);
|
|
162
161
|
if (cancelled) window.parent?.postMessage({ type: "WALLET_UI_CLOSED" }, "*");
|
|
163
162
|
const isWrongPasskeyError = /multiple passkeys \(devicenumbers\) for account/i.test(msg);
|
|
164
163
|
return session.confirmAndCloseModal({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactions.js","names":["transactionContext: TransactionContext","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';\nimport { computeUiIntentDigestFromNep413 } from '../../../../digests/intentDigest';\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 return request.payload.signingAuthMode ?? '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 const vrfIntentDigestB64u = request.type === SecureConfirmationType.SIGN_TRANSACTION\n ? getIntentDigest(request)\n : request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE\n ? await computeUiIntentDigestFromNep413({\n nearAccountId,\n recipient: request.payload.recipient,\n message: request.payload.message,\n })\n : undefined;\n const sessionPolicyDigest32 = request.payload.sessionPolicyDigest32;\n\n // 1) NEAR context + nonce reservation\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: usesNeeded, reserveNonces: true });\n if (!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: nearRpc.details ? `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}` : ERROR_MESSAGES.nearRpcFailed,\n });\n }\n session.setReservedNonces(nearRpc.reservedNonces);\n let transactionContext: TransactionContext = nearRpc.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 ...(vrfIntentDigestB64u ? { intentDigest: vrfIntentDigestB64u } : {}),\n ...(sessionPolicyDigest32 ? { sessionPolicyDigest32 } : {}),\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 keyMaterial = await ctx.indexedDB.nearKeysDB.getLocalKeyMaterial(nearAccountId, deviceNumber);\n if (!keyMaterial) {\n throw new Error(`No key material found for account ${nearAccountId} device ${deviceNumber}`);\n }\n const wrapKeySalt = keyMaterial.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;\n contractId = payload.contractId || PASSKEY_MANAGER_DEFAULT_CONFIGS.contractId;\n nearRpcUrl = payload.nearRpcUrl || 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 : (msg || ERROR_MESSAGES.collectCredentialsFailed)),\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transactions.js","names":["transactionContext: TransactionContext","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';\nimport { computeUiIntentDigestFromNep413 } from '../../../../digests/intentDigest';\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 return request.payload.signingAuthMode ?? '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 try {\n const signingAuthMode = getSigningAuthMode(request);\n const usesNeeded = getTxCount(request);\n const vrfIntentDigestB64u = request.type === SecureConfirmationType.SIGN_TRANSACTION\n ? getIntentDigest(request)\n : request.type === SecureConfirmationType.SIGN_NEP413_MESSAGE\n ? await computeUiIntentDigestFromNep413({\n nearAccountId,\n recipient: request.payload.recipient,\n message: request.payload.message,\n })\n : undefined;\n const sessionPolicyDigest32 = request.payload.sessionPolicyDigest32;\n\n // 1) NEAR context + nonce reservation\n const nearRpc = await adapters.near.fetchNearContext({ nearAccountId, txCount: usesNeeded, reserveNonces: true });\n if (!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: nearRpc.details ? `${ERROR_MESSAGES.nearRpcFailed}: ${nearRpc.details}` : ERROR_MESSAGES.nearRpcFailed,\n });\n }\n session.setReservedNonces(nearRpc.reservedNonces);\n let transactionContext: TransactionContext = nearRpc.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 ...(vrfIntentDigestB64u ? { intentDigest: vrfIntentDigestB64u } : {}),\n ...(sessionPolicyDigest32 ? { sessionPolicyDigest32 } : {}),\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 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 keyMaterial = await ctx.indexedDB.nearKeysDB.getLocalKeyMaterial(nearAccountId, deviceNumber);\n if (!keyMaterial) {\n throw new Error(`No key material found for account ${nearAccountId} device ${deviceNumber}`);\n }\n const wrapKeySalt = keyMaterial.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;\n contractId = payload.contractId || PASSKEY_MANAGER_DEFAULT_CONFIGS.contractId;\n nearRpcUrl = payload.nearRpcUrl || 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 const msg = String((toError(err))?.message || err || '');\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 : (msg || ERROR_MESSAGES.collectCredentialsFailed)),\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -51,13 +51,23 @@ async function handlePromptUserConfirmInJsMainThread(ctx, message, worker) {
|
|
|
51
51
|
});
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
try {
|
|
55
|
+
await handler({
|
|
56
|
+
ctx,
|
|
57
|
+
request,
|
|
58
|
+
worker,
|
|
59
|
+
confirmationConfig,
|
|
60
|
+
transactionSummary
|
|
61
|
+
});
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error("[SecureConfirm][Host] handler failed", e);
|
|
64
|
+
sendConfirmResponse(worker, {
|
|
65
|
+
requestId: request.requestId,
|
|
66
|
+
intentDigest: getIntentDigest(request),
|
|
67
|
+
confirmed: false,
|
|
68
|
+
error: errorMessage(e) || "Secure confirmation failed"
|
|
69
|
+
});
|
|
70
|
+
}
|
|
61
71
|
}
|
|
62
72
|
async function importFlow(label, loader) {
|
|
63
73
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleSecureConfirmRequest.js","names":["request: SecureConfirmRequest","confirmationConfig: ConfirmationConfig","transactionSummary: TransactionSummary","e: unknown","_err: unknown","HANDLERS: Partial<Record<SecureConfirmationType, Handler>>"],"sources":["../../../../../../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../';\nimport type { ConfirmationConfig } from '../../../types/signer-worker';\nimport { determineConfirmationConfig } from './determineConfirmationConfig';\nimport {\n TransactionSummary,\n SecureConfirmMessageType,\n SecureConfirmRequest,\n SecureConfirmationType,\n} from './types';\nimport { errorMessage, toError } from '../../../../utils/errors';\nimport {\n parseTransactionSummary,\n getIntentDigest,\n sendConfirmResponse,\n sanitizeForPostMessage,\n} from './flows';\nimport {\n assertNoForbiddenMainThreadSigningSecrets,\n validateSecureConfirmRequest,\n} from './adapters/requestAdapter';\nimport type {\n LocalOnlySecureConfirmRequest,\n RegistrationSecureConfirmRequest,\n SigningSecureConfirmRequest,\n} from './types';\n\n/**\n * Handles secure confirmation requests from the worker with robust error handling\n * => SecureConfirmMessageType.PROMPT_USER_CONFIRM_IN_JS_MAIN_THREAD\n * and proper data validation. Supports both transaction and registration confirmation flows.\n */\nexport async function handlePromptUserConfirmInJsMainThread(\n ctx: VrfWorkerManagerContext,\n message: {\n type: SecureConfirmMessageType.PROMPT_USER_CONFIRM_IN_JS_MAIN_THREAD,\n data: SecureConfirmRequest,\n },\n worker: Worker\n): Promise<void> {\n\n // 1. Validate and parse request\n let request: SecureConfirmRequest;\n let confirmationConfig: ConfirmationConfig;\n let transactionSummary: TransactionSummary;\n\n try {\n\n request = validateSecureConfirmRequest(message.data);\n assertNoForbiddenMainThreadSigningSecrets(request);\n confirmationConfig = determineConfirmationConfig(ctx, request);\n\n const parsedSummary = parseTransactionSummary(request.summary);\n const intentDigest = getIntentDigest(request);\n\n transactionSummary = sanitizeForPostMessage({\n ...parsedSummary,\n ...(intentDigest ? { intentDigest } : {}),\n }) as TransactionSummary;\n\n } catch (e: unknown) {\n\n console.error('[SecureConfirm][Host] validateAndParseRequest failed', e);\n // Attempt to send a structured error back to the worker to avoid hard failure\n try {\n const rid = (message?.data as any)?.requestId;\n if (typeof rid === 'string' && rid) {\n sendConfirmResponse(worker, {\n requestId: rid,\n confirmed: false,\n error: errorMessage(e) || 'Invalid secure confirm request',\n });\n return;\n }\n } catch (_err: unknown) {\n throw toError(e);\n }\n throw toError(e);\n }\n\n const handler = HANDLERS[request.type];\n if (!handler) {\n // Unsupported type fallback: return structured error to worker.\n sendConfirmResponse(worker, {\n requestId: request.requestId,\n confirmed: false,\n error: 'Unsupported secure confirmation type'\n });\n return;\n }\n\n await handler({ ctx, request, worker, confirmationConfig, transactionSummary });\n}\n\ntype HandlerArgs = {\n ctx: VrfWorkerManagerContext;\n request: SecureConfirmRequest;\n worker: Worker;\n confirmationConfig: ConfirmationConfig;\n transactionSummary: TransactionSummary;\n};\n\ntype Handler = (args: HandlerArgs) => Promise<void>;\n\nasync function importFlow<T>(label: string, loader: () => Promise<T>): Promise<T> {\n try {\n return await loader();\n } catch (e) {\n console.error(`[SecureConfirm][Host] failed to import ${label} flow module`, e);\n throw e;\n }\n}\n\nconst HANDLERS: Partial<Record<SecureConfirmationType, Handler>> = {\n [SecureConfirmationType.DECRYPT_PRIVATE_KEY_WITH_PRF]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleLocalOnlyFlow } = await importFlow('localOnly', () => import('./flows/localOnly'));\n await handleLocalOnlyFlow(ctx, request as LocalOnlySecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.SHOW_SECURE_PRIVATE_KEY_UI]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleLocalOnlyFlow } = await importFlow('localOnly', () => import('./flows/localOnly'));\n await handleLocalOnlyFlow(ctx, request as LocalOnlySecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.REGISTER_ACCOUNT]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleRegistrationFlow } = await importFlow('registration', () => import('./flows/registration'));\n await handleRegistrationFlow(ctx, request as RegistrationSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.LINK_DEVICE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleRegistrationFlow } = await importFlow('registration', () => import('./flows/registration'));\n await handleRegistrationFlow(ctx, request as RegistrationSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.SIGN_TRANSACTION]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleTransactionSigningFlow } = await importFlow('transactions', () => import('./flows/transactions'));\n await handleTransactionSigningFlow(ctx, request as SigningSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.SIGN_NEP413_MESSAGE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleTransactionSigningFlow } = await importFlow('transactions', () => import('./flows/transactions'));\n await handleTransactionSigningFlow(ctx, request as SigningSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n};\n"],"mappings":";;;;;;;;;;;;;AA+BA,eAAsB,sCACpB,KACA,SAIA,QACe;CAGf,IAAIA;CACJ,IAAIC;CACJ,IAAIC;AAEJ,KAAI;AAEF,YAAU,6BAA6B,QAAQ;AAC/C,4CAA0C;AAC1C,uBAAqB,4BAA4B,KAAK;EAEtD,MAAM,gBAAgB,wBAAwB,QAAQ;EACtD,MAAM,eAAe,gBAAgB;AAErC,uBAAqB,uBAAuB;GAC1C,GAAG;GACH,GAAI,eAAe,EAAE,iBAAiB;;UAGjCC,GAAY;AAEnB,UAAQ,MAAM,wDAAwD;AAEtE,MAAI;GACF,MAAM,OAAO,SAAS,OAAc;AACpC,OAAI,OAAO,QAAQ,YAAY,KAAK;AAClC,wBAAoB,QAAQ;KAC1B,WAAW;KACX,WAAW;KACX,OAAO,aAAa,MAAM;;AAE5B;;WAEKC,MAAe;AACtB,SAAM,QAAQ;;AAEhB,QAAM,QAAQ;;CAGhB,MAAM,UAAU,SAAS,QAAQ;AACjC,KAAI,CAAC,SAAS;AAEZ,sBAAoB,QAAQ;GAC1B,WAAW,QAAQ;GACnB,WAAW;GACX,OAAO;;AAET;;AAGF,
|
|
1
|
+
{"version":3,"file":"handleSecureConfirmRequest.js","names":["request: SecureConfirmRequest","confirmationConfig: ConfirmationConfig","transactionSummary: TransactionSummary","e: unknown","_err: unknown","HANDLERS: Partial<Record<SecureConfirmationType, Handler>>"],"sources":["../../../../../../../../src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.ts"],"sourcesContent":["import type { VrfWorkerManagerContext } from '../';\nimport type { ConfirmationConfig } from '../../../types/signer-worker';\nimport { determineConfirmationConfig } from './determineConfirmationConfig';\nimport {\n TransactionSummary,\n SecureConfirmMessageType,\n SecureConfirmRequest,\n SecureConfirmationType,\n} from './types';\nimport { errorMessage, toError } from '../../../../utils/errors';\nimport {\n parseTransactionSummary,\n getIntentDigest,\n sendConfirmResponse,\n sanitizeForPostMessage,\n} from './flows';\nimport {\n assertNoForbiddenMainThreadSigningSecrets,\n validateSecureConfirmRequest,\n} from './adapters/requestAdapter';\nimport type {\n LocalOnlySecureConfirmRequest,\n RegistrationSecureConfirmRequest,\n SigningSecureConfirmRequest,\n} from './types';\n\n/**\n * Handles secure confirmation requests from the worker with robust error handling\n * => SecureConfirmMessageType.PROMPT_USER_CONFIRM_IN_JS_MAIN_THREAD\n * and proper data validation. Supports both transaction and registration confirmation flows.\n */\nexport async function handlePromptUserConfirmInJsMainThread(\n ctx: VrfWorkerManagerContext,\n message: {\n type: SecureConfirmMessageType.PROMPT_USER_CONFIRM_IN_JS_MAIN_THREAD,\n data: SecureConfirmRequest,\n },\n worker: Worker\n): Promise<void> {\n\n // 1. Validate and parse request\n let request: SecureConfirmRequest;\n let confirmationConfig: ConfirmationConfig;\n let transactionSummary: TransactionSummary;\n\n try {\n\n request = validateSecureConfirmRequest(message.data);\n assertNoForbiddenMainThreadSigningSecrets(request);\n confirmationConfig = determineConfirmationConfig(ctx, request);\n\n const parsedSummary = parseTransactionSummary(request.summary);\n const intentDigest = getIntentDigest(request);\n\n transactionSummary = sanitizeForPostMessage({\n ...parsedSummary,\n ...(intentDigest ? { intentDigest } : {}),\n }) as TransactionSummary;\n\n } catch (e: unknown) {\n\n console.error('[SecureConfirm][Host] validateAndParseRequest failed', e);\n // Attempt to send a structured error back to the worker to avoid hard failure\n try {\n const rid = (message?.data as any)?.requestId;\n if (typeof rid === 'string' && rid) {\n sendConfirmResponse(worker, {\n requestId: rid,\n confirmed: false,\n error: errorMessage(e) || 'Invalid secure confirm request',\n });\n return;\n }\n } catch (_err: unknown) {\n throw toError(e);\n }\n throw toError(e);\n }\n\n const handler = HANDLERS[request.type];\n if (!handler) {\n // Unsupported type fallback: return structured error to worker.\n sendConfirmResponse(worker, {\n requestId: request.requestId,\n confirmed: false,\n error: 'Unsupported secure confirmation type'\n });\n return;\n }\n\n try {\n await handler({ ctx, request, worker, confirmationConfig, transactionSummary });\n } catch (e: unknown) {\n console.error('[SecureConfirm][Host] handler failed', e);\n // Best-effort: always respond to the worker so VRF-side requests don't hang indefinitely.\n sendConfirmResponse(worker, {\n requestId: request.requestId,\n intentDigest: getIntentDigest(request),\n confirmed: false,\n error: errorMessage(e) || 'Secure confirmation failed',\n });\n }\n}\n\ntype HandlerArgs = {\n ctx: VrfWorkerManagerContext;\n request: SecureConfirmRequest;\n worker: Worker;\n confirmationConfig: ConfirmationConfig;\n transactionSummary: TransactionSummary;\n};\n\ntype Handler = (args: HandlerArgs) => Promise<void>;\n\nasync function importFlow<T>(label: string, loader: () => Promise<T>): Promise<T> {\n try {\n return await loader();\n } catch (e) {\n console.error(`[SecureConfirm][Host] failed to import ${label} flow module`, e);\n throw e;\n }\n}\n\nconst HANDLERS: Partial<Record<SecureConfirmationType, Handler>> = {\n [SecureConfirmationType.DECRYPT_PRIVATE_KEY_WITH_PRF]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleLocalOnlyFlow } = await importFlow('localOnly', () => import('./flows/localOnly'));\n await handleLocalOnlyFlow(ctx, request as LocalOnlySecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.SHOW_SECURE_PRIVATE_KEY_UI]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleLocalOnlyFlow } = await importFlow('localOnly', () => import('./flows/localOnly'));\n await handleLocalOnlyFlow(ctx, request as LocalOnlySecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.REGISTER_ACCOUNT]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleRegistrationFlow } = await importFlow('registration', () => import('./flows/registration'));\n await handleRegistrationFlow(ctx, request as RegistrationSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.LINK_DEVICE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleRegistrationFlow } = await importFlow('registration', () => import('./flows/registration'));\n await handleRegistrationFlow(ctx, request as RegistrationSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.SIGN_TRANSACTION]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleTransactionSigningFlow } = await importFlow('transactions', () => import('./flows/transactions'));\n await handleTransactionSigningFlow(ctx, request as SigningSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n [SecureConfirmationType.SIGN_NEP413_MESSAGE]: async ({ ctx, request, worker, confirmationConfig, transactionSummary }) => {\n const { handleTransactionSigningFlow } = await importFlow('transactions', () => import('./flows/transactions'));\n await handleTransactionSigningFlow(ctx, request as SigningSecureConfirmRequest, worker, { confirmationConfig, transactionSummary });\n },\n};\n"],"mappings":";;;;;;;;;;;;;AA+BA,eAAsB,sCACpB,KACA,SAIA,QACe;CAGf,IAAIA;CACJ,IAAIC;CACJ,IAAIC;AAEJ,KAAI;AAEF,YAAU,6BAA6B,QAAQ;AAC/C,4CAA0C;AAC1C,uBAAqB,4BAA4B,KAAK;EAEtD,MAAM,gBAAgB,wBAAwB,QAAQ;EACtD,MAAM,eAAe,gBAAgB;AAErC,uBAAqB,uBAAuB;GAC1C,GAAG;GACH,GAAI,eAAe,EAAE,iBAAiB;;UAGjCC,GAAY;AAEnB,UAAQ,MAAM,wDAAwD;AAEtE,MAAI;GACF,MAAM,OAAO,SAAS,OAAc;AACpC,OAAI,OAAO,QAAQ,YAAY,KAAK;AAClC,wBAAoB,QAAQ;KAC1B,WAAW;KACX,WAAW;KACX,OAAO,aAAa,MAAM;;AAE5B;;WAEKC,MAAe;AACtB,SAAM,QAAQ;;AAEhB,QAAM,QAAQ;;CAGhB,MAAM,UAAU,SAAS,QAAQ;AACjC,KAAI,CAAC,SAAS;AAEZ,sBAAoB,QAAQ;GAC1B,WAAW,QAAQ;GACnB,WAAW;GACX,OAAO;;AAET;;AAGF,KAAI;AACF,QAAM,QAAQ;GAAE;GAAK;GAAS;GAAQ;GAAoB;;UACnDD,GAAY;AACnB,UAAQ,MAAM,wCAAwC;AAEtD,sBAAoB,QAAQ;GAC1B,WAAW,QAAQ;GACnB,cAAc,gBAAgB;GAC9B,WAAW;GACX,OAAO,aAAa,MAAM;;;;AAehC,eAAe,WAAc,OAAe,QAAsC;AAChF,KAAI;AACF,SAAO,MAAM;UACN,GAAG;AACV,UAAQ,MAAM,0CAA0C,MAAM,eAAe;AAC7E,QAAM;;;AAIV,MAAME,WAA6D;EAChE,uBAAuB,+BAA+B,OAAO,EAAE,KAAK,SAAS,QAAQ,oBAAoB,yBAAyB;EACjI,MAAM,EAAE,wBAAwB,MAAM,WAAW,mBAAmB,OAAO;AAC3E,QAAM,oBAAoB,KAAK,SAA0C,QAAQ;GAAE;GAAoB;;;EAExG,uBAAuB,6BAA6B,OAAO,EAAE,KAAK,SAAS,QAAQ,oBAAoB,yBAAyB;EAC/H,MAAM,EAAE,wBAAwB,MAAM,WAAW,mBAAmB,OAAO;AAC3E,QAAM,oBAAoB,KAAK,SAA0C,QAAQ;GAAE;GAAoB;;;EAExG,uBAAuB,mBAAmB,OAAO,EAAE,KAAK,SAAS,QAAQ,oBAAoB,yBAAyB;EACrH,MAAM,EAAE,2BAA2B,MAAM,WAAW,sBAAsB,OAAO;AACjF,QAAM,uBAAuB,KAAK,SAA6C,QAAQ;GAAE;GAAoB;;;EAE9G,uBAAuB,cAAc,OAAO,EAAE,KAAK,SAAS,QAAQ,oBAAoB,yBAAyB;EAChH,MAAM,EAAE,2BAA2B,MAAM,WAAW,sBAAsB,OAAO;AACjF,QAAM,uBAAuB,KAAK,SAA6C,QAAQ;GAAE;GAAoB;;;EAE9G,uBAAuB,mBAAmB,OAAO,EAAE,KAAK,SAAS,QAAQ,oBAAoB,yBAAyB;EACrH,MAAM,EAAE,iCAAiC,MAAM,WAAW,sBAAsB,OAAO;AACvF,QAAM,6BAA6B,KAAK,SAAwC,QAAQ;GAAE;GAAoB;;;EAE/G,uBAAuB,sBAAsB,OAAO,EAAE,KAAK,SAAS,QAAQ,oBAAoB,yBAAyB;EACxH,MAAM,EAAE,iCAAiC,MAAM,WAAW,sBAAsB,OAAO;AACvF,QAAM,6BAA6B,KAAK,SAAwC,QAAQ;GAAE;GAAoB"}
|
|
@@ -447,13 +447,13 @@ var WebAuthnManager = class {
|
|
|
447
447
|
/**
|
|
448
448
|
* Persist refreshed server-encrypted VRF keypair in IndexedDB.
|
|
449
449
|
*/
|
|
450
|
-
async updateServerEncryptedVrfKeypair(nearAccountId, serverEncrypted) {
|
|
450
|
+
async updateServerEncryptedVrfKeypair(nearAccountId, serverEncrypted, deviceNumber) {
|
|
451
451
|
await IndexedDBManager.clientDB.updateUser(nearAccountId, { serverEncryptedVrfKeypair: {
|
|
452
452
|
ciphertextVrfB64u: serverEncrypted.ciphertextVrfB64u,
|
|
453
453
|
kek_s_b64u: serverEncrypted.kek_s_b64u,
|
|
454
454
|
serverKeyId: serverEncrypted.serverKeyId,
|
|
455
455
|
updatedAt: Date.now()
|
|
456
|
-
} });
|
|
456
|
+
} }, deviceNumber);
|
|
457
457
|
}
|
|
458
458
|
async clearVrfSession() {
|
|
459
459
|
if (typeof window !== "undefined" && this.workerBaseOrigin !== window.location.origin) return;
|
|
@@ -561,7 +561,7 @@ var WebAuthnManager = class {
|
|
|
561
561
|
const active = status.active && status.nearAccountId === nearAccountId;
|
|
562
562
|
if (!active) return false;
|
|
563
563
|
const refreshed = await this.shamir3PassEncryptCurrentVrfKeypair();
|
|
564
|
-
await this.updateServerEncryptedVrfKeypair(nearAccountId, refreshed);
|
|
564
|
+
await this.updateServerEncryptedVrfKeypair(nearAccountId, refreshed, userData?.deviceNumber);
|
|
565
565
|
return true;
|
|
566
566
|
} catch {
|
|
567
567
|
return false;
|