@tatchi-xyz/sdk 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/dist/cjs/core/TatchiPasskey/emailRecovery.js +67 -45
  2. package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
  3. package/dist/cjs/core/TatchiPasskey/index.js +2 -1
  4. package/dist/cjs/core/TatchiPasskey/index.js.map +1 -1
  5. package/dist/cjs/core/TatchiPasskey/linkDevice.js +2 -1
  6. package/dist/cjs/core/TatchiPasskey/linkDevice.js.map +1 -1
  7. package/dist/cjs/core/TatchiPasskey/scanDevice.js +5 -3
  8. package/dist/cjs/core/TatchiPasskey/scanDevice.js.map +1 -1
  9. package/dist/cjs/core/WalletIframe/client/router.js +1 -1
  10. package/dist/cjs/core/WalletIframe/client/router.js.map +1 -1
  11. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
  12. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  13. package/dist/cjs/core/defaultConfigs.js +3 -7
  14. package/dist/cjs/core/defaultConfigs.js.map +1 -1
  15. package/dist/cjs/core/nearCrypto.js +29 -5
  16. package/dist/cjs/core/nearCrypto.js.map +1 -1
  17. package/dist/cjs/core/rpcCalls.js +56 -26
  18. package/dist/cjs/core/rpcCalls.js.map +1 -1
  19. package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-BCrFe5p3.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
  20. package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
  21. package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CRJrtxDb.css → ProfileDropdown-BG_6hcim.css} +1 -1
  22. package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
  23. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
  24. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
  25. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css → TouchIcon-C-RcGfr5.css} +1 -1
  26. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
  27. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
  28. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
  29. package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
  30. package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
  31. package/dist/cjs/react/components/PasskeyAuthMenu/client.js +30 -8
  32. package/dist/cjs/react/components/PasskeyAuthMenu/client.js.map +1 -1
  33. package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +22 -0
  34. package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
  35. package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
  36. package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
  37. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +254 -140
  38. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  39. package/dist/cjs/react/components/{ShowQRCode-CL4gsszN.css → ShowQRCode-CB0UCQ_h.css} +1 -1
  40. package/dist/cjs/react/components/{ShowQRCode-CL4gsszN.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
  41. package/dist/cjs/react/context/useSDKFlowRuntime.js +183 -0
  42. package/dist/cjs/react/context/useSDKFlowRuntime.js.map +1 -0
  43. package/dist/cjs/react/context/useTatchiContextValue.js +24 -15
  44. package/dist/cjs/react/context/useTatchiContextValue.js.map +1 -1
  45. package/dist/cjs/react/context/useTatchiWithSdkFlow.js +96 -0
  46. package/dist/cjs/react/context/useTatchiWithSdkFlow.js.map +1 -0
  47. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +1 -0
  48. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +67 -45
  49. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  50. package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js +2 -1
  51. package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
  52. package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
  53. package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
  54. package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
  55. package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
  56. package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js +1 -1
  57. package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
  58. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
  59. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  60. package/dist/cjs/react/sdk/src/core/defaultConfigs.js +3 -7
  61. package/dist/cjs/react/sdk/src/core/defaultConfigs.js.map +1 -1
  62. package/dist/cjs/react/sdk/src/core/nearCrypto.js +29 -5
  63. package/dist/cjs/react/sdk/src/core/nearCrypto.js.map +1 -1
  64. package/dist/cjs/react/sdk/src/core/rpcCalls.js +56 -26
  65. package/dist/cjs/react/sdk/src/core/rpcCalls.js.map +1 -1
  66. package/dist/cjs/server/email-recovery/emailParsers.js +2 -1
  67. package/dist/cjs/server/email-recovery/emailParsers.js.map +1 -1
  68. package/dist/cjs/server/email-recovery/index.js +6 -6
  69. package/dist/cjs/server/email-recovery/index.js.map +1 -1
  70. package/dist/cjs/server/email-recovery/rpcCalls.js +22 -3
  71. package/dist/cjs/server/email-recovery/rpcCalls.js.map +1 -1
  72. package/dist/cjs/server/router/cloudflare.js +8 -3
  73. package/dist/cjs/server/router/cloudflare.js.map +1 -1
  74. package/dist/cjs/server/router/express.js.map +1 -1
  75. package/dist/cjs/server/sdk/src/core/defaultConfigs.js +2 -4
  76. package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
  77. package/dist/cjs/server/sdk/src/core/nearCrypto.js +26 -7
  78. package/dist/cjs/server/sdk/src/core/nearCrypto.js.map +1 -1
  79. package/dist/esm/core/TatchiPasskey/emailRecovery.js +67 -45
  80. package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
  81. package/dist/esm/core/TatchiPasskey/index.js +2 -1
  82. package/dist/esm/core/TatchiPasskey/index.js.map +1 -1
  83. package/dist/esm/core/TatchiPasskey/linkDevice.js +2 -1
  84. package/dist/esm/core/TatchiPasskey/linkDevice.js.map +1 -1
  85. package/dist/esm/core/TatchiPasskey/scanDevice.js +5 -3
  86. package/dist/esm/core/TatchiPasskey/scanDevice.js.map +1 -1
  87. package/dist/esm/core/WalletIframe/client/router.js +1 -1
  88. package/dist/esm/core/WalletIframe/client/router.js.map +1 -1
  89. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
  90. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  91. package/dist/esm/core/defaultConfigs.js +3 -7
  92. package/dist/esm/core/defaultConfigs.js.map +1 -1
  93. package/dist/esm/core/nearCrypto.js +24 -6
  94. package/dist/esm/core/nearCrypto.js.map +1 -1
  95. package/dist/esm/core/rpcCalls.js +56 -26
  96. package/dist/esm/core/rpcCalls.js.map +1 -1
  97. package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-BCrFe5p3.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
  98. package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
  99. package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CRJrtxDb.css → ProfileDropdown-BG_6hcim.css} +1 -1
  100. package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
  101. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
  102. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DXFRw8ND.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
  103. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css → TouchIcon-C-RcGfr5.css} +1 -1
  104. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-DNgbAK_i.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
  105. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
  106. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DRwSoF8q.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
  107. package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
  108. package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
  109. package/dist/esm/react/components/PasskeyAuthMenu/client.js +30 -8
  110. package/dist/esm/react/components/PasskeyAuthMenu/client.js.map +1 -1
  111. package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +20 -0
  112. package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
  113. package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
  114. package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
  115. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +254 -140
  116. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  117. package/dist/esm/react/components/{ShowQRCode-CL4gsszN.css → ShowQRCode-CB0UCQ_h.css} +1 -1
  118. package/dist/esm/react/components/{ShowQRCode-CL4gsszN.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
  119. package/dist/esm/react/context/useSDKFlowRuntime.js +181 -0
  120. package/dist/esm/react/context/useSDKFlowRuntime.js.map +1 -0
  121. package/dist/esm/react/context/useTatchiContextValue.js +25 -16
  122. package/dist/esm/react/context/useTatchiContextValue.js.map +1 -1
  123. package/dist/esm/react/context/useTatchiWithSdkFlow.js +94 -0
  124. package/dist/esm/react/context/useTatchiWithSdkFlow.js.map +1 -0
  125. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +1 -1
  126. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +67 -45
  127. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  128. package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js +2 -1
  129. package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
  130. package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
  131. package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
  132. package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
  133. package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
  134. package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js +1 -1
  135. package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
  136. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
  137. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  138. package/dist/esm/react/sdk/src/core/defaultConfigs.js +3 -7
  139. package/dist/esm/react/sdk/src/core/defaultConfigs.js.map +1 -1
  140. package/dist/esm/react/sdk/src/core/nearCrypto.js +24 -6
  141. package/dist/esm/react/sdk/src/core/nearCrypto.js.map +1 -1
  142. package/dist/esm/react/sdk/src/core/rpcCalls.js +56 -26
  143. package/dist/esm/react/sdk/src/core/rpcCalls.js.map +1 -1
  144. package/dist/esm/react/styles/styles.css +58 -3
  145. package/dist/esm/sdk/{defaultConfigs-DpslkAQd.js → defaultConfigs-CfQDV-ya.js} +3 -7
  146. package/dist/esm/sdk/{getDeviceNumber-fXizNGQl.js → getDeviceNumber-BpernPnM.js} +4 -8
  147. package/dist/esm/sdk/getDeviceNumber-BpernPnM.js.map +1 -0
  148. package/dist/esm/sdk/offline-export-app.js +23 -6
  149. package/dist/esm/sdk/offline-export-app.js.map +1 -1
  150. package/dist/esm/sdk/{router-DuGYOd3G.js → router-BWtacLJg.js} +1 -1
  151. package/dist/esm/sdk/{rpcCalls-BQrJMTdg.js → rpcCalls-CYGJSCgm.js} +3 -3
  152. package/dist/esm/sdk/{rpcCalls-YVeUVMk2.js → rpcCalls-DZZSa-sk.js} +57 -27
  153. package/dist/esm/sdk/{transactions-bqaAwL4k.js → transactions-Cn9xTWlK.js} +2 -2
  154. package/dist/esm/sdk/{transactions-bqaAwL4k.js.map → transactions-Cn9xTWlK.js.map} +1 -1
  155. package/dist/esm/sdk/{transactions-BalIhtJ9.js → transactions-DfdwDQCn.js} +1 -1
  156. package/dist/esm/sdk/wallet-iframe-host.js +549 -557
  157. package/dist/esm/server/email-recovery/emailParsers.js +3 -1
  158. package/dist/esm/server/email-recovery/emailParsers.js.map +1 -1
  159. package/dist/esm/server/email-recovery/index.js +6 -6
  160. package/dist/esm/server/email-recovery/index.js.map +1 -1
  161. package/dist/esm/server/email-recovery/rpcCalls.js +22 -3
  162. package/dist/esm/server/email-recovery/rpcCalls.js.map +1 -1
  163. package/dist/esm/server/router/cloudflare.js +8 -3
  164. package/dist/esm/server/router/cloudflare.js.map +1 -1
  165. package/dist/esm/server/router/express.js.map +1 -1
  166. package/dist/esm/server/sdk/src/core/defaultConfigs.js +2 -4
  167. package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
  168. package/dist/esm/server/sdk/src/core/nearCrypto.js +26 -8
  169. package/dist/esm/server/sdk/src/core/nearCrypto.js.map +1 -1
  170. package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
  171. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +5 -4
  172. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
  173. package/dist/types/src/core/TatchiPasskey/index.d.ts +1 -1
  174. package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
  175. package/dist/types/src/core/TatchiPasskey/scanDevice.d.ts.map +1 -1
  176. package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts +1 -1
  177. package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts.map +1 -1
  178. package/dist/types/src/core/WalletIframe/client/router.d.ts +1 -1
  179. package/dist/types/src/core/WalletIframe/client/router.d.ts.map +1 -1
  180. package/dist/types/src/core/WalletIframe/shared/messages.d.ts +1 -1
  181. package/dist/types/src/core/WalletIframe/shared/messages.d.ts.map +1 -1
  182. package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts +2 -1
  183. package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts.map +1 -1
  184. package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
  185. package/dist/types/src/core/nearCrypto.d.ts +14 -0
  186. package/dist/types/src/core/nearCrypto.d.ts.map +1 -1
  187. package/dist/types/src/core/rpcCalls.d.ts +11 -8
  188. package/dist/types/src/core/rpcCalls.d.ts.map +1 -1
  189. package/dist/types/src/core/types/tatchi.d.ts +0 -4
  190. package/dist/types/src/core/types/tatchi.d.ts.map +1 -1
  191. package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts +2 -0
  192. package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts.map +1 -1
  193. package/dist/types/src/react/components/PasskeyAuthMenu/client.d.ts.map +1 -1
  194. package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts +10 -0
  195. package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts.map +1 -0
  196. package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts +8 -3
  197. package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts.map +1 -1
  198. package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts +2 -0
  199. package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts.map +1 -1
  200. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts +1 -1
  201. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
  202. package/dist/types/src/react/context/useSDKFlowRuntime.d.ts +10 -0
  203. package/dist/types/src/react/context/useSDKFlowRuntime.d.ts.map +1 -0
  204. package/dist/types/src/react/context/useTatchiContextValue.d.ts.map +1 -1
  205. package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts +9 -0
  206. package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts.map +1 -0
  207. package/dist/types/src/react/types.d.ts +31 -0
  208. package/dist/types/src/react/types.d.ts.map +1 -1
  209. package/dist/types/src/server/email-recovery/emailParsers.d.ts.map +1 -1
  210. package/dist/types/src/server/email-recovery/index.d.ts +5 -6
  211. package/dist/types/src/server/email-recovery/index.d.ts.map +1 -1
  212. package/dist/types/src/server/email-recovery/rpcCalls.d.ts +1 -0
  213. package/dist/types/src/server/email-recovery/rpcCalls.d.ts.map +1 -1
  214. package/dist/types/src/server/router/cloudflare-adaptor.d.ts.map +1 -1
  215. package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
  216. package/package.json +1 -1
  217. package/dist/esm/sdk/getDeviceNumber-fXizNGQl.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["tasks: Promise<unknown>[]","error: unknown","res","arr: SignTransactionResult[]","signOptions: DelegateActionHooksOptions | undefined","signResult: SignDelegateActionResult","relayOptions: DelegateRelayHooksOptions | undefined","relayResult: DelegateRelayResult","combined: SignAndSendDelegateActionResult","router: WalletIframeRouter","local: RecoveryEmailRecord[]","actions: ActionArgs[]"],"sources":["../../../../../../../src/core/TatchiPasskey/index.ts"],"sourcesContent":["import { WebAuthnManager } from '../WebAuthnManager';\nimport {\n loginAndCreateSession,\n getLoginSession,\n getRecentLogins,\n logoutAndClearSession,\n} from './login';\nimport {\n executeAction,\n signTransactionsWithActions,\n sendTransaction,\n signAndSendTransactions,\n} from './actions';\nimport { AccountRecoveryFlow, type RecoveryResult } from './recoverAccount';\nimport { registerPasskey } from './registration';\nimport { registerPasskeyInternal } from './registration';\nimport {\n MinimalNearClient,\n type NearClient,\n type SignedTransaction,\n type AccessKeyList,\n} from '../NearClient';\nimport type {\n ActionResult,\n DelegateRelayResult,\n GetRecentLoginsResult,\n LoginAndCreateSessionResult,\n LoginResult,\n LoginSession,\n LoginState,\n RegistrationResult,\n SignAndSendDelegateActionResult,\n SignDelegateActionResult,\n SignTransactionResult,\n TatchiConfigs,\n TatchiConfigsInput,\n} from '../types/tatchi';\nimport type {\n AccountRecoveryHooksOptions,\n ActionHooksOptions,\n DelegateActionHooksOptions,\n DelegateRelayHooksOptions,\n LoginHooksOptions,\n RegistrationHooksOptions,\n SendTransactionHooksOptions,\n SignAndSendDelegateActionHooksOptions,\n SignAndSendTransactionHooksOptions,\n SignNEP413HooksOptions,\n SignTransactionHooksOptions,\n} from '../types/sdkSentEvents';\nimport { ActionPhase, ActionStatus } from '../types/sdkSentEvents';\nimport { ConfirmationConfig, type WasmSignedDelegate } from '../types/signer-worker';\nimport { DEFAULT_AUTHENTICATOR_OPTIONS } from '../types/authenticatorOptions';\nimport { toAccountId, type AccountId } from '../types/accountIds';\nimport type { DerivedAddressRecord, RecoveryEmailRecord } from '../IndexedDBManager';\nimport { configureIndexedDB } from '../IndexedDBManager';\nimport { chainsigAddressManager } from '../ChainsigAddressManager';\nimport { ActionType, type ActionArgs, type TransactionInput } from '../types/actions';\nimport type {\n DeviceLinkingQRData,\n LinkDeviceResult,\n ScanAndLinkDeviceOptionsDevice1,\n StartDevice2LinkingFlowArgs,\n StartDevice2LinkingFlowResults\n} from '../types/linkDevice';\nimport { LinkDeviceFlow } from './linkDevice';\nimport { linkDeviceWithScannedQRData } from './scanDevice';\nimport {\n signNEP413Message,\n type SignNEP413MessageParams,\n type SignNEP413MessageResult\n} from './signNEP413';\nimport { signDelegateAction } from './delegateAction';\nimport { SignedDelegate } from '../types/delegate';\nimport { sendDelegateActionViaRelayer } from './relay';\nimport type { UserPreferencesManager } from '../WebAuthnManager/userPreferences';\nimport type { WalletIframeRouter } from '../WalletIframe/client/router';\nimport { __isWalletIframeHostMode } from '../WalletIframe/host-mode';\nimport { toError } from '../../utils/errors';\nimport { isOffline, openOfflineExport } from '../OfflineExport';\nimport { buildSetRecoveryEmailsActions, getRecoveryEmailHashesContractCall } from '../rpcCalls';\nimport {\n prepareRecoveryEmails,\n getLocalRecoveryEmails,\n bytesToHex,\n} from '../EmailRecovery';\nimport type { DelegateActionInput } from '../types/delegate';\nimport { buildConfigsFromEnv } from '../defaultConfigs';\nimport { EmailRecoveryFlowOptions } from './emailRecovery';\n\n///////////////////////////////////////\n// PASSKEY MANAGER\n///////////////////////////////////////\n\nexport interface PasskeyManagerContext {\n webAuthnManager: WebAuthnManager;\n nearClient: NearClient;\n configs: TatchiConfigs;\n}\n\nlet warnedAboutSameOriginWallet = false;\n\n/**\n * Main TatchiPasskey class that provides framework-agnostic passkey operations\n * with flexible event-based callbacks for custom UX implementation\n */\nexport class TatchiPasskey {\n private readonly webAuthnManager: WebAuthnManager;\n private readonly nearClient: NearClient;\n readonly configs: TatchiConfigs;\n private iframeRouter: WalletIframeRouter | null = null;\n // Deduplicate concurrent initWalletIframe() calls to avoid mounting multiple iframes.\n private walletIframeInitInFlight: Promise<void> | null = null;\n // Wallet-iframe mode: mirror wallet-host preferences into app-origin in-memory cache.\n private walletIframePrefsUnsubscribe: (() => void) | null = null;\n // Internal active Device2 flow when running locally (not exposed)\n private activeDeviceLinkFlow: LinkDeviceFlow | null = null;\n private activeAccountRecoveryFlow: AccountRecoveryFlow | null = null;\n private activeEmailRecoveryFlow: import('./emailRecovery').EmailRecoveryFlow | null = null;\n\n constructor(\n configs: TatchiConfigsInput,\n nearClient?: NearClient\n ) {\n this.configs = buildConfigsFromEnv(configs);\n // Configure IndexedDB naming before any local persistence is touched.\n // - Wallet iframe host keeps canonical DB names.\n // - App origin disables IndexedDB entirely when iframe mode is enabled.\n const mode = __isWalletIframeHostMode()\n ? 'wallet'\n : (this.configs.iframeWallet?.walletOrigin ? 'disabled' : 'legacy');\n configureIndexedDB({ mode });\n // Use provided client or create default one\n this.nearClient = nearClient || new MinimalNearClient(this.configs.nearRpcUrl);\n this.webAuthnManager = new WebAuthnManager(this.configs, this.nearClient);\n // VRF worker initializes automatically in the constructor\n }\n\n /**\n * Direct access to user preferences manager for convenience\n * Example: passkeyManager.userPreferences.onThemeChange(cb)\n */\n get userPreferences(): UserPreferencesManager {\n return this.webAuthnManager.getUserPreferences();\n }\n\n /**\n * Initialize the hidden wallet service iframe client (optional) and warm critical resources.\n * Always warms local resources; initializes iframe when `walletOrigin` is provided.\n * Idempotent and safe to call multiple times.\n */\n async initWalletIframe(nearAccountId?: string): Promise<void> {\n const walletOriginConfigured = !!this.configs.iframeWallet?.walletOrigin;\n // Warm local critical resources (NonceManager, workers) regardless of iframe usage.\n // In iframe mode, avoid persisting user state (lastUserAccountId, preferences) on the app origin.\n const shouldAvoidLocalUserState = walletOriginConfigured && !__isWalletIframeHostMode();\n await this.webAuthnManager.warmCriticalResources(shouldAvoidLocalUserState ? undefined : nearAccountId);\n\n // Guardrail: when running inside the wallet service iframe host, never attempt to\n // initialize a nested wallet iframe client, even if configs accidentally include iframeWallet.\n // The host runs the real TatchiPasskey instance and must remain self-contained.\n if (__isWalletIframeHostMode()) {\n return;\n }\n\n const walletIframeConfig = this.configs.iframeWallet;\n const walletOrigin = walletIframeConfig?.walletOrigin;\n // If no wallet origin configured, we're done after local warm-up\n if (!walletOrigin) {\n // Reflect local login state so callers depending on init() get fresh status\n await this.getLoginSession(nearAccountId);\n return;\n }\n\n // Emit same-origin co-hosting warning only when actually initializing the iframe\n if (!warnedAboutSameOriginWallet) {\n try {\n const isWalletIframeHost = __isWalletIframeHostMode();\n const parsed = new URL(walletOrigin);\n if (typeof window !== 'undefined' && parsed.origin === window.location.origin && !isWalletIframeHost) {\n warnedAboutSameOriginWallet = true;\n console.warn('[TatchiPasskey] iframeWallet.walletOrigin matches the host origin. Consider moving the wallet to a dedicated origin for stronger isolation.');\n }\n } catch {\n // ignore invalid URL here; constructor downstream will surface an error\n }\n }\n\n // Initialize iframe router once (and prevent concurrent calls from mounting multiple iframes).\n if (!this.iframeRouter) {\n if (!this.walletIframeInitInFlight) {\n this.walletIframeInitInFlight = (async () => {\n const { WalletIframeRouter } = await import('../WalletIframe/client/router');\n this.iframeRouter = new WalletIframeRouter({\n walletOrigin,\n servicePath: walletIframeConfig?.walletServicePath || '/wallet-service',\n connectTimeoutMs: 20_000, // 20s\n requestTimeoutMs: 60_000, // 60s\n theme: this.configs.walletTheme,\n nearRpcUrl: this.configs.nearRpcUrl,\n nearNetwork: this.configs.nearNetwork,\n contractId: this.configs.contractId,\n nearExplorerUrl: this.configs.nearExplorerUrl,\n // Ensure relay server config reaches the wallet host for atomic registration\n relayer: this.configs.relayer,\n vrfWorkerConfigs: this.configs.vrfWorkerConfigs,\n emailRecoveryContracts: this.configs.emailRecoveryContracts,\n rpIdOverride: walletIframeConfig?.rpIdOverride,\n // Allow apps/CI to control where embedded bundles are served from\n sdkBasePath: walletIframeConfig?.sdkBasePath,\n });\n\n await this.iframeRouter.init();\n // Opportunistically warm remote NonceManager\n try { await this.iframeRouter.prefetchBlockheight(); } catch {}\n })();\n }\n\n try {\n await this.walletIframeInitInFlight;\n } finally {\n this.walletIframeInitInFlight = null;\n }\n } else {\n await this.iframeRouter.init();\n // Opportunistically warm remote NonceManager\n try { await this.iframeRouter.prefetchBlockheight(); } catch {}\n }\n\n // Wallet-iframe mode: keep app-origin UI prefs in sync with the wallet host.\n if (this.iframeRouter) {\n this.ensureWalletIframePreferencesMirror(this.iframeRouter);\n // Best-effort pull snapshot to cover missed events / older hosts.\n const cfg = await this.iframeRouter.getConfirmationConfig().catch(() => null);\n if (cfg) {\n this.userPreferences.applyWalletHostConfirmationConfig({\n nearAccountId: nearAccountId ? toAccountId(nearAccountId) : null,\n confirmationConfig: cfg,\n });\n }\n }\n\n await this.getLoginSession(nearAccountId);\n }\n\n /** Get the wallet iframe client if initialized. */\n getWalletIframeClient(): WalletIframeRouter | null {\n return this.iframeRouter;\n }\n\n private ensureWalletIframePreferencesMirror(router: WalletIframeRouter): void {\n if (this.walletIframePrefsUnsubscribe) return;\n const unsubscribe = router.onPreferencesChanged?.(payload => {\n const id = payload?.nearAccountId;\n const nearAccountId = id ? toAccountId(id) : null;\n this.userPreferences.applyWalletHostConfirmationConfig({\n nearAccountId,\n confirmationConfig: payload?.confirmationConfig,\n });\n });\n this.walletIframePrefsUnsubscribe = unsubscribe ?? null;\n }\n\n /**\n * True when the SDK is running on the app origin with a wallet iframe configured.\n * In this mode, sensitive persistence must live in the wallet-iframe origin.\n */\n private shouldUseWalletIframe(): boolean {\n return !!this.configs.iframeWallet?.walletOrigin && !__isWalletIframeHostMode();\n }\n\n private async requireWalletIframeRouter(nearAccountId?: string): Promise<WalletIframeRouter> {\n if (!this.shouldUseWalletIframe()) {\n throw new Error('[TatchiPasskey] Wallet iframe is not configured.');\n }\n if (!this.iframeRouter) {\n await this.initWalletIframe(nearAccountId);\n }\n if (!this.iframeRouter) {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable.');\n }\n return this.iframeRouter;\n }\n\n getContext(): PasskeyManagerContext {\n return {\n webAuthnManager: this.webAuthnManager,\n nearClient: this.nearClient,\n configs: this.configs\n }\n }\n\n getNearClient(): NearClient {\n return this.nearClient;\n }\n\n /**\n * Warm critical resources: delegates to WebAuthnManager and ensures iframe handshake when configured.\n */\n async warmCriticalResources(nearAccountId?: string): Promise<void> {\n // Maintain backward compatibility: delegate to consolidated init\n await this.initWalletIframe(nearAccountId);\n }\n\n /**\n * Pre-warm resources on a best-effort basis without changing visible state.\n * - When iframe=true, initializes the wallet iframe client (and warms local resources).\n * - When workers=true, warms local critical resources (nonce, IndexedDB, workers) without touching iframe.\n * - When both are false/omitted, does nothing.\n */\n async prewarm(opts?: { iframe?: boolean; workers?: boolean; nearAccountId?: string }): Promise<void> {\n const iframe = !!opts?.iframe;\n const workers = !!opts?.workers;\n const nearAccountId = opts?.nearAccountId;\n\n const tasks: Promise<unknown>[] = [];\n\n if (iframe) {\n // initWalletIframe also calls WebAuthnManager.warmCriticalResources internally\n tasks.push(this.initWalletIframe(nearAccountId));\n } else if (workers) {\n // Warm local-only resources without touching the iframe.\n // In iframe mode, avoid persisting user state (lastUserAccountId, preferences) on the app origin.\n const shouldAvoidLocalUserState = !!this.configs.iframeWallet?.walletOrigin && !__isWalletIframeHostMode();\n tasks.push(this.webAuthnManager.warmCriticalResources(shouldAvoidLocalUserState ? undefined : nearAccountId));\n }\n\n if (tasks.length === 0) return;\n try {\n await Promise.all(tasks);\n } catch {\n // Best-effort: swallow errors so prewarm never breaks app flows\n }\n }\n\n /**\n * View all access keys for a given account\n * @param accountId - NEAR account ID to view access keys for\n * @returns Promise resolving to access key list\n */\n async viewAccessKeyList(accountId: string): Promise<AccessKeyList> {\n if (this.iframeRouter) {\n return await this.iframeRouter.viewAccessKeyList(accountId);\n }\n return this.nearClient.viewAccessKeyList(accountId);\n }\n\n ///////////////////////////////////////\n // === Registration and Login ===\n ///////////////////////////////////////\n\n /**\n * Register a new passkey for the given NEAR account ID\n * Uses AccountId for on-chain operations and PRF salt derivation\n */\n async registerPasskey(\n nearAccountId: string,\n options: RegistrationHooksOptions = {}\n ): Promise<RegistrationResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const confirmationConfig = options?.confirmationConfig;\n const res = await router.registerPasskey({\n nearAccountId,\n confirmationConfig,\n options: {\n onEvent: options?.onEvent,\n ...(options?.confirmerText ? { confirmerText: options.confirmerText } : {})\n }\n });\n // Opportunistically warm resources (non-blocking)\n void (async () => { try { await this.warmCriticalResources(nearAccountId); } catch {} })();\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n return registerPasskey(\n this.getContext(),\n toAccountId(nearAccountId),\n options,\n this.configs.authenticatorOptions || DEFAULT_AUTHENTICATOR_OPTIONS,\n );\n }\n\n /**\n * Internal variant that accepts a one-time confirmationConfig override.\n * Used by wallet-iframe host to force modal/autoProceed behavior for ArrowButtonLit.\n */\n async registerPasskeyInternal(\n nearAccountId: string,\n options: RegistrationHooksOptions = {},\n confirmationConfigOverride?: ConfirmationConfig\n ): Promise<RegistrationResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const confirmationConfig = confirmationConfigOverride ?? options?.confirmationConfig;\n const res = await router.registerPasskey({\n nearAccountId,\n confirmationConfig,\n options: {\n onEvent: options?.onEvent,\n ...(options?.confirmerText ? { confirmerText: options.confirmerText } : {})\n }\n });\n void (async () => { try { await this.warmCriticalResources(nearAccountId); } catch {} })();\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n // App-wallet path: call core internal with override\n return registerPasskeyInternal(\n this.getContext(),\n toAccountId(nearAccountId),\n options,\n this.configs.authenticatorOptions || DEFAULT_AUTHENTICATOR_OPTIONS,\n confirmationConfigOverride,\n );\n }\n\n /**\n * Login and ensure a warm signing session exists.\n * - Unlocks VRF keypair (Shamir auto-unlock when possible; else WebAuthn prompt)\n * - Mints a warm signing session (policy from configs, override via options.signingSession)\n * - Optional: mints a server session (JWT/cookie) via options.session\n */\n async loginAndCreateSession(\n nearAccountId: string,\n options?: LoginHooksOptions\n ): Promise<LoginAndCreateSessionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n // Forward serializable options to wallet host, including session config\n const res = await router.loginAndCreateSession({\n nearAccountId,\n options: {\n onEvent: options?.onEvent,\n // Pass through session so the wallet host calls relay to mint JWT/cookie sessions\n session: options?.session,\n signingSession: options?.signingSession,\n }\n });\n // Best-effort warm-up after successful login (non-blocking)\n void (async () => { try { await this.warmCriticalResources(nearAccountId); } catch {} })();\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n // Initialize current user before login\n await this.webAuthnManager.initializeCurrentUser(toAccountId(nearAccountId), this.nearClient);\n const res = await loginAndCreateSession(this.getContext(), toAccountId(nearAccountId), options);\n // Best-effort warm-up after successful login (non-blocking)\n try { void this.warmCriticalResources(nearAccountId); } catch {}\n return res;\n }\n\n /**\n * Logout: clears VRF keypair and all in-worker session state.\n */\n async logoutAndClearSession(): Promise<void> {\n await logoutAndClearSession(this.getContext());\n // Also clear wallet-origin VRF session if service iframe is active\n if (this.iframeRouter) {\n try { await this.iframeRouter.clearVrfSession?.(); } catch {}\n }\n }\n\n /**\n * Read login state + warm signing session status (no prompts).\n */\n async getLoginSession(nearAccountId?: string): Promise<LoginSession> {\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const session = await router.getLoginSession(nearAccountId);\n try { await router.prefetchBlockheight(); } catch {}\n return session;\n }\n return await getLoginSession(this.getContext(), nearAccountId ? toAccountId(nearAccountId) : undefined);\n }\n\n /**\n * Get check if accountId has a passkey from IndexedDB\n */\n async hasPasskeyCredential(nearAccountId: AccountId): Promise<boolean> {\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter();\n return await router.hasPasskeyCredential(nearAccountId);\n }\n const baseAccountId = toAccountId(nearAccountId);\n return await this.webAuthnManager.hasPasskeyCredential(baseAccountId);\n }\n\n ///////////////////////////////////////\n // === User Settings ===\n ///////////////////////////////////////\n\n /**\n * Set confirmation behavior setting for the current user\n */\n setConfirmBehavior(behavior: 'requireClick' | 'autoProceed'): void {\n if (this.shouldUseWalletIframe()) {\n // Fire and forget; persistence handled in wallet host. Avoid unhandled rejections.\n void (async () => {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.setConfirmBehavior(behavior);\n } catch {}\n })();\n return;\n }\n this.webAuthnManager.getUserPreferences().setConfirmBehavior(behavior);\n }\n\n /**\n * Set the unified confirmation configuration\n */\n setConfirmationConfig(config: ConfirmationConfig): void {\n if (this.shouldUseWalletIframe()) {\n // Fire and forget; avoid unhandled rejections in consumers\n void (async () => {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.setConfirmationConfig(config);\n } catch {}\n })();\n return;\n }\n this.webAuthnManager.getUserPreferences().setConfirmationConfig(config);\n }\n\n setUserTheme(theme: 'dark' | 'light'): void {\n if (this.shouldUseWalletIframe()) {\n void (async () => {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.setTheme(theme);\n } catch {}\n })();\n return;\n }\n this.webAuthnManager.getUserPreferences().setUserTheme(theme);\n }\n\n /**\n * Get the current confirmation configuration\n */\n getConfirmationConfig(): ConfirmationConfig {\n // Prefer wallet host value when available\n // Note: synchronous signature; returns last-known local value if iframe reply is async\n // Callers needing fresh remote value should use TatchiPasskeyIframe directly.\n return this.webAuthnManager.getUserPreferences().getConfirmationConfig();\n }\n\n /**\n * Prefetch latest block height/hash (and nonce if context missing) to reduce\n * perceived latency when the user initiates a signing flow.\n */\n async prefetchBlockheight(): Promise<void> {\n if (this.iframeRouter) {\n await this.iframeRouter.prefetchBlockheight();\n return;\n }\n try { await this.webAuthnManager.getNonceManager().prefetchBlockheight(this.nearClient); } catch {}\n }\n\n async getRecentLogins(): Promise<GetRecentLoginsResult> {\n // In iframe mode, do not fall back to app-origin IndexedDB.\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n return await router.getRecentLogins();\n } catch {\n return { accountIds: [], lastUsedAccount: null };\n }\n }\n\n return getRecentLogins(this.getContext());\n }\n\n ///////////////////////////////////////\n // === Transactions ===\n ///////////////////////////////////////\n\n /**\n * Execute a NEAR blockchain action using passkey-derived credentials\n * Supports all NEAR action types: Transfer, FunctionCall, AddKey, etc.\n *\n * @param nearAccountId - NEAR account ID to execute action with\n * @param actionArgs - Action to execute (single action or array for batched transactions)\n * @param options - Action options for event handling\n * - onEvent: EventCallback<ActionSSEEvent> - Optional event callback\n * - onError: (error: Error) => void - Optional error callback\n * - afterCall: AfterCall - Optional after call hooks\n * - waitUntil: TxExecutionStatus - Optional waitUntil status\n * @returns Promise resolving to action result\n *\n * @example\n * ```typescript\n * // Basic transfer\n * const result = await passkeyManager.executeAction('alice.near', {\n * type: ActionType.Transfer,\n * receiverId: 'bob.near',\n * amount: '1000000000000000000000000' // 1 NEAR\n * });\n *\n * // Function call with gas and deposit (already available in ActionArgs)\n * const result = await passkeyManager.executeAction('alice.near', {\n * type: ActionType.FunctionCall,\n * receiverId: 'contract.near',\n * methodName: 'set_value',\n * args: { value: 42 },\n * gas: '50000000000000', // 50 TGas\n * deposit: '100000000000000000000000' // 0.1 NEAR\n * });\n *\n * // Batched transaction\n * const result = await passkeyManager.executeAction('alice.near', [\n * {\n * type: ActionType.Transfer,\n * receiverId: 'bob.near',\n * amount: '1000000000000000000000000'\n * },\n * {\n * type: ActionType.FunctionCall,\n * receiverId: 'contract.near',\n * methodName: 'log_transfer',\n * args: { recipient: 'bob.near' }\n * }\n * ], {\n * onEvent: (event) => console.log('Action progress:', event)\n * });\n * ```\n */\n async executeAction(args: {\n nearAccountId: string,\n receiverId: string,\n actionArgs: ActionArgs | ActionArgs[],\n options?: ActionHooksOptions\n }): Promise<ActionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(args.nearAccountId);\n const confirmerText = args.options?.confirmerText;\n const res = await router.executeAction({\n nearAccountId: args.nearAccountId,\n receiverId: args.receiverId,\n actionArgs: args.actionArgs,\n options: {\n onEvent: args.options?.onEvent,\n waitUntil: args.options?.waitUntil,\n confirmationConfig: args.options?.confirmationConfig,\n confirmerText,\n }\n });\n await args.options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await args.options?.onError?.(e);\n await args.options?.afterCall?.(false);\n throw e;\n }\n }\n // same-origin mode\n return executeAction({\n context: this.getContext(),\n nearAccountId: toAccountId(args.nearAccountId),\n receiverId: toAccountId(args.receiverId),\n actionArgs: args.actionArgs,\n options: args.options\n });\n }\n\n /**\n * Sign and send multiple transactions with actions\n * This method signs transactions with actions and sends them to the network\n *\n * @param nearAccountId - NEAR account ID to sign and send transactions with\n * @param transactionInputs - Transaction inputs to sign and send\n * @param options - Sign and send transaction options\n * - onEvent: EventCallback<ActionSSEEvent> - Optional event callback\n * - onError: (error: Error) => void - Optional error callback\n * - afterCall: AfterCall - Optional after call hooks\n * - waitUntil: TxExecutionStatus - Optional waitUntil status\n * - executeSequentially: boolean - Wait for each transaction to finish before sending the next (default: true)\n * @returns Promise resolving to action results\n *\n * @example\n * ```typescript\n * // Sign and send multiple transactions in a batch\n * const results = await passkeyManager.signAndSendTransactions('alice.near', {\n * transactions: [\n * {\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * },\n * {\n * receiverId: 'contract.near',\n * actions: [{\n * action_type: ActionType.FunctionCall,\n * method_name: 'log_transfer',\n * args: JSON.stringify({ recipient: 'bob.near' }),\n * gas: '30000000000000',\n * deposit: '0'\n * }],\n * }\n * ],\n * options: {\n * onEvent: (event) => console.log('Signing and sending progress:', event)\n * executeSequentially: true\n * }\n * });\n * ```\n */\n async signAndSendTransactions({\n nearAccountId,\n transactions,\n options = {}\n }: {\n nearAccountId: string,\n transactions: TransactionInput[],\n options?: SignAndSendTransactionHooksOptions,\n }): Promise<ActionResult[]> {\n\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const confirmerText = options?.confirmerText;\n const res = await router.signAndSendTransactions({\n nearAccountId,\n transactions: transactions.map(t => ({ receiverId: t.receiverId, actions: t.actions })),\n options: {\n onEvent: options?.onEvent,\n executionWait: options?.executionWait ?? { mode: 'sequential', waitUntil: options?.waitUntil },\n confirmationConfig: options?.confirmationConfig,\n confirmerText,\n }\n });\n // Emit completion\n const txIds = (res || []).map(r => r?.transactionId).filter(Boolean).join(', ');\n options?.onEvent?.({ step: 8, phase: ActionPhase.STEP_8_ACTION_COMPLETE, status: ActionStatus.SUCCESS, message: `All transactions sent: ${txIds}` });\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return signAndSendTransactions({\n context: this.getContext(),\n nearAccountId: toAccountId(nearAccountId),\n transactionInputs: transactions,\n options\n }).then(txResults => {\n const txIds = txResults.map(txResult => txResult.transactionId).join(', ');\n options?.onEvent?.({\n step: 8,\n phase: ActionPhase.STEP_8_ACTION_COMPLETE,\n status: ActionStatus.SUCCESS,\n message: `All transactions sent: ${txIds}`\n });\n return txResults;\n });\n }\n\n /**\n * Convenience helper to sign and send a single transaction with actions.\n * Internally delegates to signAndSendTransactions() and returns the first result.\n */\n async signAndSendTransaction({\n nearAccountId,\n receiverId,\n actions,\n options = {}\n }: {\n nearAccountId: string;\n receiverId: string;\n actions: ActionArgs[];\n options?: SignAndSendTransactionHooksOptions;\n }): Promise<ActionResult> {\n const results = await this.signAndSendTransactions({\n nearAccountId,\n transactions: [\n {\n receiverId,\n actions\n }\n ],\n options\n });\n return results[0] as ActionResult;\n }\n\n /**\n * Batch sign transactions (with actions), allows you to sign transactions\n * to different receivers with a single TouchID prompt.\n * This method does not broadcast transactions, use sendTransaction() to do that.\n *\n * This method fetches the current nonce and increments it for the next N transactions,\n * so you do not need to manually increment the nonce for each transaction.\n *\n * @param nearAccountId - NEAR account ID to sign transactions with\n * @param params - Transaction signing parameters\n * - @param params.transactions: Array of transaction objects with nearAccountId, receiverId, actions, and nonce\n * - @param params.onEvent: Optional progress event callback\n * @returns Promise resolving to signed transaction results\n *\n * @example\n * ```typescript\n * // Sign a single transaction\n * const signedTransactions = await passkeyManager.signTransactionsWithActions('alice.near', {\n * transactions: [{\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * }],\n * onEvent: (event) => console.log('Signing progress:', event)\n * });\n *\n * // Sign multiple transactions in a batch\n * const signedTransactions = await passkeyManager.signTransactionsWithActions('alice.near', {\n * transactions: [\n * {\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * },\n * {\n * receiverId: 'contract.near',\n * actions: [{\n * action_type: ActionType.FunctionCall,\n * method_name: 'log_transfer',\n * args: JSON.stringify({ recipient: 'bob.near' }),\n * gas: '30000000000000',\n * deposit: '0'\n * }],\n * }\n * ]\n * });\n * ```\n */\n async signTransactionsWithActions({ nearAccountId, transactions, options }: {\n nearAccountId: string,\n transactions: TransactionInput[],\n options?: SignTransactionHooksOptions\n }): Promise<SignTransactionResult[]> {\n // route signing via wallet origin\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const txs = transactions.map((t) => ({ receiverId: t.receiverId, actions: t.actions }));\n const confirmerText = options?.confirmerText;\n const result = await router.signTransactionsWithActions({\n nearAccountId, transactions:\n txs,\n options: {\n onEvent: options?.onEvent,\n confirmationConfig: options?.confirmationConfig,\n confirmerText,\n }\n });\n const arr: SignTransactionResult[] = Array.isArray(result) ? result : [];\n await options?.afterCall?.(true, arr);\n return arr;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return signTransactionsWithActions({\n context: this.getContext(),\n nearAccountId: toAccountId(nearAccountId),\n transactionInputs: transactions,\n options\n });\n }\n\n /**\n * Send a signed transaction to the NEAR network\n * This method broadcasts a previously signed transaction and waits for execution\n *\n * @param signedTransaction - The signed transaction to broadcast\n * @param waitUntil - The execution status to wait for (defaults to FINAL)\n * @returns Promise resolving to the transaction execution outcome\n *\n * @example\n * ```typescript\n * // Sign a transaction first\n * const signedTransactions = await passkeyManager.signTransactionsWithActions('alice.near', {\n * transactions: [{\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * }]\n * });\n *\n * // Then broadcast it\n * const result = await passkeyManager.sendTransaction(\n * signedTransactions[0].signedTransaction,\n * TxExecutionStatus.FINAL\n * );\n * ```\n */\n async sendTransaction({ signedTransaction, options }: {\n signedTransaction: SignedTransaction,\n options?: SendTransactionHooksOptions\n }): Promise<ActionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n const res = await router.sendTransaction({\n signedTransaction,\n options: {\n onEvent: options?.onEvent,\n ...(options && ('waitUntil' in options)\n ? { waitUntil: options.waitUntil }\n : {})\n }\n });\n await options?.afterCall?.(true, res);\n options?.onEvent?.({ step: 8, phase: ActionPhase.STEP_8_ACTION_COMPLETE, status: ActionStatus.SUCCESS, message: `Transaction ${res?.transactionId} broadcasted` });\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return sendTransaction({ context: this.getContext(), signedTransaction, options })\n .then(txResult => {\n options?.onEvent?.({ step: 8, phase: ActionPhase.STEP_8_ACTION_COMPLETE, status: ActionStatus.SUCCESS, message: `Transaction ${txResult.transactionId} broadcasted` });\n return txResult;\n });\n }\n\n ///////////////////////////////////////\n // === DELEGATE ACTION SIGNING (NEP-461) ===\n ///////////////////////////////////////\n\n async signDelegateAction({\n nearAccountId,\n delegate,\n options,\n }: {\n nearAccountId: string;\n delegate: DelegateActionInput;\n options?: DelegateActionHooksOptions;\n }): Promise<SignDelegateActionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const result = await router.signDelegateAction({\n nearAccountId,\n delegate,\n options: {\n onEvent: options?.onEvent,\n confirmationConfig: options?.confirmationConfig,\n confirmerText: options?.confirmerText,\n }\n }) as SignDelegateActionResult;\n await options?.afterCall?.(true, result);\n return result;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return signDelegateAction({\n context: this.getContext(),\n nearAccountId: toAccountId(nearAccountId),\n delegate,\n options,\n });\n }\n\n /**\n * Convenience helper to POST a signed delegate to a relayer.\n * Does not enforce any relayer semantics; simply forwards the payload.\n */\n async sendDelegateActionViaRelayer(args: {\n relayerUrl: string;\n signedDelegate: SignedDelegate | WasmSignedDelegate;\n hash: string;\n signal?: AbortSignal;\n options?: DelegateRelayHooksOptions;\n }): Promise<DelegateRelayResult> {\n const base = args.relayerUrl.replace(/\\/+$/, '');\n const route = (this.configs.relayer?.delegateActionRoute || '/signed-delegate').replace(/^\\/?/, '/');\n const endpoint = `${base}${route}`;\n return sendDelegateActionViaRelayer({\n url: endpoint,\n payload: {\n hash: args.hash,\n signedDelegate: args.signedDelegate,\n },\n signal: args.signal,\n options: args.options,\n });\n }\n\n /**\n * Convenience helper to sign a delegate action and immediately forward it to the relayer.\n * Emits delegate signing events and relay broadcasting events through the provided options.\n */\n async signAndSendDelegateAction(args: {\n nearAccountId: string;\n delegate: DelegateActionInput;\n relayerUrl: string;\n signal?: AbortSignal;\n options?: SignAndSendDelegateActionHooksOptions;\n }): Promise<SignAndSendDelegateActionResult> {\n const { nearAccountId, delegate, relayerUrl, signal, options } = args;\n\n const signOptions: DelegateActionHooksOptions | undefined = options\n ? {\n onEvent: options.onEvent,\n onError: options.onError,\n waitUntil: options.waitUntil,\n confirmationConfig: options.confirmationConfig,\n confirmerText: options.confirmerText,\n // suppress afterCall so we can call afterCall() once at the end of the lifecycle.\n afterCall: () => {},\n }\n : undefined;\n\n let signResult: SignDelegateActionResult;\n try {\n signResult = await this.signDelegateAction({\n nearAccountId,\n delegate,\n options: signOptions,\n });\n } catch (error) {\n await options?.afterCall?.(false);\n throw error;\n }\n\n const relayOptions: DelegateRelayHooksOptions | undefined = options\n ? {\n onEvent: options.onEvent,\n onError: options.onError,\n }\n : undefined;\n\n let relayResult: DelegateRelayResult;\n try {\n relayResult = await this.sendDelegateActionViaRelayer({\n relayerUrl,\n hash: signResult.hash,\n signedDelegate: signResult.signedDelegate,\n signal,\n options: relayOptions,\n });\n } catch (error) {\n await options?.afterCall?.(false);\n throw error;\n }\n\n const combined: SignAndSendDelegateActionResult = {\n signResult,\n relayResult,\n };\n\n const success = relayResult.ok !== false;\n if (success) {\n await options?.afterCall?.(true, combined);\n } else {\n await options?.afterCall?.(false);\n }\n return combined;\n }\n\n ///////////////////////////////////////\n // === NEP-413 MESSAGE SIGNING ===\n ///////////////////////////////////////\n\n /**\n * Sign a NEP-413 message using the user's passkey-derived private key:\n * - Creates a payload with message, recipient, nonce, and state\n * - Serializes using Borsh\n * - Adds NEP-413 prefix\n * - Hashes with SHA-256\n * - Signs with Ed25519\n * - Returns base64-encoded signature\n *\n * @param nearAccountId - NEAR account ID to sign with\n * @param params - NEP-413 signing parameters\n * - message: string - The message to sign\n * - recipient: string - The recipient of the message\n * - state: string - Optional state parameter\n * @param options - Action options for event handling\n * - onEvent: EventCallback<ActionSSEEvent> - Optional event callback\n * - onError: (error: Error) => void - Optional error callback\n * - afterCall: AfterCall - Optional after call hooks\n * - waitUntil: TxExecutionStatus - Optional waitUntil status\n * @returns Promise resolving to signing result\n *\n * @example\n * ```typescript\n * const result = await passkeyManager.signNEP413Message('alice.near', {\n * message: 'Hello World',\n * recipient: 'app.example.com',\n * state: 'optional-state'\n * });\n * ```\n */\n async signNEP413Message(args: {\n nearAccountId: string,\n params: SignNEP413MessageParams,\n options?: SignNEP413HooksOptions\n }): Promise<SignNEP413MessageResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(args.nearAccountId);\n const confirmerText = args.options?.confirmerText;\n const confirmationConfig = args.options?.confirmationConfig;\n const result = await router.signNep413Message({\n nearAccountId: args.nearAccountId,\n message: args.params.message,\n recipient: args.params.recipient,\n state: args.params.state,\n options: { onEvent: args.options?.onEvent, confirmerText, confirmationConfig }\n });\n await args.options?.afterCall?.(true, result);\n // Expect wallet to return the same shape as WebAuthnManager.signNEP413Message\n return result as SignNEP413MessageResult;\n } catch (error: unknown) {\n const e = toError(error);\n await args.options?.onError?.(e);\n await args.options?.afterCall?.(false);\n throw e;\n }\n }\n\n const res = await signNEP413Message({\n context: this.getContext(),\n nearAccountId: toAccountId(args.nearAccountId),\n params: args.params,\n options: args.options\n });\n if (res?.success) {\n await args.options?.afterCall?.(true, res);\n } else {\n await args.options?.afterCall?.(false);\n }\n return res;\n }\n\n ///////////////////////////////////////\n // === KEY MANAGEMENT ===\n ///////////////////////////////////////\n\n /**\n * Canonical entrypoint to show the Export Private Key UI (secure drawer/modal)\n * without returning the key to the caller. All dApps should use this wrapper;\n * the underlying WebAuthnManager.exportNearKeypairWithUI() is fully worker-\n * driven and only ever reveals the private key inside trusted UI surfaces.\n */\n async exportNearKeypairWithUI(\n nearAccountId: string,\n options?: { variant?: 'drawer' | 'modal'; theme?: 'dark' | 'light' }\n ): Promise<void> {\n if (isOffline()) {\n // If offline, open the offline-export route\n await openOfflineExport({\n accountId: nearAccountId,\n routerOpen: this.iframeRouter?.openOfflineExport?.bind(this.iframeRouter),\n walletOrigin: this.configs?.iframeWallet?.walletOrigin,\n target: '_blank',\n });\n } else {\n // Prefer wallet iframe when ready\n if (this.iframeRouter?.isReady?.()) {\n await this.iframeRouter.exportNearKeypairWithUI(nearAccountId, options);\n return;\n }\n // Online but router not ready: prefer offline-export route via router (or new tab)\n // Only do this when we have a wallet origin configured or router API is available\n const routerOpen = this.iframeRouter?.openOfflineExport?.bind(this.iframeRouter);\n const walletOrigin = this.configs?.iframeWallet?.walletOrigin;\n if (routerOpen || walletOrigin) {\n await openOfflineExport({ accountId: nearAccountId, routerOpen, walletOrigin, target: '_blank' });\n return;\n }\n // Final fallback: local worker-driven UI\n await this.webAuthnManager.exportNearKeypairWithUI(toAccountId(nearAccountId), options);\n }\n }\n\n ///////////////////////////////////////\n // === DERIVED ADDRESSES (public helpers) ===\n ///////////////////////////////////////\n\n /** Store a derived address for an account + contract + path (multi-chain capable via path encoding). */\n async setDerivedAddress(\n nearAccountId: string,\n args: { contractId: string; path: string; address: string }\n ): Promise<void> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter();\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to write derived addresses to app origin.');\n }\n return await router.setDerivedAddress({ nearAccountId, args });\n }\n await chainsigAddressManager.setDerivedAddress(toAccountId(nearAccountId), args);\n }\n\n /** Retrieve the full derived address record (or null if not found). */\n async getDerivedAddressRecord(\n nearAccountId: string,\n args: { contractId: string; path: string }\n ): Promise<DerivedAddressRecord | null> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter();\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to read derived addresses from app origin.');\n }\n return await router.getDerivedAddressRecord({ nearAccountId, args });\n }\n return await chainsigAddressManager.getDerivedAddressRecord(toAccountId(nearAccountId), args);\n }\n\n /** Retrieve only the derived address string for convenience. */\n async getDerivedAddress(\n nearAccountId: string,\n args: { contractId: string; path: string }\n ): Promise<string | null> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter();\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to read derived addresses from app origin.');\n }\n return await router.getDerivedAddress({ nearAccountId, args });\n }\n return await chainsigAddressManager.getDerivedAddress(toAccountId(nearAccountId), args);\n }\n\n ///////////////////////////////////////\n // === Email Recovery (public helpers) ===\n ///////////////////////////////////////\n\n /**\n * Get recovery emails for an account.\n * - Fetches on-chain recovery email hashes via get_recovery_emails.\n * - Resolves hashes to canonical emails using local IndexedDB mapping when available.\n * - Returns an array of { hashHex, email }, where `email` is a human-readable label\n * (canonical email when known on this device, otherwise the hash hex).\n */\n async getRecoveryEmails(nearAccountId: string): Promise<Array<{ hashHex: string; email: string }>> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter(nearAccountId);\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to read recovery email mappings from app origin.');\n }\n return await router.getRecoveryEmails(nearAccountId);\n }\n const accountId = toAccountId(nearAccountId);\n\n // Fetch on-chain recovery email hashes\n const rawHashes = await getRecoveryEmailHashesContractCall(this.nearClient, accountId);\n if (!rawHashes.length) {\n return [];\n }\n\n // Load local mapping from IndexedDB (best-effort)\n let local: RecoveryEmailRecord[] = [];\n try {\n local = await getLocalRecoveryEmails(accountId);\n } catch (error) {\n console.warn('[TatchiPasskey] Failed to load local recovery emails', error);\n }\n\n const emailByHashHex = new Map<string, string>();\n for (const rec of local) {\n if (!rec?.hashHex || !rec?.email) continue;\n if (!emailByHashHex.has(rec.hashHex)) {\n emailByHashHex.set(rec.hashHex, rec.email);\n }\n }\n\n return rawHashes.map(hashBytes => {\n const hashHex = bytesToHex(hashBytes);\n const email = emailByHashHex.get(hashHex) || hashHex;\n return { hashHex, email };\n });\n }\n\n /**\n * Set recovery emails for an account:\n * - Canonicalizes and hashes emails client-side.\n * - Persists mapping in IndexedDB.\n * - Deploys/attaches the EmailRecoverer contract when needed.\n * - Calls set_recovery_emails(...) on the per-account contract.\n */\n async setRecoveryEmails(\n nearAccountId: string,\n recoveryEmails: string[],\n options?: ActionHooksOptions\n ): Promise<ActionResult> {\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const res = await router.setRecoveryEmails({ nearAccountId, recoveryEmails, options });\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n const accountId = toAccountId(nearAccountId);\n\n // Canonicalize, hash, and persist mapping locally (best-effort)\n const { hashes: recoveryEmailHashes } = await prepareRecoveryEmails(accountId, recoveryEmails);\n\n const actions: ActionArgs[] = await buildSetRecoveryEmailsActions(\n this.nearClient,\n accountId,\n recoveryEmailHashes,\n this.configs.emailRecoveryContracts\n );\n\n // Delegate to executeAction so iframe vs same-origin routing is respected.\n return this.executeAction({\n nearAccountId,\n receiverId: nearAccountId,\n actionArgs: actions,\n options,\n });\n }\n\n ///////////////////////////////////////\n // === Account Recovery Flow ===\n ///////////////////////////////////////\n\n /**\n * Creates an AccountRecoveryFlow instance, for step-by-step account recovery UX\n */\n async recoverAccountFlow(args: {\n accountId?: string;\n options?: AccountRecoveryHooksOptions\n }): Promise<RecoveryResult> {\n\n const accountIdInput = args?.accountId || '';\n const options = args?.options;\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n const res = await router.recoverAccountFlow({\n accountId: accountIdInput,\n onEvent: options?.onEvent\n });\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n // Local orchestration using AccountRecoveryFlow for a single-call UX\n try {\n const flow = new AccountRecoveryFlow(this.getContext(), options);\n // Phase 1: Discover available accounts\n const discovered = await flow.discover(accountIdInput || '');\n if (!Array.isArray(discovered) || discovered.length === 0) {\n const err = new Error('No recoverable accounts found');\n await options?.onError?.(err);\n await options?.afterCall?.(false);\n return { success: false, accountId: accountIdInput || '', publicKey: '', message: err.message, error: err.message };\n }\n // Phase 2: User selects account in UI\n // Select the first account-scope; OS chooser selects the actual credential\n const selected = discovered[0];\n\n // Phase 3: Execute recovery with secure credential lookup\n const result = await flow.recover({\n credentialId: selected.credentialId,\n accountId: selected.accountId\n });\n\n await options?.afterCall?.(true, result);\n return result;\n\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n ///////////////////////////////////////\n // === Email Recovery Flow ===\n ///////////////////////////////////////\n\n private getEmailRecoveryFlow(options?: EmailRecoveryFlowOptions) {\n const { EmailRecoveryFlow } = require('./emailRecovery') as typeof import('./emailRecovery');\n if (!this.activeEmailRecoveryFlow) {\n this.activeEmailRecoveryFlow = new EmailRecoveryFlow(this.getContext(), options);\n } else if (options) {\n this.activeEmailRecoveryFlow.setOptions(options);\n }\n return this.activeEmailRecoveryFlow;\n }\n\n async startEmailRecovery(args: {\n accountId: string;\n recoveryEmail: string;\n options?: EmailRecoveryFlowOptions;\n }): Promise<{ mailtoUrl: string; nearPublicKey: string }> {\n const { accountId, recoveryEmail, options } = args;\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n const confirmerText = options?.confirmerText;\n const confirmationConfig = options?.confirmationConfig;\n const safeOptions = {\n ...(confirmerText ? { confirmerText } : {}),\n ...(confirmationConfig ? { confirmationConfig } : {}),\n };\n const res = await router.startEmailRecovery({\n accountId,\n recoveryEmail,\n onEvent: options?.onEvent,\n options: Object.keys(safeOptions).length > 0 ? safeOptions : undefined,\n });\n await options?.afterCall?.(true, undefined);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n const flow = this.getEmailRecoveryFlow(options);\n return await flow.start({ accountId, recoveryEmail });\n }\n\n async finalizeEmailRecovery(args: {\n accountId: string;\n nearPublicKey?: string;\n options?: EmailRecoveryFlowOptions;\n }): Promise<void> {\n const { accountId, nearPublicKey, options } = args;\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.finalizeEmailRecovery({\n accountId,\n nearPublicKey,\n onEvent: options?.onEvent,\n });\n await options?.afterCall?.(true, undefined);\n return;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n const flow = this.getEmailRecoveryFlow(options);\n await flow.finalize({ accountId, nearPublicKey });\n }\n\n /**\n * Best-effort cancellation for an in-flight email recovery flow.\n * Intended for UI \"user cancelled sending email\" / retry UX.\n */\n async cancelEmailRecovery(args?: { accountId?: string; nearPublicKey?: string }): Promise<void> {\n const { accountId, nearPublicKey } = args || {};\n // In wallet-iframe mode, instruct the wallet host to stop the active flow.\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.stopEmailRecovery({ accountId, nearPublicKey });\n } catch {}\n return;\n }\n\n try {\n await this.activeEmailRecoveryFlow?.cancelAndReset({ accountId, nearPublicKey });\n } catch {}\n this.activeEmailRecoveryFlow = null;\n }\n\n ///////////////////////////////////////\n // === Link Device ===\n ///////////////////////////////////////\n\n /**\n * Device2: Start device linking flow\n * Returns QR payload and data URL to render; emits onEvent during the flow.\n * Runs inside iframe when available for better isolation.\n */\n async startDevice2LinkingFlow(args: StartDevice2LinkingFlowArgs): Promise<StartDevice2LinkingFlowResults> {\n // In wallet-iframe mode, device linking must run inside the wallet origin.\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter();\n const options = args?.options;\n return await router.startDevice2LinkingFlow({\n ui: args?.ui,\n cameraId: args?.cameraId,\n options,\n });\n }\n // Local fallback: keep internal flow reference for cancellation\n this.activeDeviceLinkFlow?.cancel();\n const flow = new LinkDeviceFlow(this.getContext(), {\n cameraId: args?.cameraId,\n options: args?.options,\n });\n this.activeDeviceLinkFlow = flow;\n const { qrData, qrCodeDataURL } = await flow.generateQR();\n return { qrData, qrCodeDataURL };\n }\n\n /**\n * Device2: Stops device linking flow inside the iframe host.\n */\n async stopDevice2LinkingFlow(): Promise<void> {\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.stopDevice2LinkingFlow();\n } catch {}\n return;\n }\n if (this.iframeRouter) {\n await this.iframeRouter.stopDevice2LinkingFlow();\n return;\n }\n this.activeDeviceLinkFlow?.cancel();\n this.activeDeviceLinkFlow = null;\n }\n\n /**\n * Device1: Link device using pre-scanned QR data.\n * You can use a QR scanning component of your choice,\n * or use the built-in <QRCodeScanner /> component.\n *\n * @param qrData The QR data obtained from scanning Device2's QR code\n * @param options Device linking options including funding amount and event callbacks\n * @returns Promise that resolves to the linking result\n */\n async linkDeviceWithScannedQRData(\n qrData: DeviceLinkingQRData,\n options: ScanAndLinkDeviceOptionsDevice1\n ): Promise<LinkDeviceResult> {\n // In wallet-iframe mode, device linking must run inside the wallet origin.\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter();\n const res = await router.linkDeviceWithScannedQRData({\n qrData,\n fundingAmount: options.fundingAmount,\n options: {\n onEvent: options.onEvent,\n confirmationConfig: options.confirmationConfig,\n confirmerText: options.confirmerText,\n }\n });\n return res as LinkDeviceResult;\n }\n return linkDeviceWithScannedQRData(this.getContext(), qrData, options);\n }\n\n /**\n * Delete a device key from an account\n */\n async deleteDeviceKey(\n accountId: string,\n publicKeyToDelete: string,\n options?: ActionHooksOptions\n ): Promise<ActionResult> {\n // Validate that we're not deleting the last key\n const keysView = this.iframeRouter\n ? await this.iframeRouter.viewAccessKeyList(accountId)\n : await this.nearClient.viewAccessKeyList(toAccountId(accountId));\n if (keysView.keys.length <= 1) {\n throw new Error('Cannot delete the last access key from an account');\n }\n\n // Find the key to delete\n const keyToDelete = keysView.keys.find((k: { public_key: string }) => k.public_key === publicKeyToDelete);\n if (!keyToDelete) {\n throw new Error(`Access key ${publicKeyToDelete} not found on account ${accountId}`);\n }\n\n // Use the executeAction method with DeleteKey action\n return this.executeAction({\n nearAccountId: accountId,\n receiverId: accountId,\n actionArgs: {\n type: ActionType.DeleteKey,\n publicKey: publicKeyToDelete\n },\n options: options\n });\n }\n\n}\n\n// Re-export types for convenience\nexport type {\n TatchiConfigs,\n TatchiConfigsInput,\n RegistrationResult,\n LoginAndCreateSessionResult,\n LoginResult,\n LoginSession,\n SigningSessionStatus,\n ActionResult,\n} from '../types/tatchi';\nexport type {\n ActionHooksOptions,\n AfterCall,\n EventCallback,\n LoginHooksOptions,\n LoginSSEvent,\n RegistrationHooksOptions,\n RegistrationSSEEvent,\n SignNEP413HooksOptions,\n} from '../types/sdkSentEvents';\n// Context alias (optional convenience)\nexport type TatchiPasskeyContext = PasskeyManagerContext;\n\nexport type {\n DeviceLinkingQRData,\n DeviceLinkingSession,\n LinkDeviceResult\n} from '../types/linkDevice';\n\n// Re-export device linking error types and classes\nexport {\n DeviceLinkingPhase,\n DeviceLinkingError,\n DeviceLinkingErrorCode\n} from '../types/linkDevice';\n\n// Re-export account recovery types and classes\nexport type {\n RecoveryResult,\n AccountLookupResult,\n PasskeyOption,\n PasskeyOptionWithoutCredential,\n PasskeySelection\n} from './recoverAccount';\n\nexport {\n AccountRecoveryFlow\n} from './recoverAccount';\n\n// Re-export NEP-413 types\nexport type {\n SignNEP413MessageParams,\n SignNEP413MessageResult\n} from './signNEP413';\n\n// Re-export QR scanning flow\nexport {\n ScanQRCodeFlow,\n type ScanQRCodeFlowOptions,\n type ScanQRCodeFlowEvents,\n ScanQRCodeFlowState\n} from '../../utils/qrScanner';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["tasks: Promise<unknown>[]","error: unknown","res","arr: SignTransactionResult[]","signOptions: DelegateActionHooksOptions | undefined","signResult: SignDelegateActionResult","relayOptions: DelegateRelayHooksOptions | undefined","relayResult: DelegateRelayResult","combined: SignAndSendDelegateActionResult","router: WalletIframeRouter","local: RecoveryEmailRecord[]","actions: ActionArgs[]"],"sources":["../../../../../../../src/core/TatchiPasskey/index.ts"],"sourcesContent":["import { WebAuthnManager } from '../WebAuthnManager';\nimport {\n loginAndCreateSession,\n getLoginSession,\n getRecentLogins,\n logoutAndClearSession,\n} from './login';\nimport {\n executeAction,\n signTransactionsWithActions,\n sendTransaction,\n signAndSendTransactions,\n} from './actions';\nimport { AccountRecoveryFlow, type RecoveryResult } from './recoverAccount';\nimport { registerPasskey } from './registration';\nimport { registerPasskeyInternal } from './registration';\nimport {\n MinimalNearClient,\n type NearClient,\n type SignedTransaction,\n type AccessKeyList,\n} from '../NearClient';\nimport type {\n ActionResult,\n DelegateRelayResult,\n GetRecentLoginsResult,\n LoginAndCreateSessionResult,\n LoginResult,\n LoginSession,\n LoginState,\n RegistrationResult,\n SignAndSendDelegateActionResult,\n SignDelegateActionResult,\n SignTransactionResult,\n TatchiConfigs,\n TatchiConfigsInput,\n} from '../types/tatchi';\nimport type {\n AccountRecoveryHooksOptions,\n ActionHooksOptions,\n DelegateActionHooksOptions,\n DelegateRelayHooksOptions,\n LoginHooksOptions,\n RegistrationHooksOptions,\n SendTransactionHooksOptions,\n SignAndSendDelegateActionHooksOptions,\n SignAndSendTransactionHooksOptions,\n SignNEP413HooksOptions,\n SignTransactionHooksOptions,\n} from '../types/sdkSentEvents';\nimport { ActionPhase, ActionStatus } from '../types/sdkSentEvents';\nimport { ConfirmationConfig, type WasmSignedDelegate } from '../types/signer-worker';\nimport { DEFAULT_AUTHENTICATOR_OPTIONS } from '../types/authenticatorOptions';\nimport { toAccountId, type AccountId } from '../types/accountIds';\nimport type { DerivedAddressRecord, RecoveryEmailRecord } from '../IndexedDBManager';\nimport { configureIndexedDB } from '../IndexedDBManager';\nimport { chainsigAddressManager } from '../ChainsigAddressManager';\nimport { ActionType, type ActionArgs, type TransactionInput } from '../types/actions';\nimport type {\n DeviceLinkingQRData,\n LinkDeviceResult,\n ScanAndLinkDeviceOptionsDevice1,\n StartDevice2LinkingFlowArgs,\n StartDevice2LinkingFlowResults\n} from '../types/linkDevice';\nimport { LinkDeviceFlow } from './linkDevice';\nimport { linkDeviceWithScannedQRData } from './scanDevice';\nimport {\n signNEP413Message,\n type SignNEP413MessageParams,\n type SignNEP413MessageResult\n} from './signNEP413';\nimport { signDelegateAction } from './delegateAction';\nimport { SignedDelegate } from '../types/delegate';\nimport { sendDelegateActionViaRelayer } from './relay';\nimport type { UserPreferencesManager } from '../WebAuthnManager/userPreferences';\nimport type { WalletIframeRouter } from '../WalletIframe/client/router';\nimport { __isWalletIframeHostMode } from '../WalletIframe/host-mode';\nimport { toError } from '../../utils/errors';\nimport { isOffline, openOfflineExport } from '../OfflineExport';\nimport { buildSetRecoveryEmailsActions, getRecoveryEmailHashesContractCall } from '../rpcCalls';\nimport {\n prepareRecoveryEmails,\n getLocalRecoveryEmails,\n bytesToHex,\n} from '../EmailRecovery';\nimport type { DelegateActionInput } from '../types/delegate';\nimport { buildConfigsFromEnv } from '../defaultConfigs';\nimport { EmailRecoveryFlowOptions } from './emailRecovery';\n\n///////////////////////////////////////\n// PASSKEY MANAGER\n///////////////////////////////////////\n\nexport interface PasskeyManagerContext {\n webAuthnManager: WebAuthnManager;\n nearClient: NearClient;\n configs: TatchiConfigs;\n}\n\nlet warnedAboutSameOriginWallet = false;\n\n/**\n * Main TatchiPasskey class that provides framework-agnostic passkey operations\n * with flexible event-based callbacks for custom UX implementation\n */\nexport class TatchiPasskey {\n private readonly webAuthnManager: WebAuthnManager;\n private readonly nearClient: NearClient;\n readonly configs: TatchiConfigs;\n private iframeRouter: WalletIframeRouter | null = null;\n // Deduplicate concurrent initWalletIframe() calls to avoid mounting multiple iframes.\n private walletIframeInitInFlight: Promise<void> | null = null;\n // Wallet-iframe mode: mirror wallet-host preferences into app-origin in-memory cache.\n private walletIframePrefsUnsubscribe: (() => void) | null = null;\n // Internal active Device2 flow when running locally (not exposed)\n private activeDeviceLinkFlow: LinkDeviceFlow | null = null;\n private activeAccountRecoveryFlow: AccountRecoveryFlow | null = null;\n private activeEmailRecoveryFlow: import('./emailRecovery').EmailRecoveryFlow | null = null;\n\n constructor(\n configs: TatchiConfigsInput,\n nearClient?: NearClient\n ) {\n this.configs = buildConfigsFromEnv(configs);\n // Configure IndexedDB naming before any local persistence is touched.\n // - Wallet iframe host keeps canonical DB names.\n // - App origin disables IndexedDB entirely when iframe mode is enabled.\n const mode = __isWalletIframeHostMode()\n ? 'wallet'\n : (this.configs.iframeWallet?.walletOrigin ? 'disabled' : 'legacy');\n configureIndexedDB({ mode });\n // Use provided client or create default one\n this.nearClient = nearClient || new MinimalNearClient(this.configs.nearRpcUrl);\n this.webAuthnManager = new WebAuthnManager(this.configs, this.nearClient);\n // VRF worker initializes automatically in the constructor\n }\n\n /**\n * Direct access to user preferences manager for convenience\n * Example: passkeyManager.userPreferences.onThemeChange(cb)\n */\n get userPreferences(): UserPreferencesManager {\n return this.webAuthnManager.getUserPreferences();\n }\n\n /**\n * Initialize the hidden wallet service iframe client (optional) and warm critical resources.\n * Always warms local resources; initializes iframe when `walletOrigin` is provided.\n * Idempotent and safe to call multiple times.\n */\n async initWalletIframe(nearAccountId?: string): Promise<void> {\n const walletOriginConfigured = !!this.configs.iframeWallet?.walletOrigin;\n // Warm local critical resources (NonceManager, workers) regardless of iframe usage.\n // In iframe mode, avoid persisting user state (lastUserAccountId, preferences) on the app origin.\n const shouldAvoidLocalUserState = walletOriginConfigured && !__isWalletIframeHostMode();\n await this.webAuthnManager.warmCriticalResources(shouldAvoidLocalUserState ? undefined : nearAccountId);\n\n // Guardrail: when running inside the wallet service iframe host, never attempt to\n // initialize a nested wallet iframe client, even if configs accidentally include iframeWallet.\n // The host runs the real TatchiPasskey instance and must remain self-contained.\n if (__isWalletIframeHostMode()) {\n return;\n }\n\n const walletIframeConfig = this.configs.iframeWallet;\n const walletOrigin = walletIframeConfig?.walletOrigin;\n // If no wallet origin configured, we're done after local warm-up\n if (!walletOrigin) {\n // Reflect local login state so callers depending on init() get fresh status\n await this.getLoginSession(nearAccountId);\n return;\n }\n\n // Emit same-origin co-hosting warning only when actually initializing the iframe\n if (!warnedAboutSameOriginWallet) {\n try {\n const isWalletIframeHost = __isWalletIframeHostMode();\n const parsed = new URL(walletOrigin);\n if (typeof window !== 'undefined' && parsed.origin === window.location.origin && !isWalletIframeHost) {\n warnedAboutSameOriginWallet = true;\n console.warn('[TatchiPasskey] iframeWallet.walletOrigin matches the host origin. Consider moving the wallet to a dedicated origin for stronger isolation.');\n }\n } catch {\n // ignore invalid URL here; constructor downstream will surface an error\n }\n }\n\n // Initialize iframe router once (and prevent concurrent calls from mounting multiple iframes).\n if (!this.iframeRouter) {\n if (!this.walletIframeInitInFlight) {\n this.walletIframeInitInFlight = (async () => {\n const { WalletIframeRouter } = await import('../WalletIframe/client/router');\n this.iframeRouter = new WalletIframeRouter({\n walletOrigin,\n servicePath: walletIframeConfig?.walletServicePath || '/wallet-service',\n connectTimeoutMs: 20_000, // 20s\n requestTimeoutMs: 60_000, // 60s\n theme: this.configs.walletTheme,\n nearRpcUrl: this.configs.nearRpcUrl,\n nearNetwork: this.configs.nearNetwork,\n contractId: this.configs.contractId,\n nearExplorerUrl: this.configs.nearExplorerUrl,\n // Ensure relay server config reaches the wallet host for atomic registration\n relayer: this.configs.relayer,\n vrfWorkerConfigs: this.configs.vrfWorkerConfigs,\n emailRecoveryContracts: this.configs.emailRecoveryContracts,\n rpIdOverride: walletIframeConfig?.rpIdOverride,\n // Allow apps/CI to control where embedded bundles are served from\n sdkBasePath: walletIframeConfig?.sdkBasePath,\n });\n\n await this.iframeRouter.init();\n // Opportunistically warm remote NonceManager\n try { await this.iframeRouter.prefetchBlockheight(); } catch {}\n })();\n }\n\n try {\n await this.walletIframeInitInFlight;\n } finally {\n this.walletIframeInitInFlight = null;\n }\n } else {\n await this.iframeRouter.init();\n // Opportunistically warm remote NonceManager\n try { await this.iframeRouter.prefetchBlockheight(); } catch {}\n }\n\n // Wallet-iframe mode: keep app-origin UI prefs in sync with the wallet host.\n if (this.iframeRouter) {\n this.ensureWalletIframePreferencesMirror(this.iframeRouter);\n // Best-effort pull snapshot to cover missed events / older hosts.\n const cfg = await this.iframeRouter.getConfirmationConfig().catch(() => null);\n if (cfg) {\n this.userPreferences.applyWalletHostConfirmationConfig({\n nearAccountId: nearAccountId ? toAccountId(nearAccountId) : null,\n confirmationConfig: cfg,\n });\n }\n }\n\n await this.getLoginSession(nearAccountId);\n }\n\n /** Get the wallet iframe client if initialized. */\n getWalletIframeClient(): WalletIframeRouter | null {\n return this.iframeRouter;\n }\n\n private ensureWalletIframePreferencesMirror(router: WalletIframeRouter): void {\n if (this.walletIframePrefsUnsubscribe) return;\n const unsubscribe = router.onPreferencesChanged?.(payload => {\n const id = payload?.nearAccountId;\n const nearAccountId = id ? toAccountId(id) : null;\n this.userPreferences.applyWalletHostConfirmationConfig({\n nearAccountId,\n confirmationConfig: payload?.confirmationConfig,\n });\n });\n this.walletIframePrefsUnsubscribe = unsubscribe ?? null;\n }\n\n /**\n * True when the SDK is running on the app origin with a wallet iframe configured.\n * In this mode, sensitive persistence must live in the wallet-iframe origin.\n */\n private shouldUseWalletIframe(): boolean {\n return !!this.configs.iframeWallet?.walletOrigin && !__isWalletIframeHostMode();\n }\n\n private async requireWalletIframeRouter(nearAccountId?: string): Promise<WalletIframeRouter> {\n if (!this.shouldUseWalletIframe()) {\n throw new Error('[TatchiPasskey] Wallet iframe is not configured.');\n }\n if (!this.iframeRouter) {\n await this.initWalletIframe(nearAccountId);\n }\n if (!this.iframeRouter) {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable.');\n }\n return this.iframeRouter;\n }\n\n getContext(): PasskeyManagerContext {\n return {\n webAuthnManager: this.webAuthnManager,\n nearClient: this.nearClient,\n configs: this.configs\n }\n }\n\n getNearClient(): NearClient {\n return this.nearClient;\n }\n\n /**\n * Warm critical resources: delegates to WebAuthnManager and ensures iframe handshake when configured.\n */\n async warmCriticalResources(nearAccountId?: string): Promise<void> {\n // Maintain backward compatibility: delegate to consolidated init\n await this.initWalletIframe(nearAccountId);\n }\n\n /**\n * Pre-warm resources on a best-effort basis without changing visible state.\n * - When iframe=true, initializes the wallet iframe client (and warms local resources).\n * - When workers=true, warms local critical resources (nonce, IndexedDB, workers) without touching iframe.\n * - When both are false/omitted, does nothing.\n */\n async prewarm(opts?: { iframe?: boolean; workers?: boolean; nearAccountId?: string }): Promise<void> {\n const iframe = !!opts?.iframe;\n const workers = !!opts?.workers;\n const nearAccountId = opts?.nearAccountId;\n\n const tasks: Promise<unknown>[] = [];\n\n if (iframe) {\n // initWalletIframe also calls WebAuthnManager.warmCriticalResources internally\n tasks.push(this.initWalletIframe(nearAccountId));\n } else if (workers) {\n // Warm local-only resources without touching the iframe.\n // In iframe mode, avoid persisting user state (lastUserAccountId, preferences) on the app origin.\n const shouldAvoidLocalUserState = !!this.configs.iframeWallet?.walletOrigin && !__isWalletIframeHostMode();\n tasks.push(this.webAuthnManager.warmCriticalResources(shouldAvoidLocalUserState ? undefined : nearAccountId));\n }\n\n if (tasks.length === 0) return;\n try {\n await Promise.all(tasks);\n } catch {\n // Best-effort: swallow errors so prewarm never breaks app flows\n }\n }\n\n /**\n * View all access keys for a given account\n * @param accountId - NEAR account ID to view access keys for\n * @returns Promise resolving to access key list\n */\n async viewAccessKeyList(accountId: string): Promise<AccessKeyList> {\n if (this.iframeRouter) {\n return await this.iframeRouter.viewAccessKeyList(accountId);\n }\n return this.nearClient.viewAccessKeyList(accountId);\n }\n\n ///////////////////////////////////////\n // === Registration and Login ===\n ///////////////////////////////////////\n\n /**\n * Register a new passkey for the given NEAR account ID\n * Uses AccountId for on-chain operations and PRF salt derivation\n */\n async registerPasskey(\n nearAccountId: string,\n options: RegistrationHooksOptions = {}\n ): Promise<RegistrationResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const confirmationConfig = options?.confirmationConfig;\n const res = await router.registerPasskey({\n nearAccountId,\n confirmationConfig,\n options: {\n onEvent: options?.onEvent,\n ...(options?.confirmerText ? { confirmerText: options.confirmerText } : {})\n }\n });\n // Opportunistically warm resources (non-blocking)\n void (async () => { try { await this.warmCriticalResources(nearAccountId); } catch {} })();\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n return registerPasskey(\n this.getContext(),\n toAccountId(nearAccountId),\n options,\n this.configs.authenticatorOptions || DEFAULT_AUTHENTICATOR_OPTIONS,\n );\n }\n\n /**\n * Internal variant that accepts a one-time confirmationConfig override.\n * Used by wallet-iframe host to force modal/autoProceed behavior for ArrowButtonLit.\n */\n async registerPasskeyInternal(\n nearAccountId: string,\n options: RegistrationHooksOptions = {},\n confirmationConfigOverride?: ConfirmationConfig\n ): Promise<RegistrationResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const confirmationConfig = confirmationConfigOverride ?? options?.confirmationConfig;\n const res = await router.registerPasskey({\n nearAccountId,\n confirmationConfig,\n options: {\n onEvent: options?.onEvent,\n ...(options?.confirmerText ? { confirmerText: options.confirmerText } : {})\n }\n });\n void (async () => { try { await this.warmCriticalResources(nearAccountId); } catch {} })();\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n // App-wallet path: call core internal with override\n return registerPasskeyInternal(\n this.getContext(),\n toAccountId(nearAccountId),\n options,\n this.configs.authenticatorOptions || DEFAULT_AUTHENTICATOR_OPTIONS,\n confirmationConfigOverride,\n );\n }\n\n /**\n * Login and ensure a warm signing session exists.\n * - Unlocks VRF keypair (Shamir auto-unlock when possible; else WebAuthn prompt)\n * - Mints a warm signing session (policy from configs, override via options.signingSession)\n * - Optional: mints a server session (JWT/cookie) via options.session\n */\n async loginAndCreateSession(\n nearAccountId: string,\n options?: LoginHooksOptions\n ): Promise<LoginAndCreateSessionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n // Forward serializable options to wallet host, including session config\n const res = await router.loginAndCreateSession({\n nearAccountId,\n options: {\n onEvent: options?.onEvent,\n // Pass through session so the wallet host calls relay to mint JWT/cookie sessions\n session: options?.session,\n signingSession: options?.signingSession,\n }\n });\n // Best-effort warm-up after successful login (non-blocking)\n void (async () => { try { await this.warmCriticalResources(nearAccountId); } catch {} })();\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n // Initialize current user before login\n await this.webAuthnManager.initializeCurrentUser(toAccountId(nearAccountId), this.nearClient);\n const res = await loginAndCreateSession(this.getContext(), toAccountId(nearAccountId), options);\n // Best-effort warm-up after successful login (non-blocking)\n try { void this.warmCriticalResources(nearAccountId); } catch {}\n return res;\n }\n\n /**\n * Logout: clears VRF keypair and all in-worker session state.\n */\n async logoutAndClearSession(): Promise<void> {\n await logoutAndClearSession(this.getContext());\n // Also clear wallet-origin VRF session if service iframe is active\n if (this.iframeRouter) {\n try { await this.iframeRouter.clearVrfSession?.(); } catch {}\n }\n }\n\n /**\n * Read login state + warm signing session status (no prompts).\n */\n async getLoginSession(nearAccountId?: string): Promise<LoginSession> {\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const session = await router.getLoginSession(nearAccountId);\n try { await router.prefetchBlockheight(); } catch {}\n return session;\n }\n return await getLoginSession(this.getContext(), nearAccountId ? toAccountId(nearAccountId) : undefined);\n }\n\n /**\n * Get check if accountId has a passkey from IndexedDB\n */\n async hasPasskeyCredential(nearAccountId: AccountId): Promise<boolean> {\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter();\n return await router.hasPasskeyCredential(nearAccountId);\n }\n const baseAccountId = toAccountId(nearAccountId);\n return await this.webAuthnManager.hasPasskeyCredential(baseAccountId);\n }\n\n ///////////////////////////////////////\n // === User Settings ===\n ///////////////////////////////////////\n\n /**\n * Set confirmation behavior setting for the current user\n */\n setConfirmBehavior(behavior: 'requireClick' | 'autoProceed'): void {\n if (this.shouldUseWalletIframe()) {\n // Fire and forget; persistence handled in wallet host. Avoid unhandled rejections.\n void (async () => {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.setConfirmBehavior(behavior);\n } catch {}\n })();\n return;\n }\n this.webAuthnManager.getUserPreferences().setConfirmBehavior(behavior);\n }\n\n /**\n * Set the unified confirmation configuration\n */\n setConfirmationConfig(config: ConfirmationConfig): void {\n if (this.shouldUseWalletIframe()) {\n // Fire and forget; avoid unhandled rejections in consumers\n void (async () => {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.setConfirmationConfig(config);\n } catch {}\n })();\n return;\n }\n this.webAuthnManager.getUserPreferences().setConfirmationConfig(config);\n }\n\n setUserTheme(theme: 'dark' | 'light'): void {\n if (this.shouldUseWalletIframe()) {\n void (async () => {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.setTheme(theme);\n } catch {}\n })();\n return;\n }\n this.webAuthnManager.getUserPreferences().setUserTheme(theme);\n }\n\n /**\n * Get the current confirmation configuration\n */\n getConfirmationConfig(): ConfirmationConfig {\n // Prefer wallet host value when available\n // Note: synchronous signature; returns last-known local value if iframe reply is async\n // Callers needing fresh remote value should use TatchiPasskeyIframe directly.\n return this.webAuthnManager.getUserPreferences().getConfirmationConfig();\n }\n\n /**\n * Prefetch latest block height/hash (and nonce if context missing) to reduce\n * perceived latency when the user initiates a signing flow.\n */\n async prefetchBlockheight(): Promise<void> {\n if (this.iframeRouter) {\n await this.iframeRouter.prefetchBlockheight();\n return;\n }\n try { await this.webAuthnManager.getNonceManager().prefetchBlockheight(this.nearClient); } catch {}\n }\n\n async getRecentLogins(): Promise<GetRecentLoginsResult> {\n // In iframe mode, do not fall back to app-origin IndexedDB.\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n return await router.getRecentLogins();\n } catch {\n return { accountIds: [], lastUsedAccount: null };\n }\n }\n\n return getRecentLogins(this.getContext());\n }\n\n ///////////////////////////////////////\n // === Transactions ===\n ///////////////////////////////////////\n\n /**\n * Execute a NEAR blockchain action using passkey-derived credentials\n * Supports all NEAR action types: Transfer, FunctionCall, AddKey, etc.\n *\n * @param nearAccountId - NEAR account ID to execute action with\n * @param actionArgs - Action to execute (single action or array for batched transactions)\n * @param options - Action options for event handling\n * - onEvent: EventCallback<ActionSSEEvent> - Optional event callback\n * - onError: (error: Error) => void - Optional error callback\n * - afterCall: AfterCall - Optional after call hooks\n * - waitUntil: TxExecutionStatus - Optional waitUntil status\n * @returns Promise resolving to action result\n *\n * @example\n * ```typescript\n * // Basic transfer\n * const result = await passkeyManager.executeAction('alice.near', {\n * type: ActionType.Transfer,\n * receiverId: 'bob.near',\n * amount: '1000000000000000000000000' // 1 NEAR\n * });\n *\n * // Function call with gas and deposit (already available in ActionArgs)\n * const result = await passkeyManager.executeAction('alice.near', {\n * type: ActionType.FunctionCall,\n * receiverId: 'contract.near',\n * methodName: 'set_value',\n * args: { value: 42 },\n * gas: '50000000000000', // 50 TGas\n * deposit: '100000000000000000000000' // 0.1 NEAR\n * });\n *\n * // Batched transaction\n * const result = await passkeyManager.executeAction('alice.near', [\n * {\n * type: ActionType.Transfer,\n * receiverId: 'bob.near',\n * amount: '1000000000000000000000000'\n * },\n * {\n * type: ActionType.FunctionCall,\n * receiverId: 'contract.near',\n * methodName: 'log_transfer',\n * args: { recipient: 'bob.near' }\n * }\n * ], {\n * onEvent: (event) => console.log('Action progress:', event)\n * });\n * ```\n */\n async executeAction(args: {\n nearAccountId: string,\n receiverId: string,\n actionArgs: ActionArgs | ActionArgs[],\n options?: ActionHooksOptions\n }): Promise<ActionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(args.nearAccountId);\n const confirmerText = args.options?.confirmerText;\n const res = await router.executeAction({\n nearAccountId: args.nearAccountId,\n receiverId: args.receiverId,\n actionArgs: args.actionArgs,\n options: {\n onEvent: args.options?.onEvent,\n waitUntil: args.options?.waitUntil,\n confirmationConfig: args.options?.confirmationConfig,\n confirmerText,\n }\n });\n await args.options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await args.options?.onError?.(e);\n await args.options?.afterCall?.(false);\n throw e;\n }\n }\n // same-origin mode\n return executeAction({\n context: this.getContext(),\n nearAccountId: toAccountId(args.nearAccountId),\n receiverId: toAccountId(args.receiverId),\n actionArgs: args.actionArgs,\n options: args.options\n });\n }\n\n /**\n * Sign and send multiple transactions with actions\n * This method signs transactions with actions and sends them to the network\n *\n * @param nearAccountId - NEAR account ID to sign and send transactions with\n * @param transactionInputs - Transaction inputs to sign and send\n * @param options - Sign and send transaction options\n * - onEvent: EventCallback<ActionSSEEvent> - Optional event callback\n * - onError: (error: Error) => void - Optional error callback\n * - afterCall: AfterCall - Optional after call hooks\n * - waitUntil: TxExecutionStatus - Optional waitUntil status\n * - executeSequentially: boolean - Wait for each transaction to finish before sending the next (default: true)\n * @returns Promise resolving to action results\n *\n * @example\n * ```typescript\n * // Sign and send multiple transactions in a batch\n * const results = await passkeyManager.signAndSendTransactions('alice.near', {\n * transactions: [\n * {\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * },\n * {\n * receiverId: 'contract.near',\n * actions: [{\n * action_type: ActionType.FunctionCall,\n * method_name: 'log_transfer',\n * args: JSON.stringify({ recipient: 'bob.near' }),\n * gas: '30000000000000',\n * deposit: '0'\n * }],\n * }\n * ],\n * options: {\n * onEvent: (event) => console.log('Signing and sending progress:', event)\n * executeSequentially: true\n * }\n * });\n * ```\n */\n async signAndSendTransactions({\n nearAccountId,\n transactions,\n options = {}\n }: {\n nearAccountId: string,\n transactions: TransactionInput[],\n options?: SignAndSendTransactionHooksOptions,\n }): Promise<ActionResult[]> {\n\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const confirmerText = options?.confirmerText;\n const res = await router.signAndSendTransactions({\n nearAccountId,\n transactions: transactions.map(t => ({ receiverId: t.receiverId, actions: t.actions })),\n options: {\n onEvent: options?.onEvent,\n executionWait: options?.executionWait ?? { mode: 'sequential', waitUntil: options?.waitUntil },\n confirmationConfig: options?.confirmationConfig,\n confirmerText,\n }\n });\n // Emit completion\n const txIds = (res || []).map(r => r?.transactionId).filter(Boolean).join(', ');\n options?.onEvent?.({ step: 8, phase: ActionPhase.STEP_8_ACTION_COMPLETE, status: ActionStatus.SUCCESS, message: `All transactions sent: ${txIds}` });\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return signAndSendTransactions({\n context: this.getContext(),\n nearAccountId: toAccountId(nearAccountId),\n transactionInputs: transactions,\n options\n }).then(txResults => {\n const txIds = txResults.map(txResult => txResult.transactionId).join(', ');\n options?.onEvent?.({\n step: 8,\n phase: ActionPhase.STEP_8_ACTION_COMPLETE,\n status: ActionStatus.SUCCESS,\n message: `All transactions sent: ${txIds}`\n });\n return txResults;\n });\n }\n\n /**\n * Convenience helper to sign and send a single transaction with actions.\n * Internally delegates to signAndSendTransactions() and returns the first result.\n */\n async signAndSendTransaction({\n nearAccountId,\n receiverId,\n actions,\n options = {}\n }: {\n nearAccountId: string;\n receiverId: string;\n actions: ActionArgs[];\n options?: SignAndSendTransactionHooksOptions;\n }): Promise<ActionResult> {\n const results = await this.signAndSendTransactions({\n nearAccountId,\n transactions: [\n {\n receiverId,\n actions\n }\n ],\n options\n });\n return results[0] as ActionResult;\n }\n\n /**\n * Batch sign transactions (with actions), allows you to sign transactions\n * to different receivers with a single TouchID prompt.\n * This method does not broadcast transactions, use sendTransaction() to do that.\n *\n * This method fetches the current nonce and increments it for the next N transactions,\n * so you do not need to manually increment the nonce for each transaction.\n *\n * @param nearAccountId - NEAR account ID to sign transactions with\n * @param params - Transaction signing parameters\n * - @param params.transactions: Array of transaction objects with nearAccountId, receiverId, actions, and nonce\n * - @param params.onEvent: Optional progress event callback\n * @returns Promise resolving to signed transaction results\n *\n * @example\n * ```typescript\n * // Sign a single transaction\n * const signedTransactions = await passkeyManager.signTransactionsWithActions('alice.near', {\n * transactions: [{\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * }],\n * onEvent: (event) => console.log('Signing progress:', event)\n * });\n *\n * // Sign multiple transactions in a batch\n * const signedTransactions = await passkeyManager.signTransactionsWithActions('alice.near', {\n * transactions: [\n * {\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * },\n * {\n * receiverId: 'contract.near',\n * actions: [{\n * action_type: ActionType.FunctionCall,\n * method_name: 'log_transfer',\n * args: JSON.stringify({ recipient: 'bob.near' }),\n * gas: '30000000000000',\n * deposit: '0'\n * }],\n * }\n * ]\n * });\n * ```\n */\n async signTransactionsWithActions({ nearAccountId, transactions, options }: {\n nearAccountId: string,\n transactions: TransactionInput[],\n options?: SignTransactionHooksOptions\n }): Promise<SignTransactionResult[]> {\n // route signing via wallet origin\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const txs = transactions.map((t) => ({ receiverId: t.receiverId, actions: t.actions }));\n const confirmerText = options?.confirmerText;\n const result = await router.signTransactionsWithActions({\n nearAccountId, transactions:\n txs,\n options: {\n onEvent: options?.onEvent,\n confirmationConfig: options?.confirmationConfig,\n confirmerText,\n }\n });\n const arr: SignTransactionResult[] = Array.isArray(result) ? result : [];\n await options?.afterCall?.(true, arr);\n return arr;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return signTransactionsWithActions({\n context: this.getContext(),\n nearAccountId: toAccountId(nearAccountId),\n transactionInputs: transactions,\n options\n });\n }\n\n /**\n * Send a signed transaction to the NEAR network\n * This method broadcasts a previously signed transaction and waits for execution\n *\n * @param signedTransaction - The signed transaction to broadcast\n * @param waitUntil - The execution status to wait for (defaults to FINAL)\n * @returns Promise resolving to the transaction execution outcome\n *\n * @example\n * ```typescript\n * // Sign a transaction first\n * const signedTransactions = await passkeyManager.signTransactionsWithActions('alice.near', {\n * transactions: [{\n * receiverId: 'bob.near',\n * actions: [{\n * action_type: ActionType.Transfer,\n * deposit: '1000000000000000000000000'\n * }],\n * }]\n * });\n *\n * // Then broadcast it\n * const result = await passkeyManager.sendTransaction(\n * signedTransactions[0].signedTransaction,\n * TxExecutionStatus.FINAL\n * );\n * ```\n */\n async sendTransaction({ signedTransaction, options }: {\n signedTransaction: SignedTransaction,\n options?: SendTransactionHooksOptions\n }): Promise<ActionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n const res = await router.sendTransaction({\n signedTransaction,\n options: {\n onEvent: options?.onEvent,\n ...(options && ('waitUntil' in options)\n ? { waitUntil: options.waitUntil }\n : {})\n }\n });\n await options?.afterCall?.(true, res);\n options?.onEvent?.({ step: 8, phase: ActionPhase.STEP_8_ACTION_COMPLETE, status: ActionStatus.SUCCESS, message: `Transaction ${res?.transactionId} broadcasted` });\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return sendTransaction({ context: this.getContext(), signedTransaction, options })\n .then(txResult => {\n options?.onEvent?.({ step: 8, phase: ActionPhase.STEP_8_ACTION_COMPLETE, status: ActionStatus.SUCCESS, message: `Transaction ${txResult.transactionId} broadcasted` });\n return txResult;\n });\n }\n\n ///////////////////////////////////////\n // === DELEGATE ACTION SIGNING (NEP-461) ===\n ///////////////////////////////////////\n\n async signDelegateAction({\n nearAccountId,\n delegate,\n options,\n }: {\n nearAccountId: string;\n delegate: DelegateActionInput;\n options?: DelegateActionHooksOptions;\n }): Promise<SignDelegateActionResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const result = await router.signDelegateAction({\n nearAccountId,\n delegate,\n options: {\n onEvent: options?.onEvent,\n confirmationConfig: options?.confirmationConfig,\n confirmerText: options?.confirmerText,\n }\n }) as SignDelegateActionResult;\n await options?.afterCall?.(true, result);\n return result;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n return signDelegateAction({\n context: this.getContext(),\n nearAccountId: toAccountId(nearAccountId),\n delegate,\n options,\n });\n }\n\n /**\n * Convenience helper to POST a signed delegate to a relayer.\n * Does not enforce any relayer semantics; simply forwards the payload.\n */\n async sendDelegateActionViaRelayer(args: {\n relayerUrl: string;\n signedDelegate: SignedDelegate | WasmSignedDelegate;\n hash: string;\n signal?: AbortSignal;\n options?: DelegateRelayHooksOptions;\n }): Promise<DelegateRelayResult> {\n const base = args.relayerUrl.replace(/\\/+$/, '');\n const route = (this.configs.relayer?.delegateActionRoute || '/signed-delegate').replace(/^\\/?/, '/');\n const endpoint = `${base}${route}`;\n return sendDelegateActionViaRelayer({\n url: endpoint,\n payload: {\n hash: args.hash,\n signedDelegate: args.signedDelegate,\n },\n signal: args.signal,\n options: args.options,\n });\n }\n\n /**\n * Convenience helper to sign a delegate action and immediately forward it to the relayer.\n * Emits delegate signing events and relay broadcasting events through the provided options.\n */\n async signAndSendDelegateAction(args: {\n nearAccountId: string;\n delegate: DelegateActionInput;\n relayerUrl: string;\n signal?: AbortSignal;\n options?: SignAndSendDelegateActionHooksOptions;\n }): Promise<SignAndSendDelegateActionResult> {\n const { nearAccountId, delegate, relayerUrl, signal, options } = args;\n\n const signOptions: DelegateActionHooksOptions | undefined = options\n ? {\n onEvent: options.onEvent,\n onError: options.onError,\n waitUntil: options.waitUntil,\n confirmationConfig: options.confirmationConfig,\n confirmerText: options.confirmerText,\n // suppress afterCall so we can call afterCall() once at the end of the lifecycle.\n afterCall: () => {},\n }\n : undefined;\n\n let signResult: SignDelegateActionResult;\n try {\n signResult = await this.signDelegateAction({\n nearAccountId,\n delegate,\n options: signOptions,\n });\n } catch (error) {\n await options?.afterCall?.(false);\n throw error;\n }\n\n const relayOptions: DelegateRelayHooksOptions | undefined = options\n ? {\n onEvent: options.onEvent,\n onError: options.onError,\n }\n : undefined;\n\n let relayResult: DelegateRelayResult;\n try {\n relayResult = await this.sendDelegateActionViaRelayer({\n relayerUrl,\n hash: signResult.hash,\n signedDelegate: signResult.signedDelegate,\n signal,\n options: relayOptions,\n });\n } catch (error) {\n await options?.afterCall?.(false);\n throw error;\n }\n\n const combined: SignAndSendDelegateActionResult = {\n signResult,\n relayResult,\n };\n\n const success = relayResult.ok !== false;\n if (success) {\n await options?.afterCall?.(true, combined);\n } else {\n await options?.afterCall?.(false);\n }\n return combined;\n }\n\n ///////////////////////////////////////\n // === NEP-413 MESSAGE SIGNING ===\n ///////////////////////////////////////\n\n /**\n * Sign a NEP-413 message using the user's passkey-derived private key:\n * - Creates a payload with message, recipient, nonce, and state\n * - Serializes using Borsh\n * - Adds NEP-413 prefix\n * - Hashes with SHA-256\n * - Signs with Ed25519\n * - Returns base64-encoded signature\n *\n * @param nearAccountId - NEAR account ID to sign with\n * @param params - NEP-413 signing parameters\n * - message: string - The message to sign\n * - recipient: string - The recipient of the message\n * - state: string - Optional state parameter\n * @param options - Action options for event handling\n * - onEvent: EventCallback<ActionSSEEvent> - Optional event callback\n * - onError: (error: Error) => void - Optional error callback\n * - afterCall: AfterCall - Optional after call hooks\n * - waitUntil: TxExecutionStatus - Optional waitUntil status\n * @returns Promise resolving to signing result\n *\n * @example\n * ```typescript\n * const result = await passkeyManager.signNEP413Message('alice.near', {\n * message: 'Hello World',\n * recipient: 'app.example.com',\n * state: 'optional-state'\n * });\n * ```\n */\n async signNEP413Message(args: {\n nearAccountId: string,\n params: SignNEP413MessageParams,\n options?: SignNEP413HooksOptions\n }): Promise<SignNEP413MessageResult> {\n // In wallet-iframe mode, always run inside the wallet origin (no app-origin fallback).\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(args.nearAccountId);\n const confirmerText = args.options?.confirmerText;\n const confirmationConfig = args.options?.confirmationConfig;\n const result = await router.signNep413Message({\n nearAccountId: args.nearAccountId,\n message: args.params.message,\n recipient: args.params.recipient,\n state: args.params.state,\n options: { onEvent: args.options?.onEvent, confirmerText, confirmationConfig }\n });\n await args.options?.afterCall?.(true, result);\n // Expect wallet to return the same shape as WebAuthnManager.signNEP413Message\n return result as SignNEP413MessageResult;\n } catch (error: unknown) {\n const e = toError(error);\n await args.options?.onError?.(e);\n await args.options?.afterCall?.(false);\n throw e;\n }\n }\n\n const res = await signNEP413Message({\n context: this.getContext(),\n nearAccountId: toAccountId(args.nearAccountId),\n params: args.params,\n options: args.options\n });\n if (res?.success) {\n await args.options?.afterCall?.(true, res);\n } else {\n await args.options?.afterCall?.(false);\n }\n return res;\n }\n\n ///////////////////////////////////////\n // === KEY MANAGEMENT ===\n ///////////////////////////////////////\n\n /**\n * Canonical entrypoint to show the Export Private Key UI (secure drawer/modal)\n * without returning the key to the caller. All dApps should use this wrapper;\n * the underlying WebAuthnManager.exportNearKeypairWithUI() is fully worker-\n * driven and only ever reveals the private key inside trusted UI surfaces.\n */\n async exportNearKeypairWithUI(\n nearAccountId: string,\n options?: { variant?: 'drawer' | 'modal'; theme?: 'dark' | 'light' }\n ): Promise<void> {\n if (isOffline()) {\n // If offline, open the offline-export route\n await openOfflineExport({\n accountId: nearAccountId,\n routerOpen: this.iframeRouter?.openOfflineExport?.bind(this.iframeRouter),\n walletOrigin: this.configs?.iframeWallet?.walletOrigin,\n target: '_blank',\n });\n } else {\n // Prefer wallet iframe when ready\n if (this.iframeRouter?.isReady?.()) {\n await this.iframeRouter.exportNearKeypairWithUI(nearAccountId, options);\n return;\n }\n // Online but router not ready: prefer offline-export route via router (or new tab)\n // Only do this when we have a wallet origin configured or router API is available\n const routerOpen = this.iframeRouter?.openOfflineExport?.bind(this.iframeRouter);\n const walletOrigin = this.configs?.iframeWallet?.walletOrigin;\n if (routerOpen || walletOrigin) {\n await openOfflineExport({ accountId: nearAccountId, routerOpen, walletOrigin, target: '_blank' });\n return;\n }\n // Final fallback: local worker-driven UI\n await this.webAuthnManager.exportNearKeypairWithUI(toAccountId(nearAccountId), options);\n }\n }\n\n ///////////////////////////////////////\n // === DERIVED ADDRESSES (public helpers) ===\n ///////////////////////////////////////\n\n /** Store a derived address for an account + contract + path (multi-chain capable via path encoding). */\n async setDerivedAddress(\n nearAccountId: string,\n args: { contractId: string; path: string; address: string }\n ): Promise<void> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter();\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to write derived addresses to app origin.');\n }\n return await router.setDerivedAddress({ nearAccountId, args });\n }\n await chainsigAddressManager.setDerivedAddress(toAccountId(nearAccountId), args);\n }\n\n /** Retrieve the full derived address record (or null if not found). */\n async getDerivedAddressRecord(\n nearAccountId: string,\n args: { contractId: string; path: string }\n ): Promise<DerivedAddressRecord | null> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter();\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to read derived addresses from app origin.');\n }\n return await router.getDerivedAddressRecord({ nearAccountId, args });\n }\n return await chainsigAddressManager.getDerivedAddressRecord(toAccountId(nearAccountId), args);\n }\n\n /** Retrieve only the derived address string for convenience. */\n async getDerivedAddress(\n nearAccountId: string,\n args: { contractId: string; path: string }\n ): Promise<string | null> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter();\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to read derived addresses from app origin.');\n }\n return await router.getDerivedAddress({ nearAccountId, args });\n }\n return await chainsigAddressManager.getDerivedAddress(toAccountId(nearAccountId), args);\n }\n\n ///////////////////////////////////////\n // === Email Recovery (public helpers) ===\n ///////////////////////////////////////\n\n /**\n * Get recovery emails for an account.\n * - Fetches on-chain recovery email hashes via get_recovery_emails.\n * - Resolves hashes to canonical emails using local IndexedDB mapping when available.\n * - Returns an array of { hashHex, email }, where `email` is a human-readable label\n * (canonical email when known on this device, otherwise the hash hex).\n */\n async getRecoveryEmails(nearAccountId: string): Promise<Array<{ hashHex: string; email: string }>> {\n if (this.shouldUseWalletIframe()) {\n let router: WalletIframeRouter;\n try {\n router = await this.requireWalletIframeRouter(nearAccountId);\n } catch {\n throw new Error('[TatchiPasskey] Wallet iframe is configured but unavailable; refusing to read recovery email mappings from app origin.');\n }\n return await router.getRecoveryEmails(nearAccountId);\n }\n const accountId = toAccountId(nearAccountId);\n\n // Fetch on-chain recovery email hashes\n const rawHashes = await getRecoveryEmailHashesContractCall(this.nearClient, accountId);\n if (!rawHashes.length) {\n return [];\n }\n\n // Load local mapping from IndexedDB (best-effort)\n let local: RecoveryEmailRecord[] = [];\n try {\n local = await getLocalRecoveryEmails(accountId);\n } catch (error) {\n console.warn('[TatchiPasskey] Failed to load local recovery emails', error);\n }\n\n const emailByHashHex = new Map<string, string>();\n for (const rec of local) {\n if (!rec?.hashHex || !rec?.email) continue;\n if (!emailByHashHex.has(rec.hashHex)) {\n emailByHashHex.set(rec.hashHex, rec.email);\n }\n }\n\n return rawHashes.map(hashBytes => {\n const hashHex = bytesToHex(hashBytes);\n const email = emailByHashHex.get(hashHex) || hashHex;\n return { hashHex, email };\n });\n }\n\n /**\n * Set recovery emails for an account:\n * - Canonicalizes and hashes emails client-side.\n * - Persists mapping in IndexedDB.\n * - Deploys/attaches the EmailRecoverer contract when needed.\n * - Calls set_recovery_emails(...) on the per-account contract.\n */\n async setRecoveryEmails(\n nearAccountId: string,\n recoveryEmails: string[],\n options?: ActionHooksOptions\n ): Promise<ActionResult> {\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter(nearAccountId);\n const res = await router.setRecoveryEmails({ nearAccountId, recoveryEmails, options });\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n const accountId = toAccountId(nearAccountId);\n\n // Canonicalize, hash, and persist mapping locally (best-effort)\n const { hashes: recoveryEmailHashes } = await prepareRecoveryEmails(accountId, recoveryEmails);\n\n const actions: ActionArgs[] = await buildSetRecoveryEmailsActions(\n this.nearClient,\n accountId,\n recoveryEmailHashes,\n this.configs.emailRecoveryContracts\n );\n\n // Delegate to executeAction so iframe vs same-origin routing is respected.\n return this.executeAction({\n nearAccountId,\n receiverId: nearAccountId,\n actionArgs: actions,\n options,\n });\n }\n\n ///////////////////////////////////////\n // === Account Recovery Flow ===\n ///////////////////////////////////////\n\n /**\n * Creates an AccountRecoveryFlow instance, for step-by-step account recovery UX\n */\n async recoverAccountFlow(args: {\n accountId?: string;\n options?: AccountRecoveryHooksOptions\n }): Promise<RecoveryResult> {\n\n const accountIdInput = args?.accountId || '';\n const options = args?.options;\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n const res = await router.recoverAccountFlow({\n accountId: accountIdInput,\n onEvent: options?.onEvent\n });\n await options?.afterCall?.(true, res);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n // Local orchestration using AccountRecoveryFlow for a single-call UX\n try {\n const flow = new AccountRecoveryFlow(this.getContext(), options);\n // Phase 1: Discover available accounts\n const discovered = await flow.discover(accountIdInput || '');\n if (!Array.isArray(discovered) || discovered.length === 0) {\n const err = new Error('No recoverable accounts found');\n await options?.onError?.(err);\n await options?.afterCall?.(false);\n return { success: false, accountId: accountIdInput || '', publicKey: '', message: err.message, error: err.message };\n }\n // Phase 2: User selects account in UI\n // Select the first account-scope; OS chooser selects the actual credential\n const selected = discovered[0];\n\n // Phase 3: Execute recovery with secure credential lookup\n const result = await flow.recover({\n credentialId: selected.credentialId,\n accountId: selected.accountId\n });\n\n await options?.afterCall?.(true, result);\n return result;\n\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n\n ///////////////////////////////////////\n // === Email Recovery Flow ===\n ///////////////////////////////////////\n\n private getEmailRecoveryFlow(options?: EmailRecoveryFlowOptions) {\n const { EmailRecoveryFlow } = require('./emailRecovery') as typeof import('./emailRecovery');\n if (!this.activeEmailRecoveryFlow) {\n this.activeEmailRecoveryFlow = new EmailRecoveryFlow(this.getContext(), options);\n } else if (options) {\n this.activeEmailRecoveryFlow.setOptions(options);\n }\n return this.activeEmailRecoveryFlow;\n }\n\n async startEmailRecovery(args: {\n accountId: string;\n recoveryEmail?: string;\n options?: EmailRecoveryFlowOptions;\n }): Promise<{ mailtoUrl: string; nearPublicKey: string }> {\n const { accountId, recoveryEmail, options } = args;\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n const normalizedRecoveryEmail =\n typeof recoveryEmail === 'string' && recoveryEmail.trim().length > 0\n ? recoveryEmail.trim()\n : undefined;\n const confirmerText = options?.confirmerText;\n const confirmationConfig = options?.confirmationConfig;\n const safeOptions = {\n ...(confirmerText ? { confirmerText } : {}),\n ...(confirmationConfig ? { confirmationConfig } : {}),\n };\n const res = await router.startEmailRecovery({\n accountId,\n recoveryEmail: normalizedRecoveryEmail,\n onEvent: options?.onEvent,\n options: Object.keys(safeOptions).length > 0 ? safeOptions : undefined,\n });\n await options?.afterCall?.(true, undefined);\n return res;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n const flow = this.getEmailRecoveryFlow(options);\n return await flow.start({ accountId, recoveryEmail });\n }\n\n async finalizeEmailRecovery(args: {\n accountId: string;\n nearPublicKey?: string;\n options?: EmailRecoveryFlowOptions;\n }): Promise<void> {\n const { accountId, nearPublicKey, options } = args;\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.finalizeEmailRecovery({\n accountId,\n nearPublicKey,\n onEvent: options?.onEvent,\n });\n await options?.afterCall?.(true, undefined);\n return;\n } catch (error: unknown) {\n const e = toError(error);\n await options?.onError?.(e);\n await options?.afterCall?.(false);\n throw e;\n }\n }\n const flow = this.getEmailRecoveryFlow(options);\n await flow.finalize({ accountId, nearPublicKey });\n }\n\n /**\n * Best-effort cancellation for an in-flight email recovery flow.\n * Intended for UI \"user cancelled sending email\" / retry UX.\n */\n async cancelEmailRecovery(args?: { accountId?: string; nearPublicKey?: string }): Promise<void> {\n const { accountId, nearPublicKey } = args || {};\n // In wallet-iframe mode, instruct the wallet host to stop the active flow.\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.stopEmailRecovery({ accountId, nearPublicKey });\n } catch {}\n return;\n }\n\n try {\n await this.activeEmailRecoveryFlow?.cancelAndReset({ accountId, nearPublicKey });\n } catch {}\n this.activeEmailRecoveryFlow = null;\n }\n\n ///////////////////////////////////////\n // === Link Device ===\n ///////////////////////////////////////\n\n /**\n * Device2: Start device linking flow\n * Returns QR payload and data URL to render; emits onEvent during the flow.\n * Runs inside iframe when available for better isolation.\n */\n async startDevice2LinkingFlow(args: StartDevice2LinkingFlowArgs): Promise<StartDevice2LinkingFlowResults> {\n // In wallet-iframe mode, device linking must run inside the wallet origin.\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter();\n const options = args?.options;\n return await router.startDevice2LinkingFlow({\n ui: args?.ui,\n cameraId: args?.cameraId,\n options,\n });\n }\n // Local fallback: keep internal flow reference for cancellation\n this.activeDeviceLinkFlow?.cancel();\n const flow = new LinkDeviceFlow(this.getContext(), {\n cameraId: args?.cameraId,\n options: args?.options,\n });\n this.activeDeviceLinkFlow = flow;\n const { qrData, qrCodeDataURL } = await flow.generateQR();\n return { qrData, qrCodeDataURL };\n }\n\n /**\n * Device2: Stops device linking flow inside the iframe host.\n */\n async stopDevice2LinkingFlow(): Promise<void> {\n if (this.shouldUseWalletIframe()) {\n try {\n const router = await this.requireWalletIframeRouter();\n await router.stopDevice2LinkingFlow();\n } catch {}\n return;\n }\n if (this.iframeRouter) {\n await this.iframeRouter.stopDevice2LinkingFlow();\n return;\n }\n this.activeDeviceLinkFlow?.cancel();\n this.activeDeviceLinkFlow = null;\n }\n\n /**\n * Device1: Link device using pre-scanned QR data.\n * You can use a QR scanning component of your choice,\n * or use the built-in <QRCodeScanner /> component.\n *\n * @param qrData The QR data obtained from scanning Device2's QR code\n * @param options Device linking options including funding amount and event callbacks\n * @returns Promise that resolves to the linking result\n */\n async linkDeviceWithScannedQRData(\n qrData: DeviceLinkingQRData,\n options: ScanAndLinkDeviceOptionsDevice1\n ): Promise<LinkDeviceResult> {\n // In wallet-iframe mode, device linking must run inside the wallet origin.\n if (this.shouldUseWalletIframe()) {\n const router = await this.requireWalletIframeRouter();\n const res = await router.linkDeviceWithScannedQRData({\n qrData,\n fundingAmount: options.fundingAmount,\n options: {\n onEvent: options.onEvent,\n confirmationConfig: options.confirmationConfig,\n confirmerText: options.confirmerText,\n }\n });\n return res as LinkDeviceResult;\n }\n return linkDeviceWithScannedQRData(this.getContext(), qrData, options);\n }\n\n /**\n * Delete a device key from an account\n */\n async deleteDeviceKey(\n accountId: string,\n publicKeyToDelete: string,\n options?: ActionHooksOptions\n ): Promise<ActionResult> {\n // Validate that we're not deleting the last key\n const keysView = this.iframeRouter\n ? await this.iframeRouter.viewAccessKeyList(accountId)\n : await this.nearClient.viewAccessKeyList(toAccountId(accountId));\n if (keysView.keys.length <= 1) {\n throw new Error('Cannot delete the last access key from an account');\n }\n\n // Find the key to delete\n const keyToDelete = keysView.keys.find((k: { public_key: string }) => k.public_key === publicKeyToDelete);\n if (!keyToDelete) {\n throw new Error(`Access key ${publicKeyToDelete} not found on account ${accountId}`);\n }\n\n // Use the executeAction method with DeleteKey action\n return this.executeAction({\n nearAccountId: accountId,\n receiverId: accountId,\n actionArgs: {\n type: ActionType.DeleteKey,\n publicKey: publicKeyToDelete\n },\n options: options\n });\n }\n\n}\n\n// Re-export types for convenience\nexport type {\n TatchiConfigs,\n TatchiConfigsInput,\n RegistrationResult,\n LoginAndCreateSessionResult,\n LoginResult,\n LoginSession,\n SigningSessionStatus,\n ActionResult,\n} from '../types/tatchi';\nexport type {\n ActionHooksOptions,\n AfterCall,\n EventCallback,\n LoginHooksOptions,\n LoginSSEvent,\n RegistrationHooksOptions,\n RegistrationSSEEvent,\n SignNEP413HooksOptions,\n} from '../types/sdkSentEvents';\n// Context alias (optional convenience)\nexport type TatchiPasskeyContext = PasskeyManagerContext;\n\nexport type {\n DeviceLinkingQRData,\n DeviceLinkingSession,\n LinkDeviceResult\n} from '../types/linkDevice';\n\n// Re-export device linking error types and classes\nexport {\n DeviceLinkingPhase,\n DeviceLinkingError,\n DeviceLinkingErrorCode\n} from '../types/linkDevice';\n\n// Re-export account recovery types and classes\nexport type {\n RecoveryResult,\n AccountLookupResult,\n PasskeyOption,\n PasskeyOptionWithoutCredential,\n PasskeySelection\n} from './recoverAccount';\n\nexport {\n AccountRecoveryFlow\n} from './recoverAccount';\n\n// Re-export NEP-413 types\nexport type {\n SignNEP413MessageParams,\n SignNEP413MessageResult\n} from './signNEP413';\n\n// Re-export QR scanning flow\nexport {\n ScanQRCodeFlow,\n type ScanQRCodeFlowOptions,\n type ScanQRCodeFlowEvents,\n ScanQRCodeFlowState\n} from '../../utils/qrScanner';\n"],"mappings":"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"}
@@ -5,11 +5,12 @@ import { ActionType, init_actions } from "../types/actions.js";
5
5
  import { DEFAULT_WAIT_STATUS, init_rpc } from "../types/rpc.js";
6
6
  import { getDeviceLinkingAccountContractCall, init_rpcCalls } from "../rpcCalls.js";
7
7
  import { init_getDeviceNumber, parseDeviceNumber } from "../WebAuthnManager/SignerWorkerManager/getDeviceNumber.js";
8
+ import { createNearKeypair, init_nearCrypto } from "../nearCrypto.js";
8
9
  import { getLoginSession, init_login } from "./login.js";
9
- import { createNearKeypair } from "../nearCrypto.js";
10
10
  import { DeviceLinkingError, DeviceLinkingErrorCode } from "../types/linkDevice.js";
11
11
 
12
12
  //#region src/core/TatchiPasskey/linkDevice.ts
13
+ init_nearCrypto();
13
14
  init_IndexedDBManager();
14
15
  init_actions();
15
16
  init_login();