@tatchi-xyz/sdk 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/dist/cjs/core/EmailRecovery/index.js +25 -0
  2. package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
  3. package/dist/cjs/core/TatchiPasskey/emailRecovery.js +135 -77
  4. package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
  5. package/dist/cjs/core/TatchiPasskey/index.js +2 -1
  6. package/dist/cjs/core/TatchiPasskey/index.js.map +1 -1
  7. package/dist/cjs/core/TatchiPasskey/linkDevice.js +2 -1
  8. package/dist/cjs/core/TatchiPasskey/linkDevice.js.map +1 -1
  9. package/dist/cjs/core/TatchiPasskey/scanDevice.js +5 -3
  10. package/dist/cjs/core/TatchiPasskey/scanDevice.js.map +1 -1
  11. package/dist/cjs/core/WalletIframe/client/router.js +1 -1
  12. package/dist/cjs/core/WalletIframe/client/router.js.map +1 -1
  13. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
  14. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  15. package/dist/cjs/core/defaultConfigs.js +3 -7
  16. package/dist/cjs/core/defaultConfigs.js.map +1 -1
  17. package/dist/cjs/core/nearCrypto.js +29 -5
  18. package/dist/cjs/core/nearCrypto.js.map +1 -1
  19. package/dist/cjs/core/rpcCalls.js +56 -26
  20. package/dist/cjs/core/rpcCalls.js.map +1 -1
  21. package/dist/cjs/core/types/emailRecovery.js +33 -0
  22. package/dist/cjs/core/types/emailRecovery.js.map +1 -0
  23. package/dist/cjs/index.js +4 -0
  24. package/dist/cjs/index.js.map +1 -1
  25. package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
  26. package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
  27. package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-BG_6hcim.css} +1 -1
  28. package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
  29. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
  30. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
  31. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-C-RcGfr5.css} +1 -1
  32. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
  33. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
  34. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
  35. package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
  36. package/dist/cjs/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
  37. package/dist/cjs/react/components/PasskeyAuthMenu/client.js +30 -8
  38. package/dist/cjs/react/components/PasskeyAuthMenu/client.js.map +1 -1
  39. package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +22 -0
  40. package/dist/cjs/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
  41. package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
  42. package/dist/cjs/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
  43. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +354 -154
  44. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  45. package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CB0UCQ_h.css} +1 -1
  46. package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
  47. package/dist/cjs/react/context/useSDKFlowRuntime.js +183 -0
  48. package/dist/cjs/react/context/useSDKFlowRuntime.js.map +1 -0
  49. package/dist/cjs/react/context/useTatchiContextValue.js +24 -15
  50. package/dist/cjs/react/context/useTatchiContextValue.js.map +1 -1
  51. package/dist/cjs/react/context/useTatchiWithSdkFlow.js +96 -0
  52. package/dist/cjs/react/context/useTatchiWithSdkFlow.js.map +1 -0
  53. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +26 -0
  54. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  55. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +135 -77
  56. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  57. package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js +2 -1
  58. package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
  59. package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
  60. package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
  61. package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
  62. package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
  63. package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js +1 -1
  64. package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
  65. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +3 -4
  66. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  67. package/dist/cjs/react/sdk/src/core/defaultConfigs.js +3 -7
  68. package/dist/cjs/react/sdk/src/core/defaultConfigs.js.map +1 -1
  69. package/dist/cjs/react/sdk/src/core/nearCrypto.js +29 -5
  70. package/dist/cjs/react/sdk/src/core/nearCrypto.js.map +1 -1
  71. package/dist/cjs/react/sdk/src/core/rpcCalls.js +56 -26
  72. package/dist/cjs/react/sdk/src/core/rpcCalls.js.map +1 -1
  73. package/dist/cjs/react/sdk/src/core/types/emailRecovery.js +33 -0
  74. package/dist/cjs/react/sdk/src/core/types/emailRecovery.js.map +1 -0
  75. package/dist/cjs/server/email-recovery/emailParsers.js +2 -1
  76. package/dist/cjs/server/email-recovery/emailParsers.js.map +1 -1
  77. package/dist/cjs/server/email-recovery/index.js +6 -6
  78. package/dist/cjs/server/email-recovery/index.js.map +1 -1
  79. package/dist/cjs/server/email-recovery/rpcCalls.js +22 -3
  80. package/dist/cjs/server/email-recovery/rpcCalls.js.map +1 -1
  81. package/dist/cjs/server/router/cloudflare.js +8 -3
  82. package/dist/cjs/server/router/cloudflare.js.map +1 -1
  83. package/dist/cjs/server/router/express.js.map +1 -1
  84. package/dist/cjs/server/sdk/src/core/defaultConfigs.js +2 -4
  85. package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
  86. package/dist/cjs/server/sdk/src/core/nearCrypto.js +26 -7
  87. package/dist/cjs/server/sdk/src/core/nearCrypto.js.map +1 -1
  88. package/dist/esm/core/EmailRecovery/index.js +25 -1
  89. package/dist/esm/core/EmailRecovery/index.js.map +1 -1
  90. package/dist/esm/core/TatchiPasskey/emailRecovery.js +136 -78
  91. package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
  92. package/dist/esm/core/TatchiPasskey/index.js +2 -1
  93. package/dist/esm/core/TatchiPasskey/index.js.map +1 -1
  94. package/dist/esm/core/TatchiPasskey/linkDevice.js +2 -1
  95. package/dist/esm/core/TatchiPasskey/linkDevice.js.map +1 -1
  96. package/dist/esm/core/TatchiPasskey/scanDevice.js +5 -3
  97. package/dist/esm/core/TatchiPasskey/scanDevice.js.map +1 -1
  98. package/dist/esm/core/WalletIframe/client/router.js +1 -1
  99. package/dist/esm/core/WalletIframe/client/router.js.map +1 -1
  100. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
  101. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  102. package/dist/esm/core/defaultConfigs.js +3 -7
  103. package/dist/esm/core/defaultConfigs.js.map +1 -1
  104. package/dist/esm/core/nearCrypto.js +24 -6
  105. package/dist/esm/core/nearCrypto.js.map +1 -1
  106. package/dist/esm/core/rpcCalls.js +56 -26
  107. package/dist/esm/core/rpcCalls.js.map +1 -1
  108. package/dist/esm/core/types/emailRecovery.js +26 -0
  109. package/dist/esm/core/types/emailRecovery.js.map +1 -0
  110. package/dist/esm/index.js +3 -1
  111. package/dist/esm/index.js.map +1 -1
  112. package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BRtht0XI.css} +1 -1
  113. package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BRtht0XI.css.map} +1 -1
  114. package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-BG_6hcim.css} +1 -1
  115. package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-BG_6hcim.css.map} +1 -1
  116. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-k8_FAYFq.css} +1 -1
  117. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-k8_FAYFq.css.map} +1 -1
  118. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-C-RcGfr5.css} +1 -1
  119. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-C-RcGfr5.css.map} +1 -1
  120. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DKMiLeT9.css} +59 -4
  121. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DKMiLeT9.css.map} +1 -1
  122. package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js +1 -0
  123. package/dist/esm/react/components/PasskeyAuthMenu/adapters/tatchi.js.map +1 -1
  124. package/dist/esm/react/components/PasskeyAuthMenu/client.js +30 -8
  125. package/dist/esm/react/components/PasskeyAuthMenu/client.js.map +1 -1
  126. package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js +20 -0
  127. package/dist/esm/react/components/PasskeyAuthMenu/controller/useSDKEvents.js.map +1 -0
  128. package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js +17 -4
  129. package/dist/esm/react/components/PasskeyAuthMenu/ui/ContentSwitcher.js.map +1 -1
  130. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +354 -154
  131. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  132. package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CB0UCQ_h.css} +1 -1
  133. package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CB0UCQ_h.css.map} +1 -1
  134. package/dist/esm/react/context/useSDKFlowRuntime.js +181 -0
  135. package/dist/esm/react/context/useSDKFlowRuntime.js.map +1 -0
  136. package/dist/esm/react/context/useTatchiContextValue.js +25 -16
  137. package/dist/esm/react/context/useTatchiContextValue.js.map +1 -1
  138. package/dist/esm/react/context/useTatchiWithSdkFlow.js +94 -0
  139. package/dist/esm/react/context/useTatchiWithSdkFlow.js.map +1 -0
  140. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +25 -1
  141. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  142. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -78
  143. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  144. package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js +2 -1
  145. package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
  146. package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -1
  147. package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
  148. package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js +5 -3
  149. package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
  150. package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js +1 -1
  151. package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
  152. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -3
  153. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  154. package/dist/esm/react/sdk/src/core/defaultConfigs.js +3 -7
  155. package/dist/esm/react/sdk/src/core/defaultConfigs.js.map +1 -1
  156. package/dist/esm/react/sdk/src/core/nearCrypto.js +24 -6
  157. package/dist/esm/react/sdk/src/core/nearCrypto.js.map +1 -1
  158. package/dist/esm/react/sdk/src/core/rpcCalls.js +56 -26
  159. package/dist/esm/react/sdk/src/core/rpcCalls.js.map +1 -1
  160. package/dist/esm/react/sdk/src/core/types/emailRecovery.js +26 -0
  161. package/dist/esm/react/sdk/src/core/types/emailRecovery.js.map +1 -0
  162. package/dist/esm/react/styles/styles.css +58 -3
  163. package/dist/esm/sdk/{defaultConfigs-DpslkAQd.js → defaultConfigs-CfQDV-ya.js} +3 -7
  164. package/dist/esm/sdk/{getDeviceNumber-fXizNGQl.js → getDeviceNumber-BpernPnM.js} +4 -8
  165. package/dist/esm/sdk/getDeviceNumber-BpernPnM.js.map +1 -0
  166. package/dist/esm/sdk/offline-export-app.js +23 -6
  167. package/dist/esm/sdk/offline-export-app.js.map +1 -1
  168. package/dist/esm/sdk/{router-DuGYOd3G.js → router-BWtacLJg.js} +1 -1
  169. package/dist/esm/sdk/{rpcCalls-BQrJMTdg.js → rpcCalls-CYGJSCgm.js} +3 -3
  170. package/dist/esm/sdk/{rpcCalls-YVeUVMk2.js → rpcCalls-DZZSa-sk.js} +57 -27
  171. package/dist/esm/sdk/{transactions-bqaAwL4k.js → transactions-Cn9xTWlK.js} +2 -2
  172. package/dist/esm/sdk/{transactions-bqaAwL4k.js.map → transactions-Cn9xTWlK.js.map} +1 -1
  173. package/dist/esm/sdk/{transactions-BalIhtJ9.js → transactions-DfdwDQCn.js} +1 -1
  174. package/dist/esm/sdk/wallet-iframe-host.js +660 -590
  175. package/dist/esm/server/email-recovery/emailParsers.js +3 -1
  176. package/dist/esm/server/email-recovery/emailParsers.js.map +1 -1
  177. package/dist/esm/server/email-recovery/index.js +6 -6
  178. package/dist/esm/server/email-recovery/index.js.map +1 -1
  179. package/dist/esm/server/email-recovery/rpcCalls.js +22 -3
  180. package/dist/esm/server/email-recovery/rpcCalls.js.map +1 -1
  181. package/dist/esm/server/router/cloudflare.js +8 -3
  182. package/dist/esm/server/router/cloudflare.js.map +1 -1
  183. package/dist/esm/server/router/express.js.map +1 -1
  184. package/dist/esm/server/sdk/src/core/defaultConfigs.js +2 -4
  185. package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
  186. package/dist/esm/server/sdk/src/core/nearCrypto.js +26 -8
  187. package/dist/esm/server/sdk/src/core/nearCrypto.js.map +1 -1
  188. package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
  189. package/dist/types/src/core/EmailRecovery/index.d.ts +8 -0
  190. package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
  191. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +8 -5
  192. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
  193. package/dist/types/src/core/TatchiPasskey/index.d.ts +1 -1
  194. package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
  195. package/dist/types/src/core/TatchiPasskey/scanDevice.d.ts.map +1 -1
  196. package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts +1 -1
  197. package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts.map +1 -1
  198. package/dist/types/src/core/WalletIframe/client/router.d.ts +1 -1
  199. package/dist/types/src/core/WalletIframe/client/router.d.ts.map +1 -1
  200. package/dist/types/src/core/WalletIframe/shared/messages.d.ts +1 -1
  201. package/dist/types/src/core/WalletIframe/shared/messages.d.ts.map +1 -1
  202. package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts +2 -1
  203. package/dist/types/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.d.ts.map +1 -1
  204. package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
  205. package/dist/types/src/core/nearCrypto.d.ts +14 -0
  206. package/dist/types/src/core/nearCrypto.d.ts.map +1 -1
  207. package/dist/types/src/core/rpcCalls.d.ts +11 -8
  208. package/dist/types/src/core/rpcCalls.d.ts.map +1 -1
  209. package/dist/types/src/core/types/emailRecovery.d.ts +10 -0
  210. package/dist/types/src/core/types/emailRecovery.d.ts.map +1 -0
  211. package/dist/types/src/core/types/index.d.ts +1 -0
  212. package/dist/types/src/core/types/index.d.ts.map +1 -1
  213. package/dist/types/src/core/types/tatchi.d.ts +0 -4
  214. package/dist/types/src/core/types/tatchi.d.ts.map +1 -1
  215. package/dist/types/src/index.d.ts +1 -0
  216. package/dist/types/src/index.d.ts.map +1 -1
  217. package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts +2 -0
  218. package/dist/types/src/react/components/PasskeyAuthMenu/adapters/tatchi.d.ts.map +1 -1
  219. package/dist/types/src/react/components/PasskeyAuthMenu/client.d.ts.map +1 -1
  220. package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts +10 -0
  221. package/dist/types/src/react/components/PasskeyAuthMenu/controller/useSDKEvents.d.ts.map +1 -0
  222. package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts +8 -3
  223. package/dist/types/src/react/components/PasskeyAuthMenu/types.d.ts.map +1 -1
  224. package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts +2 -0
  225. package/dist/types/src/react/components/PasskeyAuthMenu/ui/ContentSwitcher.d.ts.map +1 -1
  226. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts +1 -1
  227. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
  228. package/dist/types/src/react/context/useSDKFlowRuntime.d.ts +10 -0
  229. package/dist/types/src/react/context/useSDKFlowRuntime.d.ts.map +1 -0
  230. package/dist/types/src/react/context/useTatchiContextValue.d.ts.map +1 -1
  231. package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts +9 -0
  232. package/dist/types/src/react/context/useTatchiWithSdkFlow.d.ts.map +1 -0
  233. package/dist/types/src/react/types.d.ts +31 -0
  234. package/dist/types/src/react/types.d.ts.map +1 -1
  235. package/dist/types/src/server/email-recovery/emailParsers.d.ts.map +1 -1
  236. package/dist/types/src/server/email-recovery/index.d.ts +5 -6
  237. package/dist/types/src/server/email-recovery/index.d.ts.map +1 -1
  238. package/dist/types/src/server/email-recovery/rpcCalls.d.ts +1 -0
  239. package/dist/types/src/server/email-recovery/rpcCalls.d.ts.map +1 -1
  240. package/dist/types/src/server/router/cloudflare-adaptor.d.ts.map +1 -1
  241. package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
  242. package/package.json +1 -1
  243. package/dist/esm/sdk/getDeviceNumber-fXizNGQl.js.map +0 -1
