@tatchi-xyz/sdk 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/EmailRecovery/index.js +25 -0
- package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js +135 -77
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/index.js +2 -1
- package/dist/cjs/core/TatchiPasskey/index.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/cjs/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/cjs/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/cjs/core/WalletIframe/client/router.js +1 -1
- package/dist/cjs/core/WalletIframe/client/router.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
- package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/cjs/core/defaultConfigs.js +3 -7
- package/dist/cjs/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/core/nearCrypto.js +29 -5
- package/dist/cjs/core/nearCrypto.js.map +1 -1
- package/dist/cjs/core/rpcCalls.js +56 -26
- package/dist/cjs/core/rpcCalls.js.map +1 -1
- package/dist/cjs/core/types/emailRecovery.js +33 -0
- package/dist/cjs/core/types/emailRecovery.js.map +1 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-BG_6hcim.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-C-RcGfr5.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/client.js +30 -8
- package/dist/cjs/react/components/PasskeyAuthMenu/client.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +22 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +354 -154
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CB0UCQ_h.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
- package/dist/cjs/react/context/useSDKFlowRuntime.js +183 -0
- package/dist/cjs/react/context/useSDKFlowRuntime.js.map +1 -0
- package/dist/cjs/react/context/useTatchiContextValue.js +24 -15
- package/dist/cjs/react/context/useTatchiContextValue.js.map +1 -1
- package/dist/cjs/react/context/useTatchiWithSdkFlow.js +96 -0
- package/dist/cjs/react/context/useTatchiWithSdkFlow.js.map +1 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +26 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +135 -77
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js +2 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js +1 -1
- package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/defaultConfigs.js +3 -7
- package/dist/cjs/react/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/nearCrypto.js +29 -5
- package/dist/cjs/react/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/rpcCalls.js +56 -26
- package/dist/cjs/react/sdk/src/core/rpcCalls.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/types/emailRecovery.js +33 -0
- package/dist/cjs/react/sdk/src/core/types/emailRecovery.js.map +1 -0
- package/dist/cjs/server/email-recovery/emailParsers.js +2 -1
- package/dist/cjs/server/email-recovery/emailParsers.js.map +1 -1
- package/dist/cjs/server/email-recovery/index.js +6 -6
- package/dist/cjs/server/email-recovery/index.js.map +1 -1
- package/dist/cjs/server/email-recovery/rpcCalls.js +22 -3
- package/dist/cjs/server/email-recovery/rpcCalls.js.map +1 -1
- package/dist/cjs/server/router/cloudflare.js +8 -3
- package/dist/cjs/server/router/cloudflare.js.map +1 -1
- package/dist/cjs/server/router/express.js.map +1 -1
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js +2 -4
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/server/sdk/src/core/nearCrypto.js +26 -7
- package/dist/cjs/server/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/esm/core/EmailRecovery/index.js +25 -1
- package/dist/esm/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/emailRecovery.js +136 -78
- package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/index.js +2 -1
- package/dist/esm/core/TatchiPasskey/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/esm/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/esm/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/esm/core/WalletIframe/client/router.js +1 -1
- package/dist/esm/core/WalletIframe/client/router.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
- package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/esm/core/defaultConfigs.js +3 -7
- package/dist/esm/core/defaultConfigs.js.map +1 -1
- package/dist/esm/core/nearCrypto.js +24 -6
- package/dist/esm/core/nearCrypto.js.map +1 -1
- package/dist/esm/core/rpcCalls.js +56 -26
- package/dist/esm/core/rpcCalls.js.map +1 -1
- package/dist/esm/core/types/emailRecovery.js +26 -0
- package/dist/esm/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-BG_6hcim.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-C-RcGfr5.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
- package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/client.js +30 -8
- package/dist/esm/react/components/PasskeyAuthMenu/client.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +20 -0
- package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
- package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
- package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +354 -154
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CB0UCQ_h.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
- package/dist/esm/react/context/useSDKFlowRuntime.js +181 -0
- package/dist/esm/react/context/useSDKFlowRuntime.js.map +1 -0
- package/dist/esm/react/context/useTatchiContextValue.js +25 -16
- package/dist/esm/react/context/useTatchiContextValue.js.map +1 -1
- package/dist/esm/react/context/useTatchiWithSdkFlow.js +94 -0
- package/dist/esm/react/context/useTatchiWithSdkFlow.js.map +1 -0
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +25 -1
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -78
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
- package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js +1 -1
- package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
- package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
- package/dist/esm/react/sdk/src/core/defaultConfigs.js +3 -7
- package/dist/esm/react/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/react/sdk/src/core/nearCrypto.js +24 -6
- package/dist/esm/react/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/esm/react/sdk/src/core/rpcCalls.js +56 -26
- package/dist/esm/react/sdk/src/core/rpcCalls.js.map +1 -1
- package/dist/esm/react/sdk/src/core/types/emailRecovery.js +26 -0
- package/dist/esm/react/sdk/src/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/react/styles/styles.css +58 -3
- package/dist/esm/sdk/{defaultConfigs-DpslkAQd.js → defaultConfigs-CfQDV-ya.js} +3 -7
- package/dist/esm/sdk/{getDeviceNumber-fXizNGQl.js → getDeviceNumber-BpernPnM.js} +4 -8
- package/dist/esm/sdk/getDeviceNumber-BpernPnM.js.map +1 -0
- package/dist/esm/sdk/offline-export-app.js +23 -6
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{router-DuGYOd3G.js → router-BWtacLJg.js} +1 -1
- package/dist/esm/sdk/{rpcCalls-BQrJMTdg.js → rpcCalls-CYGJSCgm.js} +3 -3
- package/dist/esm/sdk/{rpcCalls-YVeUVMk2.js → rpcCalls-DZZSa-sk.js} +57 -27
- package/dist/esm/sdk/{transactions-bqaAwL4k.js → transactions-Cn9xTWlK.js} +2 -2
- package/dist/esm/sdk/{transactions-bqaAwL4k.js.map → transactions-Cn9xTWlK.js.map} +1 -1
- package/dist/esm/sdk/{transactions-BalIhtJ9.js → transactions-DfdwDQCn.js} +1 -1
- package/dist/esm/sdk/wallet-iframe-host.js +660 -590
- package/dist/esm/server/email-recovery/emailParsers.js +3 -1
- package/dist/esm/server/email-recovery/emailParsers.js.map +1 -1
- package/dist/esm/server/email-recovery/index.js +6 -6
- package/dist/esm/server/email-recovery/index.js.map +1 -1
- package/dist/esm/server/email-recovery/rpcCalls.js +22 -3
- package/dist/esm/server/email-recovery/rpcCalls.js.map +1 -1
- package/dist/esm/server/router/cloudflare.js +8 -3
- package/dist/esm/server/router/cloudflare.js.map +1 -1
- package/dist/esm/server/router/express.js.map +1 -1
- package/dist/esm/server/sdk/src/core/defaultConfigs.js +2 -4
- package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/server/sdk/src/core/nearCrypto.js +26 -8
- package/dist/esm/server/sdk/src/core/nearCrypto.js.map +1 -1
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts +8 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +8 -5
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/index.d.ts +1 -1
- package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/scanDevice.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts +1 -1
- package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/client/router.d.ts +1 -1
- package/dist/types/src/core/WalletIframe/client/router.d.ts.map +1 -1
- package/dist/types/src/core/WalletIframe/shared/messages.d.ts +1 -1
- package/dist/types/src/core/WalletIframe/shared/messages.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts +2 -1
- package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts.map +1 -1
- package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
- package/dist/types/src/core/nearCrypto.d.ts +14 -0
- package/dist/types/src/core/nearCrypto.d.ts.map +1 -1
- package/dist/types/src/core/rpcCalls.d.ts +11 -8
- package/dist/types/src/core/rpcCalls.d.ts.map +1 -1
- package/dist/types/src/core/types/emailRecovery.d.ts +10 -0
- package/dist/types/src/core/types/emailRecovery.d.ts.map +1 -0
- package/dist/types/src/core/types/index.d.ts +1 -0
- package/dist/types/src/core/types/index.d.ts.map +1 -1
- package/dist/types/src/core/types/tatchi.d.ts +0 -4
- package/dist/types/src/core/types/tatchi.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts +2 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/client.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts +10 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts.map +1 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts +8 -3
- package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts +2 -0
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/types/src/react/context/useSDKFlowRuntime.d.ts +10 -0
- package/dist/types/src/react/context/useSDKFlowRuntime.d.ts.map +1 -0
- package/dist/types/src/react/context/useTatchiContextValue.d.ts.map +1 -1
- package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts +9 -0
- package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts.map +1 -0
- package/dist/types/src/react/types.d.ts +31 -0
- package/dist/types/src/react/types.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/emailParsers.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/index.d.ts +5 -6
- package/dist/types/src/server/email-recovery/index.d.ts.map +1 -1
- package/dist/types/src/server/email-recovery/rpcCalls.d.ts +1 -0
- package/dist/types/src/server/email-recovery/rpcCalls.d.ts.map +1 -1
- package/dist/types/src/server/router/cloudflare-adaptor.d.ts.map +1 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/package.json +1 -1
- package/dist/esm/sdk/getDeviceNumber-fXizNGQl.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","names":["parsedOrigin: URL","OverlayController","err: Error & { code?: string; details?: unknown }","full: ParentToChildEnvelope","cancelEnvelope: ParentToChildEnvelope"],"sources":["../../../../../../../../src/core/WalletIframe/client/router.ts"],"sourcesContent":["/*\n * WalletIframeRouter - Client-Side Communication Layer\n *\n * Owns all iframe overlay show/hide behavior for WebAuthn activation. It is the\n * single place that decides *how* the wallet iframe is displayed (fullscreen vs\n * anchored, sticky mode, force-fullscreen during registration, etc.).\n *\n * Responsibilities:\n * - Request/Response Correlation: Tracks pending requests with unique IDs.\n * - Progress Event Bridging: Receives PROGRESS from the wallet iframe and forwards\n * them to app `onEvent` handlers.\n * - Overlay Ownership:\n * - Delegates *when* to show/hide to OnEventsProgressBus (based on progress events).\n * - Executes *how* to show/hide via OverlayController (DOM / CSS / ARIA).\n * - Also reacts to wallet-host UI messages (e.g., WALLET_UI_CLOSED) and export flows.\n * - Timeout Handling: Manages request timeouts and cleanup.\n * - Message Serialization: Strips non-serializable functions from messages.\n * - Error Handling: Converts iframe errors to parent-appropriate errors.\n *\n * High-level flow:\n *\n * Step legend\n * -----------\n * (1) App calls a router RPC (executeAction, registerPasskey, etc).\n * (2) Router posts request to iframe and tracks a pending entry.\n * (3) Wallet iframe sends PROGRESS messages back to the router.\n * (4) Router forwards ProgressPayloads into OnEventsProgressBus.\n * (5) OnEventsProgressBus decides 'show' | 'hide' and calls router adapters.\n * (6) Router delegates to OverlayController to show|hide the iframe.\n * (7) Router receives final result, resolves the pending promise, unregisters,\n * and may hide the overlay if no other request still needs it.\n *\n * +-----------+ +--------------------+ +----------------------+ +----------------------+\n * | App | | WalletIframeRouter | | OnEventsProgressBus | | OverlayController |\n * +-----+-----+ +---------+----------+ +----------+-----------+ +----------+-----------+\n * | (1) RPC call (executeAction, etc.) | |\n * |---------------------->|---------------------------->| |\n * | | |\n * | (2) post(): send request to iframe |\n * | | |\n * | (3) PROGRESS from iframe via onPortMessage() |\n * |<----------------------------------------------------| |\n * | | |\n * | (4) ProgressPayload → heuristic |\n * | |---(5) 'show'|'hide' intent-->|\n * | | |\n * | (6) showFrameForActivation() | hideFrameForActivation() |\n * | | |\n * | | (6) show()|hide() |\n * | |----------------------------->|\n * | | |\n * | (7) PM_RESULT/ERROR → resolve pending, maybe hide overlay |\n * |<----------------------------------------------------| |\n *\n * Communication Flow (requests):\n * 1. Parent calls RPC method (e.g., registerPasskey).\n * 2. Router creates unique request ID and pending entry.\n * 3. Message sent to iframe via MessagePort.\n * 4. Progress events bridged back to parent callbacks and fed into OnEventsProgressBus.\n * 5. OnEventsProgressBus emits show/hide intents; router invokes OverlayController.\n * 6. Final result resolves the pending promise; router unregisters and may hide overlay.\n */\n\nimport {\n type ParentToChildEnvelope,\n type ChildToParentEnvelope,\n type ProgressPayload,\n type PreferencesChangedPayload,\n} from '../shared/messages';\nimport { SignedTransaction } from '../../NearClient';\nimport { OnEventsProgressBus, defaultPhaseHeuristics } from './on-events-progress-bus';\nimport type {\n ActionSSEEvent,\n ActionHooksOptions,\n AfterCall,\n AccountRecoverySSEEvent,\n DelegateActionSSEEvent,\n DeviceLinkingSSEEvent,\n EmailRecoverySSEEvent,\n LoginSSEvent,\n RegistrationSSEEvent,\n SendTransactionHooksOptions,\n SignAndSendTransactionHooksOptions,\n} from '../../types/sdkSentEvents';\nimport {\n RegistrationPhase,\n LoginPhase,\n ActionPhase,\n DeviceLinkingPhase,\n AccountRecoveryPhase,\n EmailRecoveryPhase,\n} from '../../types/sdkSentEvents';\nimport type {\n ActionResult,\n GetRecentLoginsResult,\n LoginAndCreateSessionResult,\n LoginSession,\n RegistrationResult,\n SignTransactionResult,\n} from '../../types/tatchi';\nimport {\n ActionArgs,\n TransactionInput,\n TxExecutionStatus\n} from '../../types';\nimport type { DelegateActionInput } from '../../types/delegate';\nimport { IframeTransport } from './IframeTransport';\nimport OverlayController, { type DOMRectLike } from './overlay-controller';\nimport { isObject, isPlainSignedTransactionLike, extractBorshBytesFromPlainSignedTx, isBoolean } from '../validation';\nimport type { WalletUIRegistry } from '../host/iframe-lit-element-registry';\nimport { toError } from '../../../utils/errors';\nimport {\n DeviceLinkingQRData,\n LinkDeviceResult,\n StartDevice2LinkingFlowArgs,\n StartDevice2LinkingFlowResults,\n} from '../../types/linkDevice'\nimport type { AuthenticatorOptions } from '../../types/authenticatorOptions';\nimport type { ConfirmationConfig } from '../../types/signer-worker';\nimport type { AccessKeyList } from '../../NearClient';\nimport type { SignNEP413MessageResult } from '../../TatchiPasskey/signNEP413';\nimport type { RecoveryResult } from '../../TatchiPasskey';\nimport { openOfflineExportWindow } from '../../OfflineExport/index.js';\nimport type { DerivedAddressRecord } from '../../IndexedDBManager';\nimport type { EmailRecoveryContracts } from '../../types/tatchi';\n\n// Simple, framework-agnostic service iframe client.\n// Responsibilities split:\n// - IframeTransport: low-level mount + load + CONNECT/READY handshake (MessagePort)\n// - WalletIframeRouter (this): request/response correlation, progress events,\n// overlay display, and high-level wallet RPC helpers\n\nexport interface WalletIframeRouterOptions {\n walletOrigin: string; // e.g., https://wallet.example.com\n servicePath?: string; // default '/wallet-service'\n connectTimeoutMs?: number; // default 8000\n requestTimeoutMs?: number; // default 20000\n theme?: 'dark' | 'light';\n // Enable verbose client-side logging for debugging\n debug?: boolean;\n // Test-only/diagnostic options (not part of the public API contract for apps)\n testOptions?: {\n // Optional identity/ownership tags for the iframe instance (useful for tests/tools)\n routerId?: string;\n ownerTag?: string; // e.g., 'app' | 'tests'\n // Lazy mounting: when false, do not auto-connect/mount during init(); connect on first use\n autoMount?: boolean;\n };\n // Optional config forwarded to wallet host\n nearRpcUrl?: string;\n nearNetwork?: 'testnet' | 'mainnet';\n contractId?: string;\n relayer?: {\n url: string;\n };\n vrfWorkerConfigs?: Record<string, unknown>;\n rpIdOverride?: string;\n authenticatorOptions?: AuthenticatorOptions;\n emailRecoveryContracts?: Partial<EmailRecoveryContracts>;\n // SDK asset base path for embedded bundles when mounting same‑origin via srcdoc\n // Must serve dist/esm under this base path. Defaults to '/sdk'.\n sdkBasePath?: string;\n // Optional: pre-register UI components in wallet host\n uiRegistry?: Record<string, unknown>;\n // Optional: explorer base URL for TxTree links\n nearExplorerUrl?: string;\n}\n\ntype Pending = {\n resolve: (value: unknown) => void;\n reject: (reason?: unknown) => void;\n timer: number | undefined;\n onProgress?: (payload: ProgressPayload) => void;\n onTimeout: () => Error;\n};\n\ntype PostResult<T> = {\n ok: boolean,\n result: T\n}\n\nexport class WalletIframeRouter {\n private opts: Required<WalletIframeRouterOptions>;\n // Low-level transport handling iframe mount + handshake\n private transport: IframeTransport;\n private port: MessagePort | null = null;\n private ready = false;\n // Deduplicate concurrent init() calls and avoid race conditions\n private initInFlight: Promise<void> | null = null;\n private pending = new Map<string, Pending>();\n private reqCounter = 0;\n private readyListeners: Set<() => void> = new Set();\n private vrfStatusListeners: Set<(status: { active: boolean; nearAccountId: string | null; sessionDuration?: number }) => void> = new Set();\n private preferencesChangedListeners: Set<(payload: PreferencesChangedPayload) => void> = new Set();\n // Coalesce duplicate Device2 start calls (e.g., React StrictMode double-effects)\n private device2StartPromise: Promise<{ qrData: DeviceLinkingQRData; qrCodeDataURL: string }> | null = null;\n private progressBus: OnEventsProgressBus;\n private debug = false;\n private readonly walletOriginUrl: URL;\n private readonly walletOriginOrigin: string;\n private overlay: OverlayController;\n // Force the overlay to remain fullscreen during critical flows (e.g., registration)\n // and ignore anchored rect updates from helper hooks.\n private overlayForceFullscreen = false;\n // Overlay register button window-message bridging (wallet-host UI → parent)\n private readonly registerOverlayResultListeners = new Set<(\n payload: { ok: boolean; result?: RegistrationResult; cancelled?: boolean; error?: string }\n ) => void>();\n private readonly registerOverlaySubmitListeners = new Set<() => void>();\n private windowMsgHandlerBound?: (ev: MessageEvent) => void;\n\n constructor(options: WalletIframeRouterOptions) {\n if (!options?.walletOrigin) {\n throw new Error('[WalletIframeRouter] walletOrigin is required when using the wallet iframe');\n }\n\n let parsedOrigin: URL;\n try {\n parsedOrigin = new URL(options.walletOrigin);\n } catch (err) {\n throw new Error(`[WalletIframeRouter] Invalid walletOrigin: ${options.walletOrigin}`);\n }\n\n if (typeof window !== 'undefined') {\n const parentOrigin = window.location.origin;\n if (parsedOrigin.origin === parentOrigin) {\n console.warn('[WalletIframeRouter] walletOrigin matches the host origin. Isolation safeguards rely on the parent; consider moving the wallet to a dedicated origin.');\n }\n }\n\n const defaultRouterId = `w3a-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const testOptions = {\n routerId: defaultRouterId,\n ownerTag: undefined as string | undefined,\n autoMount: true,\n ...(options?.testOptions || {}),\n };\n this.opts = {\n connectTimeoutMs: 8000,\n requestTimeoutMs: 20000,\n servicePath: '/wallet-service',\n sdkBasePath: '/sdk',\n testOptions,\n ...options,\n } as Required<WalletIframeRouterOptions>;\n this.walletOriginUrl = parsedOrigin;\n this.walletOriginOrigin = parsedOrigin.origin;\n this.debug = !!this.opts.debug;\n // Encapsulate iframe mount + handshake logic in transport\n this.transport = new IframeTransport({\n walletOrigin: this.opts.walletOrigin,\n servicePath: this.opts.servicePath,\n connectTimeoutMs: this.opts.connectTimeoutMs,\n testOptions: {\n routerId: this.opts.testOptions.routerId,\n ownerTag: this.opts.testOptions.ownerTag,\n },\n });\n\n // Centralize overlay sizing/visibility. The router is the single owner of\n // \"how\" the iframe is shown/hidden (fullscreen vs anchored, sticky, etc).\n this.overlay = new OverlayController({ ensureIframe: () => this.transport.ensureIframeMounted() });\n\n // Initialize progress router with overlay control and phase heuristics.\n // OnEventsProgressBus only decides *when* to show/hide based on events; it calls\n // these adapter functions, and the router delegates to OverlayController.\n this.progressBus = new OnEventsProgressBus(\n {\n show: () => this.showFrameForActivation(),\n hide: () => this.hideFrameForActivation()\n },\n defaultPhaseHeuristics,\n this.debug\n ? (msg: string, data?: Record<string, unknown>) => {\n console.debug('[WalletIframeRouter][OnEventsProgressBus]', msg, data || {});\n }\n : undefined\n );\n\n // Bridge wallet-host overlay UI messages into router callbacks\n this.windowMsgHandlerBound = (ev: MessageEvent) => {\n if (ev.origin !== this.walletOriginOrigin) return;\n const data = ev.data as unknown;\n if (!data || typeof data !== 'object') return;\n const type = (data as { type?: unknown }).type;\n if (type === 'REGISTER_BUTTON_SUBMIT') {\n // User clicked the register arrow inside the wallet-anchored UI\n // Force the overlay to fullscreen immediately so the TxConfirmer\n // can mount and capture activation in Safari/iOS/mobile.\n this.overlayForceFullscreen = true;\n this.overlay.setSticky(true);\n this.overlay.showFullscreen();\n for (const cb of Array.from(this.registerOverlaySubmitListeners)) {\n try { cb(); } catch {}\n }\n return;\n }\n if (type === 'REGISTER_BUTTON_RESULT') {\n const payload = (data as { payload?: unknown }).payload as\n | { ok?: boolean; result?: RegistrationResult; cancelled?: boolean; error?: string }\n | undefined;\n const ok = !!payload?.ok;\n for (const cb of Array.from(this.registerOverlayResultListeners)) {\n cb({ ok, result: payload?.result, cancelled: payload?.cancelled, error: payload?.error });\n }\n // Release overlay lock after result\n this.overlayForceFullscreen = false;\n this.overlay.setSticky(false);\n // Progress bus will hide after completion; hide defensively here\n this.hideFrameForActivation();\n if (ok) {\n const acct = payload?.result?.nearAccountId;\n void this.getLoginSession(acct)\n .then(({ login: st }) => {\n this.emitVrfStatusChanged({ active: !!st.vrfActive, nearAccountId: st.nearAccountId, sessionDuration: st.vrfSessionDuration });\n })\n .catch(() => {});\n }\n return;\n }\n };\n globalThis.addEventListener?.('message', this.windowMsgHandlerBound);\n }\n\n private attachExportUiClosedListener = (walletOrigin: string): (() => void) => {\n const onUiClosed = (ev: MessageEvent) => {\n if (ev.origin !== walletOrigin) return;\n const data = ev.data as unknown;\n if (!data || (data as any).type !== 'WALLET_UI_CLOSED') return;\n this.overlay.setSticky(false);\n this.hideFrameForActivation();\n globalThis.removeEventListener?.('message', onUiClosed);\n };\n globalThis.addEventListener?.('message', onUiClosed);\n return () => { globalThis.removeEventListener?.('message', onUiClosed) };\n }\n\n private attachExportUiFallbackListener = (walletOrigin: string, accountId: string): (() => void) => {\n const onFallback = async (ev: MessageEvent) => {\n if (ev.origin !== walletOrigin) return;\n const data = ev.data as any;\n if (!data || data.type !== 'OFFLINE_EXPORT_FALLBACK') return;\n globalThis.removeEventListener?.('message', onFallback);\n this.overlay.setSticky(false);\n this.hideFrameForActivation();\n await this.openOfflineExport({ accountId });\n };\n globalThis.addEventListener?.('message', onFallback);\n return () => { globalThis.removeEventListener?.('message', onFallback) };\n }\n\n /**\n * Subscribe to service-ready event. Returns an unsubscribe function.\n * If already ready, the listener is invoked on next microtask.\n */\n onReady(listener: () => void): () => void {\n if (this.ready) {\n Promise.resolve().then(() => { listener(); });\n return () => {};\n }\n this.readyListeners.add(listener);\n return () => { this.readyListeners.delete(listener); };\n }\n\n private emitReady(): void {\n if (!this.readyListeners.size) return;\n for (const cb of Array.from(this.readyListeners)) { cb(); }\n // Keep listeners registered; callers can unsubscribe if desired.\n }\n\n /**\n * Initialize the transport and configure the wallet host.\n * Safe to call multiple times; concurrent calls deduplicate via initInFlight.\n */\n async init(): Promise<void> {\n if (this.ready) return;\n if (this.initInFlight) { return this.initInFlight; }\n this.initInFlight = (async () => {\n // Respect autoMount=false by deferring connect until first use\n if (this.opts.testOptions.autoMount !== false) {\n this.port = await this.transport.connect();\n this.port.onmessage = (ev) => this.onPortMessage(ev);\n this.port.start?.();\n this.ready = true;\n }\n console.debug('[WalletIframeRouter] init: %s', this.ready ? 'connected' : 'deferred (autoMount=false)');\n await this.post({\n type: 'PM_SET_CONFIG',\n payload: {\n theme: this.opts.theme,\n nearRpcUrl: this.opts.nearRpcUrl,\n nearNetwork: this.opts.nearNetwork,\n // Align with PMSetConfigPayload which expects `contractId`\n // while keeping RouterOptions field name `contractId` for external API.\n contractId: this.opts.contractId,\n nearExplorerUrl: this.opts.nearExplorerUrl,\n relayer: this.opts.relayer,\n vrfWorkerConfigs: this.opts.vrfWorkerConfigs,\n rpIdOverride: this.opts.rpIdOverride,\n authenticatorOptions: this.opts.authenticatorOptions,\n emailRecoveryContracts: this.opts.emailRecoveryContracts,\n uiRegistry: this.opts.uiRegistry,\n // for embedded Lit components\n assetsBaseUrl: (() => {\n try {\n const base = new URL(this.opts.sdkBasePath, this.walletOriginUrl).toString();\n return base.endsWith('/') ? base : `${base}/`;\n } catch {\n const fallback = new URL('/sdk/', this.walletOriginUrl).toString();\n return fallback.endsWith('/') ? fallback : `${fallback}/`;\n }\n })(),\n }\n });\n this.emitReady();\n })();\n\n try {\n await this.initInFlight;\n } finally {\n this.initInFlight = null;\n }\n }\n\n isReady(): boolean { return this.ready; }\n\n // ===== UI registry/window-message helpers (generic mounting) =====\n registerUiTypes(registry: WalletUIRegistry): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_REGISTER_TYPES', payload: registry }, target);\n }\n\n mountUiComponent(params: { key: string; props?: Record<string, unknown>; targetSelector?: string; id?: string }): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_MOUNT', payload: params }, target);\n }\n\n updateUiComponent(params: { id: string; props?: Record<string, unknown> }): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_UPDATE', payload: params }, target);\n }\n\n unmountUiComponent(id: string): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_UNMOUNT', payload: { id } }, target);\n }\n\n // ===== Public RPC helpers =====\n\n // Subscribe to VRF status changes observed by this client\n onVrfStatusChanged(listener: (status: {\n active: boolean;\n nearAccountId: string | null;\n sessionDuration?: number\n }) => void): () => void {\n this.vrfStatusListeners.add(listener);\n return () => { this.vrfStatusListeners.delete(listener); };\n }\n\n // Subscribe to wallet-host preference changes (authoritative in wallet-iframe mode).\n onPreferencesChanged(listener: (payload: PreferencesChangedPayload) => void): () => void {\n this.preferencesChangedListeners.add(listener);\n return () => { this.preferencesChangedListeners.delete(listener); };\n }\n\n private emitVrfStatusChanged(status: {\n active: boolean;\n nearAccountId: string | null;\n sessionDuration?: number\n }): void {\n for (const cb of Array.from(this.vrfStatusListeners)) {\n try { cb(status); } catch {}\n }\n }\n\n private emitPreferencesChanged(payload: PreferencesChangedPayload): void {\n if (!this.preferencesChangedListeners.size) return;\n for (const cb of Array.from(this.preferencesChangedListeners)) {\n try { cb(payload); } catch {}\n }\n }\n\n // Overlay register button events (optional convenience API)\n onRegisterOverlayResult(listener: (payload: { ok: boolean; result?: RegistrationResult; cancelled?: boolean; error?: string }) => void): () => void {\n this.registerOverlayResultListeners.add(listener);\n return () => { this.registerOverlayResultListeners.delete(listener); };\n }\n\n onRegisterOverlaySubmit(listener: () => void): () => void {\n this.registerOverlaySubmitListeners.add(listener);\n return () => { this.registerOverlaySubmitListeners.delete(listener); };\n }\n\n // ===== TatchiPasskey RPCs =====\n\n async signTransactionsWithActions(payload: {\n nearAccountId: string;\n transactions: TransactionInput[];\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void;\n onError?: (error: Error) => void;\n afterCall?: AfterCall<SignTransactionResult[]>;\n // Allow minimal overrides (e.g., { uiMode: 'drawer' })\n confirmationConfig?: Partial<ConfirmationConfig>;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<SignTransactionResult[]> {\n // Do not forward non-cloneable functions in options; host emits its own PROGRESS messages\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n }\n : undefined;\n const res = await this.post<SignTransactionResult>({\n type: 'PM_SIGN_TXS_WITH_ACTIONS',\n payload: {\n nearAccountId: payload.nearAccountId,\n transactions: payload.transactions,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isActionSSEEvent) }\n });\n return normalizeSignedTransactionObject(res.result)\n }\n\n async signDelegateAction(payload: {\n nearAccountId: string;\n delegate: DelegateActionInput;\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void;\n onError?: (error: Error) => void;\n afterCall?: AfterCall<any>;\n confirmationConfig?: Partial<ConfirmationConfig>;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<unknown> {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n }\n : undefined;\n const res = await this.post<unknown>({\n type: 'PM_SIGN_DELEGATE_ACTION',\n payload: {\n nearAccountId: payload.nearAccountId,\n delegate: payload.delegate,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async registerPasskey(payload: {\n nearAccountId: string;\n confirmationConfig?: Partial<ConfirmationConfig>;\n options?: {\n onEvent?: (ev: RegistrationSSEEvent) => void;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<RegistrationResult> {\n // Step 1: For registration, force fullscreen overlay (not anchored to CTA)\n // so the TxConfirmer (drawer/modal) has space to render and capture activation.\n // Lock overlay to fullscreen for the duration of registration\n this.overlayForceFullscreen = true;\n this.overlay.setSticky(true);\n this.overlay.showFullscreen();\n\n try {\n // Optional one-time confirmation override (non-persistent)\n if (payload.confirmationConfig) {\n const base = await this.getConfirmationConfig();\n await this.setConfirmationConfig({ ...base, ...payload.confirmationConfig });\n }\n\n // Step 2: Strip non-serializable functions from options (functions can't cross iframe boundary)\n const safeOptions = removeFunctionsFromOptions(payload.options);\n\n // Step 3: Send PM_REGISTER message to iframe and wait for response\n const res = await this.post<RegistrationResult>({\n type: 'PM_REGISTER',\n payload: {\n nearAccountId: payload.nearAccountId,\n options: safeOptions,\n ...(payload.confirmationConfig ? { confirmationConfig: payload.confirmationConfig as unknown as Record<string, unknown> } : {})\n },\n // Bridge progress events from iframe back to parent callback\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isRegistrationSSEEvent) }\n });\n\n // Step 4: Update VRF status after successful registration\n const { login: st } = await this.getLoginSession(payload.nearAccountId);\n this.emitVrfStatusChanged({\n active: !!st.vrfActive,\n nearAccountId: st.nearAccountId,\n sessionDuration: st.vrfSessionDuration\n });\n\n return res?.result;\n } finally {\n // Step 5: Always release overlay lock and hide when done (success or error)\n this.overlayForceFullscreen = false;\n this.overlay.setSticky(false);\n this.hideFrameForActivation();\n }\n }\n\n async loginAndCreateSession(payload: {\n nearAccountId: string;\n options?: {\n onEvent?: (ev: LoginSSEvent) => void;\n // Forward session config so host can mint JWT/cookie\n session?: {\n kind: 'jwt' | 'cookie';\n relayUrl?: string;\n route?: string;\n };\n // Warm signing session policy override during login\n signingSession?: {\n ttlMs?: number;\n remainingUses?: number;\n };\n }\n }): Promise<LoginAndCreateSessionResult> {\n this.showFrameForActivation();\n try {\n const safeOptions = removeFunctionsFromOptions(payload.options);\n const res = await this.post<LoginAndCreateSessionResult>({\n type: 'PM_LOGIN',\n payload: {\n nearAccountId: payload.nearAccountId,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isLoginSSEEvent) }\n });\n const { login: st } = await this.getLoginSession(payload.nearAccountId);\n this.emitVrfStatusChanged({ active: !!st.vrfActive, nearAccountId: st.nearAccountId, sessionDuration: st.vrfSessionDuration });\n return res?.result;\n } finally {\n this.hideFrameForActivation();\n }\n }\n\n async getLoginSession(nearAccountId?: string): Promise<LoginSession> {\n const res = await this.post<LoginSession>({\n type: 'PM_GET_LOGIN_SESSION',\n payload: nearAccountId ? { nearAccountId } : undefined\n });\n return res.result;\n }\n\n async checkVrfStatus(): Promise<PostResult<{ active: boolean; nearAccountId: string | null; sessionDuration?: number }>> {\n const { login: st } = await this.getLoginSession();\n return {\n ok: true,\n result: {\n active: !!st.vrfActive,\n nearAccountId: st.nearAccountId,\n sessionDuration: st.vrfSessionDuration\n }\n };\n }\n\n async clearVrfSession(): Promise<PostResult<void>> {\n await this.post<void>({ type: 'PM_LOGOUT' });\n this.emitVrfStatusChanged({ active: false, nearAccountId: null });\n return { ok: true, result: undefined };\n }\n\n async signNep413Message(payload: {\n nearAccountId: string;\n message: string;\n recipient: string;\n state?: string;\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void;\n confirmerText?: { title?: string; body?: string };\n confirmationConfig?: Partial<ConfirmationConfig>;\n }\n }): Promise<SignNEP413MessageResult> {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n }\n : undefined;\n const res = await this.post<SignNEP413MessageResult>({\n type: 'PM_SIGN_NEP413',\n payload: {\n nearAccountId: payload.nearAccountId,\n params: {\n message: payload.message,\n recipient: payload.recipient,\n state: payload.state\n },\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isActionSSEEvent) }\n });\n return res.result\n }\n\n async signTransactionWithKeyPair(payload: {\n signedTransaction: SignedTransaction;\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void\n }\n }): Promise<ActionResult> {\n // Strip non-cloneable functions from options; host emits PROGRESS events\n const { options } = payload;\n const res = await this.post<ActionResult>( {\n type: 'PM_SEND_TRANSACTION',\n payload: {\n signedTransaction: payload.signedTransaction,\n options: options\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async executeAction(payload: {\n nearAccountId: string;\n receiverId: string;\n actionArgs: ActionArgs | ActionArgs[];\n options?: ActionHooksOptions\n }): Promise<ActionResult> {\n // Strip non-cloneable functions from options; host emits PROGRESS events\n const { options } = payload;\n const safeOptions = options\n ? {\n waitUntil: options.waitUntil,\n confirmationConfig: options.confirmationConfig,\n ...(options.confirmerText ? { confirmerText: options.confirmerText } : {}),\n }\n : undefined;\n\n const res = await this.post<ActionResult>({\n type: 'PM_EXECUTE_ACTION',\n payload: {\n ...payload,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async setConfirmBehavior(behavior: 'requireClick' | 'autoProceed'): Promise<void> {\n let { nearAccountId } = (await this.getLoginSession()).login;\n await this.post<void>({\n type: 'PM_SET_CONFIRM_BEHAVIOR',\n payload: { behavior, nearAccountId }\n });\n }\n\n async setConfirmationConfig(config: ConfirmationConfig): Promise<void> {\n let { nearAccountId } = (await this.getLoginSession()).login;\n await this.post<void>({\n type: 'PM_SET_CONFIRMATION_CONFIG',\n payload: { config, nearAccountId }\n });\n }\n\n async getConfirmationConfig(): Promise<ConfirmationConfig> {\n const res = await this.post<ConfirmationConfig>({ type: 'PM_GET_CONFIRMATION_CONFIG' });\n return res.result\n }\n\n async setTheme(theme: 'dark' | 'light'): Promise<void> {\n await this.post<void>({ type: 'PM_SET_THEME', payload: { theme } });\n }\n\n async prefetchBlockheight(): Promise<void> {\n await this.post<void>({ type: 'PM_PREFETCH_BLOCKHEIGHT' } );\n }\n\n async getRecentLogins(): Promise<GetRecentLoginsResult> {\n const res = await this.post<GetRecentLoginsResult>({ type: 'PM_GET_RECENT_LOGINS' } );\n return res.result;\n }\n\n // === Local persistence helpers (wallet-origin IndexedDB) ===\n\n async setDerivedAddress(payload: {\n nearAccountId: string;\n args: { contractId: string; path: string; address: string };\n }): Promise<void> {\n await this.post<void>({\n type: 'PM_SET_DERIVED_ADDRESS',\n payload,\n });\n }\n\n async getDerivedAddressRecord(payload: {\n nearAccountId: string;\n args: { contractId: string; path: string };\n }): Promise<DerivedAddressRecord | null> {\n const res = await this.post<DerivedAddressRecord | null>({\n type: 'PM_GET_DERIVED_ADDRESS_RECORD',\n payload,\n });\n return (res.result as DerivedAddressRecord | null) || null;\n }\n\n async getDerivedAddress(payload: {\n nearAccountId: string;\n args: { contractId: string; path: string };\n }): Promise<string | null> {\n const res = await this.post<string | null>({\n type: 'PM_GET_DERIVED_ADDRESS',\n payload,\n });\n return (res.result as string | null) || null;\n }\n\n async getRecoveryEmails(\n nearAccountId: string,\n ): Promise<Array<{ hashHex: string; email: string }>> {\n const res = await this.post<Array<{ hashHex: string; email: string }>>({\n type: 'PM_GET_RECOVERY_EMAILS',\n payload: { nearAccountId },\n });\n return (res.result as Array<{ hashHex: string; email: string }>) || [];\n }\n\n async setRecoveryEmails(payload: {\n nearAccountId: string;\n recoveryEmails: string[];\n options?: ActionHooksOptions;\n }): Promise<ActionResult> {\n const { options } = payload;\n const safeOptions = options\n ? {\n waitUntil: options.waitUntil,\n confirmationConfig: options.confirmationConfig,\n }\n : undefined;\n\n const res = await this.post<ActionResult>({\n type: 'PM_SET_RECOVERY_EMAILS',\n payload: {\n nearAccountId: payload.nearAccountId,\n recoveryEmails: payload.recoveryEmails,\n options: safeOptions,\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) },\n });\n return res.result;\n }\n\n // Bridge typed public onEvent callbacks to the transport's onProgress callback.\n // - onEvent: consumer's strongly-typed event handler (e.g., ActionSSEEvent)\n // - isExpectedEvent: runtime type guard that validates a ProgressPayload as that event type\n // Returns an onProgress handler that safely narrows before invoking onEvent.\n private wrapOnEvent<TEvent extends ProgressPayload>(\n onEvent: ((event: TEvent) => void) | undefined,\n isExpectedEvent: (progress: ProgressPayload) => progress is TEvent\n ): ((progress: ProgressPayload) => void) | undefined {\n if (!onEvent) return undefined;\n return (progress: ProgressPayload) => {\n try {\n if (isExpectedEvent(progress)) onEvent(progress);\n } catch {}\n };\n }\n\n async signAndSendTransactions(payload: {\n nearAccountId: string;\n transactions: TransactionInput[];\n options?: SignAndSendTransactionHooksOptions\n }): Promise<ActionResult[]> {\n\n const { options } = payload;\n // cannot send objects/functions through postMessage(), clean options first\n const safeOptions = options\n ? {\n waitUntil: options.waitUntil,\n executionWait: options.executionWait,\n confirmationConfig: options.confirmationConfig,\n ...(options.confirmerText ? { confirmerText: options.confirmerText } : {}),\n }\n : undefined;\n\n const res = await this.post<ActionResult[]>({\n type: 'PM_SIGN_AND_SEND_TXS',\n payload: {\n nearAccountId: payload.nearAccountId,\n transactions: payload.transactions,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async hasPasskeyCredential(nearAccountId: string): Promise<boolean> {\n const res = await this.post<boolean>({\n type: 'PM_HAS_PASSKEY',\n payload: { nearAccountId }\n });\n return !!res?.result;\n }\n\n async viewAccessKeyList(accountId: string): Promise<AccessKeyList> {\n const res = await this.post<AccessKeyList>({\n type: 'PM_VIEW_ACCESS_KEYS',\n payload: { accountId }\n });\n return res.result\n }\n\n async deleteDeviceKey(\n accountId: string,\n publicKeyToDelete: string,\n options?: { onEvent?: (ev: ActionSSEEvent) => void }\n ) : Promise<ActionResult> {\n const res = await this.post<ActionResult>({\n type: 'PM_DELETE_DEVICE_KEY',\n payload: {\n accountId,\n publicKeyToDelete\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result\n }\n\n async sendTransaction(args: {\n signedTransaction: SignedTransaction;\n options?: SendTransactionHooksOptions;\n }): Promise<ActionResult> {\n // Strip non-cloneable functions from options; host emits PROGRESS events\n const { options } = args;\n const safeOptions = options\n ? { waitUntil: options.waitUntil }\n : undefined;\n\n const res = await this.post<ActionResult>({\n type: 'PM_SEND_TRANSACTION',\n payload: {\n signedTransaction: args.signedTransaction,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result\n }\n\n async exportNearKeypairWithUI(\n nearAccountId: string,\n options?: { variant?: 'drawer' | 'modal'; theme?: 'dark' | 'light' }\n ): Promise<void> {\n try {\n // Make the wallet iframe visible while the export viewer is open.\n // Unlike request/response flows, the wallet host renders UI and manages\n // its own lifecycle; it will notify us when to hide via window message.\n this.showFrameForActivation();\n const walletOrigin = this.walletOriginOrigin;\n const detachClosed = this.attachExportUiClosedListener(walletOrigin);\n const detachFallback = this.attachExportUiFallbackListener(walletOrigin, nearAccountId);\n await this.post<void>({\n type: 'PM_EXPORT_NEAR_KEYPAIR_UI',\n payload: { nearAccountId, variant: options?.variant, theme: options?.theme },\n options: { sticky: true }\n });\n // Cleanup once posted (handlers will remove themselves on events)\n void detachClosed;\n void detachFallback;\n return;\n } catch (e) {\n // Fallback to offline-export route (new tab) if wallet host is unreachable or errors out\n await this.openOfflineExport({ accountId: nearAccountId });\n }\n }\n\n /**\n * Open the offline-export route as a full-screen overlay iframe and instruct it via postMessage\n * to begin the export flow for the given account. Cleans up when the viewer closes or on error.\n */\n async openOfflineExport({ accountId, timeoutMs = 20000 }: { accountId: string; timeoutMs?: number }): Promise<void> {\n const walletOrigin = this.opts.walletOrigin || window.location.origin;\n // Default: open a new tab/window for clarity\n openOfflineExportWindow({ walletOrigin, target: '_blank', accountId });\n return Promise.resolve();\n }\n\n // ===== Account Recovery (single-endpoint flow) =====\n async recoverAccountFlow(payload: {\n accountId?: string;\n onEvent?: (ev: AccountRecoverySSEEvent) => void\n }): Promise<RecoveryResult> {\n const res = await this.post<RecoveryResult>({\n type: 'PM_RECOVER_ACCOUNT_FLOW',\n payload: { accountId: payload.accountId },\n options: {\n onProgress: this.wrapOnEvent(payload.onEvent, isAccountRecoverySSEEvent)\n }\n });\n return res.result\n }\n\n // ===== Email Recovery (wallet-hosted) =====\n async startEmailRecovery(payload: {\n accountId: string;\n recoveryEmail: string;\n onEvent?: (ev: EmailRecoverySSEEvent) => void;\n options?: {\n confirmerText?: { title?: string; body?: string };\n confirmationConfig?: Partial<ConfirmationConfig>;\n }\n }): Promise<{ mailtoUrl: string; nearPublicKey: string }> {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n }\n : undefined;\n const res = await this.post<{ mailtoUrl: string; nearPublicKey: string }>({\n type: 'PM_START_EMAIL_RECOVERY',\n payload: {\n accountId: payload.accountId,\n recoveryEmail: payload.recoveryEmail,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: {\n onProgress: this.wrapOnEvent(payload.onEvent, isEmailRecoverySSEEvent)\n }\n });\n return res.result;\n }\n\n async finalizeEmailRecovery(payload: {\n accountId: string;\n nearPublicKey?: string;\n onEvent?: (ev: EmailRecoverySSEEvent) => void\n }): Promise<void> {\n await this.post<void>({\n type: 'PM_FINALIZE_EMAIL_RECOVERY',\n payload: { accountId: payload.accountId, nearPublicKey: payload.nearPublicKey },\n options: {\n onProgress: this.wrapOnEvent(payload.onEvent, isEmailRecoverySSEEvent)\n }\n });\n }\n\n async stopEmailRecovery(payload?: { accountId?: string; nearPublicKey?: string }): Promise<void> {\n await this.post<void>({\n type: 'PM_STOP_EMAIL_RECOVERY',\n payload: { accountId: payload?.accountId, nearPublicKey: payload?.nearPublicKey },\n });\n }\n\n // ===== Device Linking (iframe-hosted) =====\n async linkDeviceWithScannedQRData(payload: {\n qrData: DeviceLinkingQRData;\n fundingAmount: string;\n options?: {\n onEvent?: (ev: DeviceLinkingSSEEvent) => void;\n confirmationConfig?: Partial<ConfirmationConfig>;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<LinkDeviceResult> {\n // TouchID required within host\n this.showFrameForActivation();\n try {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n }\n : undefined;\n const res = await this.post<LinkDeviceResult>({\n type: 'PM_LINK_DEVICE_WITH_SCANNED_QR_DATA',\n payload: {\n qrData: payload.qrData,\n fundingAmount: payload.fundingAmount,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: {\n onProgress: this.wrapOnEvent(payload.options?.onEvent, isDeviceLinkingSSEEvent)\n }\n });\n return res.result\n } finally {\n this.hideFrameForActivation();\n }\n }\n\n async startDevice2LinkingFlow(payload?: StartDevice2LinkingFlowArgs): Promise<StartDevice2LinkingFlowResults> {\n if (this.device2StartPromise) {\n return this.device2StartPromise\n }\n const options = payload?.options;\n const safeOptions = options\n ? {\n ...(options.confirmationConfig\n ? { confirmationConfig: options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(options.confirmerText ? { confirmerText: options.confirmerText } : {}),\n }\n : undefined;\n const p = this.post<StartDevice2LinkingFlowResults>({\n type: 'PM_START_DEVICE2_LINKING_FLOW',\n payload: {\n ui: payload?.ui,\n cameraId: payload?.cameraId,\n options: safeOptions\n },\n options: {\n onProgress: this.wrapOnEvent(options?.onEvent, isDeviceLinkingSSEEvent),\n sticky: true\n }\n }).then((res) => res.result)\n .finally(() => { this.device2StartPromise = null; });\n\n this.device2StartPromise = p;\n return p;\n }\n\n async stopDevice2LinkingFlow(): Promise<void> {\n await this.post<void>({ type: 'PM_STOP_DEVICE2_LINKING_FLOW' });\n this.progressBus.clearAll();\n }\n\n // ===== Control APIs =====\n async cancelRequest(requestId: string): Promise<void> {\n // Best-effort cancel. Host will attempt to close open modals and mark the request as cancelled.\n await this.post<void>({ type: 'PM_CANCEL', payload: { requestId } }).catch(() => {});\n // Always clear local progress + hide overlay even if the host didn't receive the message\n this.progressBus.unregister(requestId);\n this.hideFrameForActivation();\n }\n\n async cancelAll(): Promise<void> {\n // Try to cancel all requests on the host, but don't depend on READY/port availability\n await this.post<void>({ type: 'PM_CANCEL', payload: {} }).catch(() => {});\n // Clear all local progress listeners and force-hide the overlay\n this.progressBus.clearAll();\n this.hideFrameForActivation();\n }\n\n private onPortMessage(e: MessageEvent<ChildToParentEnvelope>) {\n const msg = e.data as ChildToParentEnvelope;\n // Some wallet-host messages are push-style and are not correlated to a requestId.\n if (msg.type === 'PREFERENCES_CHANGED') {\n this.emitPreferencesChanged(msg.payload as PreferencesChangedPayload);\n return;\n }\n const requestId = msg.requestId;\n if (!requestId) return;\n\n // Bridge PROGRESS events to caller-provided onEvent callback via pending registry\n if (msg.type === 'PROGRESS') {\n const payload = (msg.payload as ProgressPayload);\n // Route via ProgressBus (handles overlay + sticky delivery)\n this.progressBus.dispatch({ requestId: requestId, payload: payload });\n // Refresh timeout for long-running operations whenever progress is received\n const pend = this.pending.get(requestId);\n if (pend) {\n if (pend.timer) window.clearTimeout(pend.timer);\n pend.timer = window.setTimeout(() => {\n const err = pend.onTimeout();\n pend.reject(err);\n }, this.opts.requestTimeoutMs);\n }\n return;\n }\n\n const pending = this.pending.get(requestId);\n // Hide overlay on completion only if no other requests still need it,\n // and this request wasn't marked sticky (UI-managed lifecycle).\n if (!this.progressBus.isSticky(requestId)) {\n if (!this.progressBus.wantsVisible()) {\n this.hideFrameForActivation();\n }\n }\n if (!pending) {\n // Even if no pending exists (e.g., early cancel or pre-resolved),\n // ensure any lingering progress subscriber is removed.\n if (this.debug) {\n console.debug('[WalletIframeRouter] Non-PROGRESS without pending → hide + unregister', {\n requestId,\n type: (msg as unknown as { type?: unknown })?.type || 'unknown'\n });\n }\n this.progressBus.unregister(requestId);\n return;\n }\n this.pending.delete(requestId);\n if (pending.timer) window.clearTimeout(pending.timer);\n\n if (msg.type === 'ERROR') {\n const err: Error & { code?: string; details?: unknown } = new Error(msg.payload?.message || 'Wallet error');\n err.code = msg.payload?.code;\n err.details = msg.payload?.details;\n // Deliver to pending promise if present\n pending.reject(err);\n // Also notify all progress subscribers for this requestId\n this.progressBus.dispatch({\n requestId: requestId,\n payload: {\n step: 0,\n phase: 'error',\n status: 'error',\n message: msg.payload?.message\n }\n });\n this.progressBus.unregister(requestId);\n return;\n }\n\n pending.resolve(msg.payload);\n if (!this.progressBus.isSticky(requestId)) {\n this.progressBus.unregister(requestId);\n }\n }\n\n /**\n * Post a typed envelope over the MessagePort with robust readiness handling.\n * This is the core method that handles all communication with the iframe.\n *\n * Flow:\n * 1. Ensure iframe is ready (lazy initialization)\n * 2. Generate unique request ID for correlation\n * 3. Set up timeout and progress handling\n * 4. Send message to iframe via MessagePort\n * 5. Wait for response (PM_RESULT or ERROR)\n * 6. Clean up on completion or timeout\n */\n private async post<T>(\n envelope: Omit<ParentToChildEnvelope, 'requestId'>,\n ): Promise<PostResult<T>> {\n\n // Step 1: Lazily initialize the iframe/client if not ready yet\n if (!this.ready || !this.port) {\n await this.init();\n }\n\n // Step 2: Generate unique request ID for correlation\n const requestId = `${Date.now()}-${++this.reqCounter}`;\n const full: ParentToChildEnvelope = { ...(envelope as ParentToChildEnvelope), requestId };\n const { options } = full;\n\n return new Promise<PostResult<T>>((resolve, reject) => {\n const onTimeout = () => {\n const pending = this.pending.get(requestId);\n if (pending?.timer !== undefined) window.clearTimeout(pending.timer);\n this.pending.delete(requestId);\n this.progressBus.unregister(requestId);\n this.overlay.setSticky(false);\n if (!this.progressBus.wantsVisible()) {\n this.hideFrameForActivation();\n }\n this.sendBestEffortCancel(requestId);\n return new Error(`Wallet request timeout for ${envelope.type}`);\n };\n\n // Step 3: Set up timeout handler for request\n const timer = window.setTimeout(() => {\n const err = onTimeout();\n reject(err);\n }, this.opts.requestTimeoutMs);\n\n // Step 4: Register pending request for correlation\n this.pending.set(requestId, {\n resolve: (v) => resolve(v as PostResult<T>),\n reject,\n timer,\n onProgress: options?.onProgress,\n onTimeout,\n });\n\n // Step 5: Register progress handler for real-time updates\n this.progressBus.register({\n requestId: requestId,\n sticky: !!options?.sticky, // Some flows need to persist after completion\n onProgress: (payload: ProgressPayload) => {\n // Bridge progress events from iframe back to parent callback\n try {\n options?.onProgress?.(payload);\n } catch {}\n },\n });\n\n try {\n // Step 6: Strip non-cloneable fields (functions) from envelope options before posting\n const wireOptions = (options && isObject(options))\n ? (() => {\n const stickyVal = (options as { sticky?: unknown }).sticky;\n return isBoolean(stickyVal) ? { sticky: stickyVal } : undefined;\n })()\n : undefined;\n const serializableFull = wireOptions ? { ...full, options: wireOptions } : { ...full, options: undefined };\n\n // Align overlay stickiness with request options (phase 2 will use intents)\n this.overlay.setSticky(!!(wireOptions && (wireOptions as { sticky?: boolean }).sticky));\n\n // Step 7: Apply overlay intent (conservative) if not already visible, then post\n if (!this.overlay.getState().visible) {\n const intent = this.computeOverlayIntent(serializableFull.type);\n if (intent.mode === 'fullscreen') {\n this.overlay.setSticky(!!(wireOptions && (wireOptions as { sticky?: boolean }).sticky));\n this.overlay.showFullscreen();\n }\n }\n\n // Send message to iframe via MessagePort\n this.port!.postMessage(serializableFull as ParentToChildEnvelope);\n } catch (err) {\n // Step 8: Handle send errors - clean up and reject\n this.pending.delete(requestId);\n window.clearTimeout(timer);\n this.progressBus.unregister(requestId);\n reject(toError(err));\n }\n });\n }\n\n /**\n * computeOverlayIntent - Preflight \"Show\" Decision\n *\n * This method makes the initial decision about whether to show the overlay\n * BEFORE sending the request to the iframe. It's a conservative preflight\n * check that ensures the iframe is visible in time for user activation.\n *\n * Key Responsibilities:\n * - Preflight Decision: Determines overlay visibility before request is sent\n * - User Activation Timing: Ensures iframe is visible when WebAuthn prompts appear\n * - Conservative Approach: Only shows overlay if not already visible\n * - Request Type Mapping: Maps message types to overlay requirements\n *\n * How it differs from other components:\n *\n * vs OnEventsProgressBus (lifecycle and close decision):\n * - computeOverlayIntent: \"SHOW\" decision - runs before sending request\n * - OnEventsProgressBus: \"CLOSE\" decision - runs during operation lifecycle\n * - OnEventsProgressBus drives ongoing UI phases and manages sticky behavior\n * - OnEventsProgressBus handles PM_RESULT/ERROR and decides when to hide overlay\n *\n * vs OverlayController (single executor):\n * - computeOverlayIntent: DECIDES what to do (show/hide decision logic)\n * - OverlayController: EXECUTES the decision (actual CSS manipulation)\n * - OverlayController receives commands from both intent and ProgressBus\n * - OverlayController keeps all style mutations in one place\n *\n * Architecture Flow:\n * 1. computeOverlayIntent() → decides to show overlay\n * 2. OverlayController.showFullscreen() → executes the decision\n * 3. Request sent to iframe → operation begins\n * 4. OnEventsProgressBus manages lifecycle → handles progress events\n * 5. OnEventsProgressBus decides to hide → when operation completes\n * 6. OverlayController.hide() → executes the hide decision\n *\n * Special Cases:\n * - Anchored flows (UI registry with viewportRect) are message-driven\n * - Parent sets bounds and sticky via registry messages\n * - computeOverlayIntent returns 'hidden' for these (don't pre-show)\n * - Some legacy paths still call showFrameForActivation() directly\n *\n * Future Evolution:\n * - If host always emits early PROGRESS for a type, this can be reduced\n * - Intent is to move toward OnEventsProgressBus-driven lifecycle management\n * - This provides predictable, glitch-free activation without hardcoding\n */\n private computeOverlayIntent(type: ParentToChildEnvelope['type']): { mode: 'hidden' | 'fullscreen' } {\n switch (type) {\n // Operations that require fullscreen overlay for WebAuthn activation\n case 'PM_EXPORT_NEAR_KEYPAIR_UI':\n case 'PM_REGISTER':\n case 'PM_LOGIN':\n case 'PM_LINK_DEVICE_WITH_SCANNED_QR_DATA':\n case 'PM_SIGN_AND_SEND_TXS':\n case 'PM_EXECUTE_ACTION':\n case 'PM_SEND_TRANSACTION':\n case 'PM_SIGN_TXS_WITH_ACTIONS':\n return { mode: 'fullscreen' };\n\n // All other operations (background/read-only) don't need overlay\n default:\n return { mode: 'hidden' };\n }\n }\n\n // Temporarily show the service iframe to capture user activation\n private showFrameForActivation(): void {\n // Ensure iframe exists so overlay can be applied immediately\n this.transport.ensureIframeMounted();\n if (this.overlayForceFullscreen) {\n this.overlay.showFullscreen();\n } else {\n // Prefer fullscreen by default\n this.overlay.showFullscreen();\n }\n }\n\n private hideFrameForActivation(): void {\n if (!this.overlay.getState().visible) return;\n this.overlay.hide();\n }\n\n private sendBestEffortCancel(targetRequestId?: string): void {\n const port = this.port;\n if (!port) return;\n const cancelEnvelope: ParentToChildEnvelope = {\n type: 'PM_CANCEL',\n requestId: `cancel-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n payload: targetRequestId ? { requestId: targetRequestId } : {}\n };\n port.postMessage(cancelEnvelope);\n }\n\n /**\n * Public toggle to surface the wallet iframe for user activation or hide it.\n * Useful when mounting inline UI components that require direct user clicks.\n */\n setOverlayVisible(visible: boolean): void {\n if (visible) {\n // Respect fullscreen lock when present\n if (this.overlayForceFullscreen) {\n this.overlay.showFullscreen();\n } else {\n this.showFrameForActivation();\n }\n } else {\n this.hideFrameForActivation();\n }\n }\n\n /** Public helper for tests/tools: get the underlying iframe element. */\n getIframeEl(): HTMLIFrameElement | null {\n return this.transport.getIframeEl();\n }\n\n /** Public helper for tests/tools: inspect current overlay state. */\n getOverlayState(): { visible: boolean; mode: 'hidden' | 'fullscreen' | 'anchored'; sticky: boolean; rect?: DOMRectLike } {\n return this.overlay.getState();\n }\n\n /**\n * Position and show the wallet iframe as an anchored overlay matching a DOMRect.\n * Accepts viewport-relative coordinates (from getBoundingClientRect()).\n *\n * Important: Some apps apply CSS transforms (or filters/perspective) on html/body,\n * which changes the containing block for position: fixed. In those cases a fixed\n * iframe will be offset by the page scroll. To avoid that mismatch, anchor the\n * overlay using absolute positioning in document coordinates.\n */\n setOverlayBounds(rect: { top: number; left: number; width: number; height: number }): void {\n if (this.overlayForceFullscreen) return; // ignore anchored bounds while locked to fullscreen\n this.transport.ensureIframeMounted();\n this.overlay.showAnchored(rect as DOMRectLike);\n }\n\n // setAnchoredOverlayBounds/clearAnchoredOverlay removed with Arrow overlay deprecation\n\n // Post a window message and surface errors in debug mode instead of silently swallowing them\n private postWindowMessage(w: Window, data: unknown, target: string): void {\n try {\n w.postMessage(data, target);\n } catch (err) {\n if (this.debug) {\n console.error('[WalletIframeRouter] window.postMessage failed', { error: err, data });\n }\n }\n }\n\n}\n\n// ===== Runtime type guards to safely bridge ProgressPayload → typed SSE events =====\nconst REGISTRATION_PHASES = new Set<string>(Object.values(RegistrationPhase) as string[]);\nconst LOGIN_PHASES = new Set<string>(Object.values(LoginPhase) as string[]);\nconst ACTION_PHASES = new Set<string>(Object.values(ActionPhase) as string[]);\nconst DEVICE_LINKING_PHASES = new Set<string>(Object.values(DeviceLinkingPhase) as string[]);\nconst ACCOUNT_RECOVERY_PHASES = new Set<string>(Object.values(AccountRecoveryPhase) as string[]);\nconst EMAIL_RECOVERY_PHASES = new Set<string>(Object.values(EmailRecoveryPhase) as string[]);\n\nfunction phaseOf(progress: ProgressPayload): string {\n return String((progress as { phase?: unknown })?.phase ?? '');\n}\n\nfunction isRegistrationSSEEvent(progress: ProgressPayload): progress is RegistrationSSEEvent {\n return REGISTRATION_PHASES.has(phaseOf(progress));\n}\n\nfunction isLoginSSEEvent(p: ProgressPayload): p is LoginSSEvent {\n return LOGIN_PHASES.has(phaseOf(p));\n}\n\nfunction isActionSSEEvent(p: ProgressPayload): p is ActionSSEEvent {\n return ACTION_PHASES.has(phaseOf(p));\n}\n\nexport function isDelegateSSEEvent(p: ProgressPayload): p is DelegateActionSSEEvent {\n if (!isActionSSEEvent(p)) return false;\n const data = (p as any).data;\n return !!data && typeof data === 'object' && (data as any).context === 'delegate';\n}\n\nfunction isDeviceLinkingSSEEvent(p: ProgressPayload): p is DeviceLinkingSSEEvent {\n return DEVICE_LINKING_PHASES.has(phaseOf(p));\n}\n\nfunction isAccountRecoverySSEEvent(p: ProgressPayload): p is AccountRecoverySSEEvent {\n return ACCOUNT_RECOVERY_PHASES.has(phaseOf(p));\n}\n\nfunction isEmailRecoverySSEEvent(p: ProgressPayload): p is EmailRecoverySSEEvent {\n return EMAIL_RECOVERY_PHASES.has(phaseOf(p));\n}\n\n/**\n * Strips out class functions as they cannot be sent over postMessage to iframe\n */\n function normalizeSignedTransactionObject(result: SignTransactionResult) {\n const arr = Array.isArray(result) ? result : [];\n const normalized = arr.map(entry => {\n if (entry?.signedTransaction) {\n const st = entry.signedTransaction as unknown;\n if (isPlainSignedTransactionLike(st)) {\n entry.signedTransaction = SignedTransaction.fromPlain({\n transaction: (st as { transaction: unknown }).transaction,\n signature: (st as { signature: unknown }).signature,\n borsh_bytes: extractBorshBytesFromPlainSignedTx(st),\n });\n }\n }\n return entry;\n });\n return normalized\n }\n\n/**\n * Strips out functions as they cannot be sent over postMessage to iframe\n */\nimport { stripFunctionsShallow } from '../validation';\n\nfunction removeFunctionsFromOptions(options?: object): object | undefined {\n return stripFunctionsShallow(options as Record<string, unknown>);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.js","names":["parsedOrigin: URL","OverlayController","err: Error & { code?: string; details?: unknown }","full: ParentToChildEnvelope","cancelEnvelope: ParentToChildEnvelope"],"sources":["../../../../../../../../src/core/WalletIframe/client/router.ts"],"sourcesContent":["/*\n * WalletIframeRouter - Client-Side Communication Layer\n *\n * Owns all iframe overlay show/hide behavior for WebAuthn activation. It is the\n * single place that decides *how* the wallet iframe is displayed (fullscreen vs\n * anchored, sticky mode, force-fullscreen during registration, etc.).\n *\n * Responsibilities:\n * - Request/Response Correlation: Tracks pending requests with unique IDs.\n * - Progress Event Bridging: Receives PROGRESS from the wallet iframe and forwards\n * them to app `onEvent` handlers.\n * - Overlay Ownership:\n * - Delegates *when* to show/hide to OnEventsProgressBus (based on progress events).\n * - Executes *how* to show/hide via OverlayController (DOM / CSS / ARIA).\n * - Also reacts to wallet-host UI messages (e.g., WALLET_UI_CLOSED) and export flows.\n * - Timeout Handling: Manages request timeouts and cleanup.\n * - Message Serialization: Strips non-serializable functions from messages.\n * - Error Handling: Converts iframe errors to parent-appropriate errors.\n *\n * High-level flow:\n *\n * Step legend\n * -----------\n * (1) App calls a router RPC (executeAction, registerPasskey, etc).\n * (2) Router posts request to iframe and tracks a pending entry.\n * (3) Wallet iframe sends PROGRESS messages back to the router.\n * (4) Router forwards ProgressPayloads into OnEventsProgressBus.\n * (5) OnEventsProgressBus decides 'show' | 'hide' and calls router adapters.\n * (6) Router delegates to OverlayController to show|hide the iframe.\n * (7) Router receives final result, resolves the pending promise, unregisters,\n * and may hide the overlay if no other request still needs it.\n *\n * +-----------+ +--------------------+ +----------------------+ +----------------------+\n * | App | | WalletIframeRouter | | OnEventsProgressBus | | OverlayController |\n * +-----+-----+ +---------+----------+ +----------+-----------+ +----------+-----------+\n * | (1) RPC call (executeAction, etc.) | |\n * |---------------------->|---------------------------->| |\n * | | |\n * | (2) post(): send request to iframe |\n * | | |\n * | (3) PROGRESS from iframe via onPortMessage() |\n * |<----------------------------------------------------| |\n * | | |\n * | (4) ProgressPayload → heuristic |\n * | |---(5) 'show'|'hide' intent-->|\n * | | |\n * | (6) showFrameForActivation() | hideFrameForActivation() |\n * | | |\n * | | (6) show()|hide() |\n * | |----------------------------->|\n * | | |\n * | (7) PM_RESULT/ERROR → resolve pending, maybe hide overlay |\n * |<----------------------------------------------------| |\n *\n * Communication Flow (requests):\n * 1. Parent calls RPC method (e.g., registerPasskey).\n * 2. Router creates unique request ID and pending entry.\n * 3. Message sent to iframe via MessagePort.\n * 4. Progress events bridged back to parent callbacks and fed into OnEventsProgressBus.\n * 5. OnEventsProgressBus emits show/hide intents; router invokes OverlayController.\n * 6. Final result resolves the pending promise; router unregisters and may hide overlay.\n */\n\nimport {\n type ParentToChildEnvelope,\n type ChildToParentEnvelope,\n type ProgressPayload,\n type PreferencesChangedPayload,\n} from '../shared/messages';\nimport { SignedTransaction } from '../../NearClient';\nimport { OnEventsProgressBus, defaultPhaseHeuristics } from './on-events-progress-bus';\nimport type {\n ActionSSEEvent,\n ActionHooksOptions,\n AfterCall,\n AccountRecoverySSEEvent,\n DelegateActionSSEEvent,\n DeviceLinkingSSEEvent,\n EmailRecoverySSEEvent,\n LoginSSEvent,\n RegistrationSSEEvent,\n SendTransactionHooksOptions,\n SignAndSendTransactionHooksOptions,\n} from '../../types/sdkSentEvents';\nimport {\n RegistrationPhase,\n LoginPhase,\n ActionPhase,\n DeviceLinkingPhase,\n AccountRecoveryPhase,\n EmailRecoveryPhase,\n} from '../../types/sdkSentEvents';\nimport type {\n ActionResult,\n GetRecentLoginsResult,\n LoginAndCreateSessionResult,\n LoginSession,\n RegistrationResult,\n SignTransactionResult,\n} from '../../types/tatchi';\nimport {\n ActionArgs,\n TransactionInput,\n TxExecutionStatus\n} from '../../types';\nimport type { DelegateActionInput } from '../../types/delegate';\nimport { IframeTransport } from './IframeTransport';\nimport OverlayController, { type DOMRectLike } from './overlay-controller';\nimport { isObject, isPlainSignedTransactionLike, extractBorshBytesFromPlainSignedTx, isBoolean } from '../validation';\nimport type { WalletUIRegistry } from '../host/iframe-lit-element-registry';\nimport { toError } from '../../../utils/errors';\nimport {\n DeviceLinkingQRData,\n LinkDeviceResult,\n StartDevice2LinkingFlowArgs,\n StartDevice2LinkingFlowResults,\n} from '../../types/linkDevice'\nimport type { AuthenticatorOptions } from '../../types/authenticatorOptions';\nimport type { ConfirmationConfig } from '../../types/signer-worker';\nimport type { AccessKeyList } from '../../NearClient';\nimport type { SignNEP413MessageResult } from '../../TatchiPasskey/signNEP413';\nimport type { RecoveryResult } from '../../TatchiPasskey';\nimport { openOfflineExportWindow } from '../../OfflineExport/index.js';\nimport type { DerivedAddressRecord } from '../../IndexedDBManager';\nimport type { EmailRecoveryContracts } from '../../types/tatchi';\n\n// Simple, framework-agnostic service iframe client.\n// Responsibilities split:\n// - IframeTransport: low-level mount + load + CONNECT/READY handshake (MessagePort)\n// - WalletIframeRouter (this): request/response correlation, progress events,\n// overlay display, and high-level wallet RPC helpers\n\nexport interface WalletIframeRouterOptions {\n walletOrigin: string; // e.g., https://wallet.example.com\n servicePath?: string; // default '/wallet-service'\n connectTimeoutMs?: number; // default 8000\n requestTimeoutMs?: number; // default 20000\n theme?: 'dark' | 'light';\n // Enable verbose client-side logging for debugging\n debug?: boolean;\n // Test-only/diagnostic options (not part of the public API contract for apps)\n testOptions?: {\n // Optional identity/ownership tags for the iframe instance (useful for tests/tools)\n routerId?: string;\n ownerTag?: string; // e.g., 'app' | 'tests'\n // Lazy mounting: when false, do not auto-connect/mount during init(); connect on first use\n autoMount?: boolean;\n };\n // Optional config forwarded to wallet host\n nearRpcUrl?: string;\n nearNetwork?: 'testnet' | 'mainnet';\n contractId?: string;\n relayer?: {\n url: string;\n };\n vrfWorkerConfigs?: Record<string, unknown>;\n rpIdOverride?: string;\n authenticatorOptions?: AuthenticatorOptions;\n emailRecoveryContracts?: Partial<EmailRecoveryContracts>;\n // SDK asset base path for embedded bundles when mounting same‑origin via srcdoc\n // Must serve dist/esm under this base path. Defaults to '/sdk'.\n sdkBasePath?: string;\n // Optional: pre-register UI components in wallet host\n uiRegistry?: Record<string, unknown>;\n // Optional: explorer base URL for TxTree links\n nearExplorerUrl?: string;\n}\n\ntype Pending = {\n resolve: (value: unknown) => void;\n reject: (reason?: unknown) => void;\n timer: number | undefined;\n onProgress?: (payload: ProgressPayload) => void;\n onTimeout: () => Error;\n};\n\ntype PostResult<T> = {\n ok: boolean,\n result: T\n}\n\nexport class WalletIframeRouter {\n private opts: Required<WalletIframeRouterOptions>;\n // Low-level transport handling iframe mount + handshake\n private transport: IframeTransport;\n private port: MessagePort | null = null;\n private ready = false;\n // Deduplicate concurrent init() calls and avoid race conditions\n private initInFlight: Promise<void> | null = null;\n private pending = new Map<string, Pending>();\n private reqCounter = 0;\n private readyListeners: Set<() => void> = new Set();\n private vrfStatusListeners: Set<(status: { active: boolean; nearAccountId: string | null; sessionDuration?: number }) => void> = new Set();\n private preferencesChangedListeners: Set<(payload: PreferencesChangedPayload) => void> = new Set();\n // Coalesce duplicate Device2 start calls (e.g., React StrictMode double-effects)\n private device2StartPromise: Promise<{ qrData: DeviceLinkingQRData; qrCodeDataURL: string }> | null = null;\n private progressBus: OnEventsProgressBus;\n private debug = false;\n private readonly walletOriginUrl: URL;\n private readonly walletOriginOrigin: string;\n private overlay: OverlayController;\n // Force the overlay to remain fullscreen during critical flows (e.g., registration)\n // and ignore anchored rect updates from helper hooks.\n private overlayForceFullscreen = false;\n // Overlay register button window-message bridging (wallet-host UI → parent)\n private readonly registerOverlayResultListeners = new Set<(\n payload: { ok: boolean; result?: RegistrationResult; cancelled?: boolean; error?: string }\n ) => void>();\n private readonly registerOverlaySubmitListeners = new Set<() => void>();\n private windowMsgHandlerBound?: (ev: MessageEvent) => void;\n\n constructor(options: WalletIframeRouterOptions) {\n if (!options?.walletOrigin) {\n throw new Error('[WalletIframeRouter] walletOrigin is required when using the wallet iframe');\n }\n\n let parsedOrigin: URL;\n try {\n parsedOrigin = new URL(options.walletOrigin);\n } catch (err) {\n throw new Error(`[WalletIframeRouter] Invalid walletOrigin: ${options.walletOrigin}`);\n }\n\n if (typeof window !== 'undefined') {\n const parentOrigin = window.location.origin;\n if (parsedOrigin.origin === parentOrigin) {\n console.warn('[WalletIframeRouter] walletOrigin matches the host origin. Isolation safeguards rely on the parent; consider moving the wallet to a dedicated origin.');\n }\n }\n\n const defaultRouterId = `w3a-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const testOptions = {\n routerId: defaultRouterId,\n ownerTag: undefined as string | undefined,\n autoMount: true,\n ...(options?.testOptions || {}),\n };\n this.opts = {\n connectTimeoutMs: 8000,\n requestTimeoutMs: 20000,\n servicePath: '/wallet-service',\n sdkBasePath: '/sdk',\n testOptions,\n ...options,\n } as Required<WalletIframeRouterOptions>;\n this.walletOriginUrl = parsedOrigin;\n this.walletOriginOrigin = parsedOrigin.origin;\n this.debug = !!this.opts.debug;\n // Encapsulate iframe mount + handshake logic in transport\n this.transport = new IframeTransport({\n walletOrigin: this.opts.walletOrigin,\n servicePath: this.opts.servicePath,\n connectTimeoutMs: this.opts.connectTimeoutMs,\n testOptions: {\n routerId: this.opts.testOptions.routerId,\n ownerTag: this.opts.testOptions.ownerTag,\n },\n });\n\n // Centralize overlay sizing/visibility. The router is the single owner of\n // \"how\" the iframe is shown/hidden (fullscreen vs anchored, sticky, etc).\n this.overlay = new OverlayController({ ensureIframe: () => this.transport.ensureIframeMounted() });\n\n // Initialize progress router with overlay control and phase heuristics.\n // OnEventsProgressBus only decides *when* to show/hide based on events; it calls\n // these adapter functions, and the router delegates to OverlayController.\n this.progressBus = new OnEventsProgressBus(\n {\n show: () => this.showFrameForActivation(),\n hide: () => this.hideFrameForActivation()\n },\n defaultPhaseHeuristics,\n this.debug\n ? (msg: string, data?: Record<string, unknown>) => {\n console.debug('[WalletIframeRouter][OnEventsProgressBus]', msg, data || {});\n }\n : undefined\n );\n\n // Bridge wallet-host overlay UI messages into router callbacks\n this.windowMsgHandlerBound = (ev: MessageEvent) => {\n if (ev.origin !== this.walletOriginOrigin) return;\n const data = ev.data as unknown;\n if (!data || typeof data !== 'object') return;\n const type = (data as { type?: unknown }).type;\n if (type === 'REGISTER_BUTTON_SUBMIT') {\n // User clicked the register arrow inside the wallet-anchored UI\n // Force the overlay to fullscreen immediately so the TxConfirmer\n // can mount and capture activation in Safari/iOS/mobile.\n this.overlayForceFullscreen = true;\n this.overlay.setSticky(true);\n this.overlay.showFullscreen();\n for (const cb of Array.from(this.registerOverlaySubmitListeners)) {\n try { cb(); } catch {}\n }\n return;\n }\n if (type === 'REGISTER_BUTTON_RESULT') {\n const payload = (data as { payload?: unknown }).payload as\n | { ok?: boolean; result?: RegistrationResult; cancelled?: boolean; error?: string }\n | undefined;\n const ok = !!payload?.ok;\n for (const cb of Array.from(this.registerOverlayResultListeners)) {\n cb({ ok, result: payload?.result, cancelled: payload?.cancelled, error: payload?.error });\n }\n // Release overlay lock after result\n this.overlayForceFullscreen = false;\n this.overlay.setSticky(false);\n // Progress bus will hide after completion; hide defensively here\n this.hideFrameForActivation();\n if (ok) {\n const acct = payload?.result?.nearAccountId;\n void this.getLoginSession(acct)\n .then(({ login: st }) => {\n this.emitVrfStatusChanged({ active: !!st.vrfActive, nearAccountId: st.nearAccountId, sessionDuration: st.vrfSessionDuration });\n })\n .catch(() => {});\n }\n return;\n }\n };\n globalThis.addEventListener?.('message', this.windowMsgHandlerBound);\n }\n\n private attachExportUiClosedListener = (walletOrigin: string): (() => void) => {\n const onUiClosed = (ev: MessageEvent) => {\n if (ev.origin !== walletOrigin) return;\n const data = ev.data as unknown;\n if (!data || (data as any).type !== 'WALLET_UI_CLOSED') return;\n this.overlay.setSticky(false);\n this.hideFrameForActivation();\n globalThis.removeEventListener?.('message', onUiClosed);\n };\n globalThis.addEventListener?.('message', onUiClosed);\n return () => { globalThis.removeEventListener?.('message', onUiClosed) };\n }\n\n private attachExportUiFallbackListener = (walletOrigin: string, accountId: string): (() => void) => {\n const onFallback = async (ev: MessageEvent) => {\n if (ev.origin !== walletOrigin) return;\n const data = ev.data as any;\n if (!data || data.type !== 'OFFLINE_EXPORT_FALLBACK') return;\n globalThis.removeEventListener?.('message', onFallback);\n this.overlay.setSticky(false);\n this.hideFrameForActivation();\n await this.openOfflineExport({ accountId });\n };\n globalThis.addEventListener?.('message', onFallback);\n return () => { globalThis.removeEventListener?.('message', onFallback) };\n }\n\n /**\n * Subscribe to service-ready event. Returns an unsubscribe function.\n * If already ready, the listener is invoked on next microtask.\n */\n onReady(listener: () => void): () => void {\n if (this.ready) {\n Promise.resolve().then(() => { listener(); });\n return () => {};\n }\n this.readyListeners.add(listener);\n return () => { this.readyListeners.delete(listener); };\n }\n\n private emitReady(): void {\n if (!this.readyListeners.size) return;\n for (const cb of Array.from(this.readyListeners)) { cb(); }\n // Keep listeners registered; callers can unsubscribe if desired.\n }\n\n /**\n * Initialize the transport and configure the wallet host.\n * Safe to call multiple times; concurrent calls deduplicate via initInFlight.\n */\n async init(): Promise<void> {\n if (this.ready) return;\n if (this.initInFlight) { return this.initInFlight; }\n this.initInFlight = (async () => {\n // Respect autoMount=false by deferring connect until first use\n if (this.opts.testOptions.autoMount !== false) {\n this.port = await this.transport.connect();\n this.port.onmessage = (ev) => this.onPortMessage(ev);\n this.port.start?.();\n this.ready = true;\n }\n console.debug('[WalletIframeRouter] init: %s', this.ready ? 'connected' : 'deferred (autoMount=false)');\n await this.post({\n type: 'PM_SET_CONFIG',\n payload: {\n theme: this.opts.theme,\n nearRpcUrl: this.opts.nearRpcUrl,\n nearNetwork: this.opts.nearNetwork,\n // Align with PMSetConfigPayload which expects `contractId`\n // while keeping RouterOptions field name `contractId` for external API.\n contractId: this.opts.contractId,\n nearExplorerUrl: this.opts.nearExplorerUrl,\n relayer: this.opts.relayer,\n vrfWorkerConfigs: this.opts.vrfWorkerConfigs,\n rpIdOverride: this.opts.rpIdOverride,\n authenticatorOptions: this.opts.authenticatorOptions,\n emailRecoveryContracts: this.opts.emailRecoveryContracts,\n uiRegistry: this.opts.uiRegistry,\n // for embedded Lit components\n assetsBaseUrl: (() => {\n try {\n const base = new URL(this.opts.sdkBasePath, this.walletOriginUrl).toString();\n return base.endsWith('/') ? base : `${base}/`;\n } catch {\n const fallback = new URL('/sdk/', this.walletOriginUrl).toString();\n return fallback.endsWith('/') ? fallback : `${fallback}/`;\n }\n })(),\n }\n });\n this.emitReady();\n })();\n\n try {\n await this.initInFlight;\n } finally {\n this.initInFlight = null;\n }\n }\n\n isReady(): boolean { return this.ready; }\n\n // ===== UI registry/window-message helpers (generic mounting) =====\n registerUiTypes(registry: WalletUIRegistry): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_REGISTER_TYPES', payload: registry }, target);\n }\n\n mountUiComponent(params: { key: string; props?: Record<string, unknown>; targetSelector?: string; id?: string }): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_MOUNT', payload: params }, target);\n }\n\n updateUiComponent(params: { id: string; props?: Record<string, unknown> }): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_UPDATE', payload: params }, target);\n }\n\n unmountUiComponent(id: string): void {\n const iframe = this.transport.ensureIframeMounted();\n const w = iframe.contentWindow;\n if (!w) return;\n const target = this.walletOriginOrigin;\n this.postWindowMessage(w, { type: 'WALLET_UI_UNMOUNT', payload: { id } }, target);\n }\n\n // ===== Public RPC helpers =====\n\n // Subscribe to VRF status changes observed by this client\n onVrfStatusChanged(listener: (status: {\n active: boolean;\n nearAccountId: string | null;\n sessionDuration?: number\n }) => void): () => void {\n this.vrfStatusListeners.add(listener);\n return () => { this.vrfStatusListeners.delete(listener); };\n }\n\n // Subscribe to wallet-host preference changes (authoritative in wallet-iframe mode).\n onPreferencesChanged(listener: (payload: PreferencesChangedPayload) => void): () => void {\n this.preferencesChangedListeners.add(listener);\n return () => { this.preferencesChangedListeners.delete(listener); };\n }\n\n private emitVrfStatusChanged(status: {\n active: boolean;\n nearAccountId: string | null;\n sessionDuration?: number\n }): void {\n for (const cb of Array.from(this.vrfStatusListeners)) {\n try { cb(status); } catch {}\n }\n }\n\n private emitPreferencesChanged(payload: PreferencesChangedPayload): void {\n if (!this.preferencesChangedListeners.size) return;\n for (const cb of Array.from(this.preferencesChangedListeners)) {\n try { cb(payload); } catch {}\n }\n }\n\n // Overlay register button events (optional convenience API)\n onRegisterOverlayResult(listener: (payload: { ok: boolean; result?: RegistrationResult; cancelled?: boolean; error?: string }) => void): () => void {\n this.registerOverlayResultListeners.add(listener);\n return () => { this.registerOverlayResultListeners.delete(listener); };\n }\n\n onRegisterOverlaySubmit(listener: () => void): () => void {\n this.registerOverlaySubmitListeners.add(listener);\n return () => { this.registerOverlaySubmitListeners.delete(listener); };\n }\n\n // ===== TatchiPasskey RPCs =====\n\n async signTransactionsWithActions(payload: {\n nearAccountId: string;\n transactions: TransactionInput[];\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void;\n onError?: (error: Error) => void;\n afterCall?: AfterCall<SignTransactionResult[]>;\n // Allow minimal overrides (e.g., { uiMode: 'drawer' })\n confirmationConfig?: Partial<ConfirmationConfig>;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<SignTransactionResult[]> {\n // Do not forward non-cloneable functions in options; host emits its own PROGRESS messages\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n }\n : undefined;\n const res = await this.post<SignTransactionResult>({\n type: 'PM_SIGN_TXS_WITH_ACTIONS',\n payload: {\n nearAccountId: payload.nearAccountId,\n transactions: payload.transactions,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isActionSSEEvent) }\n });\n return normalizeSignedTransactionObject(res.result)\n }\n\n async signDelegateAction(payload: {\n nearAccountId: string;\n delegate: DelegateActionInput;\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void;\n onError?: (error: Error) => void;\n afterCall?: AfterCall<any>;\n confirmationConfig?: Partial<ConfirmationConfig>;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<unknown> {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n }\n : undefined;\n const res = await this.post<unknown>({\n type: 'PM_SIGN_DELEGATE_ACTION',\n payload: {\n nearAccountId: payload.nearAccountId,\n delegate: payload.delegate,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async registerPasskey(payload: {\n nearAccountId: string;\n confirmationConfig?: Partial<ConfirmationConfig>;\n options?: {\n onEvent?: (ev: RegistrationSSEEvent) => void;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<RegistrationResult> {\n // Step 1: For registration, force fullscreen overlay (not anchored to CTA)\n // so the TxConfirmer (drawer/modal) has space to render and capture activation.\n // Lock overlay to fullscreen for the duration of registration\n this.overlayForceFullscreen = true;\n this.overlay.setSticky(true);\n this.overlay.showFullscreen();\n\n try {\n // Optional one-time confirmation override (non-persistent)\n if (payload.confirmationConfig) {\n const base = await this.getConfirmationConfig();\n await this.setConfirmationConfig({ ...base, ...payload.confirmationConfig });\n }\n\n // Step 2: Strip non-serializable functions from options (functions can't cross iframe boundary)\n const safeOptions = removeFunctionsFromOptions(payload.options);\n\n // Step 3: Send PM_REGISTER message to iframe and wait for response\n const res = await this.post<RegistrationResult>({\n type: 'PM_REGISTER',\n payload: {\n nearAccountId: payload.nearAccountId,\n options: safeOptions,\n ...(payload.confirmationConfig ? { confirmationConfig: payload.confirmationConfig as unknown as Record<string, unknown> } : {})\n },\n // Bridge progress events from iframe back to parent callback\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isRegistrationSSEEvent) }\n });\n\n // Step 4: Update VRF status after successful registration\n const { login: st } = await this.getLoginSession(payload.nearAccountId);\n this.emitVrfStatusChanged({\n active: !!st.vrfActive,\n nearAccountId: st.nearAccountId,\n sessionDuration: st.vrfSessionDuration\n });\n\n return res?.result;\n } finally {\n // Step 5: Always release overlay lock and hide when done (success or error)\n this.overlayForceFullscreen = false;\n this.overlay.setSticky(false);\n this.hideFrameForActivation();\n }\n }\n\n async loginAndCreateSession(payload: {\n nearAccountId: string;\n options?: {\n onEvent?: (ev: LoginSSEvent) => void;\n // Forward session config so host can mint JWT/cookie\n session?: {\n kind: 'jwt' | 'cookie';\n relayUrl?: string;\n route?: string;\n };\n // Warm signing session policy override during login\n signingSession?: {\n ttlMs?: number;\n remainingUses?: number;\n };\n }\n }): Promise<LoginAndCreateSessionResult> {\n this.showFrameForActivation();\n try {\n const safeOptions = removeFunctionsFromOptions(payload.options);\n const res = await this.post<LoginAndCreateSessionResult>({\n type: 'PM_LOGIN',\n payload: {\n nearAccountId: payload.nearAccountId,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isLoginSSEEvent) }\n });\n const { login: st } = await this.getLoginSession(payload.nearAccountId);\n this.emitVrfStatusChanged({ active: !!st.vrfActive, nearAccountId: st.nearAccountId, sessionDuration: st.vrfSessionDuration });\n return res?.result;\n } finally {\n this.hideFrameForActivation();\n }\n }\n\n async getLoginSession(nearAccountId?: string): Promise<LoginSession> {\n const res = await this.post<LoginSession>({\n type: 'PM_GET_LOGIN_SESSION',\n payload: nearAccountId ? { nearAccountId } : undefined\n });\n return res.result;\n }\n\n async checkVrfStatus(): Promise<PostResult<{ active: boolean; nearAccountId: string | null; sessionDuration?: number }>> {\n const { login: st } = await this.getLoginSession();\n return {\n ok: true,\n result: {\n active: !!st.vrfActive,\n nearAccountId: st.nearAccountId,\n sessionDuration: st.vrfSessionDuration\n }\n };\n }\n\n async clearVrfSession(): Promise<PostResult<void>> {\n await this.post<void>({ type: 'PM_LOGOUT' });\n this.emitVrfStatusChanged({ active: false, nearAccountId: null });\n return { ok: true, result: undefined };\n }\n\n async signNep413Message(payload: {\n nearAccountId: string;\n message: string;\n recipient: string;\n state?: string;\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void;\n confirmerText?: { title?: string; body?: string };\n confirmationConfig?: Partial<ConfirmationConfig>;\n }\n }): Promise<SignNEP413MessageResult> {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n }\n : undefined;\n const res = await this.post<SignNEP413MessageResult>({\n type: 'PM_SIGN_NEP413',\n payload: {\n nearAccountId: payload.nearAccountId,\n params: {\n message: payload.message,\n recipient: payload.recipient,\n state: payload.state\n },\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: { onProgress: this.wrapOnEvent(payload.options?.onEvent, isActionSSEEvent) }\n });\n return res.result\n }\n\n async signTransactionWithKeyPair(payload: {\n signedTransaction: SignedTransaction;\n options?: {\n onEvent?: (ev: ActionSSEEvent) => void\n }\n }): Promise<ActionResult> {\n // Strip non-cloneable functions from options; host emits PROGRESS events\n const { options } = payload;\n const res = await this.post<ActionResult>( {\n type: 'PM_SEND_TRANSACTION',\n payload: {\n signedTransaction: payload.signedTransaction,\n options: options\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async executeAction(payload: {\n nearAccountId: string;\n receiverId: string;\n actionArgs: ActionArgs | ActionArgs[];\n options?: ActionHooksOptions\n }): Promise<ActionResult> {\n // Strip non-cloneable functions from options; host emits PROGRESS events\n const { options } = payload;\n const safeOptions = options\n ? {\n waitUntil: options.waitUntil,\n confirmationConfig: options.confirmationConfig,\n ...(options.confirmerText ? { confirmerText: options.confirmerText } : {}),\n }\n : undefined;\n\n const res = await this.post<ActionResult>({\n type: 'PM_EXECUTE_ACTION',\n payload: {\n ...payload,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async setConfirmBehavior(behavior: 'requireClick' | 'autoProceed'): Promise<void> {\n let { nearAccountId } = (await this.getLoginSession()).login;\n await this.post<void>({\n type: 'PM_SET_CONFIRM_BEHAVIOR',\n payload: { behavior, nearAccountId }\n });\n }\n\n async setConfirmationConfig(config: ConfirmationConfig): Promise<void> {\n let { nearAccountId } = (await this.getLoginSession()).login;\n await this.post<void>({\n type: 'PM_SET_CONFIRMATION_CONFIG',\n payload: { config, nearAccountId }\n });\n }\n\n async getConfirmationConfig(): Promise<ConfirmationConfig> {\n const res = await this.post<ConfirmationConfig>({ type: 'PM_GET_CONFIRMATION_CONFIG' });\n return res.result\n }\n\n async setTheme(theme: 'dark' | 'light'): Promise<void> {\n await this.post<void>({ type: 'PM_SET_THEME', payload: { theme } });\n }\n\n async prefetchBlockheight(): Promise<void> {\n await this.post<void>({ type: 'PM_PREFETCH_BLOCKHEIGHT' } );\n }\n\n async getRecentLogins(): Promise<GetRecentLoginsResult> {\n const res = await this.post<GetRecentLoginsResult>({ type: 'PM_GET_RECENT_LOGINS' } );\n return res.result;\n }\n\n // === Local persistence helpers (wallet-origin IndexedDB) ===\n\n async setDerivedAddress(payload: {\n nearAccountId: string;\n args: { contractId: string; path: string; address: string };\n }): Promise<void> {\n await this.post<void>({\n type: 'PM_SET_DERIVED_ADDRESS',\n payload,\n });\n }\n\n async getDerivedAddressRecord(payload: {\n nearAccountId: string;\n args: { contractId: string; path: string };\n }): Promise<DerivedAddressRecord | null> {\n const res = await this.post<DerivedAddressRecord | null>({\n type: 'PM_GET_DERIVED_ADDRESS_RECORD',\n payload,\n });\n return (res.result as DerivedAddressRecord | null) || null;\n }\n\n async getDerivedAddress(payload: {\n nearAccountId: string;\n args: { contractId: string; path: string };\n }): Promise<string | null> {\n const res = await this.post<string | null>({\n type: 'PM_GET_DERIVED_ADDRESS',\n payload,\n });\n return (res.result as string | null) || null;\n }\n\n async getRecoveryEmails(\n nearAccountId: string,\n ): Promise<Array<{ hashHex: string; email: string }>> {\n const res = await this.post<Array<{ hashHex: string; email: string }>>({\n type: 'PM_GET_RECOVERY_EMAILS',\n payload: { nearAccountId },\n });\n return (res.result as Array<{ hashHex: string; email: string }>) || [];\n }\n\n async setRecoveryEmails(payload: {\n nearAccountId: string;\n recoveryEmails: string[];\n options?: ActionHooksOptions;\n }): Promise<ActionResult> {\n const { options } = payload;\n const safeOptions = options\n ? {\n waitUntil: options.waitUntil,\n confirmationConfig: options.confirmationConfig,\n }\n : undefined;\n\n const res = await this.post<ActionResult>({\n type: 'PM_SET_RECOVERY_EMAILS',\n payload: {\n nearAccountId: payload.nearAccountId,\n recoveryEmails: payload.recoveryEmails,\n options: safeOptions,\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) },\n });\n return res.result;\n }\n\n // Bridge typed public onEvent callbacks to the transport's onProgress callback.\n // - onEvent: consumer's strongly-typed event handler (e.g., ActionSSEEvent)\n // - isExpectedEvent: runtime type guard that validates a ProgressPayload as that event type\n // Returns an onProgress handler that safely narrows before invoking onEvent.\n private wrapOnEvent<TEvent extends ProgressPayload>(\n onEvent: ((event: TEvent) => void) | undefined,\n isExpectedEvent: (progress: ProgressPayload) => progress is TEvent\n ): ((progress: ProgressPayload) => void) | undefined {\n if (!onEvent) return undefined;\n return (progress: ProgressPayload) => {\n try {\n if (isExpectedEvent(progress)) onEvent(progress);\n } catch {}\n };\n }\n\n async signAndSendTransactions(payload: {\n nearAccountId: string;\n transactions: TransactionInput[];\n options?: SignAndSendTransactionHooksOptions\n }): Promise<ActionResult[]> {\n\n const { options } = payload;\n // cannot send objects/functions through postMessage(), clean options first\n const safeOptions = options\n ? {\n waitUntil: options.waitUntil,\n executionWait: options.executionWait,\n confirmationConfig: options.confirmationConfig,\n ...(options.confirmerText ? { confirmerText: options.confirmerText } : {}),\n }\n : undefined;\n\n const res = await this.post<ActionResult[]>({\n type: 'PM_SIGN_AND_SEND_TXS',\n payload: {\n nearAccountId: payload.nearAccountId,\n transactions: payload.transactions,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result;\n }\n\n async hasPasskeyCredential(nearAccountId: string): Promise<boolean> {\n const res = await this.post<boolean>({\n type: 'PM_HAS_PASSKEY',\n payload: { nearAccountId }\n });\n return !!res?.result;\n }\n\n async viewAccessKeyList(accountId: string): Promise<AccessKeyList> {\n const res = await this.post<AccessKeyList>({\n type: 'PM_VIEW_ACCESS_KEYS',\n payload: { accountId }\n });\n return res.result\n }\n\n async deleteDeviceKey(\n accountId: string,\n publicKeyToDelete: string,\n options?: { onEvent?: (ev: ActionSSEEvent) => void }\n ) : Promise<ActionResult> {\n const res = await this.post<ActionResult>({\n type: 'PM_DELETE_DEVICE_KEY',\n payload: {\n accountId,\n publicKeyToDelete\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result\n }\n\n async sendTransaction(args: {\n signedTransaction: SignedTransaction;\n options?: SendTransactionHooksOptions;\n }): Promise<ActionResult> {\n // Strip non-cloneable functions from options; host emits PROGRESS events\n const { options } = args;\n const safeOptions = options\n ? { waitUntil: options.waitUntil }\n : undefined;\n\n const res = await this.post<ActionResult>({\n type: 'PM_SEND_TRANSACTION',\n payload: {\n signedTransaction: args.signedTransaction,\n options: safeOptions\n },\n options: { onProgress: this.wrapOnEvent(options?.onEvent, isActionSSEEvent) }\n });\n return res.result\n }\n\n async exportNearKeypairWithUI(\n nearAccountId: string,\n options?: { variant?: 'drawer' | 'modal'; theme?: 'dark' | 'light' }\n ): Promise<void> {\n try {\n // Make the wallet iframe visible while the export viewer is open.\n // Unlike request/response flows, the wallet host renders UI and manages\n // its own lifecycle; it will notify us when to hide via window message.\n this.showFrameForActivation();\n const walletOrigin = this.walletOriginOrigin;\n const detachClosed = this.attachExportUiClosedListener(walletOrigin);\n const detachFallback = this.attachExportUiFallbackListener(walletOrigin, nearAccountId);\n await this.post<void>({\n type: 'PM_EXPORT_NEAR_KEYPAIR_UI',\n payload: { nearAccountId, variant: options?.variant, theme: options?.theme },\n options: { sticky: true }\n });\n // Cleanup once posted (handlers will remove themselves on events)\n void detachClosed;\n void detachFallback;\n return;\n } catch (e) {\n // Fallback to offline-export route (new tab) if wallet host is unreachable or errors out\n await this.openOfflineExport({ accountId: nearAccountId });\n }\n }\n\n /**\n * Open the offline-export route as a full-screen overlay iframe and instruct it via postMessage\n * to begin the export flow for the given account. Cleans up when the viewer closes or on error.\n */\n async openOfflineExport({ accountId, timeoutMs = 20000 }: { accountId: string; timeoutMs?: number }): Promise<void> {\n const walletOrigin = this.opts.walletOrigin || window.location.origin;\n // Default: open a new tab/window for clarity\n openOfflineExportWindow({ walletOrigin, target: '_blank', accountId });\n return Promise.resolve();\n }\n\n // ===== Account Recovery (single-endpoint flow) =====\n async recoverAccountFlow(payload: {\n accountId?: string;\n onEvent?: (ev: AccountRecoverySSEEvent) => void\n }): Promise<RecoveryResult> {\n const res = await this.post<RecoveryResult>({\n type: 'PM_RECOVER_ACCOUNT_FLOW',\n payload: { accountId: payload.accountId },\n options: {\n onProgress: this.wrapOnEvent(payload.onEvent, isAccountRecoverySSEEvent)\n }\n });\n return res.result\n }\n\n // ===== Email Recovery (wallet-hosted) =====\n async startEmailRecovery(payload: {\n accountId: string;\n recoveryEmail?: string;\n onEvent?: (ev: EmailRecoverySSEEvent) => void;\n options?: {\n confirmerText?: { title?: string; body?: string };\n confirmationConfig?: Partial<ConfirmationConfig>;\n }\n }): Promise<{ mailtoUrl: string; nearPublicKey: string }> {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n }\n : undefined;\n const res = await this.post<{ mailtoUrl: string; nearPublicKey: string }>({\n type: 'PM_START_EMAIL_RECOVERY',\n payload: {\n accountId: payload.accountId,\n ...(payload.recoveryEmail ? { recoveryEmail: payload.recoveryEmail } : {}),\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: {\n onProgress: this.wrapOnEvent(payload.onEvent, isEmailRecoverySSEEvent)\n }\n });\n return res.result;\n }\n\n async finalizeEmailRecovery(payload: {\n accountId: string;\n nearPublicKey?: string;\n onEvent?: (ev: EmailRecoverySSEEvent) => void\n }): Promise<void> {\n await this.post<void>({\n type: 'PM_FINALIZE_EMAIL_RECOVERY',\n payload: { accountId: payload.accountId, nearPublicKey: payload.nearPublicKey },\n options: {\n onProgress: this.wrapOnEvent(payload.onEvent, isEmailRecoverySSEEvent)\n }\n });\n }\n\n async stopEmailRecovery(payload?: { accountId?: string; nearPublicKey?: string }): Promise<void> {\n await this.post<void>({\n type: 'PM_STOP_EMAIL_RECOVERY',\n payload: { accountId: payload?.accountId, nearPublicKey: payload?.nearPublicKey },\n });\n }\n\n // ===== Device Linking (iframe-hosted) =====\n async linkDeviceWithScannedQRData(payload: {\n qrData: DeviceLinkingQRData;\n fundingAmount: string;\n options?: {\n onEvent?: (ev: DeviceLinkingSSEEvent) => void;\n confirmationConfig?: Partial<ConfirmationConfig>;\n confirmerText?: { title?: string; body?: string };\n }\n }): Promise<LinkDeviceResult> {\n // TouchID required within host\n this.showFrameForActivation();\n try {\n const safeOptions = payload.options\n ? {\n ...(payload.options.confirmationConfig\n ? { confirmationConfig: payload.options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(payload.options.confirmerText ? { confirmerText: payload.options.confirmerText } : {}),\n }\n : undefined;\n const res = await this.post<LinkDeviceResult>({\n type: 'PM_LINK_DEVICE_WITH_SCANNED_QR_DATA',\n payload: {\n qrData: payload.qrData,\n fundingAmount: payload.fundingAmount,\n options: safeOptions && Object.keys(safeOptions).length > 0 ? safeOptions : undefined\n },\n options: {\n onProgress: this.wrapOnEvent(payload.options?.onEvent, isDeviceLinkingSSEEvent)\n }\n });\n return res.result\n } finally {\n this.hideFrameForActivation();\n }\n }\n\n async startDevice2LinkingFlow(payload?: StartDevice2LinkingFlowArgs): Promise<StartDevice2LinkingFlowResults> {\n if (this.device2StartPromise) {\n return this.device2StartPromise\n }\n const options = payload?.options;\n const safeOptions = options\n ? {\n ...(options.confirmationConfig\n ? { confirmationConfig: options.confirmationConfig as unknown as Record<string, unknown> }\n : {}),\n ...(options.confirmerText ? { confirmerText: options.confirmerText } : {}),\n }\n : undefined;\n const p = this.post<StartDevice2LinkingFlowResults>({\n type: 'PM_START_DEVICE2_LINKING_FLOW',\n payload: {\n ui: payload?.ui,\n cameraId: payload?.cameraId,\n options: safeOptions\n },\n options: {\n onProgress: this.wrapOnEvent(options?.onEvent, isDeviceLinkingSSEEvent),\n sticky: true\n }\n }).then((res) => res.result)\n .finally(() => { this.device2StartPromise = null; });\n\n this.device2StartPromise = p;\n return p;\n }\n\n async stopDevice2LinkingFlow(): Promise<void> {\n await this.post<void>({ type: 'PM_STOP_DEVICE2_LINKING_FLOW' });\n this.progressBus.clearAll();\n }\n\n // ===== Control APIs =====\n async cancelRequest(requestId: string): Promise<void> {\n // Best-effort cancel. Host will attempt to close open modals and mark the request as cancelled.\n await this.post<void>({ type: 'PM_CANCEL', payload: { requestId } }).catch(() => {});\n // Always clear local progress + hide overlay even if the host didn't receive the message\n this.progressBus.unregister(requestId);\n this.hideFrameForActivation();\n }\n\n async cancelAll(): Promise<void> {\n // Try to cancel all requests on the host, but don't depend on READY/port availability\n await this.post<void>({ type: 'PM_CANCEL', payload: {} }).catch(() => {});\n // Clear all local progress listeners and force-hide the overlay\n this.progressBus.clearAll();\n this.hideFrameForActivation();\n }\n\n private onPortMessage(e: MessageEvent<ChildToParentEnvelope>) {\n const msg = e.data as ChildToParentEnvelope;\n // Some wallet-host messages are push-style and are not correlated to a requestId.\n if (msg.type === 'PREFERENCES_CHANGED') {\n this.emitPreferencesChanged(msg.payload as PreferencesChangedPayload);\n return;\n }\n const requestId = msg.requestId;\n if (!requestId) return;\n\n // Bridge PROGRESS events to caller-provided onEvent callback via pending registry\n if (msg.type === 'PROGRESS') {\n const payload = (msg.payload as ProgressPayload);\n // Route via ProgressBus (handles overlay + sticky delivery)\n this.progressBus.dispatch({ requestId: requestId, payload: payload });\n // Refresh timeout for long-running operations whenever progress is received\n const pend = this.pending.get(requestId);\n if (pend) {\n if (pend.timer) window.clearTimeout(pend.timer);\n pend.timer = window.setTimeout(() => {\n const err = pend.onTimeout();\n pend.reject(err);\n }, this.opts.requestTimeoutMs);\n }\n return;\n }\n\n const pending = this.pending.get(requestId);\n // Hide overlay on completion only if no other requests still need it,\n // and this request wasn't marked sticky (UI-managed lifecycle).\n if (!this.progressBus.isSticky(requestId)) {\n if (!this.progressBus.wantsVisible()) {\n this.hideFrameForActivation();\n }\n }\n if (!pending) {\n // Even if no pending exists (e.g., early cancel or pre-resolved),\n // ensure any lingering progress subscriber is removed.\n if (this.debug) {\n console.debug('[WalletIframeRouter] Non-PROGRESS without pending → hide + unregister', {\n requestId,\n type: (msg as unknown as { type?: unknown })?.type || 'unknown'\n });\n }\n this.progressBus.unregister(requestId);\n return;\n }\n this.pending.delete(requestId);\n if (pending.timer) window.clearTimeout(pending.timer);\n\n if (msg.type === 'ERROR') {\n const err: Error & { code?: string; details?: unknown } = new Error(msg.payload?.message || 'Wallet error');\n err.code = msg.payload?.code;\n err.details = msg.payload?.details;\n // Deliver to pending promise if present\n pending.reject(err);\n // Also notify all progress subscribers for this requestId\n this.progressBus.dispatch({\n requestId: requestId,\n payload: {\n step: 0,\n phase: 'error',\n status: 'error',\n message: msg.payload?.message\n }\n });\n this.progressBus.unregister(requestId);\n return;\n }\n\n pending.resolve(msg.payload);\n if (!this.progressBus.isSticky(requestId)) {\n this.progressBus.unregister(requestId);\n }\n }\n\n /**\n * Post a typed envelope over the MessagePort with robust readiness handling.\n * This is the core method that handles all communication with the iframe.\n *\n * Flow:\n * 1. Ensure iframe is ready (lazy initialization)\n * 2. Generate unique request ID for correlation\n * 3. Set up timeout and progress handling\n * 4. Send message to iframe via MessagePort\n * 5. Wait for response (PM_RESULT or ERROR)\n * 6. Clean up on completion or timeout\n */\n private async post<T>(\n envelope: Omit<ParentToChildEnvelope, 'requestId'>,\n ): Promise<PostResult<T>> {\n\n // Step 1: Lazily initialize the iframe/client if not ready yet\n if (!this.ready || !this.port) {\n await this.init();\n }\n\n // Step 2: Generate unique request ID for correlation\n const requestId = `${Date.now()}-${++this.reqCounter}`;\n const full: ParentToChildEnvelope = { ...(envelope as ParentToChildEnvelope), requestId };\n const { options } = full;\n\n return new Promise<PostResult<T>>((resolve, reject) => {\n const onTimeout = () => {\n const pending = this.pending.get(requestId);\n if (pending?.timer !== undefined) window.clearTimeout(pending.timer);\n this.pending.delete(requestId);\n this.progressBus.unregister(requestId);\n this.overlay.setSticky(false);\n if (!this.progressBus.wantsVisible()) {\n this.hideFrameForActivation();\n }\n this.sendBestEffortCancel(requestId);\n return new Error(`Wallet request timeout for ${envelope.type}`);\n };\n\n // Step 3: Set up timeout handler for request\n const timer = window.setTimeout(() => {\n const err = onTimeout();\n reject(err);\n }, this.opts.requestTimeoutMs);\n\n // Step 4: Register pending request for correlation\n this.pending.set(requestId, {\n resolve: (v) => resolve(v as PostResult<T>),\n reject,\n timer,\n onProgress: options?.onProgress,\n onTimeout,\n });\n\n // Step 5: Register progress handler for real-time updates\n this.progressBus.register({\n requestId: requestId,\n sticky: !!options?.sticky, // Some flows need to persist after completion\n onProgress: (payload: ProgressPayload) => {\n // Bridge progress events from iframe back to parent callback\n try {\n options?.onProgress?.(payload);\n } catch {}\n },\n });\n\n try {\n // Step 6: Strip non-cloneable fields (functions) from envelope options before posting\n const wireOptions = (options && isObject(options))\n ? (() => {\n const stickyVal = (options as { sticky?: unknown }).sticky;\n return isBoolean(stickyVal) ? { sticky: stickyVal } : undefined;\n })()\n : undefined;\n const serializableFull = wireOptions ? { ...full, options: wireOptions } : { ...full, options: undefined };\n\n // Align overlay stickiness with request options (phase 2 will use intents)\n this.overlay.setSticky(!!(wireOptions && (wireOptions as { sticky?: boolean }).sticky));\n\n // Step 7: Apply overlay intent (conservative) if not already visible, then post\n if (!this.overlay.getState().visible) {\n const intent = this.computeOverlayIntent(serializableFull.type);\n if (intent.mode === 'fullscreen') {\n this.overlay.setSticky(!!(wireOptions && (wireOptions as { sticky?: boolean }).sticky));\n this.overlay.showFullscreen();\n }\n }\n\n // Send message to iframe via MessagePort\n this.port!.postMessage(serializableFull as ParentToChildEnvelope);\n } catch (err) {\n // Step 8: Handle send errors - clean up and reject\n this.pending.delete(requestId);\n window.clearTimeout(timer);\n this.progressBus.unregister(requestId);\n reject(toError(err));\n }\n });\n }\n\n /**\n * computeOverlayIntent - Preflight \"Show\" Decision\n *\n * This method makes the initial decision about whether to show the overlay\n * BEFORE sending the request to the iframe. It's a conservative preflight\n * check that ensures the iframe is visible in time for user activation.\n *\n * Key Responsibilities:\n * - Preflight Decision: Determines overlay visibility before request is sent\n * - User Activation Timing: Ensures iframe is visible when WebAuthn prompts appear\n * - Conservative Approach: Only shows overlay if not already visible\n * - Request Type Mapping: Maps message types to overlay requirements\n *\n * How it differs from other components:\n *\n * vs OnEventsProgressBus (lifecycle and close decision):\n * - computeOverlayIntent: \"SHOW\" decision - runs before sending request\n * - OnEventsProgressBus: \"CLOSE\" decision - runs during operation lifecycle\n * - OnEventsProgressBus drives ongoing UI phases and manages sticky behavior\n * - OnEventsProgressBus handles PM_RESULT/ERROR and decides when to hide overlay\n *\n * vs OverlayController (single executor):\n * - computeOverlayIntent: DECIDES what to do (show/hide decision logic)\n * - OverlayController: EXECUTES the decision (actual CSS manipulation)\n * - OverlayController receives commands from both intent and ProgressBus\n * - OverlayController keeps all style mutations in one place\n *\n * Architecture Flow:\n * 1. computeOverlayIntent() → decides to show overlay\n * 2. OverlayController.showFullscreen() → executes the decision\n * 3. Request sent to iframe → operation begins\n * 4. OnEventsProgressBus manages lifecycle → handles progress events\n * 5. OnEventsProgressBus decides to hide → when operation completes\n * 6. OverlayController.hide() → executes the hide decision\n *\n * Special Cases:\n * - Anchored flows (UI registry with viewportRect) are message-driven\n * - Parent sets bounds and sticky via registry messages\n * - computeOverlayIntent returns 'hidden' for these (don't pre-show)\n * - Some legacy paths still call showFrameForActivation() directly\n *\n * Future Evolution:\n * - If host always emits early PROGRESS for a type, this can be reduced\n * - Intent is to move toward OnEventsProgressBus-driven lifecycle management\n * - This provides predictable, glitch-free activation without hardcoding\n */\n private computeOverlayIntent(type: ParentToChildEnvelope['type']): { mode: 'hidden' | 'fullscreen' } {\n switch (type) {\n // Operations that require fullscreen overlay for WebAuthn activation\n case 'PM_EXPORT_NEAR_KEYPAIR_UI':\n case 'PM_REGISTER':\n case 'PM_LOGIN':\n case 'PM_LINK_DEVICE_WITH_SCANNED_QR_DATA':\n case 'PM_SIGN_AND_SEND_TXS':\n case 'PM_EXECUTE_ACTION':\n case 'PM_SEND_TRANSACTION':\n case 'PM_SIGN_TXS_WITH_ACTIONS':\n return { mode: 'fullscreen' };\n\n // All other operations (background/read-only) don't need overlay\n default:\n return { mode: 'hidden' };\n }\n }\n\n // Temporarily show the service iframe to capture user activation\n private showFrameForActivation(): void {\n // Ensure iframe exists so overlay can be applied immediately\n this.transport.ensureIframeMounted();\n if (this.overlayForceFullscreen) {\n this.overlay.showFullscreen();\n } else {\n // Prefer fullscreen by default\n this.overlay.showFullscreen();\n }\n }\n\n private hideFrameForActivation(): void {\n if (!this.overlay.getState().visible) return;\n this.overlay.hide();\n }\n\n private sendBestEffortCancel(targetRequestId?: string): void {\n const port = this.port;\n if (!port) return;\n const cancelEnvelope: ParentToChildEnvelope = {\n type: 'PM_CANCEL',\n requestId: `cancel-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n payload: targetRequestId ? { requestId: targetRequestId } : {}\n };\n port.postMessage(cancelEnvelope);\n }\n\n /**\n * Public toggle to surface the wallet iframe for user activation or hide it.\n * Useful when mounting inline UI components that require direct user clicks.\n */\n setOverlayVisible(visible: boolean): void {\n if (visible) {\n // Respect fullscreen lock when present\n if (this.overlayForceFullscreen) {\n this.overlay.showFullscreen();\n } else {\n this.showFrameForActivation();\n }\n } else {\n this.hideFrameForActivation();\n }\n }\n\n /** Public helper for tests/tools: get the underlying iframe element. */\n getIframeEl(): HTMLIFrameElement | null {\n return this.transport.getIframeEl();\n }\n\n /** Public helper for tests/tools: inspect current overlay state. */\n getOverlayState(): { visible: boolean; mode: 'hidden' | 'fullscreen' | 'anchored'; sticky: boolean; rect?: DOMRectLike } {\n return this.overlay.getState();\n }\n\n /**\n * Position and show the wallet iframe as an anchored overlay matching a DOMRect.\n * Accepts viewport-relative coordinates (from getBoundingClientRect()).\n *\n * Important: Some apps apply CSS transforms (or filters/perspective) on html/body,\n * which changes the containing block for position: fixed. In those cases a fixed\n * iframe will be offset by the page scroll. To avoid that mismatch, anchor the\n * overlay using absolute positioning in document coordinates.\n */\n setOverlayBounds(rect: { top: number; left: number; width: number; height: number }): void {\n if (this.overlayForceFullscreen) return; // ignore anchored bounds while locked to fullscreen\n this.transport.ensureIframeMounted();\n this.overlay.showAnchored(rect as DOMRectLike);\n }\n\n // setAnchoredOverlayBounds/clearAnchoredOverlay removed with Arrow overlay deprecation\n\n // Post a window message and surface errors in debug mode instead of silently swallowing them\n private postWindowMessage(w: Window, data: unknown, target: string): void {\n try {\n w.postMessage(data, target);\n } catch (err) {\n if (this.debug) {\n console.error('[WalletIframeRouter] window.postMessage failed', { error: err, data });\n }\n }\n }\n\n}\n\n// ===== Runtime type guards to safely bridge ProgressPayload → typed SSE events =====\nconst REGISTRATION_PHASES = new Set<string>(Object.values(RegistrationPhase) as string[]);\nconst LOGIN_PHASES = new Set<string>(Object.values(LoginPhase) as string[]);\nconst ACTION_PHASES = new Set<string>(Object.values(ActionPhase) as string[]);\nconst DEVICE_LINKING_PHASES = new Set<string>(Object.values(DeviceLinkingPhase) as string[]);\nconst ACCOUNT_RECOVERY_PHASES = new Set<string>(Object.values(AccountRecoveryPhase) as string[]);\nconst EMAIL_RECOVERY_PHASES = new Set<string>(Object.values(EmailRecoveryPhase) as string[]);\n\nfunction phaseOf(progress: ProgressPayload): string {\n return String((progress as { phase?: unknown })?.phase ?? '');\n}\n\nfunction isRegistrationSSEEvent(progress: ProgressPayload): progress is RegistrationSSEEvent {\n return REGISTRATION_PHASES.has(phaseOf(progress));\n}\n\nfunction isLoginSSEEvent(p: ProgressPayload): p is LoginSSEvent {\n return LOGIN_PHASES.has(phaseOf(p));\n}\n\nfunction isActionSSEEvent(p: ProgressPayload): p is ActionSSEEvent {\n return ACTION_PHASES.has(phaseOf(p));\n}\n\nexport function isDelegateSSEEvent(p: ProgressPayload): p is DelegateActionSSEEvent {\n if (!isActionSSEEvent(p)) return false;\n const data = (p as any).data;\n return !!data && typeof data === 'object' && (data as any).context === 'delegate';\n}\n\nfunction isDeviceLinkingSSEEvent(p: ProgressPayload): p is DeviceLinkingSSEEvent {\n return DEVICE_LINKING_PHASES.has(phaseOf(p));\n}\n\nfunction isAccountRecoverySSEEvent(p: ProgressPayload): p is AccountRecoverySSEEvent {\n return ACCOUNT_RECOVERY_PHASES.has(phaseOf(p));\n}\n\nfunction isEmailRecoverySSEEvent(p: ProgressPayload): p is EmailRecoverySSEEvent {\n return EMAIL_RECOVERY_PHASES.has(phaseOf(p));\n}\n\n/**\n * Strips out class functions as they cannot be sent over postMessage to iframe\n */\n function normalizeSignedTransactionObject(result: SignTransactionResult) {\n const arr = Array.isArray(result) ? result : [];\n const normalized = arr.map(entry => {\n if (entry?.signedTransaction) {\n const st = entry.signedTransaction as unknown;\n if (isPlainSignedTransactionLike(st)) {\n entry.signedTransaction = SignedTransaction.fromPlain({\n transaction: (st as { transaction: unknown }).transaction,\n signature: (st as { signature: unknown }).signature,\n borsh_bytes: extractBorshBytesFromPlainSignedTx(st),\n });\n }\n }\n return entry;\n });\n return normalized\n }\n\n/**\n * Strips out functions as they cannot be sent over postMessage to iframe\n */\nimport { stripFunctionsShallow } from '../validation';\n\nfunction removeFunctionsFromOptions(options?: object): object | undefined {\n return stripFunctionsShallow(options as Record<string, unknown>);\n}\n"],"mappings":"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"}
|
package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js
CHANGED
|
@@ -2,12 +2,14 @@ import { assertString, init_validation, isObject } from "../../../WalletIframe/v
|
|
|
2
2
|
import { base58Encode, init_base58 } from "../../../../utils/base58.js";
|
|
3
3
|
import { init_vrf_worker, validateVRFChallenge } from "../../../types/vrf-worker.js";
|
|
4
4
|
import { init_credentialsHelpers, normalizeRegistrationCredential } from "../../credentialsHelpers.js";
|
|
5
|
+
import { ensureEd25519Prefix, init_nearCrypto } from "../../../nearCrypto.js";
|
|
5
6
|
|
|
6
7
|
//#region src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.ts
|
|
7
8
|
init_credentialsHelpers();
|
|
8
9
|
init_vrf_worker();
|
|
9
10
|
init_validation();
|
|
10
11
|
init_base58();
|
|
12
|
+
init_nearCrypto();
|
|
11
13
|
function validateTransactionContextMaybe(input) {
|
|
12
14
|
if (input == null) return void 0;
|
|
13
15
|
if (!isObject(input)) throw new Error("Invalid transactionContext: expected object");
|
|
@@ -68,9 +70,6 @@ function parseAndValidateRegistrationCredentialConfirmationPayload(payload) {
|
|
|
68
70
|
error: normalizedError
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
|
-
const ensureEd25519Prefix = (value) => {
|
|
72
|
-
return value.startsWith("ed25519:") ? value : `ed25519:${value}`;
|
|
73
|
-
};
|
|
74
73
|
const toPublicKeyString = (pk) => {
|
|
75
74
|
if (typeof pk === "string") return pk;
|
|
76
75
|
return ensureEd25519Prefix(base58Encode(pk.keyData));
|
package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","names":[],"sources":["../../../../../../../../../src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.ts"],"sourcesContent":["import { normalizeRegistrationCredential } from '../../credentialsHelpers';\nimport type { WebAuthnRegistrationCredential } from '../../../types/webauthn';\nimport { validateVRFChallenge, type VRFChallenge } from '../../../types/vrf-worker';\nimport type { TransactionContext } from '../../../types/rpc';\nimport { isObject, assertString } from '../../../WalletIframe/validation';\nimport { DelegateActionInput } from '../../../types/delegate';\nimport { base58Encode } from '../../../../utils/base58';\n\n// Strongly typed payload expected from the WASM → JS boundary\nexport interface RegistrationCredentialConfirmationPayload {\n confirmed: boolean;\n requestId: string;\n intentDigest: string;\n credential: WebAuthnRegistrationCredential; // serialized PublicKeyCredential (no methods)\n vrfChallenge: VRFChallenge;\n transactionContext?: TransactionContext;\n error?: string;\n}\n\nfunction validateTransactionContextMaybe(input: unknown): TransactionContext | undefined {\n if (input == null) return undefined;\n if (!isObject(input)) {\n throw new Error('Invalid transactionContext: expected object');\n }\n\n const {\n nearPublicKeyStr,\n nextNonce,\n txBlockHeight,\n txBlockHash,\n accessKeyInfo,\n } = input as {\n nearPublicKeyStr?: unknown;\n nextNonce?: unknown;\n txBlockHeight?: unknown;\n txBlockHash?: unknown;\n accessKeyInfo?: unknown;\n };\n\n // Minimal structural validation; AccessKeyView is complex. Be tolerant because the WASM struct omits it.\n const normalizedNearPublicKeyStr = assertString(\n nearPublicKeyStr,\n 'transactionContext.nearPublicKeyStr',\n );\n const normalizedNextNonce = assertString(nextNonce, 'transactionContext.nextNonce');\n const normalizedTxBlockHeight = assertString(\n txBlockHeight,\n 'transactionContext.txBlockHeight',\n );\n const normalizedTxBlockHash = assertString(txBlockHash, 'transactionContext.txBlockHash');\n\n let normalizedAccessKeyInfo = accessKeyInfo as TransactionContext['accessKeyInfo'] | undefined;\n if (normalizedAccessKeyInfo != null && !isObject(normalizedAccessKeyInfo)) {\n throw new Error('Invalid transactionContext.accessKeyInfo: expected object');\n }\n if (normalizedAccessKeyInfo == null) {\n // Synthesize a minimal placeholder; not used by registration flows consuming this payload\n normalizedAccessKeyInfo = { nonce: 0 } as unknown as TransactionContext['accessKeyInfo'];\n }\n\n return {\n nearPublicKeyStr: normalizedNearPublicKeyStr,\n nextNonce: normalizedNextNonce,\n txBlockHeight: normalizedTxBlockHeight,\n txBlockHash: normalizedTxBlockHash,\n accessKeyInfo: normalizedAccessKeyInfo,\n };\n}\n\nfunction validateCredentialMaybe(input: unknown): WebAuthnRegistrationCredential | undefined {\n if (input == null) return undefined;\n\n const cred = normalizeRegistrationCredential(input);\n if (cred.type !== 'public-key') {\n throw new Error('Invalid credential.type: expected \"public-key\"');\n }\n\n const { id, rawId, response, authenticatorAttachment } = cred as {\n id?: unknown;\n rawId?: unknown;\n response?: unknown;\n authenticatorAttachment?: unknown;\n };\n\n // Core field/type validation (serialized shapes should be base64url strings)\n assertString(id, 'credential.id');\n assertString(rawId, 'credential.rawId');\n\n if (!isObject(response)) {\n throw new Error('Invalid credential.response: expected object');\n }\n\n const {\n clientDataJSON,\n attestationObject,\n transports,\n } = response as {\n clientDataJSON?: unknown;\n attestationObject?: unknown;\n transports?: unknown;\n };\n\n assertString(clientDataJSON, 'credential.response.clientDataJSON');\n assertString(attestationObject, 'credential.response.attestationObject');\n\n if (!Array.isArray(transports)) {\n throw new Error('Invalid credential.response.transports: expected string[]');\n }\n for (const t of transports) {\n if (typeof t !== 'string') {\n throw new Error('Invalid credential.response.transports item: expected string');\n }\n }\n\n if (authenticatorAttachment != null && typeof authenticatorAttachment !== 'string') {\n throw new Error('Invalid credential.authenticatorAttachment: expected string | undefined');\n }\n\n // Note: prf.results may be undefined/null here. We intentionally do NOT\n // require them at the boundary; internal callers that need PRF (e.g. key\n // derivation) will extract/compute them separately. Contract payloads must\n // not include PRF values.\n return cred;\n}\n\nfunction validateVrfChallengeMaybe(input: unknown): VRFChallenge | undefined {\n if (input == null) return undefined;\n return validateVRFChallenge(input as Parameters<typeof validateVRFChallenge>[0]);\n}\n\nexport function parseAndValidateRegistrationCredentialConfirmationPayload(\n payload: unknown,\n): RegistrationCredentialConfirmationPayload {\n\n if (!isObject(payload)) {\n throw new Error('Invalid response payload: expected object');\n }\n\n const {\n confirmed,\n requestId,\n intentDigest,\n credential,\n vrfChallenge,\n transactionContext,\n error,\n } = payload as {\n confirmed?: unknown;\n requestId?: unknown;\n intentDigest?: unknown;\n credential?: unknown;\n vrfChallenge?: unknown;\n transactionContext?: unknown;\n error?: unknown;\n };\n\n const normalizedRequestId = assertString(requestId, 'requestId');\n\n // intentDigest is only used for TX signing requests, not registration or link device requests\n const normalizedIntentDigest =\n intentDigest == null ? '' : assertString(intentDigest, 'intentDigest');\n\n const normalizedCredential =\n credential != null ? validateCredentialMaybe(credential) : undefined;\n\n if (!normalizedCredential) {\n throw new Error('Missing registration credential');\n }\n\n const normalizedVrfChallenge =\n vrfChallenge != null ? validateVrfChallengeMaybe(vrfChallenge) : undefined;\n\n if (!normalizedVrfChallenge) {\n throw new Error('Missing VRF Challenge');\n }\n\n const normalizedTransactionContext =\n transactionContext != null ? validateTransactionContextMaybe(transactionContext) : undefined;\n\n const normalizedError =\n error == null ? undefined : assertString(error, 'error');\n\n return {\n confirmed: !!confirmed,\n requestId: normalizedRequestId,\n intentDigest: normalizedIntentDigest,\n credential: normalizedCredential,\n vrfChallenge: normalizedVrfChallenge,\n transactionContext: normalizedTransactionContext,\n error: normalizedError,\n };\n}\n\nexport
|
|
1
|
+
{"version":3,"file":"validation.js","names":[],"sources":["../../../../../../../../../src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.ts"],"sourcesContent":["import { normalizeRegistrationCredential } from '../../credentialsHelpers';\nimport type { WebAuthnRegistrationCredential } from '../../../types/webauthn';\nimport { validateVRFChallenge, type VRFChallenge } from '../../../types/vrf-worker';\nimport type { TransactionContext } from '../../../types/rpc';\nimport { isObject, assertString } from '../../../WalletIframe/validation';\nimport { DelegateActionInput } from '../../../types/delegate';\nimport { base58Encode } from '../../../../utils/base58';\nimport { ensureEd25519Prefix } from '../../../nearCrypto';\n\n// Strongly typed payload expected from the WASM → JS boundary\nexport interface RegistrationCredentialConfirmationPayload {\n confirmed: boolean;\n requestId: string;\n intentDigest: string;\n credential: WebAuthnRegistrationCredential; // serialized PublicKeyCredential (no methods)\n vrfChallenge: VRFChallenge;\n transactionContext?: TransactionContext;\n error?: string;\n}\n\nfunction validateTransactionContextMaybe(input: unknown): TransactionContext | undefined {\n if (input == null) return undefined;\n if (!isObject(input)) {\n throw new Error('Invalid transactionContext: expected object');\n }\n\n const {\n nearPublicKeyStr,\n nextNonce,\n txBlockHeight,\n txBlockHash,\n accessKeyInfo,\n } = input as {\n nearPublicKeyStr?: unknown;\n nextNonce?: unknown;\n txBlockHeight?: unknown;\n txBlockHash?: unknown;\n accessKeyInfo?: unknown;\n };\n\n // Minimal structural validation; AccessKeyView is complex. Be tolerant because the WASM struct omits it.\n const normalizedNearPublicKeyStr = assertString(\n nearPublicKeyStr,\n 'transactionContext.nearPublicKeyStr',\n );\n const normalizedNextNonce = assertString(nextNonce, 'transactionContext.nextNonce');\n const normalizedTxBlockHeight = assertString(\n txBlockHeight,\n 'transactionContext.txBlockHeight',\n );\n const normalizedTxBlockHash = assertString(txBlockHash, 'transactionContext.txBlockHash');\n\n let normalizedAccessKeyInfo = accessKeyInfo as TransactionContext['accessKeyInfo'] | undefined;\n if (normalizedAccessKeyInfo != null && !isObject(normalizedAccessKeyInfo)) {\n throw new Error('Invalid transactionContext.accessKeyInfo: expected object');\n }\n if (normalizedAccessKeyInfo == null) {\n // Synthesize a minimal placeholder; not used by registration flows consuming this payload\n normalizedAccessKeyInfo = { nonce: 0 } as unknown as TransactionContext['accessKeyInfo'];\n }\n\n return {\n nearPublicKeyStr: normalizedNearPublicKeyStr,\n nextNonce: normalizedNextNonce,\n txBlockHeight: normalizedTxBlockHeight,\n txBlockHash: normalizedTxBlockHash,\n accessKeyInfo: normalizedAccessKeyInfo,\n };\n}\n\nfunction validateCredentialMaybe(input: unknown): WebAuthnRegistrationCredential | undefined {\n if (input == null) return undefined;\n\n const cred = normalizeRegistrationCredential(input);\n if (cred.type !== 'public-key') {\n throw new Error('Invalid credential.type: expected \"public-key\"');\n }\n\n const { id, rawId, response, authenticatorAttachment } = cred as {\n id?: unknown;\n rawId?: unknown;\n response?: unknown;\n authenticatorAttachment?: unknown;\n };\n\n // Core field/type validation (serialized shapes should be base64url strings)\n assertString(id, 'credential.id');\n assertString(rawId, 'credential.rawId');\n\n if (!isObject(response)) {\n throw new Error('Invalid credential.response: expected object');\n }\n\n const {\n clientDataJSON,\n attestationObject,\n transports,\n } = response as {\n clientDataJSON?: unknown;\n attestationObject?: unknown;\n transports?: unknown;\n };\n\n assertString(clientDataJSON, 'credential.response.clientDataJSON');\n assertString(attestationObject, 'credential.response.attestationObject');\n\n if (!Array.isArray(transports)) {\n throw new Error('Invalid credential.response.transports: expected string[]');\n }\n for (const t of transports) {\n if (typeof t !== 'string') {\n throw new Error('Invalid credential.response.transports item: expected string');\n }\n }\n\n if (authenticatorAttachment != null && typeof authenticatorAttachment !== 'string') {\n throw new Error('Invalid credential.authenticatorAttachment: expected string | undefined');\n }\n\n // Note: prf.results may be undefined/null here. We intentionally do NOT\n // require them at the boundary; internal callers that need PRF (e.g. key\n // derivation) will extract/compute them separately. Contract payloads must\n // not include PRF values.\n return cred;\n}\n\nfunction validateVrfChallengeMaybe(input: unknown): VRFChallenge | undefined {\n if (input == null) return undefined;\n return validateVRFChallenge(input as Parameters<typeof validateVRFChallenge>[0]);\n}\n\nexport function parseAndValidateRegistrationCredentialConfirmationPayload(\n payload: unknown,\n): RegistrationCredentialConfirmationPayload {\n\n if (!isObject(payload)) {\n throw new Error('Invalid response payload: expected object');\n }\n\n const {\n confirmed,\n requestId,\n intentDigest,\n credential,\n vrfChallenge,\n transactionContext,\n error,\n } = payload as {\n confirmed?: unknown;\n requestId?: unknown;\n intentDigest?: unknown;\n credential?: unknown;\n vrfChallenge?: unknown;\n transactionContext?: unknown;\n error?: unknown;\n };\n\n const normalizedRequestId = assertString(requestId, 'requestId');\n\n // intentDigest is only used for TX signing requests, not registration or link device requests\n const normalizedIntentDigest =\n intentDigest == null ? '' : assertString(intentDigest, 'intentDigest');\n\n const normalizedCredential =\n credential != null ? validateCredentialMaybe(credential) : undefined;\n\n if (!normalizedCredential) {\n throw new Error('Missing registration credential');\n }\n\n const normalizedVrfChallenge =\n vrfChallenge != null ? validateVrfChallengeMaybe(vrfChallenge) : undefined;\n\n if (!normalizedVrfChallenge) {\n throw new Error('Missing VRF Challenge');\n }\n\n const normalizedTransactionContext =\n transactionContext != null ? validateTransactionContextMaybe(transactionContext) : undefined;\n\n const normalizedError =\n error == null ? undefined : assertString(error, 'error');\n\n return {\n confirmed: !!confirmed,\n requestId: normalizedRequestId,\n intentDigest: normalizedIntentDigest,\n credential: normalizedCredential,\n vrfChallenge: normalizedVrfChallenge,\n transactionContext: normalizedTransactionContext,\n error: normalizedError,\n };\n}\n\nexport { ensureEd25519Prefix };\n\nexport const toPublicKeyString = (pk: DelegateActionInput['publicKey']): string => {\n if (typeof pk === 'string') {\n return pk;\n }\n return ensureEd25519Prefix(base58Encode(pk.keyData));\n};\n"],"mappings":";;;;;;;;;;;;AAoBA,SAAS,gCAAgC,OAAgD;AACvF,KAAI,SAAS,KAAM,QAAO;AAC1B,KAAI,CAAC,SAAS,OACZ,OAAM,IAAI,MAAM;CAGlB,MAAM,EACJ,kBACA,WACA,eACA,aACA,kBACE;CASJ,MAAM,6BAA6B,aACjC,kBACA;CAEF,MAAM,sBAAsB,aAAa,WAAW;CACpD,MAAM,0BAA0B,aAC9B,eACA;CAEF,MAAM,wBAAwB,aAAa,aAAa;CAExD,IAAI,0BAA0B;AAC9B,KAAI,2BAA2B,QAAQ,CAAC,SAAS,yBAC/C,OAAM,IAAI,MAAM;AAElB,KAAI,2BAA2B,KAE7B,2BAA0B,EAAE,OAAO;AAGrC,QAAO;EACL,kBAAkB;EAClB,WAAW;EACX,eAAe;EACf,aAAa;EACb,eAAe;;;AAInB,SAAS,wBAAwB,OAA4D;AAC3F,KAAI,SAAS,KAAM,QAAO;CAE1B,MAAM,OAAO,gCAAgC;AAC7C,KAAI,KAAK,SAAS,aAChB,OAAM,IAAI,MAAM;CAGlB,MAAM,EAAE,IAAI,OAAO,UAAU,4BAA4B;AAQzD,cAAa,IAAI;AACjB,cAAa,OAAO;AAEpB,KAAI,CAAC,SAAS,UACZ,OAAM,IAAI,MAAM;CAGlB,MAAM,EACJ,gBACA,mBACA,eACE;AAMJ,cAAa,gBAAgB;AAC7B,cAAa,mBAAmB;AAEhC,KAAI,CAAC,MAAM,QAAQ,YACjB,OAAM,IAAI,MAAM;AAElB,MAAK,MAAM,KAAK,WACd,KAAI,OAAO,MAAM,SACf,OAAM,IAAI,MAAM;AAIpB,KAAI,2BAA2B,QAAQ,OAAO,4BAA4B,SACxE,OAAM,IAAI,MAAM;AAOlB,QAAO;;AAGT,SAAS,0BAA0B,OAA0C;AAC3E,KAAI,SAAS,KAAM,QAAO;AAC1B,QAAO,qBAAqB;;AAG9B,SAAgB,0DACd,SAC2C;AAE3C,KAAI,CAAC,SAAS,SACZ,OAAM,IAAI,MAAM;CAGlB,MAAM,EACJ,WACA,WACA,cACA,YACA,cACA,oBACA,UACE;CAUJ,MAAM,sBAAsB,aAAa,WAAW;CAGpD,MAAM,yBACJ,gBAAgB,OAAO,KAAK,aAAa,cAAc;CAEzD,MAAM,uBACJ,cAAc,OAAO,wBAAwB,cAAc;AAE7D,KAAI,CAAC,qBACH,OAAM,IAAI,MAAM;CAGlB,MAAM,yBACJ,gBAAgB,OAAO,0BAA0B,gBAAgB;AAEnE,KAAI,CAAC,uBACH,OAAM,IAAI,MAAM;CAGlB,MAAM,+BACJ,sBAAsB,OAAO,gCAAgC,sBAAsB;CAErF,MAAM,kBACJ,SAAS,OAAO,SAAY,aAAa,OAAO;AAElD,QAAO;EACL,WAAW,CAAC,CAAC;EACb,WAAW;EACX,cAAc;EACd,YAAY;EACZ,cAAc;EACd,oBAAoB;EACpB,OAAO;;;AAMX,MAAa,qBAAqB,OAAiD;AACjF,KAAI,OAAO,OAAO,SAChB,QAAO;AAET,QAAO,oBAAoB,aAAa,GAAG"}
|
|
@@ -23,9 +23,7 @@ function buildConfigsFromEnv(overrides = {}) {
|
|
|
23
23
|
pollingIntervalMs: overrides.relayer?.emailRecovery?.pollingIntervalMs ?? defaults.relayer?.emailRecovery?.pollingIntervalMs,
|
|
24
24
|
maxPollingDurationMs: overrides.relayer?.emailRecovery?.maxPollingDurationMs ?? defaults.relayer?.emailRecovery?.maxPollingDurationMs,
|
|
25
25
|
pendingTtlMs: overrides.relayer?.emailRecovery?.pendingTtlMs ?? defaults.relayer?.emailRecovery?.pendingTtlMs,
|
|
26
|
-
mailtoAddress: overrides.relayer?.emailRecovery?.mailtoAddress ?? defaults.relayer?.emailRecovery?.mailtoAddress
|
|
27
|
-
dkimVerifierAccountId: overrides.relayer?.emailRecovery?.dkimVerifierAccountId ?? defaults.relayer?.emailRecovery?.dkimVerifierAccountId,
|
|
28
|
-
verificationViewMethod: overrides.relayer?.emailRecovery?.verificationViewMethod ?? defaults.relayer?.emailRecovery?.verificationViewMethod
|
|
26
|
+
mailtoAddress: overrides.relayer?.emailRecovery?.mailtoAddress ?? defaults.relayer?.emailRecovery?.mailtoAddress
|
|
29
27
|
}
|
|
30
28
|
},
|
|
31
29
|
authenticatorOptions: overrides.authenticatorOptions ?? defaults.authenticatorOptions,
|
|
@@ -70,9 +68,7 @@ var init_defaultConfigs = __esm({ "src/core/defaultConfigs.ts": (() => {
|
|
|
70
68
|
pollingIntervalMs: 4e3,
|
|
71
69
|
maxPollingDurationMs: 1800 * 1e3,
|
|
72
70
|
pendingTtlMs: 1800 * 1e3,
|
|
73
|
-
mailtoAddress: "recover@web3authn.org"
|
|
74
|
-
dkimVerifierAccountId: "email-dkim-verifier-v1.testnet",
|
|
75
|
-
verificationViewMethod: "get_verification_result"
|
|
71
|
+
mailtoAddress: "recover@web3authn.org"
|
|
76
72
|
}
|
|
77
73
|
},
|
|
78
74
|
vrfWorkerConfigs: { shamir3pass: {
|
|
@@ -94,7 +90,7 @@ var init_defaultConfigs = __esm({ "src/core/defaultConfigs.ts": (() => {
|
|
|
94
90
|
}
|
|
95
91
|
};
|
|
96
92
|
DEFAULT_EMAIL_RECOVERY_CONTRACTS = {
|
|
97
|
-
emailRecovererGlobalContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.
|
|
93
|
+
emailRecovererGlobalContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailRecovererGlobalContract,
|
|
98
94
|
zkEmailVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.zkEmailVerifierContract,
|
|
99
95
|
emailDkimVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract
|
|
100
96
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultConfigs.js","names":["merged: TatchiConfigs","PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs","DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts"],"sources":["../../../../../../src/core/defaultConfigs.ts"],"sourcesContent":["import type { EmailRecoveryContracts, TatchiConfigs, TatchiConfigsInput } from './types/tatchi';\n\n// Default SDK configs suitable for local dev.\n// Cross-origin wallet isolation is recommended; set iframeWallet in your app config when you have a dedicated origin.\n// Consumers can shallow-merge overrides by field.\n\nexport const PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs = {\n // You can provide a single URL or a comma-separated list for failover.\n // First URL is treated as primary, subsequent URLs are fallbacks.\n nearRpcUrl: 'https://test.rpc.fastnear.com, https://rpc.testnet.near.org',\n nearNetwork: 'testnet',\n contractId: 'w3a-v1.testnet',\n nearExplorerUrl: 'https://testnet.nearblocks.io',\n // Warm signing session defaults used by login/unlock flows.\n // Enforcement (TTL/uses) is owned by the VRF worker; signer workers remain one-shot.\n signingSessionDefaults: {\n ttlMs: 0, // 0 minutes\n remainingUses: 0, // default to requiring a touchID prompt for each transaction\n },\n relayer: {\n // accountId: 'w3a-v1.testnet',\n // No default relayer URL. Force apps to configure via env/overrides.\n // Using an empty string triggers early validation errors in code paths that require it.\n url: '',\n delegateActionRoute: '/signed-delegate',\n emailRecovery: {\n // Require at least 0.01 NEAR available to start email recovery.\n minBalanceYocto: '10000000000000000000000', // 0.01 NEAR\n // Poll every 4 seconds for verification status / access key.\n pollingIntervalMs: 4000,\n // Stop polling after 30 minutes.\n maxPollingDurationMs: 30 * 60 * 1000,\n // Expire pending recovery records after 30 minutes.\n pendingTtlMs: 30 * 60 * 1000,\n // Default recovery mailbox for examples / docs.\n mailtoAddress: 'recover@web3authn.org',\n // EmailDKIMVerifier contract that stores verification results.\n dkimVerifierAccountId: 'email-dkim-verifier-v1.testnet',\n // View method used to fetch VerificationResult by request_id.\n verificationViewMethod: 'get_verification_result',\n },\n },\n vrfWorkerConfigs: {\n shamir3pass: {\n // default Shamir's P in vrf-wasm-worker, needs to match relay server's Shamir P\n p: '3N5w46AIGjGT2v5Vua_TMD5Ywfa9U2F7-WzW8SNDsIM',\n // No default relay server URL to avoid accidental localhost usage in non-dev envs\n // Defaults to relayer.url when undefined\n relayServerUrl: '',\n applyServerLockRoute: '/vrf/apply-server-lock',\n removeServerLockRoute: '/vrf/remove-server-lock',\n }\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: 'w3a-email-recoverer-v1.testnet',\n zkEmailVerifierContract: 'zk-email-verifier-v1.testnet',\n emailDkimVerifierContract: 'email-dkim-verifier-v1.testnet',\n },\n // Configure iframeWallet in application code to point at your dedicated wallet origin when available.\n iframeWallet: {\n walletOrigin: 'https://wallet.example.localhost',\n walletServicePath: '/wallet-service',\n sdkBasePath: '/sdk',\n rpIdOverride: 'example.localhost',\n }\n};\n\nexport const DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts = {\n emailRecovererGlobalContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n zkEmailVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.zkEmailVerifierContract,\n emailDkimVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n};\n\n// Merge defaults with overrides\nexport function buildConfigsFromEnv(overrides: TatchiConfigsInput = {}): TatchiConfigs {\n\n const defaults = PASSKEY_MANAGER_DEFAULT_CONFIGS;\n const relayerUrl = overrides.relayer?.url ?? defaults.relayer?.url ?? '';\n // Prefer explicit override for relayer URL; fall back to default preset.\n // Used below to default VRF relayServerUrl when it is undefined.\n const relayServerUrlDefault = relayerUrl;\n\n const merged: TatchiConfigs = {\n nearRpcUrl: overrides.nearRpcUrl ?? defaults.nearRpcUrl,\n nearNetwork: overrides.nearNetwork ?? defaults.nearNetwork,\n contractId: overrides.contractId ?? defaults.contractId,\n nearExplorerUrl: overrides.nearExplorerUrl ?? defaults.nearExplorerUrl,\n walletTheme: overrides.walletTheme ?? defaults.walletTheme,\n signingSessionDefaults: {\n ttlMs: overrides.signingSessionDefaults?.ttlMs\n ?? defaults.signingSessionDefaults?.ttlMs,\n remainingUses: overrides.signingSessionDefaults?.remainingUses\n ?? defaults.signingSessionDefaults?.remainingUses,\n },\n relayer: {\n url: relayerUrl,\n delegateActionRoute: overrides.relayer?.delegateActionRoute\n ?? defaults.relayer?.delegateActionRoute,\n emailRecovery: {\n minBalanceYocto: overrides.relayer?.emailRecovery?.minBalanceYocto\n ?? defaults.relayer?.emailRecovery?.minBalanceYocto,\n pollingIntervalMs: overrides.relayer?.emailRecovery?.pollingIntervalMs\n ?? defaults.relayer?.emailRecovery?.pollingIntervalMs,\n maxPollingDurationMs: overrides.relayer?.emailRecovery?.maxPollingDurationMs\n ?? defaults.relayer?.emailRecovery?.maxPollingDurationMs,\n pendingTtlMs: overrides.relayer?.emailRecovery?.pendingTtlMs\n ?? defaults.relayer?.emailRecovery?.pendingTtlMs,\n mailtoAddress: overrides.relayer?.emailRecovery?.mailtoAddress\n ?? defaults.relayer?.emailRecovery?.mailtoAddress,\n dkimVerifierAccountId: overrides.relayer?.emailRecovery?.dkimVerifierAccountId\n ?? defaults.relayer?.emailRecovery?.dkimVerifierAccountId,\n verificationViewMethod: overrides.relayer?.emailRecovery?.verificationViewMethod\n ?? defaults.relayer?.emailRecovery?.verificationViewMethod,\n },\n },\n authenticatorOptions: overrides.authenticatorOptions ?? defaults.authenticatorOptions,\n vrfWorkerConfigs: {\n shamir3pass: {\n p: overrides.vrfWorkerConfigs?.shamir3pass?.p\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.p,\n relayServerUrl: overrides.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? relayServerUrlDefault,\n applyServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute,\n removeServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute,\n },\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: overrides.emailRecoveryContracts?.emailRecovererGlobalContract\n ?? defaults.emailRecoveryContracts?.emailRecovererGlobalContract,\n zkEmailVerifierContract: overrides.emailRecoveryContracts?.zkEmailVerifierContract\n ?? defaults.emailRecoveryContracts?.zkEmailVerifierContract,\n emailDkimVerifierContract: overrides.emailRecoveryContracts?.emailDkimVerifierContract\n ?? defaults.emailRecoveryContracts?.emailDkimVerifierContract,\n },\n iframeWallet: {\n walletOrigin: overrides.iframeWallet?.walletOrigin\n ?? defaults.iframeWallet?.walletOrigin,\n walletServicePath: overrides.iframeWallet?.walletServicePath\n ?? defaults.iframeWallet?.walletServicePath\n ?? '/wallet-service',\n sdkBasePath: overrides.iframeWallet?.sdkBasePath\n ?? defaults.iframeWallet?.sdkBasePath\n ?? '/sdk',\n rpIdOverride: overrides.iframeWallet?.rpIdOverride\n ?? defaults.iframeWallet?.rpIdOverride,\n }\n };\n if (!merged.contractId) {\n throw new Error('[configPresets] Missing required config: contractId');\n }\n if (!merged.relayer.url) {\n throw new Error('[configPresets] Missing required config: relayer.url');\n }\n return merged;\n}\n"],"mappings":";;;AA0EA,SAAgB,oBAAoB,YAAgC,IAAmB;CAErF,MAAM,WAAW;CACjB,MAAM,aAAa,UAAU,SAAS,OAAO,SAAS,SAAS,OAAO;CAGtE,MAAM,wBAAwB;CAE9B,MAAMA,SAAwB;EAC5B,YAAY,UAAU,cAAc,SAAS;EAC7C,aAAa,UAAU,eAAe,SAAS;EAC/C,YAAY,UAAU,cAAc,SAAS;EAC7C,iBAAiB,UAAU,mBAAmB,SAAS;EACvD,aAAa,UAAU,eAAe,SAAS;EAC/C,wBAAwB;GACtB,OAAO,UAAU,wBAAwB,SACpC,SAAS,wBAAwB;GACtC,eAAe,UAAU,wBAAwB,iBAC5C,SAAS,wBAAwB;;EAExC,SAAS;GACP,KAAK;GACL,qBAAqB,UAAU,SAAS,uBACnC,SAAS,SAAS;GACvB,eAAe;IACb,iBAAiB,UAAU,SAAS,eAAe,mBAC9C,SAAS,SAAS,eAAe;IACtC,mBAAmB,UAAU,SAAS,eAAe,qBAChD,SAAS,SAAS,eAAe;IACtC,sBAAsB,UAAU,SAAS,eAAe,wBACnD,SAAS,SAAS,eAAe;IACtC,cAAc,UAAU,SAAS,eAAe,gBAC3C,SAAS,SAAS,eAAe;IACtC,eAAe,UAAU,SAAS,eAAe,iBAC5C,SAAS,SAAS,eAAe;IACtC,uBAAuB,UAAU,SAAS,eAAe,yBACpD,SAAS,SAAS,eAAe;IACtC,wBAAwB,UAAU,SAAS,eAAe,0BACrD,SAAS,SAAS,eAAe;;;EAG1C,sBAAsB,UAAU,wBAAwB,SAAS;EACjE,kBAAkB,EAChB,aAAa;GACX,GAAG,UAAU,kBAAkB,aAAa,KACvC,SAAS,kBAAkB,aAAa;GAC7C,gBAAgB,UAAU,kBAAkB,aAAa,kBACpD,SAAS,kBAAkB,aAAa,kBACxC;GACL,sBAAsB,UAAU,kBAAkB,aAAa,wBAC1D,SAAS,kBAAkB,aAAa;GAC7C,uBAAuB,UAAU,kBAAkB,aAAa,yBAC3D,SAAS,kBAAkB,aAAa;;EAGjD,wBAAwB;GACtB,8BAA8B,UAAU,wBAAwB,gCAC3D,SAAS,wBAAwB;GACtC,yBAAyB,UAAU,wBAAwB,2BACtD,SAAS,wBAAwB;GACtC,2BAA2B,UAAU,wBAAwB,6BACxD,SAAS,wBAAwB;;EAExC,cAAc;GACZ,cAAc,UAAU,cAAc,gBACjC,SAAS,cAAc;GAC5B,mBAAmB,UAAU,cAAc,qBACtC,SAAS,cAAc,qBACvB;GACL,aAAa,UAAU,cAAc,eAChC,SAAS,cAAc,eACvB;GACL,cAAc,UAAU,cAAc,gBACjC,SAAS,cAAc;;;AAGhC,KAAI,CAAC,OAAO,WACV,OAAM,IAAI,MAAM;AAElB,KAAI,CAAC,OAAO,QAAQ,IAClB,OAAM,IAAI,MAAM;AAElB,QAAO;;;;CAtJIC,kCAAiD;EAG5D,YAAY;EACZ,aAAa;EACb,YAAY;EACZ,iBAAiB;EAGjB,wBAAwB;GACtB,OAAO;GACP,eAAe;;EAEjB,SAAS;GAIP,KAAK;GACL,qBAAqB;GACrB,eAAe;IAEb,iBAAiB;IAEjB,mBAAmB;IAEnB,sBAAsB,OAAU;IAEhC,cAAc,OAAU;IAExB,eAAe;IAEf,uBAAuB;IAEvB,wBAAwB;;;EAG5B,kBAAkB,EAChB,aAAa;GAEX,GAAG;GAGH,gBAAgB;GAChB,sBAAsB;GACtB,uBAAuB;;EAG3B,wBAAwB;GACtB,8BAA8B;GAC9B,yBAAyB;GACzB,2BAA2B;;EAG7B,cAAc;GACZ,cAAc;GACd,mBAAmB;GACnB,aAAa;GACb,cAAc;;;CAILC,mCAA2D;EACtE,8BAA8B,gCAAgC,uBAAuB;EACrF,yBAAyB,gCAAgC,uBAAuB;EAChF,2BAA2B,gCAAgC,uBAAuB"}
|
|
1
|
+
{"version":3,"file":"defaultConfigs.js","names":["merged: TatchiConfigs","PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs","DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts"],"sources":["../../../../../../src/core/defaultConfigs.ts"],"sourcesContent":["import type { EmailRecoveryContracts, TatchiConfigs, TatchiConfigsInput } from './types/tatchi';\n\n// Default SDK configs suitable for local dev.\n// Cross-origin wallet isolation is recommended; set iframeWallet in your app config when you have a dedicated origin.\n// Consumers can shallow-merge overrides by field.\n\nexport const PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs = {\n // You can provide a single URL or a comma-separated list for failover.\n // First URL is treated as primary, subsequent URLs are fallbacks.\n nearRpcUrl: 'https://test.rpc.fastnear.com, https://rpc.testnet.near.org',\n nearNetwork: 'testnet',\n contractId: 'w3a-v1.testnet',\n nearExplorerUrl: 'https://testnet.nearblocks.io',\n // Warm signing session defaults used by login/unlock flows.\n // Enforcement (TTL/uses) is owned by the VRF worker; signer workers remain one-shot.\n signingSessionDefaults: {\n ttlMs: 0, // 0 minutes\n remainingUses: 0, // default to requiring a touchID prompt for each transaction\n },\n relayer: {\n // accountId: 'w3a-v1.testnet',\n // No default relayer URL. Force apps to configure via env/overrides.\n // Using an empty string triggers early validation errors in code paths that require it.\n url: '',\n delegateActionRoute: '/signed-delegate',\n emailRecovery: {\n // Require at least 0.01 NEAR available to start email recovery.\n minBalanceYocto: '10000000000000000000000', // 0.01 NEAR\n // Poll every 4 seconds for verification status / access key.\n pollingIntervalMs: 4000,\n // Stop polling after 30 minutes.\n maxPollingDurationMs: 30 * 60 * 1000,\n // Expire pending recovery records after 30 minutes.\n pendingTtlMs: 30 * 60 * 1000,\n // Default recovery mailbox for examples / docs.\n mailtoAddress: 'recover@web3authn.org',\n },\n },\n vrfWorkerConfigs: {\n shamir3pass: {\n // default Shamir's P in vrf-wasm-worker, needs to match relay server's Shamir P\n p: '3N5w46AIGjGT2v5Vua_TMD5Ywfa9U2F7-WzW8SNDsIM',\n // No default relay server URL to avoid accidental localhost usage in non-dev envs\n // Defaults to relayer.url when undefined\n relayServerUrl: '',\n applyServerLockRoute: '/vrf/apply-server-lock',\n removeServerLockRoute: '/vrf/remove-server-lock',\n }\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: 'w3a-email-recoverer-v1.testnet',\n zkEmailVerifierContract: 'zk-email-verifier-v1.testnet',\n emailDkimVerifierContract: 'email-dkim-verifier-v1.testnet',\n },\n // Configure iframeWallet in application code to point at your dedicated wallet origin when available.\n iframeWallet: {\n walletOrigin: 'https://wallet.example.localhost',\n walletServicePath: '/wallet-service',\n sdkBasePath: '/sdk',\n rpIdOverride: 'example.localhost',\n }\n};\n\nexport const DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts = {\n emailRecovererGlobalContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailRecovererGlobalContract,\n zkEmailVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.zkEmailVerifierContract,\n emailDkimVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n};\n\n// Merge defaults with overrides\nexport function buildConfigsFromEnv(overrides: TatchiConfigsInput = {}): TatchiConfigs {\n\n const defaults = PASSKEY_MANAGER_DEFAULT_CONFIGS;\n const relayerUrl = overrides.relayer?.url ?? defaults.relayer?.url ?? '';\n // Prefer explicit override for relayer URL; fall back to default preset.\n // Used below to default VRF relayServerUrl when it is undefined.\n const relayServerUrlDefault = relayerUrl;\n\n const merged: TatchiConfigs = {\n nearRpcUrl: overrides.nearRpcUrl ?? defaults.nearRpcUrl,\n nearNetwork: overrides.nearNetwork ?? defaults.nearNetwork,\n contractId: overrides.contractId ?? defaults.contractId,\n nearExplorerUrl: overrides.nearExplorerUrl ?? defaults.nearExplorerUrl,\n walletTheme: overrides.walletTheme ?? defaults.walletTheme,\n signingSessionDefaults: {\n ttlMs: overrides.signingSessionDefaults?.ttlMs\n ?? defaults.signingSessionDefaults?.ttlMs,\n remainingUses: overrides.signingSessionDefaults?.remainingUses\n ?? defaults.signingSessionDefaults?.remainingUses,\n },\n relayer: {\n url: relayerUrl,\n delegateActionRoute: overrides.relayer?.delegateActionRoute\n ?? defaults.relayer?.delegateActionRoute,\n emailRecovery: {\n minBalanceYocto: overrides.relayer?.emailRecovery?.minBalanceYocto\n ?? defaults.relayer?.emailRecovery?.minBalanceYocto,\n pollingIntervalMs: overrides.relayer?.emailRecovery?.pollingIntervalMs\n ?? defaults.relayer?.emailRecovery?.pollingIntervalMs,\n maxPollingDurationMs: overrides.relayer?.emailRecovery?.maxPollingDurationMs\n ?? defaults.relayer?.emailRecovery?.maxPollingDurationMs,\n pendingTtlMs: overrides.relayer?.emailRecovery?.pendingTtlMs\n ?? defaults.relayer?.emailRecovery?.pendingTtlMs,\n mailtoAddress: overrides.relayer?.emailRecovery?.mailtoAddress\n ?? defaults.relayer?.emailRecovery?.mailtoAddress,\n },\n },\n authenticatorOptions: overrides.authenticatorOptions ?? defaults.authenticatorOptions,\n vrfWorkerConfigs: {\n shamir3pass: {\n p: overrides.vrfWorkerConfigs?.shamir3pass?.p\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.p,\n relayServerUrl: overrides.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? relayServerUrlDefault,\n applyServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute,\n removeServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute,\n },\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: overrides.emailRecoveryContracts?.emailRecovererGlobalContract\n ?? defaults.emailRecoveryContracts?.emailRecovererGlobalContract,\n zkEmailVerifierContract: overrides.emailRecoveryContracts?.zkEmailVerifierContract\n ?? defaults.emailRecoveryContracts?.zkEmailVerifierContract,\n emailDkimVerifierContract: overrides.emailRecoveryContracts?.emailDkimVerifierContract\n ?? defaults.emailRecoveryContracts?.emailDkimVerifierContract,\n },\n iframeWallet: {\n walletOrigin: overrides.iframeWallet?.walletOrigin\n ?? defaults.iframeWallet?.walletOrigin,\n walletServicePath: overrides.iframeWallet?.walletServicePath\n ?? defaults.iframeWallet?.walletServicePath\n ?? '/wallet-service',\n sdkBasePath: overrides.iframeWallet?.sdkBasePath\n ?? defaults.iframeWallet?.sdkBasePath\n ?? '/sdk',\n rpIdOverride: overrides.iframeWallet?.rpIdOverride\n ?? defaults.iframeWallet?.rpIdOverride,\n }\n };\n if (!merged.contractId) {\n throw new Error('[configPresets] Missing required config: contractId');\n }\n if (!merged.relayer.url) {\n throw new Error('[configPresets] Missing required config: relayer.url');\n }\n return merged;\n}\n"],"mappings":";;;AAsEA,SAAgB,oBAAoB,YAAgC,IAAmB;CAErF,MAAM,WAAW;CACjB,MAAM,aAAa,UAAU,SAAS,OAAO,SAAS,SAAS,OAAO;CAGtE,MAAM,wBAAwB;CAE9B,MAAMA,SAAwB;EAC5B,YAAY,UAAU,cAAc,SAAS;EAC7C,aAAa,UAAU,eAAe,SAAS;EAC/C,YAAY,UAAU,cAAc,SAAS;EAC7C,iBAAiB,UAAU,mBAAmB,SAAS;EACvD,aAAa,UAAU,eAAe,SAAS;EAC/C,wBAAwB;GACtB,OAAO,UAAU,wBAAwB,SACpC,SAAS,wBAAwB;GACtC,eAAe,UAAU,wBAAwB,iBAC5C,SAAS,wBAAwB;;EAExC,SAAS;GACP,KAAK;GACL,qBAAqB,UAAU,SAAS,uBACnC,SAAS,SAAS;GACvB,eAAe;IACb,iBAAiB,UAAU,SAAS,eAAe,mBAC9C,SAAS,SAAS,eAAe;IACtC,mBAAmB,UAAU,SAAS,eAAe,qBAChD,SAAS,SAAS,eAAe;IACtC,sBAAsB,UAAU,SAAS,eAAe,wBACnD,SAAS,SAAS,eAAe;IACtC,cAAc,UAAU,SAAS,eAAe,gBAC3C,SAAS,SAAS,eAAe;IACtC,eAAe,UAAU,SAAS,eAAe,iBAC5C,SAAS,SAAS,eAAe;;;EAG1C,sBAAsB,UAAU,wBAAwB,SAAS;EACjE,kBAAkB,EAChB,aAAa;GACX,GAAG,UAAU,kBAAkB,aAAa,KACvC,SAAS,kBAAkB,aAAa;GAC7C,gBAAgB,UAAU,kBAAkB,aAAa,kBACpD,SAAS,kBAAkB,aAAa,kBACxC;GACL,sBAAsB,UAAU,kBAAkB,aAAa,wBAC1D,SAAS,kBAAkB,aAAa;GAC7C,uBAAuB,UAAU,kBAAkB,aAAa,yBAC3D,SAAS,kBAAkB,aAAa;;EAGjD,wBAAwB;GACtB,8BAA8B,UAAU,wBAAwB,gCAC3D,SAAS,wBAAwB;GACtC,yBAAyB,UAAU,wBAAwB,2BACtD,SAAS,wBAAwB;GACtC,2BAA2B,UAAU,wBAAwB,6BACxD,SAAS,wBAAwB;;EAExC,cAAc;GACZ,cAAc,UAAU,cAAc,gBACjC,SAAS,cAAc;GAC5B,mBAAmB,UAAU,cAAc,qBACtC,SAAS,cAAc,qBACvB;GACL,aAAa,UAAU,cAAc,eAChC,SAAS,cAAc,eACvB;GACL,cAAc,UAAU,cAAc,gBACjC,SAAS,cAAc;;;AAGhC,KAAI,CAAC,OAAO,WACV,OAAM,IAAI,MAAM;AAElB,KAAI,CAAC,OAAO,QAAQ,IAClB,OAAM,IAAI,MAAM;AAElB,QAAO;;;;CA9IIC,kCAAiD;EAG5D,YAAY;EACZ,aAAa;EACb,YAAY;EACZ,iBAAiB;EAGjB,wBAAwB;GACtB,OAAO;GACP,eAAe;;EAEjB,SAAS;GAIP,KAAK;GACL,qBAAqB;GACrB,eAAe;IAEb,iBAAiB;IAEjB,mBAAmB;IAEnB,sBAAsB,OAAU;IAEhC,cAAc,OAAU;IAExB,eAAe;;;EAGnB,kBAAkB,EAChB,aAAa;GAEX,GAAG;GAGH,gBAAgB;GAChB,sBAAsB;GACtB,uBAAuB;;EAG3B,wBAAwB;GACtB,8BAA8B;GAC9B,yBAAyB;GACzB,2BAA2B;;EAG7B,cAAc;GACZ,cAAc;GACd,mBAAmB;GACnB,aAAa;GACb,cAAc;;;CAILC,mCAA2D;EACtE,8BAA8B,gCAAgC,uBAAuB;EACrF,yBAAyB,gCAAgC,uBAAuB;EAChF,2BAA2B,gCAAgC,uBAAuB"}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
import { __esm } from "../../../_virtual/rolldown_runtime.js";
|
|
1
2
|
import bs58 from "bs58";
|
|
2
3
|
import * as ed25519 from "@noble/ed25519";
|
|
3
4
|
|
|
4
5
|
//#region src/core/nearCrypto.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Ensure a key string has the NEAR Ed25519 prefix (`ed25519:`).
|
|
8
|
+
*
|
|
9
|
+
* - Accepts either `ed25519:<base58>` or a bare `<base58>` string.
|
|
10
|
+
* - Canonicalizes `ED25519:` → `ed25519:`.
|
|
11
|
+
* - If a different prefix is present (e.g. `secp256k1:`), returns the input unchanged.
|
|
12
|
+
*/
|
|
13
|
+
function ensureEd25519Prefix(value) {
|
|
14
|
+
const raw = String(value || "").trim();
|
|
15
|
+
if (!raw) return "";
|
|
16
|
+
if (/^[a-z0-9_]+:/i.test(raw)) {
|
|
17
|
+
if (/^ed25519:/i.test(raw)) return `${NEAR_ED25519_KEY_PREFIX}${raw.replace(/^ed25519:/i, "")}`;
|
|
18
|
+
return raw;
|
|
19
|
+
}
|
|
20
|
+
return `${NEAR_ED25519_KEY_PREFIX}${raw}`;
|
|
8
21
|
}
|
|
9
22
|
/**
|
|
10
23
|
* Creates a NEAR-compatible Ed25519 keypair formatted as strings:
|
|
@@ -17,14 +30,19 @@ async function createNearKeypair() {
|
|
|
17
30
|
const secret = new Uint8Array(64);
|
|
18
31
|
secret.set(seed, 0);
|
|
19
32
|
secret.set(pub, 32);
|
|
20
|
-
const publicKey =
|
|
21
|
-
const privateKey =
|
|
33
|
+
const publicKey = ensureEd25519Prefix(bs58.encode(pub));
|
|
34
|
+
const privateKey = ensureEd25519Prefix(bs58.encode(secret));
|
|
22
35
|
return {
|
|
23
36
|
publicKey,
|
|
24
37
|
privateKey
|
|
25
38
|
};
|
|
26
39
|
}
|
|
40
|
+
var NEAR_ED25519_KEY_PREFIX;
|
|
41
|
+
var init_nearCrypto = __esm({ "src/core/nearCrypto.ts": (() => {
|
|
42
|
+
NEAR_ED25519_KEY_PREFIX = "ed25519:";
|
|
43
|
+
}) });
|
|
27
44
|
|
|
28
45
|
//#endregion
|
|
29
|
-
|
|
46
|
+
init_nearCrypto();
|
|
47
|
+
export { createNearKeypair, ensureEd25519Prefix, init_nearCrypto };
|
|
30
48
|
//# sourceMappingURL=nearCrypto.js.map
|