@tatchi-xyz/sdk 0.16.0 → 0.17.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 (470) hide show
  1. package/dist/cjs/core/EmailRecovery/index.js +12 -5
  2. package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
  3. package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js +35 -36
  4. package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
  5. package/dist/cjs/core/NearClient.js +2 -1
  6. package/dist/cjs/core/NearClient.js.map +1 -1
  7. package/dist/cjs/core/TatchiPasskey/emailRecovery.js +136 -27
  8. package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
  9. package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js +1 -0
  10. package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
  11. package/dist/cjs/core/TatchiPasskey/index.js +25 -0
  12. package/dist/cjs/core/TatchiPasskey/index.js.map +1 -1
  13. package/dist/cjs/core/TatchiPasskey/linkDevice.js +2 -0
  14. package/dist/cjs/core/TatchiPasskey/linkDevice.js.map +1 -1
  15. package/dist/cjs/core/TatchiPasskey/login.js +15 -4
  16. package/dist/cjs/core/TatchiPasskey/login.js.map +1 -1
  17. package/dist/cjs/core/TatchiPasskey/recoverAccount.js +1 -0
  18. package/dist/cjs/core/TatchiPasskey/recoverAccount.js.map +1 -1
  19. package/dist/cjs/core/TatchiPasskey/scanDevice.js +1 -0
  20. package/dist/cjs/core/TatchiPasskey/scanDevice.js.map +1 -1
  21. package/dist/cjs/core/WalletIframe/client/IframeTransport.js +10 -0
  22. package/dist/cjs/core/WalletIframe/client/IframeTransport.js.map +1 -1
  23. package/dist/cjs/core/WalletIframe/client/router.js +9 -0
  24. package/dist/cjs/core/WalletIframe/client/router.js.map +1 -1
  25. package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
  26. package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
  27. package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
  28. package/dist/cjs/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
  29. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +10 -1
  30. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js.map +1 -1
  31. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +1 -0
  32. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
  33. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +1 -0
  34. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
  35. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +1 -0
  36. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
  37. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +1 -0
  38. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
  39. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
  40. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
  41. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +1 -0
  42. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
  43. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +1 -0
  44. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
  45. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +1 -0
  46. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
  47. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -0
  48. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  49. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/index.js +1 -0
  50. package/dist/cjs/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
  51. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
  52. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
  53. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +6 -0
  54. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  55. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
  56. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
  57. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -0
  58. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  59. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +1 -0
  60. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
  61. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +4 -15
  62. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
  63. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +1 -0
  64. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
  65. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +1 -0
  66. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
  67. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +1 -0
  68. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
  69. package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/index.js +17 -0
  70. package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
  71. package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +64 -54
  72. package/dist/cjs/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
  73. package/dist/cjs/core/WebAuthnManager/credentialsHelpers.js +12 -2
  74. package/dist/cjs/core/WebAuthnManager/credentialsHelpers.js.map +1 -1
  75. package/dist/cjs/core/WebAuthnManager/index.js +6 -1
  76. package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
  77. package/dist/cjs/core/WebAuthnManager/touchIdPrompt.js +209 -201
  78. package/dist/cjs/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
  79. package/dist/cjs/core/WebAuthnManager/userHandle.js +2 -1
  80. package/dist/cjs/core/WebAuthnManager/userHandle.js.map +1 -1
  81. package/dist/cjs/core/defaultConfigs.js +1 -1
  82. package/dist/cjs/core/defaultConfigs.js.map +1 -1
  83. package/dist/cjs/core/types/vrf-worker.js +10 -1
  84. package/dist/cjs/core/types/vrf-worker.js.map +1 -1
  85. package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-STvIsylA.css → LinkedDevicesModal-B6api181.css} +1 -1
  86. package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-STvIsylA.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-B6api181.css.map} +1 -1
  87. package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-iARgUwK1.css → ProfileDropdown-B-DrG_u5.css} +1 -1
  88. package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-iARgUwK1.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-B-DrG_u5.css.map} +1 -1
  89. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css → Web3AuthProfileButton-BnZDUeCL.css} +1 -1
  90. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css.map → Web3AuthProfileButton-BnZDUeCL.css.map} +1 -1
  91. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css → TouchIcon-CAGCi8MY.css} +1 -1
  92. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css.map → TouchIcon-CAGCi8MY.css.map} +1 -1
  93. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css → PasskeyAuthMenu-CNNxVj4L.css} +14 -1
  94. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css.map → PasskeyAuthMenu-CNNxVj4L.css.map} +1 -1
  95. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +122 -53
  96. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  97. package/dist/cjs/react/components/{ShowQRCode-DCnR__fx.css → ShowQRCode-nZhZSaba.css} +1 -1
  98. package/dist/cjs/react/components/{ShowQRCode-DCnR__fx.css.map → ShowQRCode-nZhZSaba.css.map} +1 -1
  99. package/dist/cjs/react/deviceDetection.js +75 -92
  100. package/dist/cjs/react/deviceDetection.js.map +1 -1
  101. package/dist/cjs/react/hooks/usePreconnectWalletAssets.js +32 -27
  102. package/dist/cjs/react/hooks/usePreconnectWalletAssets.js.map +1 -1
  103. package/dist/cjs/react/hooks/useQRCamera.js +1 -0
  104. package/dist/cjs/react/hooks/useQRCamera.js.map +1 -1
  105. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +12 -5
  106. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  107. package/dist/cjs/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js +35 -36
  108. package/dist/cjs/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
  109. package/dist/cjs/react/sdk/src/core/NearClient.js +2 -1
  110. package/dist/cjs/react/sdk/src/core/NearClient.js.map +1 -1
  111. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -27
  112. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  113. package/dist/cjs/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +1 -0
  114. package/dist/cjs/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
  115. package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js +25 -0
  116. package/dist/cjs/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
  117. package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js +2 -0
  118. package/dist/cjs/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
  119. package/dist/cjs/react/sdk/src/core/TatchiPasskey/login.js +15 -4
  120. package/dist/cjs/react/sdk/src/core/TatchiPasskey/login.js.map +1 -1
  121. package/dist/cjs/react/sdk/src/core/TatchiPasskey/recoverAccount.js +1 -0
  122. package/dist/cjs/react/sdk/src/core/TatchiPasskey/recoverAccount.js.map +1 -1
  123. package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js +1 -0
  124. package/dist/cjs/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
  125. package/dist/cjs/react/sdk/src/core/WalletIframe/client/IframeTransport.js +10 -0
  126. package/dist/cjs/react/sdk/src/core/WalletIframe/client/IframeTransport.js.map +1 -1
  127. package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js +9 -0
  128. package/dist/cjs/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
  129. package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
  130. package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
  131. package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
  132. package/dist/cjs/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
  133. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +10 -1
  134. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js.map +1 -1
  135. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +1 -0
  136. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
  137. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +1 -0
  138. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
  139. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +1 -0
  140. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
  141. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +1 -0
  142. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
  143. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
  144. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
  145. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +1 -0
  146. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
  147. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +1 -0
  148. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
  149. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +1 -0
  150. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
  151. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +2 -0
  152. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  153. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js +1 -0
  154. package/dist/cjs/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
  155. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
  156. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
  157. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +6 -0
  158. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  159. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
  160. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
  161. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -0
  162. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  163. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +1 -0
  164. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
  165. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +4 -15
  166. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
  167. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +1 -0
  168. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
  169. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +1 -0
  170. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
  171. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +1 -0
  172. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
  173. package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js +17 -0
  174. package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
  175. package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +64 -54
  176. package/dist/cjs/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
  177. package/dist/cjs/react/sdk/src/core/WebAuthnManager/credentialsHelpers.js +12 -2
  178. package/dist/cjs/react/sdk/src/core/WebAuthnManager/credentialsHelpers.js.map +1 -1
  179. package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js +6 -1
  180. package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
  181. package/dist/cjs/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js +209 -201
  182. package/dist/cjs/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
  183. package/dist/cjs/react/sdk/src/core/WebAuthnManager/userHandle.js +2 -1
  184. package/dist/cjs/react/sdk/src/core/WebAuthnManager/userHandle.js.map +1 -1
  185. package/dist/cjs/react/sdk/src/core/defaultConfigs.js +1 -1
  186. package/dist/cjs/react/sdk/src/core/defaultConfigs.js.map +1 -1
  187. package/dist/cjs/react/sdk/src/core/types/vrf-worker.js +10 -1
  188. package/dist/cjs/react/sdk/src/core/types/vrf-worker.js.map +1 -1
  189. package/dist/cjs/react/sdk/src/utils/index.js +13 -3
  190. package/dist/cjs/server/email-recovery/emailEncryptor.js +11 -0
  191. package/dist/cjs/server/email-recovery/emailEncryptor.js.map +1 -1
  192. package/dist/cjs/server/email-recovery/emailParsers.js +57 -0
  193. package/dist/cjs/server/email-recovery/emailParsers.js.map +1 -1
  194. package/dist/cjs/server/email-recovery/index.js +1 -1
  195. package/dist/cjs/server/email-recovery/index.js.map +1 -1
  196. package/dist/cjs/server/email-recovery/rpcCalls.js +14 -1
  197. package/dist/cjs/server/email-recovery/rpcCalls.js.map +1 -1
  198. package/dist/cjs/server/index.js +1 -0
  199. package/dist/cjs/server/router/cloudflare.js.map +1 -1
  200. package/dist/cjs/server/router/express.js.map +1 -1
  201. package/dist/cjs/server/sdk/src/core/defaultConfigs.js +1 -1
  202. package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
  203. package/dist/cjs/utils/index.js +13 -3
  204. package/dist/esm/core/EmailRecovery/index.js +12 -5
  205. package/dist/esm/core/EmailRecovery/index.js.map +1 -1
  206. package/dist/esm/core/IndexedDBManager/passkeyClientDB.js +35 -36
  207. package/dist/esm/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
  208. package/dist/esm/core/NearClient.js +2 -1
  209. package/dist/esm/core/NearClient.js.map +1 -1
  210. package/dist/esm/core/TatchiPasskey/emailRecovery.js +136 -27
  211. package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
  212. package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js +2 -1
  213. package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
  214. package/dist/esm/core/TatchiPasskey/index.js +26 -1
  215. package/dist/esm/core/TatchiPasskey/index.js.map +1 -1
  216. package/dist/esm/core/TatchiPasskey/linkDevice.js +4 -2
  217. package/dist/esm/core/TatchiPasskey/linkDevice.js.map +1 -1
  218. package/dist/esm/core/TatchiPasskey/login.js +13 -7
  219. package/dist/esm/core/TatchiPasskey/login.js.map +1 -1
  220. package/dist/esm/core/TatchiPasskey/recoverAccount.js +2 -1
  221. package/dist/esm/core/TatchiPasskey/recoverAccount.js.map +1 -1
  222. package/dist/esm/core/TatchiPasskey/scanDevice.js +2 -1
  223. package/dist/esm/core/TatchiPasskey/scanDevice.js.map +1 -1
  224. package/dist/esm/core/WalletIframe/client/IframeTransport.js +11 -1
  225. package/dist/esm/core/WalletIframe/client/IframeTransport.js.map +1 -1
  226. package/dist/esm/core/WalletIframe/client/router.js +9 -0
  227. package/dist/esm/core/WalletIframe/client/router.js.map +1 -1
  228. package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
  229. package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
  230. package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
  231. package/dist/esm/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
  232. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +6 -2
  233. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +2 -1
  234. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
  235. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +2 -1
  236. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
  237. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +2 -1
  238. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
  239. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +2 -1
  240. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
  241. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
  242. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
  243. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +2 -1
  244. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
  245. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +2 -1
  246. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
  247. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +2 -1
  248. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
  249. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +4 -2
  250. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  251. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/index.js +2 -1
  252. package/dist/esm/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
  253. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
  254. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
  255. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +8 -2
  256. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  257. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
  258. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
  259. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +2 -1
  260. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  261. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +2 -1
  262. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
  263. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +5 -16
  264. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
  265. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +2 -1
  266. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
  267. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +2 -1
  268. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
  269. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +2 -1
  270. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
  271. package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/index.js +12 -0
  272. package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
  273. package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +61 -55
  274. package/dist/esm/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
  275. package/dist/esm/core/WebAuthnManager/credentialsHelpers.js +8 -3
  276. package/dist/esm/core/WebAuthnManager/index.js +8 -3
  277. package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
  278. package/dist/esm/core/WebAuthnManager/touchIdPrompt.js +207 -204
  279. package/dist/esm/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
  280. package/dist/esm/core/WebAuthnManager/userHandle.js +2 -1
  281. package/dist/esm/core/WebAuthnManager/userHandle.js.map +1 -1
  282. package/dist/esm/core/defaultConfigs.js +1 -1
  283. package/dist/esm/core/defaultConfigs.js.map +1 -1
  284. package/dist/esm/core/types/vrf-worker.js +6 -2
  285. package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-STvIsylA.css → LinkedDevicesModal-B6api181.css} +1 -1
  286. package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-STvIsylA.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-B6api181.css.map} +1 -1
  287. package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-iARgUwK1.css → ProfileDropdown-B-DrG_u5.css} +1 -1
  288. package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-iARgUwK1.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-B-DrG_u5.css.map} +1 -1
  289. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css → Web3AuthProfileButton-BnZDUeCL.css} +1 -1
  290. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-Db3NeoAC.css.map → Web3AuthProfileButton-BnZDUeCL.css.map} +1 -1
  291. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css → TouchIcon-CAGCi8MY.css} +1 -1
  292. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BXM5NR4A.css.map → TouchIcon-CAGCi8MY.css.map} +1 -1
  293. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css → PasskeyAuthMenu-CNNxVj4L.css} +14 -1
  294. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-De1qTSmU.css.map → PasskeyAuthMenu-CNNxVj4L.css.map} +1 -1
  295. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +123 -54
  296. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  297. package/dist/esm/react/components/{ShowQRCode-DCnR__fx.css → ShowQRCode-nZhZSaba.css} +1 -1
  298. package/dist/esm/react/components/{ShowQRCode-DCnR__fx.css.map → ShowQRCode-nZhZSaba.css.map} +1 -1
  299. package/dist/esm/react/deviceDetection.js +72 -93
  300. package/dist/esm/react/deviceDetection.js.map +1 -1
  301. package/dist/esm/react/hooks/usePreconnectWalletAssets.js +32 -27
  302. package/dist/esm/react/hooks/usePreconnectWalletAssets.js.map +1 -1
  303. package/dist/esm/react/hooks/useQRCamera.js +2 -1
  304. package/dist/esm/react/hooks/useQRCamera.js.map +1 -1
  305. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +12 -5
  306. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  307. package/dist/esm/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js +35 -36
  308. package/dist/esm/react/sdk/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
  309. package/dist/esm/react/sdk/src/core/NearClient.js +2 -1
  310. package/dist/esm/react/sdk/src/core/NearClient.js.map +1 -1
  311. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +136 -27
  312. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  313. package/dist/esm/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +2 -1
  314. package/dist/esm/react/sdk/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
  315. package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js +26 -1
  316. package/dist/esm/react/sdk/src/core/TatchiPasskey/index.js.map +1 -1
  317. package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js +4 -2
  318. package/dist/esm/react/sdk/src/core/TatchiPasskey/linkDevice.js.map +1 -1
  319. package/dist/esm/react/sdk/src/core/TatchiPasskey/login.js +13 -7
  320. package/dist/esm/react/sdk/src/core/TatchiPasskey/login.js.map +1 -1
  321. package/dist/esm/react/sdk/src/core/TatchiPasskey/recoverAccount.js +2 -1
  322. package/dist/esm/react/sdk/src/core/TatchiPasskey/recoverAccount.js.map +1 -1
  323. package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js +2 -1
  324. package/dist/esm/react/sdk/src/core/TatchiPasskey/scanDevice.js.map +1 -1
  325. package/dist/esm/react/sdk/src/core/WalletIframe/client/IframeTransport.js +11 -1
  326. package/dist/esm/react/sdk/src/core/WalletIframe/client/IframeTransport.js.map +1 -1
  327. package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js +9 -0
  328. package/dist/esm/react/sdk/src/core/WalletIframe/client/router.js.map +1 -1
  329. package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js +1 -1
  330. package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.js.map +1 -1
  331. package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js +52 -52
  332. package/dist/esm/react/sdk/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.js.map +1 -1
  333. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/getDeviceNumber.js +6 -2
  334. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js +2 -1
  335. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/checkCanRegisterUser.js.map +1 -1
  336. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js +2 -1
  337. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/decryptPrivateKeyWithPrf.js.map +1 -1
  338. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js +2 -1
  339. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/deriveNearKeypairAndEncryptFromSerialized.js.map +1 -1
  340. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js +2 -1
  341. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/exportNearKeypairUi.js.map +1 -1
  342. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js +2 -1
  343. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/registerDevice2WithDerivedKey.js.map +1 -1
  344. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js +2 -1
  345. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signDelegateAction.js.map +1 -1
  346. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js +2 -1
  347. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signNep413Message.js.map +1 -1
  348. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js +2 -1
  349. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/signTransactionsWithActions.js.map +1 -1
  350. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js +4 -2
  351. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/handlers/validation.js.map +1 -1
  352. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js +2 -1
  353. package/dist/esm/react/sdk/src/core/WebAuthnManager/SignerWorkerManager/index.js.map +1 -1
  354. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js +1 -0
  355. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.js.map +1 -1
  356. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +8 -2
  357. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  358. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js +2 -1
  359. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/determineConfirmationConfig.js.map +1 -1
  360. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +2 -1
  361. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  362. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +2 -1
  363. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
  364. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +5 -16
  365. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
  366. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js +2 -1
  367. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/deriveVrfKeypairFromPrf.js.map +1 -1
  368. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js +2 -1
  369. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfChallenge.js.map +1 -1
  370. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js +2 -1
  371. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/handlers/generateVrfKeypairBootstrap.js.map +1 -1
  372. package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js +12 -0
  373. package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/index.js.map +1 -0
  374. package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js +61 -55
  375. package/dist/esm/react/sdk/src/core/WebAuthnManager/WebAuthnFallbacks/safari-fallbacks.js.map +1 -1
  376. package/dist/esm/react/sdk/src/core/WebAuthnManager/credentialsHelpers.js +8 -3
  377. package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js +8 -3
  378. package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
  379. package/dist/esm/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js +207 -204
  380. package/dist/esm/react/sdk/src/core/WebAuthnManager/touchIdPrompt.js.map +1 -1
  381. package/dist/esm/react/sdk/src/core/WebAuthnManager/userHandle.js +2 -1
  382. package/dist/esm/react/sdk/src/core/WebAuthnManager/userHandle.js.map +1 -1
  383. package/dist/esm/react/sdk/src/core/defaultConfigs.js +1 -1
  384. package/dist/esm/react/sdk/src/core/defaultConfigs.js.map +1 -1
  385. package/dist/esm/react/sdk/src/core/types/vrf-worker.js +6 -2
  386. package/dist/esm/react/sdk/src/utils/index.js +10 -4
  387. package/dist/esm/react/styles/styles.css +13 -0
  388. package/dist/esm/sdk/{safari-fallbacks-oQKu9xUs.js → WebAuthnFallbacks-Bl4BTsNt.js} +131 -135
  389. package/dist/esm/sdk/{createAdapters-pNiL2KNq.js → createAdapters-BumKM2ft.js} +59 -54
  390. package/dist/esm/sdk/createAdapters-BumKM2ft.js.map +1 -0
  391. package/dist/esm/sdk/{createAdapters-BWLe9Ddo.js → createAdapters-qVGD6i0g.js} +10 -3
  392. package/dist/esm/sdk/{defaultConfigs-VzvDejmy.js → defaultConfigs-DpslkAQd.js} +1 -1
  393. package/dist/esm/sdk/{getDeviceNumber-CkWRT17I.js → getDeviceNumber-fXizNGQl.js} +2 -2
  394. package/dist/esm/sdk/getDeviceNumber-fXizNGQl.js.map +1 -0
  395. package/dist/esm/sdk/{getDeviceNumber-CfmlgfMX.js → getDeviceNumber-zsOHT_Um.js} +6 -3
  396. package/dist/esm/sdk/{localOnly-DnpSyDaF.js → localOnly-Byi3AK7A.js} +2 -2
  397. package/dist/esm/sdk/{localOnly-DnpSyDaF.js.map → localOnly-Byi3AK7A.js.map} +1 -1
  398. package/dist/esm/sdk/{localOnly-BdumO2st.js → localOnly-pXMTqh1m.js} +5 -4
  399. package/dist/esm/sdk/offline-export-app.js +46 -44
  400. package/dist/esm/sdk/offline-export-app.js.map +1 -1
  401. package/dist/esm/sdk/{overlay-BTqPGG-o.js → overlay-ZGbucXIa.js} +2 -0
  402. package/dist/esm/sdk/{registration-C633u6x8.js → registration-CBiS4Ua_.js} +2 -2
  403. package/dist/esm/sdk/{registration-C633u6x8.js.map → registration-CBiS4Ua_.js.map} +1 -1
  404. package/dist/esm/sdk/{registration-xyYUFRqk.js → registration-DLPLsGCz.js} +5 -4
  405. package/dist/esm/sdk/{requestHelpers-DLBGBHMw.js → requestHelpers-Dh1hEYL9.js} +206 -204
  406. package/dist/esm/sdk/{router-BG6KC_p7.js → router-BLFegW7J.js} +20 -2
  407. package/dist/esm/sdk/{rpcCalls-fLObBbbz.js → rpcCalls-DEv9x5-f.js} +2 -2
  408. package/dist/esm/sdk/{rpcCalls-CAU5XYEF.js → rpcCalls-OhgEeFig.js} +1 -1
  409. package/dist/esm/sdk/{transactions-jH38BZ-Q.js → transactions-BIqKZeR0.js} +6 -18
  410. package/dist/esm/sdk/transactions-BIqKZeR0.js.map +1 -0
  411. package/dist/esm/sdk/{transactions-CzZAt1Yn.js → transactions-Bk-VavcV.js} +10 -21
  412. package/dist/esm/sdk/tx-confirm-ui.js +53 -53
  413. package/dist/esm/sdk/{tx-confirmer-wrapper-CqfVBUaA.js → tx-confirmer-wrapper-lHNgz9i4.js} +53 -53
  414. package/dist/esm/sdk/tx-confirmer.css +6 -4
  415. package/dist/esm/sdk/w3a-tx-confirmer.js +1 -1
  416. package/dist/esm/sdk/wallet-iframe-host.js +271 -89
  417. package/dist/esm/server/email-recovery/emailEncryptor.js +11 -1
  418. package/dist/esm/server/email-recovery/emailEncryptor.js.map +1 -1
  419. package/dist/esm/server/email-recovery/emailParsers.js +55 -1
  420. package/dist/esm/server/email-recovery/emailParsers.js.map +1 -1
  421. package/dist/esm/server/email-recovery/index.js +2 -2
  422. package/dist/esm/server/email-recovery/index.js.map +1 -1
  423. package/dist/esm/server/email-recovery/rpcCalls.js +14 -1
  424. package/dist/esm/server/email-recovery/rpcCalls.js.map +1 -1
  425. package/dist/esm/server/index.js +2 -2
  426. package/dist/esm/server/router/cloudflare.js.map +1 -1
  427. package/dist/esm/server/router/express.js.map +1 -1
  428. package/dist/esm/server/sdk/src/core/defaultConfigs.js +1 -1
  429. package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
  430. package/dist/esm/utils/index.js +10 -4
  431. package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker.js +3 -0
  432. package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
  433. package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
  434. package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts +11 -21
  435. package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts.map +1 -1
  436. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +12 -1
  437. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
  438. package/dist/types/src/core/TatchiPasskey/index.d.ts +8 -0
  439. package/dist/types/src/core/TatchiPasskey/index.d.ts.map +1 -1
  440. package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts +4 -0
  441. package/dist/types/src/core/WalletIframe/TatchiPasskeyIframe.d.ts.map +1 -1
  442. package/dist/types/src/core/WalletIframe/client/IframeTransport.d.ts.map +1 -1
  443. package/dist/types/src/core/WalletIframe/client/router.d.ts +4 -0
  444. package/dist/types/src/core/WalletIframe/client/router.d.ts.map +1 -1
  445. package/dist/types/src/core/WalletIframe/host/wallet-iframe-handlers.d.ts.map +1 -1
  446. package/dist/types/src/core/WalletIframe/shared/messages.d.ts +6 -2
  447. package/dist/types/src/core/WalletIframe/shared/messages.d.ts.map +1 -1
  448. package/dist/types/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-drawer.d.ts.map +1 -1
  449. package/dist/types/src/core/WebAuthnManager/LitComponents/IframeTxConfirmer/viewer-modal.d.ts.map +1 -1
  450. package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/vrf.d.ts.map +1 -1
  451. package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.d.ts.map +1 -1
  452. package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.d.ts.map +1 -1
  453. package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
  454. package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
  455. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
  456. package/dist/types/src/react/hooks/usePreconnectWalletAssets.d.ts.map +1 -1
  457. package/dist/types/src/server/email-recovery/emailEncryptor.d.ts +4 -0
  458. package/dist/types/src/server/email-recovery/emailEncryptor.d.ts.map +1 -1
  459. package/dist/types/src/server/email-recovery/emailParsers.d.ts +7 -0
  460. package/dist/types/src/server/email-recovery/emailParsers.d.ts.map +1 -1
  461. package/dist/types/src/server/email-recovery/index.d.ts +1 -1
  462. package/dist/types/src/server/email-recovery/rpcCalls.d.ts +1 -1
  463. package/dist/types/src/server/email-recovery/rpcCalls.d.ts.map +1 -1
  464. package/dist/types/src/wasm_vrf_worker/pkg/wasm_vrf_worker.d.ts.map +1 -1
  465. package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
  466. package/dist/workers/web3authn-vrf.worker.js +3 -0
  467. package/package.json +1 -1
  468. package/dist/esm/sdk/createAdapters-pNiL2KNq.js.map +0 -1
  469. package/dist/esm/sdk/getDeviceNumber-CkWRT17I.js.map +0 -1
  470. package/dist/esm/sdk/transactions-jH38BZ-Q.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"express.js","names":["out: ShamirApplyServerLockResponse","e: any","out: ShamirRemoveServerLockResponse","normalizedHeaders: Record<string, string>","v","base: Logger","allowedOrigin: string | '*' | undefined","error: any","e: any","result","currentKeyId: string | null","shamirReady: boolean | null","shamirCurrentKeyId: string | null","shamirError: string | undefined","timer: any"],"sources":["../../../../src/server/core/SessionService.ts","../../../../src/core/WalletIframe/validation.ts","../../../../src/server/core/shamirHandlers.ts","../../../../src/server/email-recovery/zkEmail/index.ts","../../../../src/server/email-recovery/emailParsers.ts","../../../../src/server/core/logger.ts","../../../../src/server/router/logger.ts","../../../../src/server/router/express-adaptor.ts"],"sourcesContent":["\nexport interface SessionConfig {\n jwt?: {\n /** Required: JWT signing hook; return a complete token */\n signToken?: (input: { header: Record<string, unknown>; payload: Record<string, unknown> }) => Promise<string> | string;\n /** Required: JWT verification hook */\n verifyToken?: (token: string) => Promise<{ valid: boolean; payload?: any }> | { valid: boolean; payload?: any };\n /** Optional: sliding refresh window (seconds) to allow /session/refresh before exp, default 900 (15 min) */\n refreshWindowSec?: number;\n /** Optional: build additional claims to include in the payload */\n buildClaims?: (input: { sub: string; context?: Record<string, unknown> }) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;\n };\n cookie?: {\n /** Cookie name. Default: 'w3a_session' */\n name?: string;\n /** Optional override: build Set-Cookie header for a new token */\n buildSetHeader?: (token: string) => string;\n /** Optional override: build Set-Cookie header that clears the cookie */\n buildClearHeader?: () => string;\n /** Optional override: extract token from headers (Authorization/Cookie) */\n extractToken?: (headers: Record<string, string | string[] | undefined>, cookieName: string) => string | null;\n };\n}\n\nexport class SessionService<TClaims = any> {\n private cfg: NonNullable<SessionConfig>;\n\n constructor(cfg: NonNullable<SessionConfig>) {\n this.cfg = cfg || ({} as any);\n }\n\n getCookieName(): string {\n return this.cfg?.cookie?.name || 'w3a_session';\n }\n\n buildSetCookie(token: string): string {\n if (this.cfg?.cookie?.buildSetHeader) return this.cfg.cookie.buildSetHeader(token);\n const name = this.getCookieName();\n const cookieParts = [`${name}=${token}`];\n const path = '/';\n const httpOnly = true;\n const secure = true; // default secure\n const sameSite = 'Lax';\n const maxAge = 24 * 3600; // 1 day default\n cookieParts.push(`Path=${path}`);\n if (httpOnly) cookieParts.push('HttpOnly');\n if (secure) cookieParts.push('Secure');\n if (sameSite) cookieParts.push(`SameSite=${sameSite}`);\n if (maxAge) {\n cookieParts.push(`Max-Age=${maxAge}`);\n const expires = new Date(Date.now() + (maxAge * 1000)).toUTCString();\n cookieParts.push(`Expires=${expires}`);\n }\n return cookieParts.join('; ');\n }\n\n buildClearCookie(): string {\n if (this.cfg?.cookie?.buildClearHeader) return this.cfg.cookie.buildClearHeader();\n const name = this.getCookieName();\n const path = '/';\n const secure = true;\n const httpOnly = true;\n const parts = [\n `${name}=`,\n `Path=${path}`,\n 'Max-Age=0',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT'\n ];\n if (httpOnly) parts.push('HttpOnly');\n if (secure) parts.push('Secure');\n const sameSite = 'Lax';\n if (sameSite) parts.push(`SameSite=${sameSite}`);\n return parts.join('; ');\n }\n\n /** Sign a JWT with configured algorithm. Adds iat/exp and copies iss/aud. */\n async signJwt(sub: string, extraClaims?: Record<string, unknown>): Promise<string> {\n const jwt = this.cfg?.jwt || {};\n const built = await Promise.resolve(jwt.buildClaims?.({ sub, context: extraClaims })) || {};\n const payload = { sub, ...(extraClaims || {}), ...(built || {}) } as Record<string, unknown>;\n if (typeof jwt.signToken === 'function') {\n // Full override of signing: user supplies the complete token\n const token = await Promise.resolve(jwt.signToken({ header: { typ: 'JWT' }, payload } as any));\n return token;\n }\n throw new Error('SessionService: No JWT signing hook or provider configured');\n }\n\n /** Verify signature and expiration. Returns payload on success. */\n async verifyJwt(token: string): Promise<{ valid: boolean; payload?: any }> {\n const verify = this.cfg?.jwt?.verifyToken;\n if (typeof verify !== 'function') return { valid: false };\n return await Promise.resolve(verify(token));\n }\n\n parse(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; claims?: TClaims } | { ok: false }>{\n const authHeader = (headers['authorization'] || headers['Authorization']) as string | undefined;\n let token: string | null = null;\n if (authHeader && /^Bearer\\s+/.test(authHeader)) token = authHeader.replace(/^Bearer\\s+/i, '').trim();\n const cookieHeader = (headers['cookie'] || headers['Cookie']) as string | undefined;\n if (!token && cookieHeader) {\n const name = this.getCookieName();\n for (const part of cookieHeader.split(';')) {\n const [k, v] = part.split('=');\n if (k && k.trim() === name) { token = (v || '').trim(); break; }\n }\n }\n if (!token) return Promise.resolve({ ok: false });\n return this.verifyJwt(token).then(v => v.valid ? { ok: true, claims: v.payload as TClaims } : { ok: false });\n }\n\n // === token helpers ===\n extractTokenFromHeaders(headers: Record<string, string | string[] | undefined>): string | null {\n if (this.cfg?.cookie?.extractToken) return this.cfg.cookie.extractToken(headers, this.getCookieName());\n const authHeader = (headers['authorization'] || headers['Authorization']) as string | undefined;\n if (authHeader && /^Bearer\\s+/.test(authHeader)) return authHeader.replace(/^Bearer\\s+/i, '').trim();\n const cookieHeader = (headers['cookie'] || headers['Cookie']) as string | undefined;\n if (cookieHeader) {\n const name = this.getCookieName();\n for (const part of cookieHeader.split(';')) {\n const [k, v] = part.split('=');\n if (k && k.trim() === name) return (v || '').trim();\n }\n }\n return null;\n }\n\n async refresh(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; jwt?: string; code?: string; message?: string }>{\n try {\n const token = this.extractTokenFromHeaders(headers);\n if (!token) return { ok: false, code: 'unauthorized', message: 'No session token' };\n const v = await this.verifyJwt(token);\n if (!v.valid) return { ok: false, code: 'unauthorized', message: 'Invalid token' };\n const payload: any = v.payload || {};\n if (!this.isWithinRefreshWindow(payload)) return { ok: false, code: 'not_eligible', message: 'Not within refresh window' };\n const sub = String(payload.sub || '');\n if (!sub) return { ok: false, code: 'invalid_claims', message: 'Missing sub claim' };\n const next = await this.signJwt(sub);\n return { ok: true, jwt: next };\n } catch (e: any) {\n return { ok: false, code: 'internal', message: e?.message || 'Refresh failed' };\n }\n }\n\n nowSeconds(): number { return Math.floor(Date.now() / 1000); }\n\n private isWithinRefreshWindow(payload: any): boolean {\n try {\n const now = this.nowSeconds();\n const exp = Number(payload?.exp || 0);\n if (!exp || now >= exp) return false; // no refresh if already expired\n const windowSec = Number(this.cfg?.jwt?.refreshWindowSec || 15 * 60);\n return (exp - now) <= windowSec;\n } catch { return false; }\n }\n}\n\n/*\n * Utility: parse comma-separated list of origins into a normalized unique list\n * - canonicalizes to protocol + host + optional port\n * - lowercases host, strips path/query/hash, trims spaces/trailing slashes\n */\nexport function parseCsvList(input?: string): string[] {\n const out = new Set<string>();\n for (const raw of String(input || '').split(',')) {\n const s = raw.trim();\n if (!s) continue;\n try {\n const u = new URL(s);\n const host = u.hostname.toLowerCase();\n const port = u.port ? `:${u.port}` : '';\n const proto = u.protocol === 'http:' || u.protocol === 'https:' ? u.protocol : 'https:';\n out.add(`${proto}//${host}${port}`);\n } catch {\n const stripped = s.replace(/\\/$/, '');\n if (stripped) out.add(stripped);\n }\n }\n return Array.from(out);\n}\n\n/*\n * Utility: merge multiple CSV lists of origins and return normalized list or '*'\n */\nexport function buildCorsOrigins(...inputs: Array<string | undefined>): string[] | '*' {\n const merged = new Set<string>();\n for (const input of inputs) {\n for (const origin of parseCsvList(input)) merged.add(origin);\n }\n const list = Array.from(merged);\n return list.length > 0 ? list : '*';\n}\n","// Shared runtime validation helpers for Wallet Iframe code.\n\nexport function isObject(x: unknown): x is Record<string, unknown> {\n return x !== null && typeof x === 'object';\n}\n\nexport function isString(x: unknown): x is string {\n return typeof x === 'string';\n}\n\nexport function isNonEmptyString(x: unknown): x is string {\n return typeof x === 'string' && x.length > 0;\n}\n\nexport function isNumber(x: unknown): x is number {\n return typeof x === 'number';\n}\n\nexport function isFiniteNumber(x: unknown): x is number {\n return typeof x === 'number' && Number.isFinite(x);\n}\n\nexport function isFunction(x: unknown): x is Function {\n return typeof x === 'function';\n}\n\nexport function isBoolean(x: unknown): x is boolean {\n return typeof x === 'boolean';\n}\n\nexport function isArray<T = unknown>(x: unknown): x is T[] {\n return Array.isArray(x);\n}\n\n// ========= Assertions (throw on mismatch) =========\n\nexport function assertString(val: unknown, name = 'value'): string {\n if (typeof val !== 'string') throw new Error(`Invalid ${name}: expected string`);\n return val;\n}\n\nexport function assertNumber(val: unknown, name = 'value'): number {\n if (typeof val !== 'number' || !Number.isFinite(val)) throw new Error(`Invalid ${name}: expected finite number`);\n return val;\n}\n\nexport function assertBoolean(val: unknown, name = 'value'): boolean {\n if (typeof val !== 'boolean') throw new Error(`Invalid ${name}: expected boolean`);\n return val;\n}\n\nexport function assertObject<T extends Record<string, unknown> = Record<string, unknown>>(val: unknown, name = 'value'): T {\n if (!isObject(val)) throw new Error(`Invalid ${name}: expected object`);\n return val as T;\n}\n\nexport function assertArray<T = unknown>(val: unknown, name = 'value'): T[] {\n if (!Array.isArray(val)) throw new Error(`Invalid ${name}: expected array`);\n return val as T[];\n}\n\n// Shallowly remove function-valued properties (postMessage/clone safety)\nexport function stripFunctionsShallow<T extends Record<string, unknown>>(obj?: T): Partial<T> | undefined {\n if (!obj || !isObject(obj)) return undefined;\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!isFunction(v)) out[k] = v as unknown;\n }\n return out as Partial<T>;\n}\n\n// ===============================\n// SignedTransaction shape helpers\n// ===============================\n\nexport interface PlainSignedTransactionLike {\n transaction: unknown;\n signature: unknown;\n borsh_bytes?: unknown;\n borshBytes?: unknown;\n base64Encode?: unknown;\n}\n\nexport function isPlainSignedTransactionLike(x: unknown): x is PlainSignedTransactionLike {\n if (!isObject(x)) return false;\n const hasTx = 'transaction' in x;\n const hasSig = 'signature' in x;\n const bytes = x as { borsh_bytes?: unknown; borshBytes?: unknown };\n const hasBytes = Array.isArray(bytes.borsh_bytes) || bytes.borshBytes instanceof Uint8Array;\n const hasMethod = typeof (x as { base64Encode?: unknown }).base64Encode === 'function';\n return hasTx && hasSig && hasBytes && !hasMethod;\n}\n\nexport function extractBorshBytesFromPlainSignedTx(x: PlainSignedTransactionLike): number[] {\n const asArray = Array.isArray(x.borsh_bytes) ? (x.borsh_bytes as number[]) : undefined;\n if (asArray) return asArray;\n const asU8 = (x.borshBytes instanceof Uint8Array) ? x.borshBytes : undefined;\n return Array.from(asU8 || new Uint8Array());\n}\n","import type {\n ShamirApplyServerLockRequest,\n ShamirApplyServerLockResponse,\n ShamirRemoveServerLockRequest,\n ShamirRemoveServerLockResponse,\n} from './types';\nimport type { ShamirService } from './ShamirService';\nimport { isString } from '../../core/WalletIframe/validation';\n\nexport async function handleApplyServerLock(\n service: ShamirService,\n request: { body?: { kek_c_b64u?: string } },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const kek_c_b64u = request.body?.kek_c_b64u;\n if (!isString(kek_c_b64u) || !kek_c_b64u) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'kek_c_b64u required and must be a non-empty string' }),\n };\n }\n\n const out: ShamirApplyServerLockResponse = await service.applyServerLock(kek_c_b64u);\n const keyId = service.getCurrentShamirKeyId();\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...out, keyId }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleRemoveServerLock(\n service: ShamirService,\n request: { body?: { kek_cs_b64u?: string; keyId?: string } },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const body = request.body;\n if (!body) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'Missing body' }),\n };\n }\n const { kek_cs_b64u, keyId } = body;\n if (!isString(kek_cs_b64u) || !kek_cs_b64u) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'kek_cs_b64u required and must be a non-empty string' }),\n };\n }\n if (!isString(keyId) || !keyId) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'keyId required and must be a non-empty string' }),\n };\n }\n\n const providedKeyId = String(keyId);\n const currentKeyId = service.getCurrentShamirKeyId();\n let out: ShamirRemoveServerLockResponse;\n\n if (currentKeyId && providedKeyId === currentKeyId) {\n out = await service.removeServerLock(kek_cs_b64u);\n } else if (service.hasGraceKey(providedKeyId)) {\n out = await service.removeGraceServerLockWithKey(providedKeyId, { kek_cs_b64u } as ShamirRemoveServerLockRequest);\n } else {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'unknown keyId' }),\n };\n }\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(out),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleGetShamirKeyInfo(\n service: ShamirService,\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n await service.ensureReady();\n const currentKeyId = service.getCurrentShamirKeyId();\n const graceKeyIds = service.getGraceKeyIds();\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n currentKeyId,\n p_b64u: service.getShamirConfig()?.shamir_p_b64u ?? null,\n graceKeyIds,\n }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleListGraceKeys(\n service: ShamirService,\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n await service.ensureGraceKeysLoaded();\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ graceKeyIds: service.getGraceKeyIds() }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleAddGraceKey(\n service: ShamirService,\n request: { e_s_b64u?: string; d_s_b64u?: string },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const { e_s_b64u, d_s_b64u } = request || ({} as any);\n if (!isString(e_s_b64u) || !e_s_b64u || !isString(d_s_b64u) || !d_s_b64u) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'e_s_b64u and d_s_b64u required' }),\n };\n }\n\n await service.ensureGraceKeysLoaded();\n const added = await service.addGraceKeyInternal({ e_s_b64u, d_s_b64u }, { persist: true, skipIfExists: true });\n if (!added) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'failed to add grace key' }),\n };\n }\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ keyId: added.keyId }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleRemoveGraceKey(\n service: ShamirService,\n request: { keyId?: string },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const keyId = request?.keyId;\n if (!isString(keyId) || !keyId) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'keyId required and must be a non-empty string' }),\n };\n }\n\n const removed = await service.removeGraceKeyInternal(keyId, { persist: true });\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ removed }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n","import { ZkEmailProverClient, type ZkEmailProverClientOptions, type ZkEmailProverError } from './proverClient';\n\nexport { ZkEmailProverClient } from './proverClient';\nexport type { ZkEmailProverClientOptions, ZkEmailProverError, ZkEmailProverResponse } from './proverClient';\n\nexport interface ForwardableEmailPayload {\n from: string;\n to: string;\n headers: Record<string, string>;\n raw?: string;\n rawSize?: number;\n}\n\nexport type NormalizedEmailResult =\n | { ok: true; payload: ForwardableEmailPayload }\n | { ok: false; code: string; message: string };\n\nexport interface GenerateZkEmailProofResult {\n proof: unknown;\n publicInputs: string[];\n}\n\nexport interface ParsedZkEmailBindings {\n accountId: string;\n newPublicKey: string;\n fromEmail: string;\n timestamp: string;\n requestId: string;\n}\n\n/**\n * Build a minimal ForwardableEmailPayload from a raw RFC822 email string.\n * This is primarily used by server-side helpers that receive only a raw\n * email blob (no pre-normalized headers).\n */\nexport function buildForwardablePayloadFromRawEmail(raw: string): ForwardableEmailPayload {\n const safeRaw = typeof raw === 'string' ? raw : '';\n const lines = safeRaw.split(/\\r?\\n/);\n\n const getHeader = (name: string): string | undefined => {\n const line = lines.find(l => new RegExp(`^${name}:`, 'i').test(l));\n if (!line) return undefined;\n const idx = line.indexOf(':');\n const rest = idx >= 0 ? line.slice(idx + 1) : '';\n const value = rest.trim();\n return value || undefined;\n };\n\n const fromHeader = getHeader('from') || 'unknown@zkemail.local';\n const toHeader = getHeader('to') || 'recover@zkemail.local';\n\n const headers: Record<string, string> = {};\n const subjectHeader = getHeader('subject');\n const dateHeader = getHeader('date');\n\n if (fromHeader) headers.from = fromHeader;\n if (toHeader) headers.to = toHeader;\n if (subjectHeader) headers.subject = subjectHeader;\n if (dateHeader) headers.date = dateHeader;\n\n return {\n from: fromHeader,\n to: toHeader,\n headers,\n raw: safeRaw,\n rawSize: safeRaw.length,\n };\n}\n\nexport function normalizeForwardableEmailPayload(input: unknown): NormalizedEmailResult {\n if (!input || typeof input !== 'object') {\n return { ok: false, code: 'invalid_email', message: 'JSON body required' };\n }\n\n const body = input as Partial<ForwardableEmailPayload>;\n const { from, to, headers, raw, rawSize } = body;\n\n if (!from || typeof from !== 'string' || !to || typeof to !== 'string') {\n return { ok: false, code: 'invalid_email', message: 'from and to are required' };\n }\n\n if (!headers || typeof headers !== 'object') {\n return { ok: false, code: 'invalid_email', message: 'headers object is required' };\n }\n\n const normalizedHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers as Record<string, unknown>)) {\n normalizedHeaders[String(k).toLowerCase()] = String(v);\n }\n\n return {\n ok: true,\n payload: {\n from,\n to,\n headers: normalizedHeaders,\n raw: typeof raw === 'string' ? raw : undefined,\n rawSize: typeof rawSize === 'number' ? rawSize : undefined,\n },\n };\n}\n\n/**\n * Parse NEAR accountId from the Subject line inside a raw RFC822 email.\n *\n * Expected format (case-insensitive on \"Subject\" and \"recover\"):\n * Subject: recover-123ABC bob.testnet ed25519:<pk>\n *\n * Returns the parsed accountId (e.g. \"bob.testnet\") or null if not found.\n */\nexport function parseAccountIdFromSubject(raw: string | undefined | null): string | null {\n if (!raw || typeof raw !== 'string') return null;\n\n // Accept either a full RFC822 message (with \"Subject: ...\" header)\n // or a bare Subject value (\"recover-123ABC bob.testnet ed25519:<pk>\").\n let subjectText = '';\n const lines = raw.split(/\\r?\\n/);\n const subjectLine = lines.find(line => /^subject:/i.test(line));\n if (subjectLine) {\n const idx = subjectLine.indexOf(':');\n const restRaw = idx >= 0 ? subjectLine.slice(idx + 1) : '';\n subjectText = restRaw.trim();\n } else {\n subjectText = raw.trim();\n }\n\n if (!subjectText) return null;\n\n // Strip common reply/forward prefixes\n subjectText = subjectText.replace(/^(re|fwd):\\s*/i, '').trim();\n if (!subjectText) return null;\n\n // Strict format: \"recover-<request_id> <accountId> [ed25519:<pk>]\"\n const match = subjectText.match(\n /^recover-([A-Za-z0-9]{6})\\s+([^\\s]+)(?:\\s+ed25519:[^\\s]+)?\\s*$/i\n );\n if (match?.[2]) {\n return match[2];\n }\n\n return null;\n}\n\nfunction parseSubjectBindings(\n rawSubject: string | undefined | null\n): { accountId: string; newPublicKey: string; requestId: string } | null {\n if (!rawSubject || typeof rawSubject !== 'string') return null;\n\n const lines = rawSubject.split(/\\r?\\n/);\n let subjectText = '';\n const subjectLine = lines.find(line => /^subject:/i.test(line));\n if (subjectLine) {\n const idx = subjectLine.indexOf(':');\n const restRaw = idx >= 0 ? subjectLine.slice(idx + 1) : '';\n subjectText = restRaw.trim();\n } else {\n subjectText = rawSubject.trim();\n }\n if (!subjectText) return null;\n\n subjectText = subjectText.replace(/^(re|fwd):\\s*/i, '').trim();\n if (!subjectText) return null;\n\n // Strict format:\n // \"recover-<request_id> <accountId> ed25519:<pk>\"\n const match = subjectText.match(\n /^recover-([A-Za-z0-9]{6})\\s+([^\\s]+)\\s+ed25519:([^\\s]+)\\s*$/i\n );\n if (!match) return null;\n\n const [, requestId, accountId, newPublicKey] = match;\n\n return {\n accountId,\n newPublicKey,\n requestId,\n };\n}\n\nexport function extractZkEmailBindingsFromPayload(\n payload: ForwardableEmailPayload\n): ParsedZkEmailBindings | null {\n const raw = payload.raw || '';\n const lines = raw.split(/\\r?\\n/);\n\n const subjectLine = lines.find(line => /^subject:/i.test(line));\n const subjectBindings = parseSubjectBindings(subjectLine ?? '');\n if (!subjectBindings) {\n return null;\n }\n\n const headers = payload.headers || {};\n let fromEmailRaw: string | undefined =\n (headers['from'] as any) ||\n (headers['x-from-email'] as any);\n let dateRaw: string | undefined =\n (headers['date'] as any) ||\n (headers['x-original-date'] as any);\n\n // Fallback: if headers object does not contain from/date,\n // attempt to parse them from the raw RFC822 email lines.\n if (!fromEmailRaw || !dateRaw) {\n for (const line of lines) {\n if (!fromEmailRaw && /^from:/i.test(line)) {\n const idx = line.indexOf(':');\n fromEmailRaw = idx >= 0 ? line.slice(idx + 1).trim() : '';\n }\n if (!dateRaw && /^date:/i.test(line)) {\n const idx = line.indexOf(':');\n dateRaw = idx >= 0 ? line.slice(idx + 1).trim() : '';\n }\n if (fromEmailRaw && dateRaw) break;\n }\n }\n\n const fromEmail = String(fromEmailRaw || '').trim();\n const timestamp = String(dateRaw || '').trim();\n\n if (!fromEmail || !timestamp) {\n return null;\n }\n\n return {\n accountId: subjectBindings.accountId,\n newPublicKey: subjectBindings.newPublicKey,\n fromEmail,\n timestamp,\n requestId: subjectBindings.requestId,\n };\n}\n\nexport async function generateZkEmailProofFromPayload(\n payload: ForwardableEmailPayload,\n prover: ZkEmailProverClientOptions | ZkEmailProverClient\n): Promise<GenerateZkEmailProofResult> {\n if (!payload.raw || typeof payload.raw !== 'string') {\n const err: ZkEmailProverError = Object.assign(\n new Error('raw email contents are required to generate a zk-email proof'),\n { code: 'missing_raw_email' }\n );\n throw err;\n }\n\n const client =\n (prover && typeof (prover as any).proveEmail === 'function')\n ? (prover as ZkEmailProverClient)\n : new ZkEmailProverClient(prover as ZkEmailProverClientOptions);\n\n const res = await client.proveEmail(payload.raw);\n\n return {\n proof: res.proof,\n publicInputs: res.publicSignals,\n };\n}\n","import type { EmailRecoveryMode } from './types';\nimport { normalizeForwardableEmailPayload, parseAccountIdFromSubject } from './zkEmail';\n\nexport enum EmailRecoveryModeHint {\n ZkEmail = 'zk-email',\n TeeEncrypted = 'tee-encrypted',\n OnchainPublic = 'onchain-public',\n}\n\nexport function normalizeRecoveryMode(raw: string | undefined | null): EmailRecoveryMode | null {\n if (!raw) return null;\n const value = raw.trim().toLowerCase();\n if (value === EmailRecoveryModeHint.ZkEmail) return 'zk-email';\n if (value === EmailRecoveryModeHint.TeeEncrypted) return 'tee-encrypted';\n if (value === EmailRecoveryModeHint.OnchainPublic) return 'onchain-public';\n return null;\n}\n\nexport function extractRecoveryModeFromBody(emailBlob?: string): EmailRecoveryMode | null {\n if (!emailBlob) return null;\n\n const lines = emailBlob.split(/\\r?\\n/);\n const bodyStartIndex = lines.findIndex(line => line.trim() === '');\n if (bodyStartIndex === -1) return null;\n\n const bodyLines = lines.slice(bodyStartIndex + 1);\n const firstNonEmptyBodyLine = bodyLines.find(line => line.trim() !== '');\n if (!firstNonEmptyBodyLine) return null;\n\n const candidate = firstNonEmptyBodyLine.trim();\n const normalized = normalizeRecoveryMode(candidate);\n if (normalized) return normalized;\n\n const lower = candidate.toLowerCase();\n if (lower.includes(EmailRecoveryModeHint.ZkEmail)) return 'zk-email';\n if (lower.includes(EmailRecoveryModeHint.TeeEncrypted)) return 'tee-encrypted';\n if (lower.includes(EmailRecoveryModeHint.OnchainPublic)) return 'onchain-public';\n\n return null;\n}\n\ntype HeaderValue = string | string[] | undefined;\ntype HeadersLike = Headers | Record<string, HeaderValue> | undefined;\n\nexport type RecoverEmailParseResult =\n | { ok: true; accountId: string; emailBlob: string; explicitMode?: string }\n | { ok: false; status: number; code: string; message: string };\n\nfunction getHeader(headers: HeadersLike, name: string): string | undefined {\n if (!headers) return undefined;\n\n const maybeHeaders = headers as any;\n if (typeof maybeHeaders.get === 'function') {\n const v = maybeHeaders.get(name);\n return (typeof v === 'string') ? v : undefined;\n }\n\n const record = headers as Record<string, HeaderValue>;\n const v = record[name.toLowerCase()] ?? record[name];\n if (Array.isArray(v)) return (typeof v[0] === 'string') ? v[0] : undefined;\n return (typeof v === 'string') ? v : undefined;\n}\n\nfunction parseExplicitMode(body: unknown, headers?: HeadersLike): string | undefined {\n const modeFromBody =\n (typeof (body as any)?.explicitMode === 'string' ? String((body as any).explicitMode) : '') ||\n (typeof (body as any)?.explicit_mode === 'string' ? String((body as any).explicit_mode) : '');\n const modeFromHeader = getHeader(headers, 'x-email-recovery-mode') || getHeader(headers, 'x-recovery-mode') || '';\n const raw = (modeFromBody || modeFromHeader).trim();\n return raw ? raw : undefined;\n}\n\nexport function parseRecoverEmailRequest(body: unknown, opts: { headers?: HeadersLike } = {}): RecoverEmailParseResult {\n const explicitMode = parseExplicitMode(body, opts.headers);\n\n const normalized = normalizeForwardableEmailPayload(body);\n if (!normalized.ok) {\n return { ok: false, status: 400, code: normalized.code, message: normalized.message };\n }\n\n const payload = normalized.payload;\n const emailBlob = payload.raw || '';\n const emailHeaders = payload.headers || {};\n\n const subjectHeader = emailHeaders['subject'];\n const parsedAccountId = parseAccountIdFromSubject(subjectHeader || emailBlob);\n const headerAccountId = String(emailHeaders['x-near-account-id'] || emailHeaders['x-account-id'] || '').trim();\n const accountId = (parsedAccountId || headerAccountId || '').trim();\n\n if (!accountId) {\n return { ok: false, status: 400, code: 'missing_account', message: 'x-near-account-id header is required' };\n }\n if (!emailBlob) {\n return { ok: false, status: 400, code: 'missing_email', message: 'raw email blob is required' };\n }\n\n return { ok: true, accountId, emailBlob, explicitMode };\n}\n","export type Logger = {\n debug?: (...args: unknown[]) => void;\n info?: (...args: unknown[]) => void;\n warn?: (...args: unknown[]) => void;\n error?: (...args: unknown[]) => void;\n log?: (...args: unknown[]) => void;\n};\n\nexport type NormalizedLogger = {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n};\n\nfunction safe(fn?: (...args: unknown[]) => void): (...args: unknown[]) => void {\n if (!fn) return () => {};\n return (...args: unknown[]) => {\n try {\n fn(...args);\n } catch {\n // Never allow logging to break request handling.\n }\n };\n}\n\n/**\n * Library code should never call `console.*` directly; the host decides where logs go.\n * - Default: no logs\n * - To enable: pass `logger: console` (or a structured logger) to the host config.\n */\nexport function normalizeLogger(logger?: Logger | null): NormalizedLogger {\n if (!logger) {\n return { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} };\n }\n\n const base: Logger = logger;\n const log = typeof base.log === 'function' ? base.log.bind(base) : undefined;\n\n const debug = (typeof base.debug === 'function' ? base.debug.bind(base) : log);\n const info = (typeof base.info === 'function' ? base.info.bind(base) : log);\n const warn = (typeof base.warn === 'function' ? base.warn.bind(base) : log);\n const error = (typeof base.error === 'function' ? base.error.bind(base) : log);\n\n return {\n debug: safe(debug),\n info: safe(info),\n warn: safe(warn),\n error: safe(error),\n };\n}\n\n","import type { Logger, NormalizedLogger } from '../core/logger';\nimport { normalizeLogger } from '../core/logger';\n\nexport type RouterLogger = Logger;\nexport type NormalizedRouterLogger = NormalizedLogger;\nexport const normalizeRouterLogger = normalizeLogger;\n","import type { Request, Response, Router as ExpressRouter } from 'express';\nimport express from 'express';\nimport type { AuthService } from '../core/AuthService';\nimport { buildCorsOrigins } from '../core/SessionService';\nimport {\n handleApplyServerLock,\n handleRemoveServerLock,\n handleGetShamirKeyInfo,\n handleListGraceKeys,\n handleAddGraceKey,\n handleRemoveGraceKey,\n} from '../core/shamirHandlers';\nimport { parseRecoverEmailRequest } from '../email-recovery/emailParsers';\nimport type { DelegateActionPolicy } from '../delegateAction';\nimport type { RouterLogger } from './logger';\nimport { normalizeRouterLogger } from './logger';\n\nexport interface RelayRouterOptions {\n healthz?: boolean;\n readyz?: boolean;\n // Optional list(s) of CORS origins (CSV strings or literal origins).\n // Pass raw strings; the router normalizes/merges internally.\n corsOrigins?: Array<string | undefined>;\n /**\n * Optional route for submitting NEP-461 SignedDelegate meta-transactions.\n *\n * - When omitted: disabled.\n * - When set: enabled at `route`.\n *\n * `policy` is server-controlled and is never read from the request body.\n */\n signedDelegate?: {\n route: string;\n policy?: DelegateActionPolicy;\n };\n sessionRoutes?: { auth?: string; logout?: string };\n session?: SessionAdapter | null;\n // Optional logger; defaults to silent.\n logger?: RouterLogger | null;\n}\n\nfunction normalizePath(path: string): string {\n const trimmed = String(path || '').trim();\n if (!trimmed) return '';\n return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;\n}\n\nfunction withCors(res: Response, opts?: RelayRouterOptions, req?: Request): void {\n if (!opts?.corsOrigins) return;\n\n let allowedOrigin: string | '*' | undefined;\n const normalized = buildCorsOrigins(...(opts.corsOrigins || []));\n if (normalized === '*') {\n allowedOrigin = '*';\n res.set('Access-Control-Allow-Origin', '*');\n } else if (Array.isArray(normalized)) {\n const origin = String((req as any)?.headers?.origin || '').trim();\n if (origin && normalized.includes(origin)) {\n allowedOrigin = origin;\n res.set('Access-Control-Allow-Origin', origin);\n res.set('Vary', 'Origin');\n }\n }\n\n res.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');\n res.set('Access-Control-Allow-Headers', 'Content-Type,Authorization');\n // Only advertise credentials when we echo back a specific origin (not '*')\n if (allowedOrigin && allowedOrigin !== '*') {\n res.set('Access-Control-Allow-Credentials', 'true');\n }\n}\n\n// Minimal session adapter interface expected by the routers\nexport interface SessionAdapter {\n signJwt(sub: string, extra?: Record<string, unknown>): Promise<string>;\n parse(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; claims?: any } | { ok: false }>;\n buildSetCookie(token: string): string;\n buildClearCookie(): string;\n refresh(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; jwt?: string; code?: string; message?: string }>;\n}\n\nexport function createRelayRouter(service: AuthService, opts: RelayRouterOptions = {}): ExpressRouter {\n const router = express.Router();\n const mePath = opts.sessionRoutes?.auth || '/session/auth';\n const logoutPath = opts.sessionRoutes?.logout || '/session/logout';\n const logger = normalizeRouterLogger(opts.logger);\n const signedDelegatePath = (() => {\n if (!opts.signedDelegate) return '';\n const raw = String(opts.signedDelegate.route || '').trim();\n if (!raw) throw new Error('RelayRouterOptions.signedDelegate.route is required');\n return normalizePath(raw);\n })();\n const signedDelegatePolicy = opts.signedDelegate?.policy;\n\n // Optional CORS: implemented here to keep setup simple for example relayers.\n // If you prefer custom CORS middleware, omit `corsOrigins` and wire your own.\n router.use((req: Request, res: Response, next: any) => {\n withCors(res, opts, req);\n const method = String((req as any)?.method || '').toUpperCase();\n if (opts.corsOrigins && method === 'OPTIONS') {\n res.status(204).send('');\n return;\n }\n next();\n });\n\n router.post(\n '/create_account_and_register_user',\n async (req: any, res: any) => {\n try {\n const {\n new_account_id,\n new_public_key,\n vrf_data,\n webauthn_registration,\n deterministic_vrf_public_key,\n authenticator_options\n } = req.body || ({} as any);\n\n if (!new_account_id || typeof new_account_id !== 'string') throw new Error('Missing or invalid new_account_id');\n if (!new_public_key || typeof new_public_key !== 'string') throw new Error('Missing or invalid new_public_key');\n if (!vrf_data || typeof vrf_data !== 'object') throw new Error('Missing or invalid vrf_data');\n if (!webauthn_registration || typeof webauthn_registration !== 'object') throw new Error('Missing or invalid webauthn_registration');\n\n const result = await service.createAccountAndRegisterUser({\n new_account_id,\n new_public_key,\n vrf_data,\n webauthn_registration,\n deterministic_vrf_public_key,\n authenticator_options\n });\n\n if (result.success) res.status(200).json(result);\n else res.status(400).json(result);\n } catch (error: any) {\n res.status(500).json({ success: false, error: error?.message || 'internal error' });\n }\n }\n );\n\n if (signedDelegatePath) {\n router.options(signedDelegatePath, (_req: any, res: any) => {\n res.sendStatus(204);\n });\n\n router.post(signedDelegatePath, async (req: any, res: any) => {\n try {\n const { hash, signedDelegate } = req.body || {};\n if (typeof hash !== 'string' || !hash || !signedDelegate) {\n res.status(400).json({ ok: false, code: 'invalid_body', message: 'Expected { hash, signedDelegate }' });\n return;\n }\n\n const result = await service.executeSignedDelegate({\n hash,\n signedDelegate,\n policy: signedDelegatePolicy,\n });\n\n if (!result || !result.ok) {\n res.status(400).json({\n ok: false,\n code: result?.code || 'delegate_execution_failed',\n message: result?.error || 'Failed to execute delegate action',\n });\n return;\n }\n\n res.status(200).json({\n ok: true,\n relayerTxHash: result.transactionHash || null,\n status: 'submitted',\n outcome: result.outcome ?? null,\n });\n } catch (e: any) {\n res.status(500).json({\n ok: false,\n code: 'internal',\n message: e?.message || 'Internal error while executing delegate action',\n });\n }\n });\n }\n\n router.post('/vrf/apply-server-lock', async (req: any, res: any) => {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n return res.status(503).json({ error: 'shamir_disabled', message: 'Shamir 3-pass is not configured on this server' });\n }\n try {\n const serverResponse = await handleApplyServerLock(shamir, { body: req.body });\n Object.entries(serverResponse.headers).forEach(([k, v]) => res.set(k, v as any));\n res.status(serverResponse.status);\n res.send(JSON.parse(serverResponse.body));\n } catch (e: any) {\n res.status(500).json({ error: 'internal', details: e?.message });\n }\n });\n\n router.post('/vrf/remove-server-lock', async (req: any, res: any) => {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n return res.status(503).json({ error: 'shamir_disabled', message: 'Shamir 3-pass is not configured on this server' });\n }\n try {\n const serverResponse = await handleRemoveServerLock(shamir, { body: req.body });\n Object.entries(serverResponse.headers).forEach(([k, v]) => res.set(k, v as any));\n res.status(serverResponse.status);\n res.send(JSON.parse(serverResponse.body));\n } catch (e: any) {\n res.status(500).json({ error: 'internal', details: e?.message });\n }\n });\n\n // VRF + WebAuthn session verification (VIEW call) + optional session issuance\n router.post('/verify-authentication-response', async (req: any, res: any) => {\n try {\n if (!req?.body) {\n res.status(400).json({ code: 'invalid_body', message: 'Request body is required' });\n return;\n }\n const body = req.body;\n const valid = body && body.vrf_data && body.webauthn_authentication;\n if (!valid) {\n res.status(400).json({ code: 'invalid_body', message: 'vrf_data and webauthn_authentication are required' });\n return;\n }\n const result = await service.verifyAuthenticationResponse(body);\n const status = result.success ? 200 : 400;\n if (status !== 200) {\n res.status(status).json({ code: 'not_verified', message: result.message || 'Authentication verification failed' });\n return;\n }\n const sessionKind = ((body?.sessionKind || body?.session_kind) === 'cookie') ? 'cookie' : 'jwt';\n const session = opts.session;\n if (session && result.verified) {\n try {\n const sub = String(body.vrf_data.user_id || '');\n const token = await session.signJwt(sub, { rpId: body.vrf_data.rp_id, blockHeight: body.vrf_data.block_height });\n // Best-effort server log without sensitive data\n logger.info(`[relay] creating ${sessionKind === 'cookie' ? 'HttpOnly session' : 'JWT'} for`, sub);\n if (sessionKind === 'cookie') {\n res.set('Set-Cookie', session.buildSetCookie(token));\n const { jwt: _omit, ...rest } = result as any;\n res.status(200).json(rest);\n return;\n }\n res.status(200).json({ ...result, jwt: token });\n return;\n } catch (e: any) {\n // If session issuance fails, still return verification result\n }\n }\n res.status(200).json(result);\n } catch (e: any) {\n res.status(500).json({ code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n // Session: read current claims via bearer token or cookie\n router.get(mePath, async (req: any, res: any) => {\n try {\n const session = opts.session;\n if (!session) {\n res.status(501).json({ authenticated: false, code: 'sessions_disabled', message: 'Sessions are not configured' });\n return;\n }\n const parsed = await session.parse(req.headers || {});\n if (!parsed.ok) {\n res.status(401).json({ authenticated: false, code: 'unauthorized', message: 'No valid session' });\n return;\n }\n res.status(200).json({ authenticated: true, claims: (parsed as any).claims });\n } catch (e: any) {\n res.status(500).json({ authenticated: false, code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n // Session: logout clears cookie (best-effort)\n router.post(logoutPath, async (_req: any, res: any) => {\n try {\n const session = opts.session;\n if (session) res.set('Set-Cookie', session.buildClearCookie());\n res.status(200).json({ success: true });\n } catch (e: any) {\n res.status(500).json({ success: false, error: 'internal', details: e?.message });\n }\n });\n\n // Session: refresh (sliding expiration)\n router.post('/session/refresh', async (req: any, res: any) => {\n try {\n const sessionKind = ((req.body || {}).sessionKind === 'cookie') ? 'cookie' : ((req.body || {}).session_kind === 'cookie' ? 'cookie' : 'jwt');\n const session = opts.session;\n if (!session) {\n res.status(501).json({ code: 'sessions_disabled', message: 'Sessions are not configured' });\n return;\n }\n const out = await session.refresh(req.headers || {});\n if (!out.ok || !out.jwt) {\n const code = out.code || 'not_eligible';\n const message = out.message || 'Refresh not eligible';\n res.status(code === 'unauthorized' ? 401 : 400).json({ code, message });\n return;\n }\n if (sessionKind === 'cookie') {\n res.set('Set-Cookie', session.buildSetCookie(out.jwt));\n res.status(200).json({ ok: true });\n } else {\n res.status(200).json({ ok: true, jwt: out.jwt });\n }\n } catch (e: any) {\n res.status(500).json({ code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n // Email recovery hook (DKIM/TEE flow):\n // Accept a ForwardableEmailPayload from the email worker and call the\n // per-user email-recoverer contract deployed on `accountId`.\n router.post('/recover-email', async (req: any, res: any) => {\n try {\n const prefer = String(req?.headers?.prefer || '').toLowerCase();\n const respondAsync =\n prefer.includes('respond-async') ||\n String((req?.query as any)?.async || '').trim() === '1' ||\n String((req?.query as any)?.respond_async || '').trim() === '1';\n\n const parsed = parseRecoverEmailRequest(req.body as unknown, { headers: req.headers as any });\n if (!parsed.ok) {\n res.status(parsed.status).json({ code: parsed.code, message: parsed.message });\n return;\n }\n const { accountId, emailBlob, explicitMode } = parsed;\n\n if (!service.emailRecovery) {\n res.status(503).json({ code: 'email_recovery_unavailable', message: 'EmailRecoveryService is not configured on this server' });\n return;\n }\n\n if (respondAsync) {\n void service.emailRecovery\n .requestEmailRecovery({ accountId, emailBlob, explicitMode })\n .then((result) => {\n logger.info('[recover-email] async complete', {\n success: result?.success === true,\n accountId,\n error: result?.success ? undefined : result?.error,\n });\n })\n .catch((err: any) => {\n logger.error('[recover-email] async error', {\n accountId,\n error: err?.message || String(err),\n });\n });\n\n res.status(202).json({ success: true, queued: true, accountId });\n return;\n }\n\n const result = await service.emailRecovery.requestEmailRecovery({ accountId, emailBlob, explicitMode });\n res.status(result.success ? 202 : 400).json(result);\n } catch (e: any) {\n res.status(500).json({ code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n router.get('/shamir/key-info', async (_req: any, res: any) => {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n return res.status(503).json({ error: 'shamir_disabled', message: 'Shamir 3-pass is not configured on this server' });\n }\n try {\n const serverResponse = await handleGetShamirKeyInfo(shamir);\n Object.entries(serverResponse.headers).forEach(([k, v]) => res.set(k, v as any));\n res.status(serverResponse.status);\n res.send(JSON.parse(serverResponse.body));\n } catch (e: any) {\n res.status(500).json({ error: 'internal', details: e?.message });\n }\n });\n\n if (opts.healthz) {\n router.get('/healthz', async (_req: Request, res: Response) => {\n const shamir = service.shamirService;\n const shamirConfigured = Boolean(shamir && shamir.hasShamir());\n let currentKeyId: string | null = null;\n if (shamirConfigured && shamir) {\n try {\n const payload = JSON.parse((await handleGetShamirKeyInfo(shamir)).body) as { currentKeyId?: string };\n currentKeyId = payload.currentKeyId || null;\n } catch {}\n }\n\n const proverBaseUrl = service.emailRecovery?.getZkEmailProverBaseUrl?.() ?? null;\n const zkEmailConfigured = Boolean(proverBaseUrl);\n\n res.status(200).json({\n ok: true,\n // Backwards-compatible field (was previously top-level).\n currentKeyId,\n shamir: { configured: shamirConfigured, currentKeyId },\n zkEmail: { configured: zkEmailConfigured, proverBaseUrl },\n });\n });\n }\n\n if (opts.readyz) {\n router.get('/readyz', async (_req: Request, res: Response) => {\n const shamir = service.shamirService;\n const shamirConfigured = Boolean(shamir && shamir.hasShamir());\n\n let shamirReady: boolean | null = null;\n let shamirCurrentKeyId: string | null = null;\n let shamirError: string | undefined;\n if (shamirConfigured && shamir) {\n try {\n await shamir.ensureReady();\n shamirReady = true;\n const payload = JSON.parse((await handleGetShamirKeyInfo(shamir)).body) as { currentKeyId?: string };\n shamirCurrentKeyId = payload.currentKeyId || null;\n } catch (e: any) {\n shamirReady = false;\n shamirError = e?.message || String(e);\n }\n }\n\n const zk = service.emailRecovery\n ? await service.emailRecovery.checkZkEmailProverHealth()\n : { configured: false, baseUrl: null, healthy: null as boolean | null };\n\n const ok =\n (shamirConfigured ? shamirReady === true : true) &&\n (zk.configured ? zk.healthy === true : true);\n\n res.status(ok ? 200 : 503).json({\n ok,\n shamir: {\n configured: shamirConfigured,\n ready: shamirConfigured ? shamirReady : null,\n currentKeyId: shamirCurrentKeyId,\n error: shamirError,\n },\n zkEmail: zk,\n });\n });\n }\n\n // ROR manifest for Related Origin Requests (wallet-scoped credentials)\n const wellKnownPaths = ['/.well-known/webauthn', '/.well-known/webauthn/'];\n for (const p of wellKnownPaths) {\n router.get(p, async (_req: Request, res: Response) => {\n try {\n const origins = await service.getRorOrigins();\n res.set('Content-Type', 'application/json; charset=utf-8');\n // Short TTL + SWR so updates propagate while staying cache-friendly\n res.set('Cache-Control', 'max-age=60, stale-while-revalidate=600');\n res.status(200).send(JSON.stringify({ origins }));\n } catch (e: any) {\n res.status(200).json({ origins: [] });\n }\n });\n }\n\n return router;\n}\n\nexport interface KeyRotationCronOptions {\n enabled?: boolean;\n intervalMinutes?: number;\n maxGraceKeys?: number;\n logger?: RouterLogger | null;\n}\n\nexport function startKeyRotationCronjob(\n service: AuthService,\n opts: KeyRotationCronOptions = {},\n): { stop(): void } {\n const logger = normalizeRouterLogger(opts.logger);\n const enabled = Boolean(opts.enabled);\n const intervalMinutes = Math.max(1, Number(opts.intervalMinutes || 0) || 60);\n const maxGraceKeys = Math.max(0, Number(opts.maxGraceKeys ?? 0) || 0);\n\n let timer: any = null;\n let inFlight = false;\n\n const run = async () => {\n if (!enabled) return;\n if (inFlight) {\n logger.warn('[key-rotation-cron] previous rotation still running; skipping');\n return;\n }\n inFlight = true;\n try {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n logger.warn('[key-rotation-cron] Shamir not configured; skipping rotation');\n return;\n }\n\n const rotation = await shamir.rotateShamirServerKeypair();\n logger.info('[key-rotation-cron] rotated key', {\n newKeyId: rotation.newKeyId,\n previousKeyId: rotation.previousKeyId,\n graceKeyIds: rotation.graceKeyIds,\n });\n\n if (maxGraceKeys > 0) {\n const graceKeyIds = shamir.getGraceKeyIds();\n if (graceKeyIds.length > maxGraceKeys) {\n const toRemove = graceKeyIds.slice(0, graceKeyIds.length - maxGraceKeys);\n for (const keyId of toRemove) {\n try {\n const removed = await shamir.removeGraceKeyInternal(keyId, { persist: true });\n logger.info('[key-rotation-cron] pruned grace key', { keyId, removed });\n } catch (e: any) {\n logger.warn('[key-rotation-cron] failed to prune grace key', { keyId, error: e?.message || String(e) });\n }\n }\n }\n }\n } catch (e: any) {\n logger.error('[key-rotation-cron] rotation failed', { error: e?.message || String(e) });\n } finally {\n inFlight = false;\n }\n };\n\n if (enabled) {\n timer = setInterval(() => { void run(); }, intervalMinutes * 60_000);\n }\n\n return {\n stop() {\n if (timer) clearInterval(timer);\n timer = null;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"express.js","names":["out: ShamirApplyServerLockResponse","e: any","out: ShamirRemoveServerLockResponse","normalizedHeaders: Record<string, string>","v","base: Logger","allowedOrigin: string | '*' | undefined","error: any","e: any","result","currentKeyId: string | null","shamirReady: boolean | null","shamirCurrentKeyId: string | null","shamirError: string | undefined","timer: any"],"sources":["../../../../src/server/core/SessionService.ts","../../../../src/core/WalletIframe/validation.ts","../../../../src/server/core/shamirHandlers.ts","../../../../src/server/email-recovery/zkEmail/index.ts","../../../../src/server/email-recovery/emailParsers.ts","../../../../src/server/core/logger.ts","../../../../src/server/router/logger.ts","../../../../src/server/router/express-adaptor.ts"],"sourcesContent":["\nexport interface SessionConfig {\n jwt?: {\n /** Required: JWT signing hook; return a complete token */\n signToken?: (input: { header: Record<string, unknown>; payload: Record<string, unknown> }) => Promise<string> | string;\n /** Required: JWT verification hook */\n verifyToken?: (token: string) => Promise<{ valid: boolean; payload?: any }> | { valid: boolean; payload?: any };\n /** Optional: sliding refresh window (seconds) to allow /session/refresh before exp, default 900 (15 min) */\n refreshWindowSec?: number;\n /** Optional: build additional claims to include in the payload */\n buildClaims?: (input: { sub: string; context?: Record<string, unknown> }) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;\n };\n cookie?: {\n /** Cookie name. Default: 'w3a_session' */\n name?: string;\n /** Optional override: build Set-Cookie header for a new token */\n buildSetHeader?: (token: string) => string;\n /** Optional override: build Set-Cookie header that clears the cookie */\n buildClearHeader?: () => string;\n /** Optional override: extract token from headers (Authorization/Cookie) */\n extractToken?: (headers: Record<string, string | string[] | undefined>, cookieName: string) => string | null;\n };\n}\n\nexport class SessionService<TClaims = any> {\n private cfg: NonNullable<SessionConfig>;\n\n constructor(cfg: NonNullable<SessionConfig>) {\n this.cfg = cfg || ({} as any);\n }\n\n getCookieName(): string {\n return this.cfg?.cookie?.name || 'w3a_session';\n }\n\n buildSetCookie(token: string): string {\n if (this.cfg?.cookie?.buildSetHeader) return this.cfg.cookie.buildSetHeader(token);\n const name = this.getCookieName();\n const cookieParts = [`${name}=${token}`];\n const path = '/';\n const httpOnly = true;\n const secure = true; // default secure\n const sameSite = 'Lax';\n const maxAge = 24 * 3600; // 1 day default\n cookieParts.push(`Path=${path}`);\n if (httpOnly) cookieParts.push('HttpOnly');\n if (secure) cookieParts.push('Secure');\n if (sameSite) cookieParts.push(`SameSite=${sameSite}`);\n if (maxAge) {\n cookieParts.push(`Max-Age=${maxAge}`);\n const expires = new Date(Date.now() + (maxAge * 1000)).toUTCString();\n cookieParts.push(`Expires=${expires}`);\n }\n return cookieParts.join('; ');\n }\n\n buildClearCookie(): string {\n if (this.cfg?.cookie?.buildClearHeader) return this.cfg.cookie.buildClearHeader();\n const name = this.getCookieName();\n const path = '/';\n const secure = true;\n const httpOnly = true;\n const parts = [\n `${name}=`,\n `Path=${path}`,\n 'Max-Age=0',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT'\n ];\n if (httpOnly) parts.push('HttpOnly');\n if (secure) parts.push('Secure');\n const sameSite = 'Lax';\n if (sameSite) parts.push(`SameSite=${sameSite}`);\n return parts.join('; ');\n }\n\n /** Sign a JWT with configured algorithm. Adds iat/exp and copies iss/aud. */\n async signJwt(sub: string, extraClaims?: Record<string, unknown>): Promise<string> {\n const jwt = this.cfg?.jwt || {};\n const built = await Promise.resolve(jwt.buildClaims?.({ sub, context: extraClaims })) || {};\n const payload = { sub, ...(extraClaims || {}), ...(built || {}) } as Record<string, unknown>;\n if (typeof jwt.signToken === 'function') {\n // Full override of signing: user supplies the complete token\n const token = await Promise.resolve(jwt.signToken({ header: { typ: 'JWT' }, payload } as any));\n return token;\n }\n throw new Error('SessionService: No JWT signing hook or provider configured');\n }\n\n /** Verify signature and expiration. Returns payload on success. */\n async verifyJwt(token: string): Promise<{ valid: boolean; payload?: any }> {\n const verify = this.cfg?.jwt?.verifyToken;\n if (typeof verify !== 'function') return { valid: false };\n return await Promise.resolve(verify(token));\n }\n\n parse(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; claims?: TClaims } | { ok: false }>{\n const authHeader = (headers['authorization'] || headers['Authorization']) as string | undefined;\n let token: string | null = null;\n if (authHeader && /^Bearer\\s+/.test(authHeader)) token = authHeader.replace(/^Bearer\\s+/i, '').trim();\n const cookieHeader = (headers['cookie'] || headers['Cookie']) as string | undefined;\n if (!token && cookieHeader) {\n const name = this.getCookieName();\n for (const part of cookieHeader.split(';')) {\n const [k, v] = part.split('=');\n if (k && k.trim() === name) { token = (v || '').trim(); break; }\n }\n }\n if (!token) return Promise.resolve({ ok: false });\n return this.verifyJwt(token).then(v => v.valid ? { ok: true, claims: v.payload as TClaims } : { ok: false });\n }\n\n // === token helpers ===\n extractTokenFromHeaders(headers: Record<string, string | string[] | undefined>): string | null {\n if (this.cfg?.cookie?.extractToken) return this.cfg.cookie.extractToken(headers, this.getCookieName());\n const authHeader = (headers['authorization'] || headers['Authorization']) as string | undefined;\n if (authHeader && /^Bearer\\s+/.test(authHeader)) return authHeader.replace(/^Bearer\\s+/i, '').trim();\n const cookieHeader = (headers['cookie'] || headers['Cookie']) as string | undefined;\n if (cookieHeader) {\n const name = this.getCookieName();\n for (const part of cookieHeader.split(';')) {\n const [k, v] = part.split('=');\n if (k && k.trim() === name) return (v || '').trim();\n }\n }\n return null;\n }\n\n async refresh(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; jwt?: string; code?: string; message?: string }>{\n try {\n const token = this.extractTokenFromHeaders(headers);\n if (!token) return { ok: false, code: 'unauthorized', message: 'No session token' };\n const v = await this.verifyJwt(token);\n if (!v.valid) return { ok: false, code: 'unauthorized', message: 'Invalid token' };\n const payload: any = v.payload || {};\n if (!this.isWithinRefreshWindow(payload)) return { ok: false, code: 'not_eligible', message: 'Not within refresh window' };\n const sub = String(payload.sub || '');\n if (!sub) return { ok: false, code: 'invalid_claims', message: 'Missing sub claim' };\n const next = await this.signJwt(sub);\n return { ok: true, jwt: next };\n } catch (e: any) {\n return { ok: false, code: 'internal', message: e?.message || 'Refresh failed' };\n }\n }\n\n nowSeconds(): number { return Math.floor(Date.now() / 1000); }\n\n private isWithinRefreshWindow(payload: any): boolean {\n try {\n const now = this.nowSeconds();\n const exp = Number(payload?.exp || 0);\n if (!exp || now >= exp) return false; // no refresh if already expired\n const windowSec = Number(this.cfg?.jwt?.refreshWindowSec || 15 * 60);\n return (exp - now) <= windowSec;\n } catch { return false; }\n }\n}\n\n/*\n * Utility: parse comma-separated list of origins into a normalized unique list\n * - canonicalizes to protocol + host + optional port\n * - lowercases host, strips path/query/hash, trims spaces/trailing slashes\n */\nexport function parseCsvList(input?: string): string[] {\n const out = new Set<string>();\n for (const raw of String(input || '').split(',')) {\n const s = raw.trim();\n if (!s) continue;\n try {\n const u = new URL(s);\n const host = u.hostname.toLowerCase();\n const port = u.port ? `:${u.port}` : '';\n const proto = u.protocol === 'http:' || u.protocol === 'https:' ? u.protocol : 'https:';\n out.add(`${proto}//${host}${port}`);\n } catch {\n const stripped = s.replace(/\\/$/, '');\n if (stripped) out.add(stripped);\n }\n }\n return Array.from(out);\n}\n\n/*\n * Utility: merge multiple CSV lists of origins and return normalized list or '*'\n */\nexport function buildCorsOrigins(...inputs: Array<string | undefined>): string[] | '*' {\n const merged = new Set<string>();\n for (const input of inputs) {\n for (const origin of parseCsvList(input)) merged.add(origin);\n }\n const list = Array.from(merged);\n return list.length > 0 ? list : '*';\n}\n","// Shared runtime validation helpers for Wallet Iframe code.\n\nexport function isObject(x: unknown): x is Record<string, unknown> {\n return x !== null && typeof x === 'object';\n}\n\nexport function isString(x: unknown): x is string {\n return typeof x === 'string';\n}\n\nexport function isNonEmptyString(x: unknown): x is string {\n return typeof x === 'string' && x.length > 0;\n}\n\nexport function isNumber(x: unknown): x is number {\n return typeof x === 'number';\n}\n\nexport function isFiniteNumber(x: unknown): x is number {\n return typeof x === 'number' && Number.isFinite(x);\n}\n\nexport function isFunction(x: unknown): x is Function {\n return typeof x === 'function';\n}\n\nexport function isBoolean(x: unknown): x is boolean {\n return typeof x === 'boolean';\n}\n\nexport function isArray<T = unknown>(x: unknown): x is T[] {\n return Array.isArray(x);\n}\n\n// ========= Assertions (throw on mismatch) =========\n\nexport function assertString(val: unknown, name = 'value'): string {\n if (typeof val !== 'string') throw new Error(`Invalid ${name}: expected string`);\n return val;\n}\n\nexport function assertNumber(val: unknown, name = 'value'): number {\n if (typeof val !== 'number' || !Number.isFinite(val)) throw new Error(`Invalid ${name}: expected finite number`);\n return val;\n}\n\nexport function assertBoolean(val: unknown, name = 'value'): boolean {\n if (typeof val !== 'boolean') throw new Error(`Invalid ${name}: expected boolean`);\n return val;\n}\n\nexport function assertObject<T extends Record<string, unknown> = Record<string, unknown>>(val: unknown, name = 'value'): T {\n if (!isObject(val)) throw new Error(`Invalid ${name}: expected object`);\n return val as T;\n}\n\nexport function assertArray<T = unknown>(val: unknown, name = 'value'): T[] {\n if (!Array.isArray(val)) throw new Error(`Invalid ${name}: expected array`);\n return val as T[];\n}\n\n// Shallowly remove function-valued properties (postMessage/clone safety)\nexport function stripFunctionsShallow<T extends Record<string, unknown>>(obj?: T): Partial<T> | undefined {\n if (!obj || !isObject(obj)) return undefined;\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!isFunction(v)) out[k] = v as unknown;\n }\n return out as Partial<T>;\n}\n\n// ===============================\n// SignedTransaction shape helpers\n// ===============================\n\nexport interface PlainSignedTransactionLike {\n transaction: unknown;\n signature: unknown;\n borsh_bytes?: unknown;\n borshBytes?: unknown;\n base64Encode?: unknown;\n}\n\nexport function isPlainSignedTransactionLike(x: unknown): x is PlainSignedTransactionLike {\n if (!isObject(x)) return false;\n const hasTx = 'transaction' in x;\n const hasSig = 'signature' in x;\n const bytes = x as { borsh_bytes?: unknown; borshBytes?: unknown };\n const hasBytes = Array.isArray(bytes.borsh_bytes) || bytes.borshBytes instanceof Uint8Array;\n const hasMethod = typeof (x as { base64Encode?: unknown }).base64Encode === 'function';\n return hasTx && hasSig && hasBytes && !hasMethod;\n}\n\nexport function extractBorshBytesFromPlainSignedTx(x: PlainSignedTransactionLike): number[] {\n const asArray = Array.isArray(x.borsh_bytes) ? (x.borsh_bytes as number[]) : undefined;\n if (asArray) return asArray;\n const asU8 = (x.borshBytes instanceof Uint8Array) ? x.borshBytes : undefined;\n return Array.from(asU8 || new Uint8Array());\n}\n","import type {\n ShamirApplyServerLockRequest,\n ShamirApplyServerLockResponse,\n ShamirRemoveServerLockRequest,\n ShamirRemoveServerLockResponse,\n} from './types';\nimport type { ShamirService } from './ShamirService';\nimport { isString } from '../../core/WalletIframe/validation';\n\nexport async function handleApplyServerLock(\n service: ShamirService,\n request: { body?: { kek_c_b64u?: string } },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const kek_c_b64u = request.body?.kek_c_b64u;\n if (!isString(kek_c_b64u) || !kek_c_b64u) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'kek_c_b64u required and must be a non-empty string' }),\n };\n }\n\n const out: ShamirApplyServerLockResponse = await service.applyServerLock(kek_c_b64u);\n const keyId = service.getCurrentShamirKeyId();\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...out, keyId }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleRemoveServerLock(\n service: ShamirService,\n request: { body?: { kek_cs_b64u?: string; keyId?: string } },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const body = request.body;\n if (!body) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'Missing body' }),\n };\n }\n const { kek_cs_b64u, keyId } = body;\n if (!isString(kek_cs_b64u) || !kek_cs_b64u) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'kek_cs_b64u required and must be a non-empty string' }),\n };\n }\n if (!isString(keyId) || !keyId) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'keyId required and must be a non-empty string' }),\n };\n }\n\n const providedKeyId = String(keyId);\n const currentKeyId = service.getCurrentShamirKeyId();\n let out: ShamirRemoveServerLockResponse;\n\n if (currentKeyId && providedKeyId === currentKeyId) {\n out = await service.removeServerLock(kek_cs_b64u);\n } else if (service.hasGraceKey(providedKeyId)) {\n out = await service.removeGraceServerLockWithKey(providedKeyId, { kek_cs_b64u } as ShamirRemoveServerLockRequest);\n } else {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'unknown keyId' }),\n };\n }\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(out),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleGetShamirKeyInfo(\n service: ShamirService,\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n await service.ensureReady();\n const currentKeyId = service.getCurrentShamirKeyId();\n const graceKeyIds = service.getGraceKeyIds();\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n currentKeyId,\n p_b64u: service.getShamirConfig()?.shamir_p_b64u ?? null,\n graceKeyIds,\n }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleListGraceKeys(\n service: ShamirService,\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n await service.ensureGraceKeysLoaded();\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ graceKeyIds: service.getGraceKeyIds() }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleAddGraceKey(\n service: ShamirService,\n request: { e_s_b64u?: string; d_s_b64u?: string },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const { e_s_b64u, d_s_b64u } = request || ({} as any);\n if (!isString(e_s_b64u) || !e_s_b64u || !isString(d_s_b64u) || !d_s_b64u) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'e_s_b64u and d_s_b64u required' }),\n };\n }\n\n await service.ensureGraceKeysLoaded();\n const added = await service.addGraceKeyInternal({ e_s_b64u, d_s_b64u }, { persist: true, skipIfExists: true });\n if (!added) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'failed to add grace key' }),\n };\n }\n\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ keyId: added.keyId }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n\nexport async function handleRemoveGraceKey(\n service: ShamirService,\n request: { keyId?: string },\n): Promise<{ status: number; headers: Record<string, string>; body: string }> {\n try {\n const keyId = request?.keyId;\n if (!isString(keyId) || !keyId) {\n return {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'keyId required and must be a non-empty string' }),\n };\n }\n\n const removed = await service.removeGraceKeyInternal(keyId, { persist: true });\n return {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ removed }),\n };\n } catch (e: any) {\n return {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'internal', details: e?.message }),\n };\n }\n}\n","import { ZkEmailProverClient, type ZkEmailProverClientOptions, type ZkEmailProverError } from './proverClient';\n\nexport { ZkEmailProverClient } from './proverClient';\nexport type { ZkEmailProverClientOptions, ZkEmailProverError, ZkEmailProverResponse } from './proverClient';\n\nexport interface ForwardableEmailPayload {\n from: string;\n to: string;\n headers: Record<string, string>;\n raw?: string;\n rawSize?: number;\n}\n\nexport type NormalizedEmailResult =\n | { ok: true; payload: ForwardableEmailPayload }\n | { ok: false; code: string; message: string };\n\nexport interface GenerateZkEmailProofResult {\n proof: unknown;\n publicInputs: string[];\n}\n\nexport interface ParsedZkEmailBindings {\n accountId: string;\n newPublicKey: string;\n fromEmail: string;\n timestamp: string;\n requestId: string;\n}\n\n/**\n * Build a minimal ForwardableEmailPayload from a raw RFC822 email string.\n * This is primarily used by server-side helpers that receive only a raw\n * email blob (no pre-normalized headers).\n */\nexport function buildForwardablePayloadFromRawEmail(raw: string): ForwardableEmailPayload {\n const safeRaw = typeof raw === 'string' ? raw : '';\n const lines = safeRaw.split(/\\r?\\n/);\n\n const getHeader = (name: string): string | undefined => {\n const line = lines.find(l => new RegExp(`^${name}:`, 'i').test(l));\n if (!line) return undefined;\n const idx = line.indexOf(':');\n const rest = idx >= 0 ? line.slice(idx + 1) : '';\n const value = rest.trim();\n return value || undefined;\n };\n\n const fromHeader = getHeader('from') || 'unknown@zkemail.local';\n const toHeader = getHeader('to') || 'recover@zkemail.local';\n\n const headers: Record<string, string> = {};\n const subjectHeader = getHeader('subject');\n const dateHeader = getHeader('date');\n\n if (fromHeader) headers.from = fromHeader;\n if (toHeader) headers.to = toHeader;\n if (subjectHeader) headers.subject = subjectHeader;\n if (dateHeader) headers.date = dateHeader;\n\n return {\n from: fromHeader,\n to: toHeader,\n headers,\n raw: safeRaw,\n rawSize: safeRaw.length,\n };\n}\n\nexport function normalizeForwardableEmailPayload(input: unknown): NormalizedEmailResult {\n if (!input || typeof input !== 'object') {\n return { ok: false, code: 'invalid_email', message: 'JSON body required' };\n }\n\n const body = input as Partial<ForwardableEmailPayload>;\n const { from, to, headers, raw, rawSize } = body;\n\n if (!from || typeof from !== 'string' || !to || typeof to !== 'string') {\n return { ok: false, code: 'invalid_email', message: 'from and to are required' };\n }\n\n if (!headers || typeof headers !== 'object') {\n return { ok: false, code: 'invalid_email', message: 'headers object is required' };\n }\n\n const normalizedHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers as Record<string, unknown>)) {\n normalizedHeaders[String(k).toLowerCase()] = String(v);\n }\n\n return {\n ok: true,\n payload: {\n from,\n to,\n headers: normalizedHeaders,\n raw: typeof raw === 'string' ? raw : undefined,\n rawSize: typeof rawSize === 'number' ? rawSize : undefined,\n },\n };\n}\n\n/**\n * Parse NEAR accountId from the Subject line inside a raw RFC822 email.\n *\n * Expected format (case-insensitive on \"Subject\" and \"recover\"):\n * Subject: recover-123ABC bob.testnet ed25519:<pk>\n *\n * Returns the parsed accountId (e.g. \"bob.testnet\") or null if not found.\n */\nexport function parseAccountIdFromSubject(raw: string | undefined | null): string | null {\n if (!raw || typeof raw !== 'string') return null;\n\n // Accept either a full RFC822 message (with \"Subject: ...\" header)\n // or a bare Subject value (\"recover-123ABC bob.testnet ed25519:<pk>\").\n let subjectText = '';\n const lines = raw.split(/\\r?\\n/);\n const subjectLine = lines.find(line => /^subject:/i.test(line));\n if (subjectLine) {\n const idx = subjectLine.indexOf(':');\n const restRaw = idx >= 0 ? subjectLine.slice(idx + 1) : '';\n subjectText = restRaw.trim();\n } else {\n subjectText = raw.trim();\n }\n\n if (!subjectText) return null;\n\n // Strip common reply/forward prefixes\n subjectText = subjectText.replace(/^(re|fwd):\\s*/i, '').trim();\n if (!subjectText) return null;\n\n // Strict format: \"recover-<request_id> <accountId> [ed25519:<pk>]\"\n const match = subjectText.match(\n /^recover-([A-Za-z0-9]{6})\\s+([^\\s]+)(?:\\s+ed25519:[^\\s]+)?\\s*$/i\n );\n if (match?.[2]) {\n return match[2];\n }\n\n return null;\n}\n\nfunction parseSubjectBindings(\n rawSubject: string | undefined | null\n): { accountId: string; newPublicKey: string; requestId: string } | null {\n if (!rawSubject || typeof rawSubject !== 'string') return null;\n\n const lines = rawSubject.split(/\\r?\\n/);\n let subjectText = '';\n const subjectLine = lines.find(line => /^subject:/i.test(line));\n if (subjectLine) {\n const idx = subjectLine.indexOf(':');\n const restRaw = idx >= 0 ? subjectLine.slice(idx + 1) : '';\n subjectText = restRaw.trim();\n } else {\n subjectText = rawSubject.trim();\n }\n if (!subjectText) return null;\n\n subjectText = subjectText.replace(/^(re|fwd):\\s*/i, '').trim();\n if (!subjectText) return null;\n\n // Strict format:\n // \"recover-<request_id> <accountId> ed25519:<pk>\"\n const match = subjectText.match(\n /^recover-([A-Za-z0-9]{6})\\s+([^\\s]+)\\s+ed25519:([^\\s]+)\\s*$/i\n );\n if (!match) return null;\n\n const [, requestId, accountId, newPublicKey] = match;\n\n return {\n accountId,\n newPublicKey,\n requestId,\n };\n}\n\nexport function extractZkEmailBindingsFromPayload(\n payload: ForwardableEmailPayload\n): ParsedZkEmailBindings | null {\n const raw = payload.raw || '';\n const lines = raw.split(/\\r?\\n/);\n\n const subjectLine = lines.find(line => /^subject:/i.test(line));\n const subjectBindings = parseSubjectBindings(subjectLine ?? '');\n if (!subjectBindings) {\n return null;\n }\n\n const headers = payload.headers || {};\n let fromEmailRaw: string | undefined =\n (headers['from'] as any) ||\n (headers['x-from-email'] as any);\n let dateRaw: string | undefined =\n (headers['date'] as any) ||\n (headers['x-original-date'] as any);\n\n // Fallback: if headers object does not contain from/date,\n // attempt to parse them from the raw RFC822 email lines.\n if (!fromEmailRaw || !dateRaw) {\n for (const line of lines) {\n if (!fromEmailRaw && /^from:/i.test(line)) {\n const idx = line.indexOf(':');\n fromEmailRaw = idx >= 0 ? line.slice(idx + 1).trim() : '';\n }\n if (!dateRaw && /^date:/i.test(line)) {\n const idx = line.indexOf(':');\n dateRaw = idx >= 0 ? line.slice(idx + 1).trim() : '';\n }\n if (fromEmailRaw && dateRaw) break;\n }\n }\n\n const fromEmail = String(fromEmailRaw || '').trim();\n const timestamp = String(dateRaw || '').trim();\n\n if (!fromEmail || !timestamp) {\n return null;\n }\n\n return {\n accountId: subjectBindings.accountId,\n newPublicKey: subjectBindings.newPublicKey,\n fromEmail,\n timestamp,\n requestId: subjectBindings.requestId,\n };\n}\n\nexport async function generateZkEmailProofFromPayload(\n payload: ForwardableEmailPayload,\n prover: ZkEmailProverClientOptions | ZkEmailProverClient\n): Promise<GenerateZkEmailProofResult> {\n if (!payload.raw || typeof payload.raw !== 'string') {\n const err: ZkEmailProverError = Object.assign(\n new Error('raw email contents are required to generate a zk-email proof'),\n { code: 'missing_raw_email' }\n );\n throw err;\n }\n\n const client =\n (prover && typeof (prover as any).proveEmail === 'function')\n ? (prover as ZkEmailProverClient)\n : new ZkEmailProverClient(prover as ZkEmailProverClientOptions);\n\n const res = await client.proveEmail(payload.raw);\n\n return {\n proof: res.proof,\n publicInputs: res.publicSignals,\n };\n}\n","import type { EmailRecoveryMode } from './types';\nimport { normalizeForwardableEmailPayload, parseAccountIdFromSubject } from './zkEmail';\n\nexport enum EmailRecoveryModeHint {\n ZkEmail = 'zk-email',\n TeeEncrypted = 'tee-encrypted',\n OnchainPublic = 'onchain-public',\n}\n\nexport function normalizeRecoveryMode(raw: string | undefined | null): EmailRecoveryMode | null {\n if (!raw) return null;\n const value = raw.trim().toLowerCase();\n if (value === EmailRecoveryModeHint.ZkEmail) return 'zk-email';\n if (value === EmailRecoveryModeHint.TeeEncrypted) return 'tee-encrypted';\n if (value === EmailRecoveryModeHint.OnchainPublic) return 'onchain-public';\n return null;\n}\n\nexport function extractRecoveryModeFromBody(emailBlob?: string): EmailRecoveryMode | null {\n if (!emailBlob) return null;\n\n const lines = emailBlob.split(/\\r?\\n/);\n const bodyStartIndex = lines.findIndex(line => line.trim() === '');\n if (bodyStartIndex === -1) return null;\n\n const bodyLines = lines.slice(bodyStartIndex + 1);\n const firstNonEmptyBodyLine = bodyLines.find(line => line.trim() !== '');\n if (!firstNonEmptyBodyLine) return null;\n\n const candidate = firstNonEmptyBodyLine.trim();\n const normalized = normalizeRecoveryMode(candidate);\n if (normalized) return normalized;\n\n const lower = candidate.toLowerCase();\n if (lower.includes(EmailRecoveryModeHint.ZkEmail)) return 'zk-email';\n if (lower.includes(EmailRecoveryModeHint.TeeEncrypted)) return 'tee-encrypted';\n if (lower.includes(EmailRecoveryModeHint.OnchainPublic)) return 'onchain-public';\n\n return null;\n}\n\ntype HeaderValue = string | string[] | undefined;\ntype HeadersLike = Headers | Record<string, HeaderValue> | undefined;\n\nexport type RecoverEmailParseResult =\n | { ok: true; accountId: string; emailBlob: string; explicitMode?: string }\n | { ok: false; status: number; code: string; message: string };\n\nfunction getHeader(headers: HeadersLike, name: string): string | undefined {\n if (!headers) return undefined;\n\n const maybeHeaders = headers as any;\n if (typeof maybeHeaders.get === 'function') {\n const v = maybeHeaders.get(name);\n return (typeof v === 'string') ? v : undefined;\n }\n\n const record = headers as Record<string, HeaderValue>;\n const v = record[name.toLowerCase()] ?? record[name];\n if (Array.isArray(v)) return (typeof v[0] === 'string') ? v[0] : undefined;\n return (typeof v === 'string') ? v : undefined;\n}\n\nfunction parseExplicitMode(body: unknown, headers?: HeadersLike): string | undefined {\n const modeFromBody =\n (typeof (body as any)?.explicitMode === 'string' ? String((body as any).explicitMode) : '') ||\n (typeof (body as any)?.explicit_mode === 'string' ? String((body as any).explicit_mode) : '');\n const modeFromHeader = getHeader(headers, 'x-email-recovery-mode') || getHeader(headers, 'x-recovery-mode') || '';\n const raw = (modeFromBody || modeFromHeader).trim();\n return raw ? raw : undefined;\n}\n\nexport function parseRecoverEmailRequest(body: unknown, opts: { headers?: HeadersLike } = {}): RecoverEmailParseResult {\n const explicitMode = parseExplicitMode(body, opts.headers);\n\n const normalized = normalizeForwardableEmailPayload(body);\n if (!normalized.ok) {\n return { ok: false, status: 400, code: normalized.code, message: normalized.message };\n }\n\n const payload = normalized.payload;\n const emailBlob = payload.raw || '';\n const emailHeaders = payload.headers || {};\n\n const subjectHeader = emailHeaders['subject'];\n const parsedAccountId = parseAccountIdFromSubject(subjectHeader || emailBlob);\n const headerAccountId = String(emailHeaders['x-near-account-id'] || emailHeaders['x-account-id'] || '').trim();\n const accountId = (parsedAccountId || headerAccountId || '').trim();\n\n if (!accountId) {\n return { ok: false, status: 400, code: 'missing_account', message: 'x-near-account-id header is required' };\n }\n if (!emailBlob) {\n return { ok: false, status: 400, code: 'missing_email', message: 'raw email blob is required' };\n }\n\n return { ok: true, accountId, emailBlob, explicitMode };\n}\n\nconst EMAIL_ADDRESS_REGEX =\n /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)/;\n\nexport function canonicalizeEmail(input: string): string {\n const raw = String(input || '').trim();\n if (!raw) return '';\n\n // Handle cases where a full header line is passed in (e.g. \"From: ...\").\n const withoutHeaderName = raw.replace(/^[a-z0-9-]+\\s*:\\s*/i, '').trim();\n\n // Prefer the common \"Name <email@domain>\" format when present, but still\n // validate/extract the actual address via regex.\n const angleMatch = withoutHeaderName.match(/<([^>]+)>/);\n const candidates = [\n angleMatch?.[1],\n withoutHeaderName,\n ].filter((v): v is string => typeof v === 'string' && v.length > 0);\n\n for (const candidate of candidates) {\n const cleaned = candidate.replace(/^mailto:\\s*/i, '');\n const match = cleaned.match(EMAIL_ADDRESS_REGEX);\n if (match?.[1]) {\n return match[1].trim().toLowerCase();\n }\n }\n\n return withoutHeaderName.toLowerCase();\n}\n\nexport function parseHeaderValue(rawEmail: string, name: string): string | undefined {\n try {\n const raw = String(rawEmail || '');\n if (!raw) return undefined;\n\n const lines = raw.split(/\\r?\\n/);\n const headerLines: string[] = [];\n\n // Only consider the header section (until the first blank line).\n for (const line of lines) {\n if (line.trim() === '') break;\n\n // RFC822 header folding: lines starting with whitespace continue previous header.\n if (/^\\s/.test(line) && headerLines.length > 0) {\n headerLines[headerLines.length - 1] += ` ${line.trim()}`;\n continue;\n }\n\n headerLines.push(line);\n }\n\n const headerName = name.trim();\n if (!headerName) return undefined;\n\n const re = new RegExp(`^${headerName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\s*:`, 'i');\n const found = headerLines.find((l) => re.test(l));\n if (!found) return undefined;\n\n const idx = found.indexOf(':');\n const value = idx >= 0 ? found.slice(idx + 1).trim() : '';\n return value || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function parseRecoverSubjectBindings(\n rawEmail: string\n): { requestId: string; accountId: string; newPublicKey: string } | null {\n // Accept either a full RFC822 email or a bare Subject value.\n let subjectText = (parseHeaderValue(rawEmail, 'subject') || String(rawEmail || '')).trim();\n if (!subjectText) return null;\n\n // Strip common reply/forward prefixes.\n subjectText = subjectText.replace(/^(re|fwd):\\s*/i, '').trim();\n if (!subjectText) return null;\n\n // Strict format:\n // \"recover-<request_id> <accountId> ed25519:<pk>\"\n const match = subjectText.match(\n /^recover-([A-Za-z0-9]{6})\\s+([^\\s]+)\\s+ed25519:([^\\s]+)\\s*$/i\n );\n if (!match) return null;\n\n const [, requestId, accountId, newPublicKey] = match;\n return { requestId, accountId, newPublicKey };\n}\n","export type Logger = {\n debug?: (...args: unknown[]) => void;\n info?: (...args: unknown[]) => void;\n warn?: (...args: unknown[]) => void;\n error?: (...args: unknown[]) => void;\n log?: (...args: unknown[]) => void;\n};\n\nexport type NormalizedLogger = {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n};\n\nfunction safe(fn?: (...args: unknown[]) => void): (...args: unknown[]) => void {\n if (!fn) return () => {};\n return (...args: unknown[]) => {\n try {\n fn(...args);\n } catch {\n // Never allow logging to break request handling.\n }\n };\n}\n\n/**\n * Library code should never call `console.*` directly; the host decides where logs go.\n * - Default: no logs\n * - To enable: pass `logger: console` (or a structured logger) to the host config.\n */\nexport function normalizeLogger(logger?: Logger | null): NormalizedLogger {\n if (!logger) {\n return { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} };\n }\n\n const base: Logger = logger;\n const log = typeof base.log === 'function' ? base.log.bind(base) : undefined;\n\n const debug = (typeof base.debug === 'function' ? base.debug.bind(base) : log);\n const info = (typeof base.info === 'function' ? base.info.bind(base) : log);\n const warn = (typeof base.warn === 'function' ? base.warn.bind(base) : log);\n const error = (typeof base.error === 'function' ? base.error.bind(base) : log);\n\n return {\n debug: safe(debug),\n info: safe(info),\n warn: safe(warn),\n error: safe(error),\n };\n}\n\n","import type { Logger, NormalizedLogger } from '../core/logger';\nimport { normalizeLogger } from '../core/logger';\n\nexport type RouterLogger = Logger;\nexport type NormalizedRouterLogger = NormalizedLogger;\nexport const normalizeRouterLogger = normalizeLogger;\n","import type { Request, Response, Router as ExpressRouter } from 'express';\nimport express from 'express';\nimport type { AuthService } from '../core/AuthService';\nimport { buildCorsOrigins } from '../core/SessionService';\nimport {\n handleApplyServerLock,\n handleRemoveServerLock,\n handleGetShamirKeyInfo,\n handleListGraceKeys,\n handleAddGraceKey,\n handleRemoveGraceKey,\n} from '../core/shamirHandlers';\nimport { parseRecoverEmailRequest } from '../email-recovery/emailParsers';\nimport type { DelegateActionPolicy } from '../delegateAction';\nimport type { RouterLogger } from './logger';\nimport { normalizeRouterLogger } from './logger';\n\nexport interface RelayRouterOptions {\n healthz?: boolean;\n readyz?: boolean;\n // Optional list(s) of CORS origins (CSV strings or literal origins).\n // Pass raw strings; the router normalizes/merges internally.\n corsOrigins?: Array<string | undefined>;\n /**\n * Optional route for submitting NEP-461 SignedDelegate meta-transactions.\n *\n * - When omitted: disabled.\n * - When set: enabled at `route`.\n *\n * `policy` is server-controlled and is never read from the request body.\n */\n signedDelegate?: {\n route: string;\n policy?: DelegateActionPolicy;\n };\n sessionRoutes?: { auth?: string; logout?: string };\n session?: SessionAdapter | null;\n // Optional logger; defaults to silent.\n logger?: RouterLogger | null;\n}\n\nfunction normalizePath(path: string): string {\n const trimmed = String(path || '').trim();\n if (!trimmed) return '';\n return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;\n}\n\nfunction withCors(res: Response, opts?: RelayRouterOptions, req?: Request): void {\n if (!opts?.corsOrigins) return;\n\n let allowedOrigin: string | '*' | undefined;\n const normalized = buildCorsOrigins(...(opts.corsOrigins || []));\n if (normalized === '*') {\n allowedOrigin = '*';\n res.set('Access-Control-Allow-Origin', '*');\n } else if (Array.isArray(normalized)) {\n const origin = String((req as any)?.headers?.origin || '').trim();\n if (origin && normalized.includes(origin)) {\n allowedOrigin = origin;\n res.set('Access-Control-Allow-Origin', origin);\n res.set('Vary', 'Origin');\n }\n }\n\n res.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');\n res.set('Access-Control-Allow-Headers', 'Content-Type,Authorization');\n // Only advertise credentials when we echo back a specific origin (not '*')\n if (allowedOrigin && allowedOrigin !== '*') {\n res.set('Access-Control-Allow-Credentials', 'true');\n }\n}\n\n// Minimal session adapter interface expected by the routers\nexport interface SessionAdapter {\n signJwt(sub: string, extra?: Record<string, unknown>): Promise<string>;\n parse(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; claims?: any } | { ok: false }>;\n buildSetCookie(token: string): string;\n buildClearCookie(): string;\n refresh(headers: Record<string, string | string[] | undefined>): Promise<{ ok: boolean; jwt?: string; code?: string; message?: string }>;\n}\n\nexport function createRelayRouter(service: AuthService, opts: RelayRouterOptions = {}): ExpressRouter {\n const router = express.Router();\n const mePath = opts.sessionRoutes?.auth || '/session/auth';\n const logoutPath = opts.sessionRoutes?.logout || '/session/logout';\n const logger = normalizeRouterLogger(opts.logger);\n const signedDelegatePath = (() => {\n if (!opts.signedDelegate) return '';\n const raw = String(opts.signedDelegate.route || '').trim();\n if (!raw) throw new Error('RelayRouterOptions.signedDelegate.route is required');\n return normalizePath(raw);\n })();\n const signedDelegatePolicy = opts.signedDelegate?.policy;\n\n // Optional CORS: implemented here to keep setup simple for example relayers.\n // If you prefer custom CORS middleware, omit `corsOrigins` and wire your own.\n router.use((req: Request, res: Response, next: any) => {\n withCors(res, opts, req);\n const method = String((req as any)?.method || '').toUpperCase();\n if (opts.corsOrigins && method === 'OPTIONS') {\n res.status(204).send('');\n return;\n }\n next();\n });\n\n router.post(\n '/create_account_and_register_user',\n async (req: any, res: any) => {\n try {\n const {\n new_account_id,\n new_public_key,\n vrf_data,\n webauthn_registration,\n deterministic_vrf_public_key,\n authenticator_options\n } = req.body || ({} as any);\n\n if (!new_account_id || typeof new_account_id !== 'string') throw new Error('Missing or invalid new_account_id');\n if (!new_public_key || typeof new_public_key !== 'string') throw new Error('Missing or invalid new_public_key');\n if (!vrf_data || typeof vrf_data !== 'object') throw new Error('Missing or invalid vrf_data');\n if (!webauthn_registration || typeof webauthn_registration !== 'object') throw new Error('Missing or invalid webauthn_registration');\n\n const result = await service.createAccountAndRegisterUser({\n new_account_id,\n new_public_key,\n vrf_data,\n webauthn_registration,\n deterministic_vrf_public_key,\n authenticator_options\n });\n\n if (result.success) res.status(200).json(result);\n else res.status(400).json(result);\n } catch (error: any) {\n res.status(500).json({ success: false, error: error?.message || 'internal error' });\n }\n }\n );\n\n if (signedDelegatePath) {\n router.options(signedDelegatePath, (_req: any, res: any) => {\n res.sendStatus(204);\n });\n\n router.post(signedDelegatePath, async (req: any, res: any) => {\n try {\n const { hash, signedDelegate } = req.body || {};\n if (typeof hash !== 'string' || !hash || !signedDelegate) {\n res.status(400).json({ ok: false, code: 'invalid_body', message: 'Expected { hash, signedDelegate }' });\n return;\n }\n\n const result = await service.executeSignedDelegate({\n hash,\n signedDelegate,\n policy: signedDelegatePolicy,\n });\n\n if (!result || !result.ok) {\n res.status(400).json({\n ok: false,\n code: result?.code || 'delegate_execution_failed',\n message: result?.error || 'Failed to execute delegate action',\n });\n return;\n }\n\n res.status(200).json({\n ok: true,\n relayerTxHash: result.transactionHash || null,\n status: 'submitted',\n outcome: result.outcome ?? null,\n });\n } catch (e: any) {\n res.status(500).json({\n ok: false,\n code: 'internal',\n message: e?.message || 'Internal error while executing delegate action',\n });\n }\n });\n }\n\n router.post('/vrf/apply-server-lock', async (req: any, res: any) => {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n return res.status(503).json({ error: 'shamir_disabled', message: 'Shamir 3-pass is not configured on this server' });\n }\n try {\n const serverResponse = await handleApplyServerLock(shamir, { body: req.body });\n Object.entries(serverResponse.headers).forEach(([k, v]) => res.set(k, v as any));\n res.status(serverResponse.status);\n res.send(JSON.parse(serverResponse.body));\n } catch (e: any) {\n res.status(500).json({ error: 'internal', details: e?.message });\n }\n });\n\n router.post('/vrf/remove-server-lock', async (req: any, res: any) => {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n return res.status(503).json({ error: 'shamir_disabled', message: 'Shamir 3-pass is not configured on this server' });\n }\n try {\n const serverResponse = await handleRemoveServerLock(shamir, { body: req.body });\n Object.entries(serverResponse.headers).forEach(([k, v]) => res.set(k, v as any));\n res.status(serverResponse.status);\n res.send(JSON.parse(serverResponse.body));\n } catch (e: any) {\n res.status(500).json({ error: 'internal', details: e?.message });\n }\n });\n\n // VRF + WebAuthn session verification (VIEW call) + optional session issuance\n router.post('/verify-authentication-response', async (req: any, res: any) => {\n try {\n if (!req?.body) {\n res.status(400).json({ code: 'invalid_body', message: 'Request body is required' });\n return;\n }\n const body = req.body;\n const valid = body && body.vrf_data && body.webauthn_authentication;\n if (!valid) {\n res.status(400).json({ code: 'invalid_body', message: 'vrf_data and webauthn_authentication are required' });\n return;\n }\n const result = await service.verifyAuthenticationResponse(body);\n const status = result.success ? 200 : 400;\n if (status !== 200) {\n res.status(status).json({ code: 'not_verified', message: result.message || 'Authentication verification failed' });\n return;\n }\n const sessionKind = ((body?.sessionKind || body?.session_kind) === 'cookie') ? 'cookie' : 'jwt';\n const session = opts.session;\n if (session && result.verified) {\n try {\n const sub = String(body.vrf_data.user_id || '');\n const token = await session.signJwt(sub, { rpId: body.vrf_data.rp_id, blockHeight: body.vrf_data.block_height });\n // Best-effort server log without sensitive data\n logger.info(`[relay] creating ${sessionKind === 'cookie' ? 'HttpOnly session' : 'JWT'} for`, sub);\n if (sessionKind === 'cookie') {\n res.set('Set-Cookie', session.buildSetCookie(token));\n const { jwt: _omit, ...rest } = result as any;\n res.status(200).json(rest);\n return;\n }\n res.status(200).json({ ...result, jwt: token });\n return;\n } catch (e: any) {\n // If session issuance fails, still return verification result\n }\n }\n res.status(200).json(result);\n } catch (e: any) {\n res.status(500).json({ code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n // Session: read current claims via bearer token or cookie\n router.get(mePath, async (req: any, res: any) => {\n try {\n const session = opts.session;\n if (!session) {\n res.status(501).json({ authenticated: false, code: 'sessions_disabled', message: 'Sessions are not configured' });\n return;\n }\n const parsed = await session.parse(req.headers || {});\n if (!parsed.ok) {\n res.status(401).json({ authenticated: false, code: 'unauthorized', message: 'No valid session' });\n return;\n }\n res.status(200).json({ authenticated: true, claims: (parsed as any).claims });\n } catch (e: any) {\n res.status(500).json({ authenticated: false, code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n // Session: logout clears cookie (best-effort)\n router.post(logoutPath, async (_req: any, res: any) => {\n try {\n const session = opts.session;\n if (session) res.set('Set-Cookie', session.buildClearCookie());\n res.status(200).json({ success: true });\n } catch (e: any) {\n res.status(500).json({ success: false, error: 'internal', details: e?.message });\n }\n });\n\n // Session: refresh (sliding expiration)\n router.post('/session/refresh', async (req: any, res: any) => {\n try {\n const sessionKind = ((req.body || {}).sessionKind === 'cookie') ? 'cookie' : ((req.body || {}).session_kind === 'cookie' ? 'cookie' : 'jwt');\n const session = opts.session;\n if (!session) {\n res.status(501).json({ code: 'sessions_disabled', message: 'Sessions are not configured' });\n return;\n }\n const out = await session.refresh(req.headers || {});\n if (!out.ok || !out.jwt) {\n const code = out.code || 'not_eligible';\n const message = out.message || 'Refresh not eligible';\n res.status(code === 'unauthorized' ? 401 : 400).json({ code, message });\n return;\n }\n if (sessionKind === 'cookie') {\n res.set('Set-Cookie', session.buildSetCookie(out.jwt));\n res.status(200).json({ ok: true });\n } else {\n res.status(200).json({ ok: true, jwt: out.jwt });\n }\n } catch (e: any) {\n res.status(500).json({ code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n // Email recovery hook (DKIM/TEE flow):\n // Accept a ForwardableEmailPayload from the email worker and call the\n // per-user email-recoverer contract deployed on `accountId`.\n router.post('/recover-email', async (req: any, res: any) => {\n try {\n const prefer = String(req?.headers?.prefer || '').toLowerCase();\n const respondAsync =\n prefer.includes('respond-async') ||\n String((req?.query as any)?.async || '').trim() === '1' ||\n String((req?.query as any)?.respond_async || '').trim() === '1';\n\n const parsed = parseRecoverEmailRequest(req.body as unknown, { headers: req.headers as any });\n if (!parsed.ok) {\n res.status(parsed.status).json({ code: parsed.code, message: parsed.message });\n return;\n }\n const { accountId, emailBlob, explicitMode } = parsed;\n\n if (!service.emailRecovery) {\n res.status(503).json({ code: 'email_recovery_unavailable', message: 'EmailRecoveryService is not configured on this server' });\n return;\n }\n\n if (respondAsync) {\n void service.emailRecovery\n .requestEmailRecovery({ accountId, emailBlob, explicitMode })\n .then((result) => {\n logger.info('[recover-email] async complete', {\n success: result?.success === true,\n accountId,\n error: result?.success ? undefined : result?.error,\n });\n })\n .catch((err: any) => {\n logger.error('[recover-email] async error', {\n accountId,\n error: err?.message || String(err),\n });\n });\n\n res.status(202).json({ success: true, queued: true, accountId });\n return;\n }\n\n const result = await service.emailRecovery.requestEmailRecovery({ accountId, emailBlob, explicitMode });\n res.status(result.success ? 202 : 400).json(result);\n } catch (e: any) {\n res.status(500).json({ code: 'internal', message: e?.message || 'Internal error' });\n }\n });\n\n router.get('/shamir/key-info', async (_req: any, res: any) => {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n return res.status(503).json({ error: 'shamir_disabled', message: 'Shamir 3-pass is not configured on this server' });\n }\n try {\n const serverResponse = await handleGetShamirKeyInfo(shamir);\n Object.entries(serverResponse.headers).forEach(([k, v]) => res.set(k, v as any));\n res.status(serverResponse.status);\n res.send(JSON.parse(serverResponse.body));\n } catch (e: any) {\n res.status(500).json({ error: 'internal', details: e?.message });\n }\n });\n\n if (opts.healthz) {\n router.get('/healthz', async (_req: Request, res: Response) => {\n const shamir = service.shamirService;\n const shamirConfigured = Boolean(shamir && shamir.hasShamir());\n let currentKeyId: string | null = null;\n if (shamirConfigured && shamir) {\n try {\n const payload = JSON.parse((await handleGetShamirKeyInfo(shamir)).body) as { currentKeyId?: string };\n currentKeyId = payload.currentKeyId || null;\n } catch {}\n }\n\n const proverBaseUrl = service.emailRecovery?.getZkEmailProverBaseUrl?.() ?? null;\n const zkEmailConfigured = Boolean(proverBaseUrl);\n\n res.status(200).json({\n ok: true,\n // Backwards-compatible field (was previously top-level).\n currentKeyId,\n shamir: { configured: shamirConfigured, currentKeyId },\n zkEmail: { configured: zkEmailConfigured, proverBaseUrl },\n });\n });\n }\n\n if (opts.readyz) {\n router.get('/readyz', async (_req: Request, res: Response) => {\n const shamir = service.shamirService;\n const shamirConfigured = Boolean(shamir && shamir.hasShamir());\n\n let shamirReady: boolean | null = null;\n let shamirCurrentKeyId: string | null = null;\n let shamirError: string | undefined;\n if (shamirConfigured && shamir) {\n try {\n await shamir.ensureReady();\n shamirReady = true;\n const payload = JSON.parse((await handleGetShamirKeyInfo(shamir)).body) as { currentKeyId?: string };\n shamirCurrentKeyId = payload.currentKeyId || null;\n } catch (e: any) {\n shamirReady = false;\n shamirError = e?.message || String(e);\n }\n }\n\n const zk = service.emailRecovery\n ? await service.emailRecovery.checkZkEmailProverHealth()\n : { configured: false, baseUrl: null, healthy: null as boolean | null };\n\n const ok =\n (shamirConfigured ? shamirReady === true : true) &&\n (zk.configured ? zk.healthy === true : true);\n\n res.status(ok ? 200 : 503).json({\n ok,\n shamir: {\n configured: shamirConfigured,\n ready: shamirConfigured ? shamirReady : null,\n currentKeyId: shamirCurrentKeyId,\n error: shamirError,\n },\n zkEmail: zk,\n });\n });\n }\n\n // ROR manifest for Related Origin Requests (wallet-scoped credentials)\n const wellKnownPaths = ['/.well-known/webauthn', '/.well-known/webauthn/'];\n for (const p of wellKnownPaths) {\n router.get(p, async (_req: Request, res: Response) => {\n try {\n const origins = await service.getRorOrigins();\n res.set('Content-Type', 'application/json; charset=utf-8');\n // Short TTL + SWR so updates propagate while staying cache-friendly\n res.set('Cache-Control', 'max-age=60, stale-while-revalidate=600');\n res.status(200).send(JSON.stringify({ origins }));\n } catch (e: any) {\n res.status(200).json({ origins: [] });\n }\n });\n }\n\n return router;\n}\n\nexport interface KeyRotationCronOptions {\n enabled?: boolean;\n intervalMinutes?: number;\n maxGraceKeys?: number;\n logger?: RouterLogger | null;\n}\n\nexport function startKeyRotationCronjob(\n service: AuthService,\n opts: KeyRotationCronOptions = {},\n): { stop(): void } {\n const logger = normalizeRouterLogger(opts.logger);\n const enabled = Boolean(opts.enabled);\n const intervalMinutes = Math.max(1, Number(opts.intervalMinutes || 0) || 60);\n const maxGraceKeys = Math.max(0, Number(opts.maxGraceKeys ?? 0) || 0);\n\n let timer: any = null;\n let inFlight = false;\n\n const run = async () => {\n if (!enabled) return;\n if (inFlight) {\n logger.warn('[key-rotation-cron] previous rotation still running; skipping');\n return;\n }\n inFlight = true;\n try {\n const shamir = service.shamirService;\n if (!shamir || !shamir.hasShamir()) {\n logger.warn('[key-rotation-cron] Shamir not configured; skipping rotation');\n return;\n }\n\n const rotation = await shamir.rotateShamirServerKeypair();\n logger.info('[key-rotation-cron] rotated key', {\n newKeyId: rotation.newKeyId,\n previousKeyId: rotation.previousKeyId,\n graceKeyIds: rotation.graceKeyIds,\n });\n\n if (maxGraceKeys > 0) {\n const graceKeyIds = shamir.getGraceKeyIds();\n if (graceKeyIds.length > maxGraceKeys) {\n const toRemove = graceKeyIds.slice(0, graceKeyIds.length - maxGraceKeys);\n for (const keyId of toRemove) {\n try {\n const removed = await shamir.removeGraceKeyInternal(keyId, { persist: true });\n logger.info('[key-rotation-cron] pruned grace key', { keyId, removed });\n } catch (e: any) {\n logger.warn('[key-rotation-cron] failed to prune grace key', { keyId, error: e?.message || String(e) });\n }\n }\n }\n }\n } catch (e: any) {\n logger.error('[key-rotation-cron] rotation failed', { error: e?.message || String(e) });\n } finally {\n inFlight = false;\n }\n };\n\n if (enabled) {\n timer = setInterval(() => { void run(); }, intervalMinutes * 60_000);\n }\n\n return {\n stop() {\n if (timer) clearInterval(timer);\n timer = null;\n },\n };\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
 
2
2
  //#region src/core/defaultConfigs.ts
3
3
  const PASSKEY_MANAGER_DEFAULT_CONFIGS = {
4
- nearRpcUrl: "https://test.rpc.fastnear.com",
4
+ nearRpcUrl: "https://test.rpc.fastnear.com, https://rpc.testnet.near.org",
5
5
  nearNetwork: "testnet",
6
6
  contractId: "w3a-v1.testnet",
7
7
  nearExplorerUrl: "https://testnet.nearblocks.io",
@@ -1 +1 @@
1
- {"version":3,"file":"defaultConfigs.js","names":["PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs","DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts"],"sources":["../../../../../../src/core/defaultConfigs.ts"],"sourcesContent":["import type { EmailRecoveryContracts, TatchiConfigs, TatchiConfigsInput } from './types/tatchi';\n\n// Default SDK configs suitable for local dev.\n// Cross-origin wallet isolation is recommended; set iframeWallet in your app config when you have a dedicated origin.\n// Consumers can shallow-merge overrides by field.\n\nexport const PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs = {\n // You can provide a single URL or a comma-separated list for failover.\n // First URL is treated as primary, subsequent URLs are fallbacks.\n // nearRpcUrl: 'https://rpc.testnet.near.org',\n nearRpcUrl: 'https://test.rpc.fastnear.com',\n nearNetwork: 'testnet',\n contractId: 'w3a-v1.testnet',\n nearExplorerUrl: 'https://testnet.nearblocks.io',\n // Warm signing session defaults used by login/unlock flows.\n // Enforcement (TTL/uses) is owned by the VRF worker; signer workers remain one-shot.\n signingSessionDefaults: {\n ttlMs: 0, // 0 minutes\n remainingUses: 0, // default to requiring a touchID prompt for each transaction\n },\n relayer: {\n // accountId: 'w3a-v1.testnet',\n // No default relayer URL. Force apps to configure via env/overrides.\n // Using an empty string triggers early validation errors in code paths that require it.\n url: '',\n delegateActionRoute: '/signed-delegate',\n emailRecovery: {\n // Require at least 0.01 NEAR available to start email recovery.\n minBalanceYocto: '10000000000000000000000', // 0.01 NEAR\n // Poll every 4 seconds for verification status / access key.\n pollingIntervalMs: 4000,\n // Stop polling after 30 minutes.\n maxPollingDurationMs: 30 * 60 * 1000,\n // Expire pending recovery records after 30 minutes.\n pendingTtlMs: 30 * 60 * 1000,\n // Default recovery mailbox for examples / docs.\n mailtoAddress: 'recover@web3authn.org',\n // EmailDKIMVerifier contract that stores verification results.\n dkimVerifierAccountId: 'email-dkim-verifier-v1.testnet',\n // View method used to fetch VerificationResult by request_id.\n verificationViewMethod: 'get_verification_result',\n },\n },\n vrfWorkerConfigs: {\n shamir3pass: {\n // default Shamir's P in vrf-wasm-worker, needs to match relay server's Shamir P\n p: '3N5w46AIGjGT2v5Vua_TMD5Ywfa9U2F7-WzW8SNDsIM',\n // No default relay server URL to avoid accidental localhost usage in non-dev envs\n // Defaults to relayer.url when undefined\n relayServerUrl: '',\n applyServerLockRoute: '/vrf/apply-server-lock',\n removeServerLockRoute: '/vrf/remove-server-lock',\n }\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: 'w3a-email-recoverer-v1.testnet',\n zkEmailVerifierContract: 'zk-email-verifier-v1.testnet',\n emailDkimVerifierContract: 'email-dkim-verifier-v1.testnet',\n },\n // Configure iframeWallet in application code to point at your dedicated wallet origin when available.\n iframeWallet: {\n walletOrigin: 'https://wallet.example.localhost',\n walletServicePath: '/wallet-service',\n sdkBasePath: '/sdk',\n rpIdOverride: 'example.localhost',\n }\n};\n\nexport const DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts = {\n emailRecovererGlobalContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n zkEmailVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.zkEmailVerifierContract,\n emailDkimVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n};\n\n// Merge defaults with overrides\nexport function buildConfigsFromEnv(overrides: TatchiConfigsInput = {}): TatchiConfigs {\n\n const defaults = PASSKEY_MANAGER_DEFAULT_CONFIGS;\n const relayerUrl = overrides.relayer?.url ?? defaults.relayer?.url ?? '';\n // Prefer explicit override for relayer URL; fall back to default preset.\n // Used below to default VRF relayServerUrl when it is undefined.\n const relayServerUrlDefault = relayerUrl;\n\n const merged: TatchiConfigs = {\n nearRpcUrl: overrides.nearRpcUrl ?? defaults.nearRpcUrl,\n nearNetwork: overrides.nearNetwork ?? defaults.nearNetwork,\n contractId: overrides.contractId ?? defaults.contractId,\n nearExplorerUrl: overrides.nearExplorerUrl ?? defaults.nearExplorerUrl,\n walletTheme: overrides.walletTheme ?? defaults.walletTheme,\n signingSessionDefaults: {\n ttlMs: overrides.signingSessionDefaults?.ttlMs\n ?? defaults.signingSessionDefaults?.ttlMs,\n remainingUses: overrides.signingSessionDefaults?.remainingUses\n ?? defaults.signingSessionDefaults?.remainingUses,\n },\n relayer: {\n url: relayerUrl,\n delegateActionRoute: overrides.relayer?.delegateActionRoute\n ?? defaults.relayer?.delegateActionRoute,\n emailRecovery: {\n minBalanceYocto: overrides.relayer?.emailRecovery?.minBalanceYocto\n ?? defaults.relayer?.emailRecovery?.minBalanceYocto,\n pollingIntervalMs: overrides.relayer?.emailRecovery?.pollingIntervalMs\n ?? defaults.relayer?.emailRecovery?.pollingIntervalMs,\n maxPollingDurationMs: overrides.relayer?.emailRecovery?.maxPollingDurationMs\n ?? defaults.relayer?.emailRecovery?.maxPollingDurationMs,\n pendingTtlMs: overrides.relayer?.emailRecovery?.pendingTtlMs\n ?? defaults.relayer?.emailRecovery?.pendingTtlMs,\n mailtoAddress: overrides.relayer?.emailRecovery?.mailtoAddress\n ?? defaults.relayer?.emailRecovery?.mailtoAddress,\n dkimVerifierAccountId: overrides.relayer?.emailRecovery?.dkimVerifierAccountId\n ?? defaults.relayer?.emailRecovery?.dkimVerifierAccountId,\n verificationViewMethod: overrides.relayer?.emailRecovery?.verificationViewMethod\n ?? defaults.relayer?.emailRecovery?.verificationViewMethod,\n },\n },\n authenticatorOptions: overrides.authenticatorOptions ?? defaults.authenticatorOptions,\n vrfWorkerConfigs: {\n shamir3pass: {\n p: overrides.vrfWorkerConfigs?.shamir3pass?.p\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.p,\n relayServerUrl: overrides.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? relayServerUrlDefault,\n applyServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute,\n removeServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute,\n },\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: overrides.emailRecoveryContracts?.emailRecovererGlobalContract\n ?? defaults.emailRecoveryContracts?.emailRecovererGlobalContract,\n zkEmailVerifierContract: overrides.emailRecoveryContracts?.zkEmailVerifierContract\n ?? defaults.emailRecoveryContracts?.zkEmailVerifierContract,\n emailDkimVerifierContract: overrides.emailRecoveryContracts?.emailDkimVerifierContract\n ?? defaults.emailRecoveryContracts?.emailDkimVerifierContract,\n },\n iframeWallet: {\n walletOrigin: overrides.iframeWallet?.walletOrigin\n ?? defaults.iframeWallet?.walletOrigin,\n walletServicePath: overrides.iframeWallet?.walletServicePath\n ?? defaults.iframeWallet?.walletServicePath\n ?? '/wallet-service',\n sdkBasePath: overrides.iframeWallet?.sdkBasePath\n ?? defaults.iframeWallet?.sdkBasePath\n ?? '/sdk',\n rpIdOverride: overrides.iframeWallet?.rpIdOverride\n ?? defaults.iframeWallet?.rpIdOverride,\n }\n };\n if (!merged.contractId) {\n throw new Error('[configPresets] Missing required config: contractId');\n }\n if (!merged.relayer.url) {\n throw new Error('[configPresets] Missing required config: relayer.url');\n }\n return merged;\n}\n"],"mappings":";;AAMA,MAAaA,kCAAiD;CAI5D,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,iBAAiB;CAGjB,wBAAwB;EACtB,OAAO;EACP,eAAe;;CAEjB,SAAS;EAIP,KAAK;EACL,qBAAqB;EACrB,eAAe;GAEb,iBAAiB;GAEjB,mBAAmB;GAEnB,sBAAsB,OAAU;GAEhC,cAAc,OAAU;GAExB,eAAe;GAEf,uBAAuB;GAEvB,wBAAwB;;;CAG5B,kBAAkB,EAChB,aAAa;EAEX,GAAG;EAGH,gBAAgB;EAChB,sBAAsB;EACtB,uBAAuB;;CAG3B,wBAAwB;EACtB,8BAA8B;EAC9B,yBAAyB;EACzB,2BAA2B;;CAG7B,cAAc;EACZ,cAAc;EACd,mBAAmB;EACnB,aAAa;EACb,cAAc;;;AAIlB,MAAaC,mCAA2D;CACtE,8BAA8B,gCAAgC,uBAAuB;CACrF,yBAAyB,gCAAgC,uBAAuB;CAChF,2BAA2B,gCAAgC,uBAAuB"}
1
+ {"version":3,"file":"defaultConfigs.js","names":["PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs","DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts"],"sources":["../../../../../../src/core/defaultConfigs.ts"],"sourcesContent":["import type { EmailRecoveryContracts, TatchiConfigs, TatchiConfigsInput } from './types/tatchi';\n\n// Default SDK configs suitable for local dev.\n// Cross-origin wallet isolation is recommended; set iframeWallet in your app config when you have a dedicated origin.\n// Consumers can shallow-merge overrides by field.\n\nexport const PASSKEY_MANAGER_DEFAULT_CONFIGS: TatchiConfigs = {\n // You can provide a single URL or a comma-separated list for failover.\n // First URL is treated as primary, subsequent URLs are fallbacks.\n nearRpcUrl: 'https://test.rpc.fastnear.com, https://rpc.testnet.near.org',\n nearNetwork: 'testnet',\n contractId: 'w3a-v1.testnet',\n nearExplorerUrl: 'https://testnet.nearblocks.io',\n // Warm signing session defaults used by login/unlock flows.\n // Enforcement (TTL/uses) is owned by the VRF worker; signer workers remain one-shot.\n signingSessionDefaults: {\n ttlMs: 0, // 0 minutes\n remainingUses: 0, // default to requiring a touchID prompt for each transaction\n },\n relayer: {\n // accountId: 'w3a-v1.testnet',\n // No default relayer URL. Force apps to configure via env/overrides.\n // Using an empty string triggers early validation errors in code paths that require it.\n url: '',\n delegateActionRoute: '/signed-delegate',\n emailRecovery: {\n // Require at least 0.01 NEAR available to start email recovery.\n minBalanceYocto: '10000000000000000000000', // 0.01 NEAR\n // Poll every 4 seconds for verification status / access key.\n pollingIntervalMs: 4000,\n // Stop polling after 30 minutes.\n maxPollingDurationMs: 30 * 60 * 1000,\n // Expire pending recovery records after 30 minutes.\n pendingTtlMs: 30 * 60 * 1000,\n // Default recovery mailbox for examples / docs.\n mailtoAddress: 'recover@web3authn.org',\n // EmailDKIMVerifier contract that stores verification results.\n dkimVerifierAccountId: 'email-dkim-verifier-v1.testnet',\n // View method used to fetch VerificationResult by request_id.\n verificationViewMethod: 'get_verification_result',\n },\n },\n vrfWorkerConfigs: {\n shamir3pass: {\n // default Shamir's P in vrf-wasm-worker, needs to match relay server's Shamir P\n p: '3N5w46AIGjGT2v5Vua_TMD5Ywfa9U2F7-WzW8SNDsIM',\n // No default relay server URL to avoid accidental localhost usage in non-dev envs\n // Defaults to relayer.url when undefined\n relayServerUrl: '',\n applyServerLockRoute: '/vrf/apply-server-lock',\n removeServerLockRoute: '/vrf/remove-server-lock',\n }\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: 'w3a-email-recoverer-v1.testnet',\n zkEmailVerifierContract: 'zk-email-verifier-v1.testnet',\n emailDkimVerifierContract: 'email-dkim-verifier-v1.testnet',\n },\n // Configure iframeWallet in application code to point at your dedicated wallet origin when available.\n iframeWallet: {\n walletOrigin: 'https://wallet.example.localhost',\n walletServicePath: '/wallet-service',\n sdkBasePath: '/sdk',\n rpIdOverride: 'example.localhost',\n }\n};\n\nexport const DEFAULT_EMAIL_RECOVERY_CONTRACTS: EmailRecoveryContracts = {\n emailRecovererGlobalContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n zkEmailVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.zkEmailVerifierContract,\n emailDkimVerifierContract: PASSKEY_MANAGER_DEFAULT_CONFIGS.emailRecoveryContracts.emailDkimVerifierContract,\n};\n\n// Merge defaults with overrides\nexport function buildConfigsFromEnv(overrides: TatchiConfigsInput = {}): TatchiConfigs {\n\n const defaults = PASSKEY_MANAGER_DEFAULT_CONFIGS;\n const relayerUrl = overrides.relayer?.url ?? defaults.relayer?.url ?? '';\n // Prefer explicit override for relayer URL; fall back to default preset.\n // Used below to default VRF relayServerUrl when it is undefined.\n const relayServerUrlDefault = relayerUrl;\n\n const merged: TatchiConfigs = {\n nearRpcUrl: overrides.nearRpcUrl ?? defaults.nearRpcUrl,\n nearNetwork: overrides.nearNetwork ?? defaults.nearNetwork,\n contractId: overrides.contractId ?? defaults.contractId,\n nearExplorerUrl: overrides.nearExplorerUrl ?? defaults.nearExplorerUrl,\n walletTheme: overrides.walletTheme ?? defaults.walletTheme,\n signingSessionDefaults: {\n ttlMs: overrides.signingSessionDefaults?.ttlMs\n ?? defaults.signingSessionDefaults?.ttlMs,\n remainingUses: overrides.signingSessionDefaults?.remainingUses\n ?? defaults.signingSessionDefaults?.remainingUses,\n },\n relayer: {\n url: relayerUrl,\n delegateActionRoute: overrides.relayer?.delegateActionRoute\n ?? defaults.relayer?.delegateActionRoute,\n emailRecovery: {\n minBalanceYocto: overrides.relayer?.emailRecovery?.minBalanceYocto\n ?? defaults.relayer?.emailRecovery?.minBalanceYocto,\n pollingIntervalMs: overrides.relayer?.emailRecovery?.pollingIntervalMs\n ?? defaults.relayer?.emailRecovery?.pollingIntervalMs,\n maxPollingDurationMs: overrides.relayer?.emailRecovery?.maxPollingDurationMs\n ?? defaults.relayer?.emailRecovery?.maxPollingDurationMs,\n pendingTtlMs: overrides.relayer?.emailRecovery?.pendingTtlMs\n ?? defaults.relayer?.emailRecovery?.pendingTtlMs,\n mailtoAddress: overrides.relayer?.emailRecovery?.mailtoAddress\n ?? defaults.relayer?.emailRecovery?.mailtoAddress,\n dkimVerifierAccountId: overrides.relayer?.emailRecovery?.dkimVerifierAccountId\n ?? defaults.relayer?.emailRecovery?.dkimVerifierAccountId,\n verificationViewMethod: overrides.relayer?.emailRecovery?.verificationViewMethod\n ?? defaults.relayer?.emailRecovery?.verificationViewMethod,\n },\n },\n authenticatorOptions: overrides.authenticatorOptions ?? defaults.authenticatorOptions,\n vrfWorkerConfigs: {\n shamir3pass: {\n p: overrides.vrfWorkerConfigs?.shamir3pass?.p\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.p,\n relayServerUrl: overrides.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.relayServerUrl\n ?? relayServerUrlDefault,\n applyServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.applyServerLockRoute,\n removeServerLockRoute: overrides.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute\n ?? defaults.vrfWorkerConfigs?.shamir3pass?.removeServerLockRoute,\n },\n },\n emailRecoveryContracts: {\n emailRecovererGlobalContract: overrides.emailRecoveryContracts?.emailRecovererGlobalContract\n ?? defaults.emailRecoveryContracts?.emailRecovererGlobalContract,\n zkEmailVerifierContract: overrides.emailRecoveryContracts?.zkEmailVerifierContract\n ?? defaults.emailRecoveryContracts?.zkEmailVerifierContract,\n emailDkimVerifierContract: overrides.emailRecoveryContracts?.emailDkimVerifierContract\n ?? defaults.emailRecoveryContracts?.emailDkimVerifierContract,\n },\n iframeWallet: {\n walletOrigin: overrides.iframeWallet?.walletOrigin\n ?? defaults.iframeWallet?.walletOrigin,\n walletServicePath: overrides.iframeWallet?.walletServicePath\n ?? defaults.iframeWallet?.walletServicePath\n ?? '/wallet-service',\n sdkBasePath: overrides.iframeWallet?.sdkBasePath\n ?? defaults.iframeWallet?.sdkBasePath\n ?? '/sdk',\n rpIdOverride: overrides.iframeWallet?.rpIdOverride\n ?? defaults.iframeWallet?.rpIdOverride,\n }\n };\n if (!merged.contractId) {\n throw new Error('[configPresets] Missing required config: contractId');\n }\n if (!merged.relayer.url) {\n throw new Error('[configPresets] Missing required config: relayer.url');\n }\n return merged;\n}\n"],"mappings":";;AAMA,MAAaA,kCAAiD;CAG5D,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,iBAAiB;CAGjB,wBAAwB;EACtB,OAAO;EACP,eAAe;;CAEjB,SAAS;EAIP,KAAK;EACL,qBAAqB;EACrB,eAAe;GAEb,iBAAiB;GAEjB,mBAAmB;GAEnB,sBAAsB,OAAU;GAEhC,cAAc,OAAU;GAExB,eAAe;GAEf,uBAAuB;GAEvB,wBAAwB;;;CAG5B,kBAAkB,EAChB,aAAa;EAEX,GAAG;EAGH,gBAAgB;EAChB,sBAAsB;EACtB,uBAAuB;;CAG3B,wBAAwB;EACtB,8BAA8B;EAC9B,yBAAyB;EACzB,2BAA2B;;CAG7B,cAAc;EACZ,cAAc;EACd,mBAAmB;EACnB,aAAa;EACb,cAAc;;;AAIlB,MAAaC,mCAA2D;CACtE,8BAA8B,gCAAgC,uBAAuB;CACrF,yBAAyB,gCAAgC,uBAAuB;CAChF,2BAA2B,gCAAgC,uBAAuB"}
@@ -7,9 +7,19 @@ const require_errors = require('./errors.js');
7
7
  const require_deviceDetection = require('../react/deviceDetection.js');
8
8
 
9
9
  //#region src/utils/index.ts
10
- init_encoders();
11
- init_validation();
12
- init_errors();
10
+ var init_utils = require_rolldown_runtime.__esm({ "src/utils/index.ts": (() => {
11
+ init_encoders();
12
+ init_validation();
13
+ init_errors();
14
+ init_deviceDetection();
15
+ }) });
13
16
 
14
17
  //#endregion
18
+ init_utils();
19
+ Object.defineProperty(exports, 'init_utils', {
20
+ enumerable: true,
21
+ get: function () {
22
+ return init_utils;
23
+ }
24
+ });
15
25
  //# sourceMappingURL=index.js.map
@@ -5,11 +5,18 @@ import { IndexedDBManager, init_IndexedDBManager } from "../IndexedDBManager/ind
5
5
  init_accountIds();
6
6
  init_IndexedDBManager();
7
7
  const canonicalizeEmail = (email) => {
8
- let addr = email;
9
- const angleStart = email.indexOf("<");
10
- const angleEnd = email.indexOf(">");
11
- if (angleStart !== -1 && angleEnd > angleStart) addr = email.slice(angleStart + 1, angleEnd);
12
- return addr.trim().toLowerCase();
8
+ const raw = String(email || "").trim();
9
+ if (!raw) return "";
10
+ const withoutHeaderName = raw.replace(/^[a-z0-9-]+\s*:\s*/i, "").trim();
11
+ const emailRegex = /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)/;
12
+ const angleMatch = withoutHeaderName.match(/<([^>]+)>/);
13
+ const candidates = [angleMatch?.[1], withoutHeaderName].filter((v) => typeof v === "string" && v.length > 0);
14
+ for (const candidate of candidates) {
15
+ const cleaned = candidate.replace(/^mailto:\s*/i, "");
16
+ const match = cleaned.match(emailRegex);
17
+ if (match?.[1]) return match[1].trim().toLowerCase();
18
+ }
19
+ return withoutHeaderName.toLowerCase();
13
20
  };
14
21
  const bytesToHex = (bytes) => {
15
22
  const arr = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["hashed: number[][]","pairs: RecoveryEmailEntry[]"],"sources":["../../../../src/core/EmailRecovery/index.ts"],"sourcesContent":["import type { AccountId } from '../types/accountIds';\nimport { toAccountId } from '../types/accountIds';\nimport { IndexedDBManager, type RecoveryEmailRecord } from '../IndexedDBManager';\n\nexport type RecoveryEmailEntry = {\n hashHex: string;\n email: string;\n};\n\nexport { type RecoveryEmailRecord };\n\nexport const canonicalizeEmail = (email: string): string => {\n let addr = email;\n const angleStart = email.indexOf('<');\n const angleEnd = email.indexOf('>');\n if (angleStart !== -1 && angleEnd > angleStart) {\n addr = email.slice(angleStart + 1, angleEnd);\n }\n return addr.trim().toLowerCase();\n};\n\nexport const bytesToHex = (bytes: number[] | Uint8Array): string => {\n const arr = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);\n return `0x${Array.from(arr)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')}`;\n};\n\nasync function hashRecoveryEmails(emails: string[], accountId: AccountId): Promise<number[][]> {\n const encoder = new TextEncoder();\n const salt = (accountId || '').trim().toLowerCase();\n const normalized = (emails || [])\n .map(e => e.trim())\n .filter(e => e.length > 0);\n\n const hashed: number[][] = [];\n\n for (const email of normalized) {\n try {\n const canonicalEmail = canonicalizeEmail(email);\n const input = `${canonicalEmail}|${salt}`;\n const data = encoder.encode(input);\n const digest = await crypto.subtle.digest('SHA-256', data);\n const bytes = new Uint8Array(digest);\n hashed.push(Array.from(bytes));\n } catch {\n const bytes = encoder.encode(email.toLowerCase());\n hashed.push(Array.from(bytes));\n }\n }\n\n return hashed;\n}\n\n/**\n * Canonicalize and hash recovery emails for an account, and persist the mapping\n * (hashHex → canonical email) in IndexedDB on a best-effort basis.\n */\nexport async function prepareRecoveryEmails(nearAccountId: AccountId, recoveryEmails: string[]): Promise<{\n hashes: number[][];\n pairs: RecoveryEmailEntry[];\n}> {\n const accountId = toAccountId(nearAccountId);\n\n const trimmedEmails = (recoveryEmails || []).map(e => e.trim()).filter(e => e.length > 0);\n const canonicalEmails = trimmedEmails.map(canonicalizeEmail);\n const recoveryEmailHashes = await hashRecoveryEmails(recoveryEmails, accountId);\n\n const pairs: RecoveryEmailEntry[] = recoveryEmailHashes.map((hashBytes, idx) => ({\n hashHex: bytesToHex(hashBytes),\n email: canonicalEmails[idx],\n }));\n\n void (async () => {\n try {\n await IndexedDBManager.upsertRecoveryEmails(accountId, pairs);\n } catch (error) {\n console.warn('[EmailRecovery] Failed to persist local recovery emails', error);\n }\n })();\n\n return { hashes: recoveryEmailHashes, pairs };\n}\n\nexport async function getLocalRecoveryEmails(nearAccountId: AccountId): Promise<RecoveryEmailRecord[]> {\n return IndexedDBManager.getRecoveryEmails(nearAccountId);\n}\n"],"mappings":";;;;;;AAWA,MAAa,qBAAqB,UAA0B;CAC1D,IAAI,OAAO;CACX,MAAM,aAAa,MAAM,QAAQ;CACjC,MAAM,WAAW,MAAM,QAAQ;AAC/B,KAAI,eAAe,MAAM,WAAW,WAClC,QAAO,MAAM,MAAM,aAAa,GAAG;AAErC,QAAO,KAAK,OAAO;;AAGrB,MAAa,cAAc,UAAyC;CAClE,MAAM,MAAM,iBAAiB,aAAa,QAAQ,WAAW,KAAK;AAClE,QAAO,KAAK,MAAM,KAAK,KACpB,KAAI,MAAK,EAAE,SAAS,IAAI,SAAS,GAAG,MACpC,KAAK;;AAGV,eAAe,mBAAmB,QAAkB,WAA2C;CAC7F,MAAM,UAAU,IAAI;CACpB,MAAM,QAAQ,aAAa,IAAI,OAAO;CACtC,MAAM,cAAc,UAAU,IAC3B,KAAI,MAAK,EAAE,QACX,QAAO,MAAK,EAAE,SAAS;CAE1B,MAAMA,SAAqB;AAE3B,MAAK,MAAM,SAAS,WAClB,KAAI;EACF,MAAM,iBAAiB,kBAAkB;EACzC,MAAM,QAAQ,GAAG,eAAe,GAAG;EACnC,MAAM,OAAO,QAAQ,OAAO;EAC5B,MAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW;EACrD,MAAM,QAAQ,IAAI,WAAW;AAC7B,SAAO,KAAK,MAAM,KAAK;SACjB;EACN,MAAM,QAAQ,QAAQ,OAAO,MAAM;AACnC,SAAO,KAAK,MAAM,KAAK;;AAI3B,QAAO;;;;;;AAOT,eAAsB,sBAAsB,eAA0B,gBAGnE;CACD,MAAM,YAAY,YAAY;CAE9B,MAAM,iBAAiB,kBAAkB,IAAI,KAAI,MAAK,EAAE,QAAQ,QAAO,MAAK,EAAE,SAAS;CACvF,MAAM,kBAAkB,cAAc,IAAI;CAC1C,MAAM,sBAAsB,MAAM,mBAAmB,gBAAgB;CAErE,MAAMC,QAA8B,oBAAoB,KAAK,WAAW,SAAS;EAC/E,SAAS,WAAW;EACpB,OAAO,gBAAgB;;AAGzB,EAAM,YAAY;AAChB,MAAI;AACF,SAAM,iBAAiB,qBAAqB,WAAW;WAChD,OAAO;AACd,WAAQ,KAAK,2DAA2D;;;AAI5E,QAAO;EAAE,QAAQ;EAAqB;;;AAGxC,eAAsB,uBAAuB,eAA0D;AACrG,QAAO,iBAAiB,kBAAkB"}
1
+ {"version":3,"file":"index.js","names":["hashed: number[][]","pairs: RecoveryEmailEntry[]"],"sources":["../../../../src/core/EmailRecovery/index.ts"],"sourcesContent":["import type { AccountId } from '../types/accountIds';\nimport { toAccountId } from '../types/accountIds';\nimport { IndexedDBManager, type RecoveryEmailRecord } from '../IndexedDBManager';\n\nexport type RecoveryEmailEntry = {\n hashHex: string;\n email: string;\n};\n\nexport { type RecoveryEmailRecord };\n\nexport const canonicalizeEmail = (email: string): string => {\n const raw = String(email || '').trim();\n if (!raw) return '';\n\n // Handle cases where a full header line is passed in (e.g. \"From: ...\").\n const withoutHeaderName = raw.replace(/^[a-z0-9-]+\\s*:\\s*/i, '').trim();\n\n const emailRegex =\n /([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)/;\n\n // Prefer the common \"Name <email@domain>\" format when present, but still\n // validate/extract the actual address via regex.\n const angleMatch = withoutHeaderName.match(/<([^>]+)>/);\n const candidates = [\n angleMatch?.[1],\n withoutHeaderName,\n ].filter((v): v is string => typeof v === 'string' && v.length > 0);\n\n for (const candidate of candidates) {\n const cleaned = candidate.replace(/^mailto:\\s*/i, '');\n const match = cleaned.match(emailRegex);\n if (match?.[1]) {\n return match[1].trim().toLowerCase();\n }\n }\n\n return withoutHeaderName.toLowerCase();\n};\n\nexport const bytesToHex = (bytes: number[] | Uint8Array): string => {\n const arr = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);\n return `0x${Array.from(arr)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')}`;\n};\n\nasync function hashRecoveryEmails(emails: string[], accountId: AccountId): Promise<number[][]> {\n const encoder = new TextEncoder();\n const salt = (accountId || '').trim().toLowerCase();\n const normalized = (emails || [])\n .map(e => e.trim())\n .filter(e => e.length > 0);\n\n const hashed: number[][] = [];\n\n for (const email of normalized) {\n try {\n const canonicalEmail = canonicalizeEmail(email);\n const input = `${canonicalEmail}|${salt}`;\n const data = encoder.encode(input);\n const digest = await crypto.subtle.digest('SHA-256', data);\n const bytes = new Uint8Array(digest);\n hashed.push(Array.from(bytes));\n } catch {\n const bytes = encoder.encode(email.toLowerCase());\n hashed.push(Array.from(bytes));\n }\n }\n\n return hashed;\n}\n\n/**\n * Canonicalize and hash recovery emails for an account, and persist the mapping\n * (hashHex → canonical email) in IndexedDB on a best-effort basis.\n */\nexport async function prepareRecoveryEmails(nearAccountId: AccountId, recoveryEmails: string[]): Promise<{\n hashes: number[][];\n pairs: RecoveryEmailEntry[];\n}> {\n const accountId = toAccountId(nearAccountId);\n\n const trimmedEmails = (recoveryEmails || []).map(e => e.trim()).filter(e => e.length > 0);\n const canonicalEmails = trimmedEmails.map(canonicalizeEmail);\n const recoveryEmailHashes = await hashRecoveryEmails(recoveryEmails, accountId);\n\n const pairs: RecoveryEmailEntry[] = recoveryEmailHashes.map((hashBytes, idx) => ({\n hashHex: bytesToHex(hashBytes),\n email: canonicalEmails[idx],\n }));\n\n void (async () => {\n try {\n await IndexedDBManager.upsertRecoveryEmails(accountId, pairs);\n } catch (error) {\n console.warn('[EmailRecovery] Failed to persist local recovery emails', error);\n }\n })();\n\n return { hashes: recoveryEmailHashes, pairs };\n}\n\nexport async function getLocalRecoveryEmails(nearAccountId: AccountId): Promise<RecoveryEmailRecord[]> {\n return IndexedDBManager.getRecoveryEmails(nearAccountId);\n}\n"],"mappings":";;;;;;AAWA,MAAa,qBAAqB,UAA0B;CAC1D,MAAM,MAAM,OAAO,SAAS,IAAI;AAChC,KAAI,CAAC,IAAK,QAAO;CAGjB,MAAM,oBAAoB,IAAI,QAAQ,uBAAuB,IAAI;CAEjE,MAAM,aACJ;CAIF,MAAM,aAAa,kBAAkB,MAAM;CAC3C,MAAM,aAAa,CACjB,aAAa,IACb,mBACA,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS;AAEjE,MAAK,MAAM,aAAa,YAAY;EAClC,MAAM,UAAU,UAAU,QAAQ,gBAAgB;EAClD,MAAM,QAAQ,QAAQ,MAAM;AAC5B,MAAI,QAAQ,GACV,QAAO,MAAM,GAAG,OAAO;;AAI3B,QAAO,kBAAkB;;AAG3B,MAAa,cAAc,UAAyC;CAClE,MAAM,MAAM,iBAAiB,aAAa,QAAQ,WAAW,KAAK;AAClE,QAAO,KAAK,MAAM,KAAK,KACpB,KAAI,MAAK,EAAE,SAAS,IAAI,SAAS,GAAG,MACpC,KAAK;;AAGV,eAAe,mBAAmB,QAAkB,WAA2C;CAC7F,MAAM,UAAU,IAAI;CACpB,MAAM,QAAQ,aAAa,IAAI,OAAO;CACtC,MAAM,cAAc,UAAU,IAC3B,KAAI,MAAK,EAAE,QACX,QAAO,MAAK,EAAE,SAAS;CAE1B,MAAMA,SAAqB;AAE3B,MAAK,MAAM,SAAS,WAClB,KAAI;EACF,MAAM,iBAAiB,kBAAkB;EACzC,MAAM,QAAQ,GAAG,eAAe,GAAG;EACnC,MAAM,OAAO,QAAQ,OAAO;EAC5B,MAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW;EACrD,MAAM,QAAQ,IAAI,WAAW;AAC7B,SAAO,KAAK,MAAM,KAAK;SACjB;EACN,MAAM,QAAQ,QAAQ,OAAO,MAAM;AACnC,SAAO,KAAK,MAAM,KAAK;;AAI3B,QAAO;;;;;;AAOT,eAAsB,sBAAsB,eAA0B,gBAGnE;CACD,MAAM,YAAY,YAAY;CAE9B,MAAM,iBAAiB,kBAAkB,IAAI,KAAI,MAAK,EAAE,QAAQ,QAAO,MAAK,EAAE,SAAS;CACvF,MAAM,kBAAkB,cAAc,IAAI;CAC1C,MAAM,sBAAsB,MAAM,mBAAmB,gBAAgB;CAErE,MAAMC,QAA8B,oBAAoB,KAAK,WAAW,SAAS;EAC/E,SAAS,WAAW;EACpB,OAAO,gBAAgB;;AAGzB,EAAM,YAAY;AAChB,MAAI;AACF,SAAM,iBAAiB,qBAAqB,WAAW;WAChD,OAAO;AACd,WAAQ,KAAK,2DAA2D;;;AAI5E,QAAO;EAAE,QAAQ;EAAqB;;;AAGxC,eAAsB,uBAAuB,eAA0D;AACrG,QAAO,iBAAiB,kBAAkB"}
@@ -259,22 +259,17 @@ var init_passkeyClientDB = __esm({ "src/core/IndexedDBManager/passkeyClientDB.ts
259
259
  * @returns filtered authenticators for allowCredentials, plus optional wrongPasskeyError
260
260
  */
261
261
  async ensureCurrentPasskey(nearAccountId, authenticators, selectedCredentialRawId) {
262
- let authenticatorsForPrompt = authenticators;
263
- let wrongPasskeyError;
264
- if (authenticators.length > 1) {
265
- const accountIdNormalized = toAccountId(nearAccountId);
266
- const lastUser = await this.getLastUser().catch(() => null);
267
- const expectedAccountId = lastUser?.nearAccountId;
268
- const expectedDeviceNumber = lastUser?.deviceNumber;
269
- if (expectedAccountId && expectedDeviceNumber && expectedAccountId === accountIdNormalized) {
270
- const filtered = authenticators.filter((a) => a.deviceNumber === expectedDeviceNumber);
271
- if (filtered.length > 0) authenticatorsForPrompt = filtered;
272
- if (selectedCredentialRawId) {
273
- const matched = authenticators.find((a) => a.credentialId === selectedCredentialRawId);
274
- if (matched && matched.deviceNumber !== expectedDeviceNumber) wrongPasskeyError = `You have multiple passkeys (deviceNumbers) for account ${accountIdNormalized}, but used a passkey from a different device. Please use the passkey for the most recently logged-in device.`;
275
- }
276
- }
277
- }
262
+ if (authenticators.length <= 1) return { authenticatorsForPrompt: authenticators };
263
+ const accountIdNormalized = toAccountId(nearAccountId);
264
+ const lastUser = await this.getLastUser().catch(() => null);
265
+ if (!lastUser || lastUser.nearAccountId !== accountIdNormalized) return { authenticatorsForPrompt: authenticators };
266
+ const expectedDeviceNumber = lastUser.deviceNumber;
267
+ const byDeviceNumber = authenticators.filter((a) => a.deviceNumber === expectedDeviceNumber);
268
+ let expectedCredentialId = lastUser.passkeyCredential.rawId;
269
+ if (byDeviceNumber.length > 0 && !byDeviceNumber.some((a) => a.credentialId === expectedCredentialId)) expectedCredentialId = byDeviceNumber[0].credentialId;
270
+ const byCredentialId = authenticators.filter((a) => a.credentialId === expectedCredentialId);
271
+ const authenticatorsForPrompt = byCredentialId.length > 0 ? byCredentialId : byDeviceNumber.length > 0 ? byDeviceNumber : authenticators;
272
+ const wrongPasskeyError = selectedCredentialRawId && selectedCredentialRawId !== expectedCredentialId ? `You have multiple passkeys (deviceNumbers) for account ${accountIdNormalized}, but used a different passkey than the most recently logged-in one. Please use the passkey for the most recently logged-in device.` : void 0;
278
273
  return {
279
274
  authenticatorsForPrompt,
280
275
  wrongPasskeyError
@@ -385,30 +380,34 @@ var init_passkeyClientDB = __esm({ "src/core/IndexedDBManager/passkeyClientDB.ts
385
380
  * @param userData - User data with nearAccountId as primary identifier
386
381
  */
387
382
  async storeWebAuthnUserData(userData) {
388
- if (userData.deviceNumber === void 0) console.warn("WARNING: deviceNumber is undefined in storeWebAuthnUserData, will default to 1");
389
383
  const validation = this.validateNearAccountId(userData.nearAccountId);
390
384
  if (!validation.valid) throw new Error(`Cannot store WebAuthn data for invalid account ID: ${validation.error}`);
391
- let existingUser = await this.getUser(userData.nearAccountId);
392
- if (!existingUser) {
393
- const deviceNumberToUse = userData.deviceNumber || 1;
394
- existingUser = await this.registerUser({
395
- nearAccountId: userData.nearAccountId,
396
- deviceNumber: deviceNumberToUse,
397
- clientNearPublicKey: userData.clientNearPublicKey,
398
- passkeyCredential: userData.passkeyCredential,
399
- encryptedVrfKeypair: userData.encryptedVrfKeypair,
400
- version: userData.version || 2,
401
- serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair
402
- });
403
- }
404
- const finalDeviceNumber = userData.deviceNumber || existingUser.deviceNumber;
405
- await this.updateUser(userData.nearAccountId, {
385
+ const accountId = toAccountId(userData.nearAccountId);
386
+ const deviceNumber = userData.deviceNumber;
387
+ let user = await this.getUser(accountId, deviceNumber);
388
+ if (!user) user = await this.registerUser({
389
+ nearAccountId: accountId,
390
+ deviceNumber,
406
391
  clientNearPublicKey: userData.clientNearPublicKey,
392
+ passkeyCredential: userData.passkeyCredential,
407
393
  encryptedVrfKeypair: userData.encryptedVrfKeypair,
408
- serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair,
409
- version: userData.version || existingUser.version,
410
- deviceNumber: finalDeviceNumber,
411
- lastUpdated: userData.lastUpdated || Date.now()
394
+ version: userData.version || 2,
395
+ serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair
396
+ });
397
+ const updatedUser = {
398
+ ...user,
399
+ clientNearPublicKey: userData.clientNearPublicKey,
400
+ passkeyCredential: userData.passkeyCredential,
401
+ encryptedVrfKeypair: userData.encryptedVrfKeypair,
402
+ serverEncryptedVrfKeypair: userData.serverEncryptedVrfKeypair ?? user.serverEncryptedVrfKeypair,
403
+ version: userData.version ?? user.version,
404
+ lastUpdated: userData.lastUpdated ?? Date.now()
405
+ };
406
+ await this.storeUser(updatedUser);
407
+ this.emitEvent({
408
+ type: "user-updated",
409
+ accountId,
410
+ data: { updatedUser }
412
411
  });
413
412
  }
414
413
  async getAllUsers() {