@@ -1,14 +1,68 @@
1
1
  const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.js');
2
- const require_accountIds = require('../../../sdk/src/core/types/accountIds.js');
3
- const require_index = require('../../../sdk/src/core/IndexedDBManager/index.js');
2
+ const require_sdkSentEvents = require('../../../sdk/src/core/types/sdkSentEvents.js');
3
+ const require_index = require('../../../sdk/src/core/EmailRecovery/index.js');
4
+ const require_emailRecovery = require('../../../sdk/src/core/types/emailRecovery.js');
4
5
  let react = require("react");
5
6
  react = require_rolldown_runtime.__toESM(react);
6
7
  let react_jsx_runtime = require("react/jsx-runtime");
7
8
  react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
8
9
 
9
10
  //#region src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx
10
- require_index.init_IndexedDBManager();
11
- require_accountIds.init_accountIds();
11
+ require_sdkSentEvents.init_sdkSentEvents();
12
+ require_emailRecovery.init_emailRecovery();
13
+ require_index.init_EmailRecovery();
14
+ async function hashRecoveryEmailForAccountHex(args) {
15
+ const salt = String(args.accountId || "").trim().toLowerCase();
16
+ if (!salt) return null;
17
+ const canonical = require_index.canonicalizeEmail(String(args.recoveryEmail || ""));
18
+ if (!canonical || !canonical.includes("@")) return null;
19
+ if (typeof crypto === "undefined" || !crypto.subtle) return null;
20
+ const input = `${canonical}|${salt}`;
21
+ const bytes = new TextEncoder().encode(input);
22
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
23
+ return require_index.bytesToHex(new Uint8Array(digest));
24
+ }
25
+ function getEmailRecoveryErrorCode(err) {
26
+ const code = err?.code;
27
+ if (typeof code !== "string") return null;
28
+ return Object.values(require_emailRecovery.EmailRecoveryErrorCode).includes(code) ? code : null;
29
+ }
30
+ function getEmailRecoveryUiError(err) {
31
+ const fallback = err instanceof Error ? err.message : String(err || "");
32
+ const normalizedFallback = fallback.trim().toLowerCase();
33
+ if (normalizedFallback.includes("recovery email is required")) return {
34
+ message: fallback || "Recovery email is required for email-based account recovery. Make sure you send the email from your configured recovery email address.",
35
+ canRestart: true
36
+ };
37
+ const code = getEmailRecoveryErrorCode(err);
38
+ switch (code) {
39
+ case require_emailRecovery.EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED: return {
40
+ message: fallback || "Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again.",
41
+ canRestart: true
42
+ };
43
+ case require_emailRecovery.EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED: return {
44
+ message: fallback || "Registration did not verify on-chain. Please restart email recovery and try again.",
45
+ canRestart: true
46
+ };
47
+ default: return {
48
+ message: fallback || "Email recovery failed",
49
+ canRestart: false
50
+ };
51
+ }
52
+ }
53
+ function getEmailRecoveryErrorTxHash(err) {
54
+ const carrier = err;
55
+ const ctx = carrier?.context && typeof carrier.context === "object" ? carrier.context : null;
56
+ const details = carrier?.details && typeof carrier.details === "object" ? carrier.details : null;
57
+ const source = ctx ?? details;
58
+ if (!source) return null;
59
+ const txHash = source.transactionHash;
60
+ return typeof txHash === "string" && txHash.trim().length > 0 ? txHash.trim() : null;
61
+ }
62
+ function asRecord(value) {
63
+ if (!value || typeof value !== "object") return null;
64
+ return value;
65
+ }
12
66
  const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {
13
67
  const mountedRef = react.default.useRef(true);
14
68
  const mailtoAttemptTimerRef = react.default.useRef(null);
@@ -25,19 +79,22 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
25
79
  }, []);
26
80
  const [isBusy, setIsBusy] = react.default.useState(false);
27
81
  const [accountIdInput, setAccountIdInput] = react.default.useState("");
28
- const [recoveryEmailInput, setRecoveryEmailInput] = react.default.useState("");
29
82
  const [pendingMailtoUrl, setPendingMailtoUrl] = react.default.useState(null);
83
+ const [pendingNearPublicKey, setPendingNearPublicKey] = react.default.useState(null);
30
84
  const [mailtoUiState, setMailtoUiState] = react.default.useState("ready");
31
85
  const [statusText, setStatusText] = react.default.useState(null);
32
86
  const [pollingElapsedMs, setPollingElapsedMs] = react.default.useState(null);
33
87
  const [errorText, setErrorText] = react.default.useState(null);
88
+ const [canRestart, setCanRestart] = react.default.useState(false);
34
89
  const [accountInfo, setAccountInfo] = react.default.useState(null);
35
90
  const [accountInfoLoading, setAccountInfoLoading] = react.default.useState(false);
36
91
  const [accountInfoError, setAccountInfoError] = react.default.useState(null);
37
92
  const [localRecoveryEmails, setLocalRecoveryEmails] = react.default.useState([]);
93
+ const [recoveryEmailRecords, setRecoveryEmailRecords] = react.default.useState([]);
94
+ const [recoveryEmailInput, setRecoveryEmailInput] = react.default.useState("");
95
+ const [recoveryEmailMatchStatus, setRecoveryEmailMatchStatus] = react.default.useState("empty");
38
96
  const [explorerToast, setExplorerToast] = react.default.useState(null);
39
97
  const lastPrefilledAccountIdRef = react.default.useRef("");
40
- const lastPrefilledRecoveryEmailRef = react.default.useRef("");
41
98
  react.default.useEffect(() => {
42
99
  const next = (accountId || "").trim();
43
100
  if (!next) return;
@@ -48,14 +105,19 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
48
105
  }, [accountId]);
49
106
  react.default.useEffect(() => {
50
107
  setPendingMailtoUrl(null);
108
+ setPendingNearPublicKey(null);
51
109
  setMailtoUiState("ready");
52
110
  cancelRequestedRef.current = false;
53
111
  setStatusText(null);
54
112
  setPollingElapsedMs(null);
55
113
  setErrorText(null);
114
+ setCanRestart(false);
56
115
  setAccountInfo(null);
57
116
  setAccountInfoError(null);
58
117
  setLocalRecoveryEmails([]);
118
+ setRecoveryEmailRecords([]);
119
+ setRecoveryEmailInput("");
120
+ setRecoveryEmailMatchStatus("empty");
59
121
  setExplorerToast(null);
60
122
  if (mailtoAttemptTimerRef.current != null) {
61
123
  window.clearTimeout(mailtoAttemptTimerRef.current);
@@ -69,22 +131,26 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
69
131
  };
70
132
  };
71
133
  const safeSetPendingMailtoUrl = react.default.useMemo(() => safeSet(setPendingMailtoUrl), []);
134
+ const safeSetPendingNearPublicKey = react.default.useMemo(() => safeSet(setPendingNearPublicKey), []);
72
135
  const safeSetStatusText = react.default.useMemo(() => safeSet(setStatusText), []);
73
136
  const safeSetPollingElapsedMs = react.default.useMemo(() => safeSet(setPollingElapsedMs), []);
74
137
  const safeSetErrorText = react.default.useMemo(() => safeSet(setErrorText), []);
75
138
  const safeSetIsBusy = react.default.useMemo(() => safeSet(setIsBusy), []);
139
+ const safeSetCanRestart = react.default.useMemo(() => safeSet(setCanRestart), []);
76
140
  const safeSetAccountInfo = react.default.useMemo(() => safeSet(setAccountInfo), []);
77
141
  const safeSetAccountInfoLoading = react.default.useMemo(() => safeSet(setAccountInfoLoading), []);
78
142
  const safeSetAccountInfoError = react.default.useMemo(() => safeSet(setAccountInfoError), []);
79
143
  const safeSetLocalRecoveryEmails = react.default.useMemo(() => safeSet(setLocalRecoveryEmails), []);
144
+ const safeSetRecoveryEmailRecords = react.default.useMemo(() => safeSet(setRecoveryEmailRecords), []);
145
+ const safeSetRecoveryEmailMatchStatus = react.default.useMemo(() => safeSet(setRecoveryEmailMatchStatus), []);
80
146
  const safeSetExplorerToast = react.default.useMemo(() => safeSet(setExplorerToast), []);
81
147
  const safeSetMailtoUiState = react.default.useMemo(() => safeSet(setMailtoUiState), []);
82
148
  const onEvent = react.default.useCallback((ev) => {
83
149
  if (cancelRequestedRef.current) return;
84
150
  safeSetStatusText(ev?.message || null);
85
151
  emailRecoveryOptions?.onEvent?.(ev);
86
- const data = ev?.data || {};
87
- const rawTxHash = data?.transactionHash ?? data?.transaction_hash;
152
+ const data = "data" in ev ? asRecord(ev.data) : null;
153
+ const rawTxHash = data?.["transactionHash"] ?? data?.["transaction_hash"];
88
154
  const txHash = typeof rawTxHash === "string" ? rawTxHash.trim() : "";
89
155
  if (txHash) {
90
156
  const base = String(tatchiPasskey.configs?.nearExplorerUrl || "https://testnet.nearblocks.io").replace(/\/$/, "");
@@ -94,16 +160,18 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
94
160
  transactionHash: txHash
95
161
  });
96
162
  }
97
- const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;
163
+ const elapsedRaw = data?.["elapsedMs"] ?? data?.["elapsed_ms"];
98
164
  if (elapsedRaw == null) safeSetPollingElapsedMs(null);
99
165
  const elapsed = elapsedRaw == null ? NaN : Number(elapsedRaw);
100
166
  if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);
101
- if (ev?.phase === "email-recovery-error" || ev?.status === "error") {
102
- const raw = ev?.error || ev?.message || "Email recovery failed";
103
- safeSetErrorText(String(raw));
167
+ if (ev.phase === require_sdkSentEvents.EmailRecoveryPhase.ERROR || ev.status === require_sdkSentEvents.EmailRecoveryStatus.ERROR) {
168
+ const raw = "error" in ev ? ev.error : ev.message;
169
+ safeSetErrorText(raw || "Email recovery failed");
170
+ safeSetCanRestart(false);
104
171
  }
105
172
  }, [
106
173
  emailRecoveryOptions,
174
+ safeSetCanRestart,
107
175
  safeSetErrorText,
108
176
  safeSetExplorerToast,
109
177
  safeSetPollingElapsedMs,
@@ -120,6 +188,16 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
120
188
  accountId: normalized
121
189
  });
122
190
  }, [safeSetExplorerToast, tatchiPasskey]);
191
+ const showExplorerTxToast = react.default.useCallback((txHash) => {
192
+ const normalized = (txHash || "").trim();
193
+ if (!normalized) return;
194
+ const base = String(tatchiPasskey.configs?.nearExplorerUrl || "https://testnet.nearblocks.io").replace(/\/$/, "");
195
+ const url = base.includes("nearblocks.io") ? `${base}/txns/${normalized}` : `${base}/transactions/${normalized}`;
196
+ safeSetExplorerToast({
197
+ url,
198
+ transactionHash: normalized
199
+ });
200
+ }, [safeSetExplorerToast, tatchiPasskey]);
123
201
  const launchMailto = react.default.useCallback((rawMailtoUrl) => {
124
202
  const url = String(rawMailtoUrl || "").trim();
125
203
  if (!url) return;
@@ -165,40 +243,9 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
165
243
  document.removeEventListener("visibilitychange", onVisibilityChange);
166
244
  };
167
245
  }, [mailtoUiState, safeSetMailtoUiState]);
168
- const fetchLocalRecoveryEmailsFromIndexedDB = react.default.useCallback(async (rawAccountId) => {
169
- const normalized = (rawAccountId || "").trim();
170
- if (!normalized) {
171
- console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId");
172
- return [];
173
- }
174
- try {
175
- console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB", { accountId: normalized });
176
- const records = await require_index.IndexedDBManager.getRecoveryEmails(require_accountIds.toAccountId(normalized));
177
- console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records", {
178
- accountId: normalized,
179
- count: Array.isArray(records) ? records.length : 0,
180
- records
181
- });
182
- if (!Array.isArray(records) || records.length === 0) return [];
183
- const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));
184
- const emails = sorted.map((r) => String(r?.email || "").trim().toLowerCase()).filter((e) => !!e && e.includes("@"));
185
- const uniq = Array.from(new Set(emails));
186
- console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails", {
187
- accountId: normalized,
188
- emails: uniq
189
- });
190
- return uniq;
191
- } catch (err) {
192
- console.log("[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB", {
193
- accountId: normalized,
194
- error: err instanceof Error ? err.message : String(err)
195
- });
196
- return [];
197
- }
198
- }, []);
199
246
  const deriveEmailsFromRecoveryRecords = react.default.useCallback((records) => {
200
- if (!Array.isArray(records) || records.length === 0) return [];
201
- const emails = records.map((r) => String(r?.email || "").trim().toLowerCase()).filter((e) => !!e && e.includes("@"));
247
+ if (records.length === 0) return [];
248
+ const emails = records.map((r) => r.email.trim().toLowerCase()).filter((e) => e.length > 0 && e.includes("@"));
202
249
  return Array.from(new Set(emails));
203
250
  }, []);
204
251
  react.default.useEffect(() => {
@@ -216,27 +263,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
216
263
  const handle = window.setTimeout(() => {
217
264
  (async () => {
218
265
  try {
219
- const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;
220
- let localEmails = [];
221
- if (!isWalletIframeMode) {
222
- localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);
223
- if (!cancelled) console.log("[EmailRecoverySlide] local saved emails (IndexedDB)", {
224
- accountId: normalized,
225
- localEmails
226
- });
227
- }
228
266
  const records = await tatchiPasskey.getRecoveryEmails(normalized);
229
- const resolvedEmails = isWalletIframeMode ? deriveEmailsFromRecoveryRecords(records) : localEmails;
267
+ const resolvedEmails = deriveEmailsFromRecoveryRecords(records);
230
268
  if (!cancelled) {
231
269
  safeSetLocalRecoveryEmails(resolvedEmails);
232
- console.log("[EmailRecoverySlide] recovery email suggestions (state)", {
233
- accountId: normalized,
234
- emails: resolvedEmails
235
- });
236
- if (resolvedEmails.length === 1 && (recoveryEmailInput.trim() === "" || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)) {
237
- lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];
238
- setRecoveryEmailInput(resolvedEmails[0]);
239
- }
270
+ safeSetRecoveryEmailRecords(records);
240
271
  }
241
272
  const info = records ? { emailsCount: Array.isArray(records) ? records.length : 0 } : null;
242
273
  if (cancelled) return;
@@ -244,7 +275,10 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
244
275
  } catch (err) {
245
276
  if (cancelled) return;
246
277
  safeSetAccountInfo(null);
247
- safeSetAccountInfoError(err?.message || "Failed to load email recovery settings for this account");
278
+ const msg = err instanceof Error ? err.message : "";
279
+ safeSetAccountInfoError(msg || "Failed to load email recovery settings for this account");
280
+ safeSetLocalRecoveryEmails([]);
281
+ safeSetRecoveryEmailRecords([]);
248
282
  } finally {
249
283
  if (!cancelled) safeSetAccountInfoLoading(false);
250
284
  }
@@ -257,37 +291,114 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
257
291
  }, [
258
292
  accountIdInput,
259
293
  deriveEmailsFromRecoveryRecords,
260
- fetchLocalRecoveryEmailsFromIndexedDB,
261
- recoveryEmailInput,
262
294
  safeSetAccountInfo,
263
295
  safeSetAccountInfoError,
264
296
  safeSetAccountInfoLoading,
265
297
  safeSetLocalRecoveryEmails,
298
+ safeSetRecoveryEmailRecords,
266
299
  tatchiPasskey
267
300
  ]);
301
+ const recoveryEmailConfirmationRequired = !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount > 0 && localRecoveryEmails.length === 0;
302
+ react.default.useEffect(() => {
303
+ const normalizedAccountId = (accountIdInput || "").trim();
304
+ const rawEmail = (recoveryEmailInput || "").trim();
305
+ if (!rawEmail || !normalizedAccountId) {
306
+ safeSetRecoveryEmailMatchStatus("empty");
307
+ return;
308
+ }
309
+ if (!Array.isArray(recoveryEmailRecords) || recoveryEmailRecords.length === 0) {
310
+ safeSetRecoveryEmailMatchStatus("checking");
311
+ return;
312
+ }
313
+ let cancelled = false;
314
+ safeSetRecoveryEmailMatchStatus("checking");
315
+ const handle = window.setTimeout(() => {
316
+ (async () => {
317
+ try {
318
+ const hashHex = await hashRecoveryEmailForAccountHex({
319
+ recoveryEmail: rawEmail,
320
+ accountId: normalizedAccountId
321
+ });
322
+ if (cancelled) return;
323
+ if (!hashHex) {
324
+ safeSetRecoveryEmailMatchStatus("invalid");
325
+ return;
326
+ }
327
+ const normalizedHashHex = hashHex.toLowerCase();
328
+ const matches = recoveryEmailRecords.some((rec) => String(rec.hashHex || "").toLowerCase() === normalizedHashHex);
329
+ safeSetRecoveryEmailMatchStatus(matches ? "match" : "mismatch");
330
+ } catch {
331
+ if (!cancelled) safeSetRecoveryEmailMatchStatus("invalid");
332
+ }
333
+ })();
334
+ }, 250);
335
+ return () => {
336
+ cancelled = true;
337
+ window.clearTimeout(handle);
338
+ };
339
+ }, [
340
+ accountIdInput,
341
+ recoveryEmailInput,
342
+ recoveryEmailRecords,
343
+ safeSetRecoveryEmailMatchStatus
344
+ ]);
268
345
  const handleStart = react.default.useCallback(async () => {
269
346
  const normalizedAccountId = (accountIdInput || "").trim();
270
347
  if (!normalizedAccountId) {
271
348
  safeSetErrorText("Enter an account ID.");
272
349
  return;
273
350
  }
274
- const emailCandidate = (recoveryEmailInput || "").trim().toLowerCase();
275
- if (!emailCandidate) {
276
- safeSetErrorText("Enter the recovery email to send from.");
351
+ if (accountInfoLoading) {
352
+ safeSetErrorText("Checking recovery email settings…");
353
+ return;
354
+ }
355
+ if (accountInfoError) {
356
+ safeSetErrorText(accountInfoError);
357
+ return;
358
+ }
359
+ if (!accountInfo) {
360
+ safeSetErrorText("Failed to load email recovery settings for this account.");
277
361
  return;
278
362
  }
363
+ if (accountInfo.emailsCount === 0) {
364
+ safeSetErrorText("No recovery emails are configured for this account.");
365
+ return;
366
+ }
367
+ const recoveryEmail = recoveryEmailInput.trim();
368
+ if (recoveryEmailConfirmationRequired) {
369
+ if (!recoveryEmail) {
370
+ safeSetErrorText("Enter the recovery email address you will send from.");
371
+ return;
372
+ }
373
+ const hashHex = await hashRecoveryEmailForAccountHex({
374
+ recoveryEmail,
375
+ accountId: normalizedAccountId
376
+ }).catch(() => null);
377
+ if (!hashHex) {
378
+ safeSetErrorText("Enter a valid recovery email address.");
379
+ return;
380
+ }
381
+ const normalizedHashHex = hashHex.toLowerCase();
382
+ const matches = recoveryEmailRecords.some((rec) => String(rec.hashHex || "").toLowerCase() === normalizedHashHex);
383
+ if (!matches) {
384
+ safeSetErrorText("That email is not configured for recovery on this account. Please use your configured recovery email address.");
385
+ return;
386
+ }
387
+ }
279
388
  safeSetIsBusy(true);
280
389
  cancelRequestedRef.current = false;
281
390
  safeSetErrorText(null);
391
+ safeSetCanRestart(false);
282
392
  safeSetStatusText(null);
283
393
  safeSetPollingElapsedMs(null);
284
394
  safeSetPendingMailtoUrl(null);
395
+ safeSetPendingNearPublicKey(null);
285
396
  safeSetMailtoUiState("ready");
286
397
  let didForwardError = false;
287
398
  try {
288
399
  const result = await tatchiPasskey.startEmailRecovery({
289
400
  accountId: normalizedAccountId,
290
- recoveryEmail: emailCandidate,
401
+ ...recoveryEmail ? { recoveryEmail } : {},
291
402
  options: {
292
403
  onEvent,
293
404
  onError: (err) => {
@@ -295,11 +406,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
295
406
  safeSetErrorText(err?.message || "Failed to start email recovery");
296
407
  didForwardError = true;
297
408
  emailRecoveryOptions?.onError?.(err);
298
- },
299
- afterCall: async () => {}
409
+ }
300
410
  }
301
411
  });
302
412
  safeSetPendingMailtoUrl(result.mailtoUrl);
413
+ safeSetPendingNearPublicKey(result.nearPublicKey);
303
414
  safeSetStatusText("Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…");
304
415
  attemptOpenMailtoAuto(result.mailtoUrl);
305
416
  const finalizePromise = tatchiPasskey.finalizeEmailRecovery({
@@ -309,11 +420,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
309
420
  onEvent,
310
421
  onError: (err) => {
311
422
  if (cancelRequestedRef.current) return;
312
- safeSetErrorText(err?.message || "Failed to finalize email recovery");
423
+ const uiError = getEmailRecoveryUiError(err);
424
+ safeSetErrorText(uiError.message || "Failed to finalize email recovery");
425
+ safeSetCanRestart(uiError.canRestart);
426
+ const txHash = getEmailRecoveryErrorTxHash(err);
427
+ if (txHash) showExplorerTxToast(txHash);
313
428
  didForwardError = true;
314
429
  emailRecoveryOptions?.onError?.(err);
315
- },
316
- afterCall: async () => {}
430
+ }
317
431
  }
318
432
  });
319
433
  showExplorerToast(normalizedAccountId);
@@ -336,10 +450,16 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
336
450
  safeSetStatusText(null);
337
451
  safeSetPollingElapsedMs(null);
338
452
  safeSetPendingMailtoUrl(null);
453
+ safeSetPendingNearPublicKey(null);
339
454
  safeSetMailtoUiState("ready");
455
+ safeSetCanRestart(false);
340
456
  return;
341
457
  }
342
- safeSetErrorText(err?.message || "Failed to start email recovery");
458
+ const uiError = getEmailRecoveryUiError(err);
459
+ safeSetErrorText(uiError.message || "Failed to start email recovery");
460
+ safeSetCanRestart(uiError.canRestart);
461
+ const txHash = getEmailRecoveryErrorTxHash(err);
462
+ if (txHash) showExplorerTxToast(txHash);
343
463
  if (!didForwardError && err instanceof Error) emailRecoveryOptions?.onError?.(err);
344
464
  } finally {
345
465
  safeSetIsBusy(false);
@@ -347,9 +467,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
347
467
  }, [
348
468
  accountIdInput,
349
469
  emailRecoveryOptions,
350
- recoveryEmailInput,
351
470
  onEvent,
352
471
  refreshLoginState,
472
+ accountInfo,
473
+ accountInfoError,
474
+ accountInfoLoading,
475
+ recoveryEmailConfirmationRequired,
476
+ recoveryEmailInput,
477
+ recoveryEmailRecords,
353
478
  showExplorerToast,
354
479
  safeSetErrorText,
355
480
  safeSetIsBusy,
@@ -358,10 +483,64 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
358
483
  safeSetStatusText,
359
484
  safeSetMailtoUiState,
360
485
  attemptOpenMailtoAuto,
486
+ showExplorerTxToast,
361
487
  tatchiPasskey
362
488
  ]);
363
- const summaryLine = accountInfoLoading ? "Checking if account has recovery emails configured..." : accountInfo && !accountInfoError ? `Recovery emails configured: ${accountInfo.emailsCount}` : "\xA0";
489
+ const handleRestart = react.default.useCallback(async () => {
490
+ const normalizedAccountId = (accountIdInput || "").trim();
491
+ if (!normalizedAccountId) return;
492
+ safeSetIsBusy(true);
493
+ try {
494
+ cancelRequestedRef.current = true;
495
+ await tatchiPasskey.cancelEmailRecovery({
496
+ accountId: normalizedAccountId,
497
+ nearPublicKey: pendingNearPublicKey || void 0
498
+ }).catch(() => {});
499
+ safeSetErrorText(null);
500
+ safeSetStatusText(null);
501
+ safeSetPollingElapsedMs(null);
502
+ safeSetPendingMailtoUrl(null);
503
+ safeSetPendingNearPublicKey(null);
504
+ safeSetMailtoUiState("ready");
505
+ safeSetCanRestart(false);
506
+ } finally {
507
+ cancelRequestedRef.current = false;
508
+ safeSetIsBusy(false);
509
+ }
510
+ }, [
511
+ accountIdInput,
512
+ pendingNearPublicKey,
513
+ safeSetCanRestart,
514
+ safeSetErrorText,
515
+ safeSetIsBusy,
516
+ safeSetMailtoUiState,
517
+ safeSetPendingMailtoUrl,
518
+ safeSetPendingNearPublicKey,
519
+ safeSetPollingElapsedMs,
520
+ safeSetStatusText,
521
+ tatchiPasskey
522
+ ]);
523
+ const summaryLine = accountInfoLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: ["Checking if account has recovery emails configured", /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
524
+ className: "w3a-ellipsis",
525
+ "aria-hidden": "true",
526
+ children: [
527
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
528
+ className: "w3a-ellipsis-dot",
529
+ children: "."
530
+ }),
531
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
532
+ className: "w3a-ellipsis-dot",
533
+ children: "."
534
+ }),
535
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
536
+ className: "w3a-ellipsis-dot",
537
+ children: "."
538
+ })
539
+ ]
540
+ })] }) : accountInfo && !accountInfoError ? `Recovery emails configured: ${accountInfo.emailsCount}` : "\xA0";
364
541
  const noRecoveryEmailsConfigured = !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;
542
+ const disableStartForRecoveryEmailMismatch = recoveryEmailConfirmationRequired && (recoveryEmailMatchStatus === "empty" || recoveryEmailMatchStatus === "checking" || recoveryEmailMatchStatus === "invalid" || recoveryEmailMatchStatus === "mismatch");
543
+ const startDisabled = isBusy || accountInfoLoading || !!accountInfoError || !accountInfo || noRecoveryEmailsConfigured || disableStartForRecoveryEmailMismatch;
365
544
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
366
545
  className: "w3a-email-recovery-slide",
367
546
  children: [
@@ -371,92 +550,113 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
371
550
  }),
372
551
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
373
552
  className: "w3a-email-recovery-help",
374
- children: "Send a special recovery email from your recovery email address. Your account will be recovered with a new key once the email is verified."
553
+ children: "Send a special email to recover your account. This email must be sent from the designated email recovery address."
375
554
  }),
376
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
377
- className: "w3a-email-recovery-field",
555
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
556
+ className: "w3a-input-pill w3a-email-recovery-input-pill",
378
557
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
379
- className: "w3a-input-pill w3a-email-recovery-input-pill",
380
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
381
- className: "w3a-input-wrap",
382
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
383
- type: "text",
384
- value: accountIdInput,
385
- onChange: (e) => setAccountIdInput(e.target.value),
386
- placeholder: "NEAR account ID (e.g. alice.testnet)",
387
- className: "w3a-input",
388
- autoCapitalize: "none",
389
- autoCorrect: "off",
390
- spellCheck: false,
391
- inputMode: "text",
392
- disabled: isBusy
393
- })
558
+ className: "w3a-input-wrap",
559
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
560
+ type: "text",
561
+ value: accountIdInput,
562
+ onChange: (e) => setAccountIdInput(e.target.value),
563
+ placeholder: "NEAR account ID (e.g. alice.testnet)",
564
+ className: "w3a-input",
565
+ autoCapitalize: "none",
566
+ autoCorrect: "off",
567
+ spellCheck: false,
568
+ inputMode: "text",
569
+ disabled: isBusy
394
570
  })
395
571
  })
396
- }),
397
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
572
+ }) }),
573
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
398
574
  className: "w3a-email-recovery-summary",
399
575
  "aria-live": "polite",
400
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: summaryLine })
401
- }),
402
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
403
- className: "w3a-email-recovery-field",
404
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
405
- className: "w3a-input-pill w3a-email-recovery-input-pill",
406
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
407
- className: "w3a-input-wrap",
408
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
409
- type: "email",
410
- value: recoveryEmailInput,
411
- onChange: (e) => setRecoveryEmailInput(e.target.value),
412
- placeholder: "Recovery email to send from",
413
- className: "w3a-input",
414
- list: localRecoveryEmails.length > 0 ? "w3a-email-recovery-saved-emails" : void 0,
415
- autoCapitalize: "none",
416
- autoCorrect: "off",
417
- spellCheck: false,
418
- inputMode: "email",
419
- disabled: isBusy || noRecoveryEmailsConfigured
420
- })
576
+ children: [
577
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: summaryLine }),
578
+ !!accountInfoError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
579
+ className: "w3a-email-recovery-warning",
580
+ children: accountInfoError
581
+ }),
582
+ localRecoveryEmails.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
583
+ className: "w3a-email-recovery-saved-emails",
584
+ role: "list",
585
+ "aria-label": "Recovery emails",
586
+ children: localRecoveryEmails.map((email) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
587
+ className: "w3a-email-recovery-email-chip w3a-email-recovery-email-chip-static",
588
+ role: "listitem",
589
+ children: email
590
+ }, email))
591
+ }),
592
+ recoveryEmailConfirmationRequired && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
593
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
594
+ className: "w3a-email-recovery-warning",
595
+ children: "This device can’t display your configured recovery email address. Enter the email you will send from to confirm it matches what’s configured for this account."
596
+ }),
597
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
598
+ className: "w3a-input-pill w3a-email-recovery-input-pill",
599
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
600
+ className: "w3a-input-wrap",
601
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
602
+ type: "email",
603
+ value: recoveryEmailInput,
604
+ onChange: (e) => setRecoveryEmailInput(e.target.value),
605
+ placeholder: "Recovery email address (sender)",
606
+ className: "w3a-input",
607
+ autoCapitalize: "none",
608
+ autoCorrect: "off",
609
+ spellCheck: false,
610
+ inputMode: "email",
611
+ disabled: isBusy
612
+ })
613
+ })
614
+ }),
615
+ recoveryEmailMatchStatus === "checking" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: "Checking recovery email…" }),
616
+ recoveryEmailMatchStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
617
+ className: "w3a-email-recovery-warning",
618
+ children: "Enter a valid email address."
619
+ }),
620
+ recoveryEmailMatchStatus === "mismatch" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
621
+ className: "w3a-email-recovery-warning",
622
+ children: "That email is not configured for recovery on this account."
623
+ }),
624
+ recoveryEmailMatchStatus === "match" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: "Recovery email verified for this account." })
625
+ ] }),
626
+ !!accountIdInput.trim() && !noRecoveryEmailsConfigured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
627
+ className: "w3a-email-recovery-from-warning",
628
+ children: recoveryEmailInput.trim() ? `Check that you are sending the recovery email from ${recoveryEmailInput.trim()}.` : "Check that you are sending the recovery email from your designated recovery email."
421
629
  })
422
- })
423
- }),
424
- localRecoveryEmails.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
425
- className: "w3a-email-recovery-summary",
426
- "aria-live": "polite",
427
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: "Saved on this device:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
428
- className: "w3a-email-recovery-saved-emails",
429
- children: localRecoveryEmails.map((email) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
430
- type: "button",
431
- className: "w3a-email-recovery-email-chip",
432
- onClick: () => setRecoveryEmailInput(email),
433
- disabled: isBusy,
434
- children: email
435
- }, email))
436
- })]
437
- }),
438
- localRecoveryEmails.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("datalist", {
439
- id: "w3a-email-recovery-saved-emails",
440
- children: localRecoveryEmails.map((email) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", { value: email }, email))
630
+ ]
441
631
  }),
442
632
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
443
633
  className: "w3a-email-recovery-actions",
444
- children: [(!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
445
- onClick: handleStart,
446
- className: "w3a-link-device-btn w3a-link-device-btn-primary",
447
- disabled: isBusy || noRecoveryEmailsConfigured,
448
- children: noRecoveryEmailsConfigured ? "No recovery emails configured" : isBusy ? "Working…" : "Start Email Recovery"
449
- }), pendingMailtoUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
450
- type: "button",
451
- onClick: () => attemptOpenMailtoFromUserGesture(pendingMailtoUrl),
452
- className: "w3a-link-device-btn w3a-link-device-btn-primary",
453
- disabled: mailtoUiState === "opening",
454
- "aria-busy": mailtoUiState === "opening",
455
- children: [mailtoUiState === "opening" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
456
- className: "w3a-spinner",
457
- "aria-hidden": "true"
458
- }), mailtoUiState === "opening" ? "Opening email…" : "Open recovery email draft"]
459
- })]
634
+ children: [
635
+ (!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
636
+ onClick: handleStart,
637
+ className: "w3a-link-device-btn w3a-link-device-btn-primary",
638
+ disabled: startDisabled,
639
+ children: accountInfoLoading ? "Checking recovery emails…" : noRecoveryEmailsConfigured ? "No recovery emails configured" : disableStartForRecoveryEmailMismatch ? "Confirm recovery email" : isBusy ? "Working…" : "Start Email Recovery"
640
+ }),
641
+ pendingMailtoUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
642
+ type: "button",
643
+ onClick: () => attemptOpenMailtoFromUserGesture(pendingMailtoUrl),
644
+ className: "w3a-link-device-btn w3a-link-device-btn-primary",
645
+ disabled: mailtoUiState === "opening",
646
+ "aria-busy": mailtoUiState === "opening",
647
+ children: [mailtoUiState === "opening" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
648
+ className: "w3a-spinner",
649
+ "aria-hidden": "true"
650
+ }), mailtoUiState === "opening" ? "Opening email…" : "Open recovery email draft"]
651
+ }),
652
+ errorText && canRestart && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
653
+ type: "button",
654
+ onClick: handleRestart,
655
+ className: "w3a-link-device-btn",
656
+ disabled: isBusy,
657
+ children: "Restart email recovery"
658
+ })
659
+ ]
460
660
  }),
461
661
  (errorText || statusText || explorerToast) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
462
662
  className: `w3a-email-recovery-status${errorText ? " is-error" : ""}`,