zksync-sso 0.0.0-beta.1

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 (300) hide show
  1. package/.gitignore +5 -0
  2. package/.lintstagedrc.js +5 -0
  3. package/.npmignore +10 -0
  4. package/README.md +3 -0
  5. package/dist/_cjs/abi/Factory.js +197 -0
  6. package/dist/_cjs/abi/Factory.js.map +1 -0
  7. package/dist/_cjs/abi/SessionKeyModule.js +1104 -0
  8. package/dist/_cjs/abi/SessionKeyModule.js.map +1 -0
  9. package/dist/_cjs/client/actions/account.js +140 -0
  10. package/dist/_cjs/client/actions/account.js.map +1 -0
  11. package/dist/_cjs/client/actions/index.js +19 -0
  12. package/dist/_cjs/client/actions/index.js.map +1 -0
  13. package/dist/_cjs/client/actions/passkey.js +122 -0
  14. package/dist/_cjs/client/actions/passkey.js.map +1 -0
  15. package/dist/_cjs/client/actions/session.js +40 -0
  16. package/dist/_cjs/client/actions/session.js.map +1 -0
  17. package/dist/_cjs/client/clients/passkey.js +46 -0
  18. package/dist/_cjs/client/clients/passkey.js.map +1 -0
  19. package/dist/_cjs/client/clients/session.js +48 -0
  20. package/dist/_cjs/client/clients/session.js.map +1 -0
  21. package/dist/_cjs/client/decorators/index.js +19 -0
  22. package/dist/_cjs/client/decorators/index.js.map +1 -0
  23. package/dist/_cjs/client/decorators/passkey.js +15 -0
  24. package/dist/_cjs/client/decorators/passkey.js.map +1 -0
  25. package/dist/_cjs/client/decorators/session.js +7 -0
  26. package/dist/_cjs/client/decorators/session.js.map +1 -0
  27. package/dist/_cjs/client/decorators/session_wallet.js +32 -0
  28. package/dist/_cjs/client/decorators/session_wallet.js.map +1 -0
  29. package/dist/_cjs/client/index.js +22 -0
  30. package/dist/_cjs/client/index.js.map +1 -0
  31. package/dist/_cjs/client/passkey.js +20 -0
  32. package/dist/_cjs/client/passkey.js.map +1 -0
  33. package/dist/_cjs/client/smart-account.js +45 -0
  34. package/dist/_cjs/client/smart-account.js.map +1 -0
  35. package/dist/_cjs/client/utils/assertEip712Transaction.js +44 -0
  36. package/dist/_cjs/client/utils/assertEip712Transaction.js.map +1 -0
  37. package/dist/_cjs/client/utils/getEip712Domain.js +57 -0
  38. package/dist/_cjs/client/utils/getEip712Domain.js.map +1 -0
  39. package/dist/_cjs/client/utils/isEip712Transaction.js +16 -0
  40. package/dist/_cjs/client/utils/isEip712Transaction.js.map +1 -0
  41. package/dist/_cjs/client-auth-server/Signer.js +264 -0
  42. package/dist/_cjs/client-auth-server/Signer.js.map +1 -0
  43. package/dist/_cjs/client-auth-server/WalletProvider.js +107 -0
  44. package/dist/_cjs/client-auth-server/WalletProvider.js.map +1 -0
  45. package/dist/_cjs/client-auth-server/index.js +20 -0
  46. package/dist/_cjs/client-auth-server/index.js.map +1 -0
  47. package/dist/_cjs/client-auth-server/interface.js +3 -0
  48. package/dist/_cjs/client-auth-server/interface.js.map +1 -0
  49. package/dist/_cjs/client-auth-server/rpc.js +3 -0
  50. package/dist/_cjs/client-auth-server/rpc.js.map +1 -0
  51. package/dist/_cjs/client-auth-server/session.js +90 -0
  52. package/dist/_cjs/client-auth-server/session.js.map +1 -0
  53. package/dist/_cjs/communicator/PopupCommunicator.js +138 -0
  54. package/dist/_cjs/communicator/PopupCommunicator.js.map +1 -0
  55. package/dist/_cjs/communicator/index.js +6 -0
  56. package/dist/_cjs/communicator/index.js.map +1 -0
  57. package/dist/_cjs/communicator/interface.js +3 -0
  58. package/dist/_cjs/communicator/interface.js.map +1 -0
  59. package/dist/_cjs/connector/index.js +148 -0
  60. package/dist/_cjs/connector/index.js.map +1 -0
  61. package/dist/_cjs/errors/constants.js +97 -0
  62. package/dist/_cjs/errors/constants.js.map +1 -0
  63. package/dist/_cjs/errors/errors.js +122 -0
  64. package/dist/_cjs/errors/errors.js.map +1 -0
  65. package/dist/_cjs/errors/index.js +10 -0
  66. package/dist/_cjs/errors/index.js.map +1 -0
  67. package/dist/_cjs/errors/serialize.js +63 -0
  68. package/dist/_cjs/errors/serialize.js.map +1 -0
  69. package/dist/_cjs/errors/utils.js +95 -0
  70. package/dist/_cjs/errors/utils.js.map +1 -0
  71. package/dist/_cjs/index.js +6 -0
  72. package/dist/_cjs/index.js.map +1 -0
  73. package/dist/_cjs/package.json +1 -0
  74. package/dist/_cjs/utils/encoding.js +32 -0
  75. package/dist/_cjs/utils/encoding.js.map +1 -0
  76. package/dist/_cjs/utils/helpers.js +43 -0
  77. package/dist/_cjs/utils/helpers.js.map +1 -0
  78. package/dist/_cjs/utils/index.js +20 -0
  79. package/dist/_cjs/utils/index.js.map +1 -0
  80. package/dist/_cjs/utils/passkey.js +243 -0
  81. package/dist/_cjs/utils/passkey.js.map +1 -0
  82. package/dist/_cjs/utils/session.js +30 -0
  83. package/dist/_cjs/utils/session.js.map +1 -0
  84. package/dist/_cjs/utils/storage.js +93 -0
  85. package/dist/_cjs/utils/storage.js.map +1 -0
  86. package/dist/_cjs/version.js +5 -0
  87. package/dist/_cjs/version.js.map +1 -0
  88. package/dist/_esm/abi/Factory.js +194 -0
  89. package/dist/_esm/abi/Factory.js.map +1 -0
  90. package/dist/_esm/abi/SessionKeyModule.js +1101 -0
  91. package/dist/_esm/abi/SessionKeyModule.js.map +1 -0
  92. package/dist/_esm/client/actions/account.js +137 -0
  93. package/dist/_esm/client/actions/account.js.map +1 -0
  94. package/dist/_esm/client/actions/index.js +3 -0
  95. package/dist/_esm/client/actions/index.js.map +1 -0
  96. package/dist/_esm/client/actions/passkey.js +121 -0
  97. package/dist/_esm/client/actions/passkey.js.map +1 -0
  98. package/dist/_esm/client/actions/session.js +36 -0
  99. package/dist/_esm/client/actions/session.js.map +1 -0
  100. package/dist/_esm/client/clients/passkey.js +43 -0
  101. package/dist/_esm/client/clients/passkey.js.map +1 -0
  102. package/dist/_esm/client/clients/session.js +45 -0
  103. package/dist/_esm/client/clients/session.js.map +1 -0
  104. package/dist/_esm/client/decorators/index.js +3 -0
  105. package/dist/_esm/client/decorators/index.js.map +1 -0
  106. package/dist/_esm/client/decorators/passkey.js +13 -0
  107. package/dist/_esm/client/decorators/passkey.js.map +1 -0
  108. package/dist/_esm/client/decorators/session.js +5 -0
  109. package/dist/_esm/client/decorators/session.js.map +1 -0
  110. package/dist/_esm/client/decorators/session_wallet.js +171 -0
  111. package/dist/_esm/client/decorators/session_wallet.js.map +1 -0
  112. package/dist/_esm/client/index.js +3 -0
  113. package/dist/_esm/client/index.js.map +1 -0
  114. package/dist/_esm/client/passkey.js +4 -0
  115. package/dist/_esm/client/passkey.js.map +1 -0
  116. package/dist/_esm/client/smart-account.js +46 -0
  117. package/dist/_esm/client/smart-account.js.map +1 -0
  118. package/dist/_esm/client/utils/assertEip712Transaction.js +39 -0
  119. package/dist/_esm/client/utils/assertEip712Transaction.js.map +1 -0
  120. package/dist/_esm/client/utils/getEip712Domain.js +57 -0
  121. package/dist/_esm/client/utils/getEip712Domain.js.map +1 -0
  122. package/dist/_esm/client/utils/isEip712Transaction.js +13 -0
  123. package/dist/_esm/client/utils/isEip712Transaction.js.map +1 -0
  124. package/dist/_esm/client-auth-server/Signer.js +262 -0
  125. package/dist/_esm/client-auth-server/Signer.js.map +1 -0
  126. package/dist/_esm/client-auth-server/WalletProvider.js +104 -0
  127. package/dist/_esm/client-auth-server/WalletProvider.js.map +1 -0
  128. package/dist/_esm/client-auth-server/index.js +4 -0
  129. package/dist/_esm/client-auth-server/index.js.map +1 -0
  130. package/dist/_esm/client-auth-server/interface.js +2 -0
  131. package/dist/_esm/client-auth-server/interface.js.map +1 -0
  132. package/dist/_esm/client-auth-server/rpc.js +2 -0
  133. package/dist/_esm/client-auth-server/rpc.js.map +1 -0
  134. package/dist/_esm/client-auth-server/session.js +91 -0
  135. package/dist/_esm/client-auth-server/session.js.map +1 -0
  136. package/dist/_esm/communicator/PopupCommunicator.js +136 -0
  137. package/dist/_esm/communicator/PopupCommunicator.js.map +1 -0
  138. package/dist/_esm/communicator/index.js +2 -0
  139. package/dist/_esm/communicator/index.js.map +1 -0
  140. package/dist/_esm/communicator/interface.js +2 -0
  141. package/dist/_esm/communicator/interface.js.map +1 -0
  142. package/dist/_esm/connector/index.js +146 -0
  143. package/dist/_esm/connector/index.js.map +1 -0
  144. package/dist/_esm/errors/constants.js +94 -0
  145. package/dist/_esm/errors/constants.js.map +1 -0
  146. package/dist/_esm/errors/errors.js +124 -0
  147. package/dist/_esm/errors/errors.js.map +1 -0
  148. package/dist/_esm/errors/index.js +4 -0
  149. package/dist/_esm/errors/index.js.map +1 -0
  150. package/dist/_esm/errors/serialize.js +69 -0
  151. package/dist/_esm/errors/serialize.js.map +1 -0
  152. package/dist/_esm/errors/utils.js +101 -0
  153. package/dist/_esm/errors/utils.js.map +1 -0
  154. package/dist/_esm/index.js +2 -0
  155. package/dist/_esm/index.js.map +1 -0
  156. package/dist/_esm/package.json +1 -0
  157. package/dist/_esm/utils/encoding.js +26 -0
  158. package/dist/_esm/utils/encoding.js.map +1 -0
  159. package/dist/_esm/utils/helpers.js +40 -0
  160. package/dist/_esm/utils/helpers.js.map +1 -0
  161. package/dist/_esm/utils/index.js +4 -0
  162. package/dist/_esm/utils/index.js.map +1 -0
  163. package/dist/_esm/utils/passkey.js +294 -0
  164. package/dist/_esm/utils/passkey.js.map +1 -0
  165. package/dist/_esm/utils/session.js +31 -0
  166. package/dist/_esm/utils/session.js.map +1 -0
  167. package/dist/_esm/utils/storage.js +89 -0
  168. package/dist/_esm/utils/storage.js.map +1 -0
  169. package/dist/_esm/version.js +2 -0
  170. package/dist/_esm/version.js.map +1 -0
  171. package/dist/_types/abi/Factory.d.ts +149 -0
  172. package/dist/_types/abi/Factory.d.ts.map +1 -0
  173. package/dist/_types/abi/SessionKeyModule.d.ts +846 -0
  174. package/dist/_types/abi/SessionKeyModule.d.ts.map +1 -0
  175. package/dist/_types/client/actions/account.d.ts +38 -0
  176. package/dist/_types/client/actions/account.d.ts.map +1 -0
  177. package/dist/_types/client/actions/index.d.ts +3 -0
  178. package/dist/_types/client/actions/index.d.ts.map +1 -0
  179. package/dist/_types/client/actions/passkey.d.ts +45 -0
  180. package/dist/_types/client/actions/passkey.d.ts.map +1 -0
  181. package/dist/_types/client/actions/session.d.ts +14 -0
  182. package/dist/_types/client/actions/session.d.ts.map +1 -0
  183. package/dist/_types/client/clients/passkey.d.ts +32 -0
  184. package/dist/_types/client/clients/passkey.d.ts.map +1 -0
  185. package/dist/_types/client/clients/session.d.ts +26 -0
  186. package/dist/_types/client/clients/session.d.ts.map +1 -0
  187. package/dist/_types/client/decorators/index.d.ts +3 -0
  188. package/dist/_types/client/decorators/index.d.ts.map +1 -0
  189. package/dist/_types/client/decorators/passkey.d.ts +8 -0
  190. package/dist/_types/client/decorators/passkey.d.ts.map +1 -0
  191. package/dist/_types/client/decorators/session.d.ts +5 -0
  192. package/dist/_types/client/decorators/session.d.ts.map +1 -0
  193. package/dist/_types/client/decorators/session_wallet.d.ts +5 -0
  194. package/dist/_types/client/decorators/session_wallet.d.ts.map +1 -0
  195. package/dist/_types/client/index.d.ts +3 -0
  196. package/dist/_types/client/index.d.ts.map +1 -0
  197. package/dist/_types/client/passkey.d.ts +4 -0
  198. package/dist/_types/client/passkey.d.ts.map +1 -0
  199. package/dist/_types/client/smart-account.d.ts +24 -0
  200. package/dist/_types/client/smart-account.d.ts.map +1 -0
  201. package/dist/_types/client/utils/assertEip712Transaction.d.ts +11 -0
  202. package/dist/_types/client/utils/assertEip712Transaction.d.ts.map +1 -0
  203. package/dist/_types/client/utils/getEip712Domain.d.ts +3 -0
  204. package/dist/_types/client/utils/getEip712Domain.d.ts.map +1 -0
  205. package/dist/_types/client/utils/isEip712Transaction.d.ts +4 -0
  206. package/dist/_types/client/utils/isEip712Transaction.d.ts.map +1 -0
  207. package/dist/_types/client-auth-server/Signer.d.ts +52 -0
  208. package/dist/_types/client-auth-server/Signer.d.ts.map +1 -0
  209. package/dist/_types/client-auth-server/WalletProvider.d.ts +27 -0
  210. package/dist/_types/client-auth-server/WalletProvider.d.ts.map +1 -0
  211. package/dist/_types/client-auth-server/index.d.ts +4 -0
  212. package/dist/_types/client-auth-server/index.d.ts.map +1 -0
  213. package/dist/_types/client-auth-server/interface.d.ts +34 -0
  214. package/dist/_types/client-auth-server/interface.d.ts.map +1 -0
  215. package/dist/_types/client-auth-server/rpc.d.ts +55 -0
  216. package/dist/_types/client-auth-server/rpc.d.ts.map +1 -0
  217. package/dist/_types/client-auth-server/session.d.ts +45 -0
  218. package/dist/_types/client-auth-server/session.d.ts.map +1 -0
  219. package/dist/_types/communicator/PopupCommunicator.d.ts +20 -0
  220. package/dist/_types/communicator/PopupCommunicator.d.ts.map +1 -0
  221. package/dist/_types/communicator/index.d.ts +3 -0
  222. package/dist/_types/communicator/index.d.ts.map +1 -0
  223. package/dist/_types/communicator/interface.d.ts +16 -0
  224. package/dist/_types/communicator/interface.d.ts.map +1 -0
  225. package/dist/_types/connector/index.d.ts +8 -0
  226. package/dist/_types/connector/index.d.ts.map +1 -0
  227. package/dist/_types/errors/constants.d.ts +96 -0
  228. package/dist/_types/errors/constants.d.ts.map +1 -0
  229. package/dist/_types/errors/errors.d.ts +48 -0
  230. package/dist/_types/errors/errors.d.ts.map +1 -0
  231. package/dist/_types/errors/index.d.ts +5 -0
  232. package/dist/_types/errors/index.d.ts.map +1 -0
  233. package/dist/_types/errors/serialize.d.ts +13 -0
  234. package/dist/_types/errors/serialize.d.ts.map +1 -0
  235. package/dist/_types/errors/utils.d.ts +30 -0
  236. package/dist/_types/errors/utils.d.ts.map +1 -0
  237. package/dist/_types/index.d.ts +4 -0
  238. package/dist/_types/index.d.ts.map +1 -0
  239. package/dist/_types/utils/encoding.d.ts +12 -0
  240. package/dist/_types/utils/encoding.d.ts.map +1 -0
  241. package/dist/_types/utils/helpers.d.ts +4 -0
  242. package/dist/_types/utils/helpers.d.ts.map +1 -0
  243. package/dist/_types/utils/index.d.ts +4 -0
  244. package/dist/_types/utils/index.d.ts.map +1 -0
  245. package/dist/_types/utils/passkey.d.ts +47 -0
  246. package/dist/_types/utils/passkey.d.ts.map +1 -0
  247. package/dist/_types/utils/session.d.ts +95 -0
  248. package/dist/_types/utils/session.d.ts.map +1 -0
  249. package/dist/_types/utils/storage.d.ts +30 -0
  250. package/dist/_types/utils/storage.d.ts.map +1 -0
  251. package/dist/_types/version.d.ts +2 -0
  252. package/dist/_types/version.d.ts.map +1 -0
  253. package/eslint.config.js +6 -0
  254. package/package.json +144 -0
  255. package/prepare-package.mjs +39 -0
  256. package/project.json +67 -0
  257. package/src/abi/Factory.ts +193 -0
  258. package/src/abi/SessionKeyModule.ts +1100 -0
  259. package/src/client/actions/account.ts +198 -0
  260. package/src/client/actions/index.ts +2 -0
  261. package/src/client/actions/passkey.ts +165 -0
  262. package/src/client/actions/session.ts +118 -0
  263. package/src/client/clients/passkey.ts +107 -0
  264. package/src/client/clients/session.ts +105 -0
  265. package/src/client/decorators/index.ts +2 -0
  266. package/src/client/decorators/passkey.ts +22 -0
  267. package/src/client/decorators/session.ts +17 -0
  268. package/src/client/decorators/session_wallet.ts +184 -0
  269. package/src/client/index.ts +2 -0
  270. package/src/client/passkey.ts +3 -0
  271. package/src/client/smart-account.ts +68 -0
  272. package/src/client/utils/assertEip712Transaction.ts +49 -0
  273. package/src/client/utils/getEip712Domain.ts +84 -0
  274. package/src/client/utils/isEip712Transaction.ts +18 -0
  275. package/src/client-auth-server/Signer.ts +260 -0
  276. package/src/client-auth-server/WalletProvider.ts +114 -0
  277. package/src/client-auth-server/index.ts +3 -0
  278. package/src/client-auth-server/interface.ts +39 -0
  279. package/src/client-auth-server/rpc.ts +69 -0
  280. package/src/client-auth-server/session.ts +139 -0
  281. package/src/communicator/PopupCommunicator.ts +111 -0
  282. package/src/communicator/index.ts +2 -0
  283. package/src/communicator/interface.ts +15 -0
  284. package/src/connector/index.ts +171 -0
  285. package/src/errors/constants.ts +119 -0
  286. package/src/errors/errors.ts +168 -0
  287. package/src/errors/index.ts +4 -0
  288. package/src/errors/serialize.ts +91 -0
  289. package/src/errors/utils.ts +152 -0
  290. package/src/index.ts +3 -0
  291. package/src/types/index.d.ts +9 -0
  292. package/src/utils/encoding.ts +36 -0
  293. package/src/utils/helpers.ts +43 -0
  294. package/src/utils/index.ts +3 -0
  295. package/src/utils/passkey.ts +344 -0
  296. package/src/utils/session.ts +103 -0
  297. package/src/utils/storage.ts +87 -0
  298. package/src/version.ts +1 -0
  299. package/tsconfig.base.json +44 -0
  300. package/tsconfig.json +11 -0
@@ -0,0 +1,198 @@
1
+ import { type Account, type Address, type Chain, type Client, getAddress, type Hash, type Hex, parseAbi, type Prettify, toHex, type TransactionReceipt, type Transport } from "viem";
2
+ import { readContract, waitForTransactionReceipt, writeContract } from "viem/actions";
3
+ import { getGeneralPaymasterInput } from "viem/zksync";
4
+
5
+ import { FactoryAbi } from "../../abi/Factory.js";
6
+ import { encodeModuleData, encodePasskeyModuleParameters, encodeSession } from "../../utils/encoding.js";
7
+ import { noThrow } from "../../utils/helpers.js";
8
+ import { getPasskeySignatureFromPublicKeyBytes, getPublicKeyBytesFromPasskeySignature } from "../../utils/passkey.js";
9
+ import type { SessionConfig } from "../../utils/session.js";
10
+
11
+ /* TODO: try to get rid of most of the contract params like passkey, session */
12
+ /* it should come from factory, not passed manually each time */
13
+ export type DeployAccountArgs = {
14
+ credentialPublicKey: Uint8Array; // Public key of the previously registered
15
+ paymasterAddress?: Address; // Paymaster used to pay the fees of creating accounts
16
+ paymasterInput?: Hex; // Input for paymaster (if provided)
17
+ expectedOrigin?: string; // Expected origin of the passkey
18
+ uniqueAccountId?: string; // Unique account ID, can be omitted if you don't need it
19
+ contracts: {
20
+ accountFactory: Address;
21
+ passkey: Address;
22
+ session: Address;
23
+ };
24
+ initialSession?: SessionConfig;
25
+ salt?: Uint8Array; // Random 32 bytes
26
+ onTransactionSent?: (hash: Hash) => void;
27
+ };
28
+ export type DeployAccountReturnType = {
29
+ address: Address;
30
+ transactionReceipt: TransactionReceipt;
31
+ };
32
+ export type FetchAccountArgs = {
33
+ uniqueAccountId?: string; // Unique account ID, can be omitted if you don't need it
34
+ expectedOrigin?: string; // Expected origin of the passkey
35
+ contracts: {
36
+ accountFactory: Address;
37
+ passkey: Address;
38
+ session: Address;
39
+ };
40
+ };
41
+ export type FetchAccountReturnType = {
42
+ username: string;
43
+ address: Address;
44
+ passkeyPublicKey: Uint8Array;
45
+ };
46
+
47
+ const NULL_ADDRESS = "0x0000000000000000000000000000000000000000";
48
+
49
+ export const deployAccount = async <
50
+ transport extends Transport,
51
+ chain extends Chain,
52
+ account extends Account,
53
+ >(
54
+ client: Client<transport, chain, account>, // Account deployer (any viem client)
55
+ args: Prettify<DeployAccountArgs>,
56
+ ): Promise<DeployAccountReturnType> => {
57
+ if (!args.salt) {
58
+ args.salt = crypto.getRandomValues(new Uint8Array(32));
59
+ }
60
+
61
+ let origin: string | undefined = args.expectedOrigin;
62
+ if (!origin) {
63
+ try {
64
+ origin = window.location.origin;
65
+ } catch {
66
+ throw new Error("Can't identify expectedOrigin, please provide it manually");
67
+ }
68
+ }
69
+
70
+ const passkeyPublicKey = getPublicKeyBytesFromPasskeySignature(args.credentialPublicKey);
71
+ const encodedPasskeyParameters = encodePasskeyModuleParameters({
72
+ passkeyPublicKey,
73
+ expectedOrigin: origin,
74
+ });
75
+ const encodedPasskeyModuleData = encodeModuleData({
76
+ address: args.contracts.passkey,
77
+ parameters: encodedPasskeyParameters,
78
+ });
79
+ const accountId = args.uniqueAccountId || encodedPasskeyParameters;
80
+
81
+ const encodedSessionKeyModuleData = encodeModuleData({
82
+ address: args.contracts.session,
83
+ parameters: args.initialSession == null ? "0x" : encodeSession(args.initialSession),
84
+ });
85
+
86
+ let deployProxyArgs = {
87
+ account: client.account!,
88
+ chain: client.chain!,
89
+ address: args.contracts.accountFactory,
90
+ abi: FactoryAbi,
91
+ functionName: "deployProxy7579Account",
92
+ args: [
93
+ toHex(args.salt),
94
+ accountId,
95
+ [encodedPasskeyModuleData],
96
+ [encodedSessionKeyModuleData],
97
+ [],
98
+ ],
99
+ } as any;
100
+
101
+ if (args.paymasterAddress) {
102
+ deployProxyArgs = {
103
+ ...deployProxyArgs,
104
+ paymaster: args.paymasterAddress,
105
+ paymasterInput: args.paymasterInput ?? getGeneralPaymasterInput({ innerInput: "0x" }),
106
+ };
107
+ }
108
+
109
+ const transactionHash = await writeContract(client, deployProxyArgs);
110
+ if (args.onTransactionSent) {
111
+ noThrow(() => args.onTransactionSent?.(transactionHash));
112
+ }
113
+
114
+ const transactionReceipt = await waitForTransactionReceipt(client, { hash: transactionHash });
115
+ if (transactionReceipt.status !== "success") throw new Error("Account deployment transaction reverted");
116
+
117
+ const proxyAccountAddress = transactionReceipt.contractAddress;
118
+ if (!proxyAccountAddress) {
119
+ throw new Error("No contract address in transaction receipt");
120
+ }
121
+
122
+ return {
123
+ address: getAddress(proxyAccountAddress),
124
+ transactionReceipt: transactionReceipt,
125
+ };
126
+ };
127
+
128
+ export const fetchAccount = async <
129
+ transport extends Transport,
130
+ chain extends Chain,
131
+ account extends Account,
132
+ >(
133
+ client: Client<transport, chain, account>, // Account deployer (any viem client)
134
+ args: Prettify<FetchAccountArgs>,
135
+ ): Promise<FetchAccountReturnType> => {
136
+ let origin: string | undefined = args.expectedOrigin;
137
+ if (!origin) {
138
+ try {
139
+ origin = window.location.origin;
140
+ } catch {
141
+ throw new Error("Can't identify expectedOrigin, please provide it manually");
142
+ }
143
+ }
144
+
145
+ if (!args.contracts.accountFactory) throw new Error("Account factory address is not set");
146
+ if (!args.contracts.passkey) throw new Error("Passkey module address is not set");
147
+
148
+ let username: string | undefined = args.uniqueAccountId;
149
+ if (!username) {
150
+ try {
151
+ const credential = await navigator.credentials.get({
152
+ publicKey: {
153
+ challenge: new Uint8Array(32),
154
+ userVerification: "discouraged",
155
+ },
156
+ }) as PublicKeyCredential | null;
157
+
158
+ if (!credential) throw new Error("No registered passkeys");
159
+ username = credential.id;
160
+ } catch {
161
+ throw new Error("Unable to retrieve passkey");
162
+ }
163
+ }
164
+
165
+ if (!username) throw new Error("No account found");
166
+
167
+ const accountAddress = await readContract(client, {
168
+ abi: parseAbi(["function accountMappings(string) view returns (address)"]),
169
+ address: args.contracts.accountFactory,
170
+ functionName: "accountMappings",
171
+ args: [username],
172
+ });
173
+
174
+ if (!accountAddress || accountAddress == NULL_ADDRESS) throw new Error(`No account found for username: ${username}`);
175
+
176
+ const lowerKeyHalfBytes = await readContract(client, {
177
+ abi: parseAbi(["function lowerKeyHalf(string,address) view returns (bytes32)"]),
178
+ address: args.contracts.passkey,
179
+ functionName: "lowerKeyHalf",
180
+ args: [origin, accountAddress],
181
+ });
182
+ const upperKeyHalfBytes = await readContract(client, {
183
+ abi: parseAbi(["function upperKeyHalf(string,address) view returns (bytes32)"]),
184
+ address: args.contracts.passkey,
185
+ functionName: "upperKeyHalf",
186
+ args: [origin, accountAddress],
187
+ });
188
+
189
+ if (!lowerKeyHalfBytes || !upperKeyHalfBytes) throw new Error(`Passkey credentials not found in on-chain module for passkey ${username}`);
190
+
191
+ const passkeyPublicKey = getPasskeySignatureFromPublicKeyBytes([lowerKeyHalfBytes, upperKeyHalfBytes]);
192
+
193
+ return {
194
+ username,
195
+ address: accountAddress,
196
+ passkeyPublicKey,
197
+ };
198
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./account.js";
2
+ export * from "./session.js";
@@ -0,0 +1,165 @@
1
+ import { startAuthentication, startRegistration } from "@simplewebauthn/browser";
2
+ import { generateAuthenticationOptions, type GenerateAuthenticationOptionsOpts, generateRegistrationOptions, type GenerateRegistrationOptionsOpts, type VerifiedRegistrationResponse, verifyAuthenticationResponse, verifyRegistrationResponse } from "@simplewebauthn/server";
3
+ import { type AuthenticationResponseJSON, type PublicKeyCredentialCreationOptionsJSON, type PublicKeyCredentialRequestOptionsJSON, type RegistrationResponseJSON } from "@simplewebauthn/types";
4
+ import { type Account, type Address, type Chain, type Client, type Hash, toBytes, type Transport } from "viem";
5
+ import { writeContract } from "viem/actions";
6
+
7
+ const identifyPasskeyParams = () => {
8
+ let rpName: string | undefined;
9
+ let rpID: string | undefined;
10
+ let origin: string | undefined;
11
+ try {
12
+ rpName = window.location.hostname;
13
+ rpID = window.location.hostname;
14
+ origin = window.location.origin;
15
+ } catch {
16
+ // ignore
17
+ }
18
+
19
+ return { rpName, rpID, origin };
20
+ };
21
+
22
+ // let pubKey: Uint8Array = new Uint8Array();
23
+ export type GeneratePasskeyRegistrationOptionsArgs = Partial<GenerateRegistrationOptionsOpts> & { userName: string; userDisplayName: string };
24
+ export type GeneratePasskeyRegistrationOptionsReturnType = PublicKeyCredentialCreationOptionsJSON;
25
+ export const generatePasskeyRegistrationOptions = async (args: GeneratePasskeyRegistrationOptionsArgs): Promise<GeneratePasskeyRegistrationOptionsReturnType> => {
26
+ let { rpName, rpID } = identifyPasskeyParams();
27
+ rpName = args.rpName || rpName;
28
+ rpID = args.rpID || rpID;
29
+ if (!rpName || !rpID) throw new Error("Can't set rpName and rpID automatically, please provide them manually in the arguments");
30
+
31
+ const defaultOptions: GenerateRegistrationOptionsOpts = {
32
+ rpName,
33
+ rpID,
34
+ userName: args.userName,
35
+ userDisplayName: args.userDisplayName,
36
+ // We want a stable id for the passkey
37
+ attestationType: "direct",
38
+ // Not preventing users from re-registering existing authenticators
39
+ excludeCredentials: [],
40
+ // See "Guiding use of authenticators via authenticatorSelection" below
41
+ authenticatorSelection: {
42
+ residentKey: "required",
43
+ },
44
+ };
45
+ const params: GenerateRegistrationOptionsOpts = Object.assign({}, defaultOptions, args);
46
+ const options = await generateRegistrationOptions(params);
47
+ options.pubKeyCredParams = options.pubKeyCredParams.filter(
48
+ (creds) => creds.alg == 1,
49
+ );
50
+
51
+ return options;
52
+ };
53
+
54
+ export type GeneratePasskeyAuthenticationOptionsArgs = Partial<GenerateAuthenticationOptionsOpts>;
55
+ export type GeneratePasskeyAuthenticationOptionsReturnType = PublicKeyCredentialRequestOptionsJSON;
56
+ export const generatePasskeyAuthenticationOptions = async (args: GeneratePasskeyAuthenticationOptionsArgs): Promise<GeneratePasskeyAuthenticationOptionsReturnType> => {
57
+ let { rpID } = identifyPasskeyParams();
58
+ rpID = args.rpID || rpID;
59
+ if (!rpID) throw new Error("Can't set rpID automatically, please provide them manually in the arguments");
60
+
61
+ const defaultOptions: GenerateAuthenticationOptionsOpts = {
62
+ rpID: rpID,
63
+ };
64
+ const params: GenerateAuthenticationOptionsOpts = Object.assign({}, defaultOptions, args);
65
+ const options = await generateAuthenticationOptions(params);
66
+ if ("pubKeyCredParams" in options) {
67
+ options.pubKeyCredParams = (
68
+ options.pubKeyCredParams as Array<{ alg: number; type: string }>
69
+ ).filter((creds) => creds.alg == -7);
70
+ }
71
+
72
+ return options;
73
+ };
74
+
75
+ export type RegisterNewPasskeyArgs = ({ passkeyRegistrationOptions: PublicKeyCredentialCreationOptionsJSON } | GeneratePasskeyRegistrationOptionsArgs) & { origin?: string };
76
+ export type RegisterNewPasskeyReturnType = {
77
+ passkeyRegistrationOptions: PublicKeyCredentialCreationOptionsJSON;
78
+ passkeyRegistrationResponse: RegistrationResponseJSON;
79
+ verificationResponse: VerifiedRegistrationResponse;
80
+ credentialPublicKey: Uint8Array;
81
+ credentialId: string;
82
+ };
83
+ export const registerNewPasskey = async (args: RegisterNewPasskeyArgs): Promise<RegisterNewPasskeyReturnType> => {
84
+ let { origin } = identifyPasskeyParams();
85
+ origin = args.origin || origin;
86
+ if (!origin) throw new Error("Can't set origin automatically, please provide it manually in the arguments");
87
+
88
+ const passkeyRegistrationOptions = "passkeyRegistrationOptions" in args ? args.passkeyRegistrationOptions : await generatePasskeyRegistrationOptions(args);
89
+ const registrationResponse: RegistrationResponseJSON = await startRegistration(passkeyRegistrationOptions);
90
+ const verification = await verifyRegistrationResponse({
91
+ response: registrationResponse,
92
+ expectedChallenge: passkeyRegistrationOptions.challenge,
93
+ expectedOrigin: origin,
94
+ });
95
+ if (!verification.verified || !verification.registrationInfo) throw new Error("Passkey validation failed");
96
+
97
+ return {
98
+ passkeyRegistrationOptions,
99
+ passkeyRegistrationResponse: registrationResponse,
100
+ verificationResponse: verification,
101
+ credentialPublicKey: verification.registrationInfo.credentialPublicKey,
102
+ credentialId: verification.registrationInfo.credentialID,
103
+ };
104
+ };
105
+
106
+ export type RequestPasskeyAuthenticationArgs = {
107
+ challenge: Hash; // Transaction hash to sign
108
+ credentialPublicKey: Uint8Array;
109
+ rpID?: string;
110
+ origin?: string;
111
+ };
112
+ export type RequestPasskeyAuthenticationReturnType = {
113
+ passkeyAuthenticationResponse: AuthenticationResponseJSON;
114
+ passkeyAuthenticationOptions: PublicKeyCredentialRequestOptionsJSON;
115
+ };
116
+ export const requestPasskeyAuthentication = async (args: RequestPasskeyAuthenticationArgs): Promise<RequestPasskeyAuthenticationReturnType> => {
117
+ const passkeyAuthenticationOptions = await generatePasskeyAuthenticationOptions({
118
+ challenge: toBytes(args.challenge),
119
+ });
120
+ const authenticationResponse: AuthenticationResponseJSON = await startAuthentication(passkeyAuthenticationOptions);
121
+
122
+ let { rpID, origin } = identifyPasskeyParams();
123
+ rpID = args.rpID || passkeyAuthenticationOptions.rpId || rpID;
124
+ origin = args.origin || origin;
125
+ if (!rpID || !origin) throw new Error("Can't set rpID and origin automatically, please provide them manually in the arguments");
126
+
127
+ const verification = await verifyAuthenticationResponse({
128
+ response: authenticationResponse,
129
+ expectedChallenge: passkeyAuthenticationOptions.challenge,
130
+ expectedOrigin: origin,
131
+ expectedRPID: rpID,
132
+ authenticator: {
133
+ credentialPublicKey: args.credentialPublicKey,
134
+ credentialID: authenticationResponse.id,
135
+ counter: 0, // TODO: figure out if this has to be dynamic
136
+ },
137
+ });
138
+ if (!verification.verified || !verification.authenticationInfo) throw new Error("Passkey validation failed");
139
+
140
+ return {
141
+ passkeyAuthenticationResponse: authenticationResponse,
142
+ passkeyAuthenticationOptions,
143
+ };
144
+ };
145
+
146
+ export type AddAccountOwnerPasskeyArgs = {
147
+ passkeyPublicKey: Uint8Array;
148
+ contracts: { session: Address };
149
+ };
150
+ export type AddAccountOwnerPasskeyReturnType = Hash;
151
+ export const addAccountOwnerPasskey = async <
152
+ transport extends Transport,
153
+ chain extends Chain,
154
+ account extends Account,
155
+ >(client: Client<transport, chain, account>, args: AddAccountOwnerPasskeyArgs): Promise<AddAccountOwnerPasskeyReturnType> => {
156
+ /* TODO: Implement set owner passkey */
157
+ const transactionHash = await writeContract(client, {
158
+ address: args.contracts.session,
159
+ args: [args.passkeyPublicKey],
160
+ abi: [] as const,
161
+ functionName: "USE_ACTUAL_METHOD_HERE",
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
+ } as any);
164
+ return transactionHash;
165
+ };
@@ -0,0 +1,118 @@
1
+ import { type Account, type Address, type Chain, type Client, encodeFunctionData, type Hash, type Prettify, type TransactionReceipt, type Transport } from "viem";
2
+ import { waitForTransactionReceipt } from "viem/actions";
3
+ import { getGeneralPaymasterInput, sendTransaction } from "viem/zksync";
4
+
5
+ import { SessionKeyModuleAbi } from "../../abi/SessionKeyModule.js";
6
+ import { noThrow } from "../../utils/helpers.js";
7
+ import type { SessionConfig } from "../../utils/session.js";
8
+
9
+ /* DO NOT USE THIS. USE FUNCTION FROM PASSKEY ACTIONS INSTEAD */
10
+ /* TODO: Remove */
11
+ /* export type RequestSessionArgs = Prettify<SessionPreferences & {
12
+ sessionKey?: Hash;
13
+ contracts: {
14
+ session: Address
15
+ }
16
+ }> & ({ passkeyRegistrationResponse: RegistrationResponseJSON } | { passkeyRegistrationOptions: GeneratePasskeyRegistrationOptionsArgs });
17
+ export type RequestSessionReturnType<chain extends Chain> = {
18
+ transactionReceipt: ExtractChainFormatterReturnType<chain, "transactionReceipt", TransactionReceipt>;
19
+ sessionKey: Hash;
20
+ }
21
+ export const requestSession = async <
22
+ transport extends Transport,
23
+ chain extends Chain,
24
+ account extends Account
25
+ >(client: Client<transport, chain, account>, args: RequestSessionArgs): Promise<RequestSessionReturnType<chain>> => {
26
+ const passkeyRegistrationResponse: RegistrationResponseJSON =
27
+ 'passkeyRegistrationResponse' in args
28
+ ? args.passkeyRegistrationResponse
29
+ : (await requestPasskeySignature(args.passkeyRegistrationOptions)).passkeyRegistrationResponse;
30
+
31
+ const sessionKey = args.sessionKey || generatePrivateKey();
32
+ const sessionKeyPublicAddress = publicKeyToAddress(sessionKey);
33
+ const transactionHash = await createSessionWithPasskey(client, {
34
+ sessionKeyPublicAddress,
35
+ passkeyRegistrationResponse,
36
+ contracts: args.contracts,
37
+ spendLimit: args.spendLimit,
38
+ validUntil: args.validUntil,
39
+ });
40
+ const receipt = await waitForTransactionReceipt(client, { hash: transactionHash });
41
+ if (receipt.status === "reverted") throw new Error("Transaction reverted");
42
+ return {
43
+ transactionReceipt: receipt,
44
+ sessionKey,
45
+ };
46
+ } */
47
+
48
+ /* DO NOT USE THIS. USE FUNCTION FROM PASSKEY ACTIONS INSTEAD */
49
+ /* TODO: Remove */
50
+ /* export type CreateSessionWithPasskeyArgs = Prettify<SessionPreferences & {
51
+ sessionKeyPublicAddress: Address;
52
+ passkeyRegistrationResponse: RegistrationResponseJSON;
53
+ contracts: { session: Address };
54
+ }>
55
+ export type CreateSessionWithPasskeyReturnType = Hash;
56
+ export const createSessionWithPasskey = async <
57
+ transport extends Transport,
58
+ chain extends Chain,
59
+ account extends Account,
60
+ >(client: Client<transport, chain, account>, args: CreateSessionWithPasskeyArgs): Promise<CreateSessionWithPasskeyReturnType> => {
61
+ // TODO: Implement set session
62
+ const transactionHash = await writeContract(client, {
63
+ address: args.contracts.session,
64
+ args: [args.sessionKeyPublicAddress, args.passkeyRegistrationResponse, args.spendLimit, args.validUntil],
65
+ abi: [] as const,
66
+ functionName: "USE_ACTUAL_METHOD_HERE2222",
67
+ } as any);
68
+ return transactionHash;
69
+ } */
70
+
71
+ export type CreateSessionArgs = {
72
+ sessionConfig: SessionConfig;
73
+ contracts: {
74
+ session: Address; // session module
75
+ };
76
+ onTransactionSent?: (hash: Hash) => void;
77
+ };
78
+ export type CreateSessionReturnType = {
79
+ transactionReceipt: TransactionReceipt;
80
+ };
81
+ export const createSession = async <
82
+ transport extends Transport,
83
+ chain extends Chain,
84
+ account extends Account,
85
+ >(client: Client<transport, chain, account>, args: Prettify<CreateSessionArgs>): Promise<Prettify<CreateSessionReturnType>> => {
86
+ const callData = encodeFunctionData({
87
+ abi: SessionKeyModuleAbi,
88
+ functionName: "createSession",
89
+ args: [args.sessionConfig],
90
+ });
91
+
92
+ let sendTransactionArgs = {
93
+ to: args.contracts.session,
94
+ data: callData,
95
+ gas: 10_000_000n, // TODO: Remove when gas estimation is fixed
96
+ } as any;
97
+
98
+ if ((client as any).paymasterAddress) {
99
+ sendTransactionArgs = {
100
+ ...sendTransactionArgs,
101
+ account: client.account,
102
+ paymaster: (client as any).paymasterAddress,
103
+ paymasterInput: (client as any).paymasterInput ?? getGeneralPaymasterInput({ innerInput: "0x" }),
104
+ };
105
+ }
106
+
107
+ const transactionHash = await sendTransaction(client, sendTransactionArgs);
108
+ if (args.onTransactionSent) {
109
+ noThrow(() => args.onTransactionSent?.(transactionHash));
110
+ }
111
+
112
+ const transactionReceipt = await waitForTransactionReceipt(client, { hash: transactionHash });
113
+ if (transactionReceipt.status !== "success") throw new Error("createSession transaction reverted");
114
+
115
+ return {
116
+ transactionReceipt,
117
+ };
118
+ };
@@ -0,0 +1,107 @@
1
+ import { type Account, type Address, type Chain, type Client, createClient, getAddress, type Hex, type Prettify, type PublicActions, publicActions, type PublicRpcSchema, type RpcSchema, type Transport, type WalletActions, walletActions, type WalletClientConfig, type WalletRpcSchema } from "viem";
2
+ import { eip712WalletActions } from "viem/zksync";
3
+
4
+ import { passkeyHashSignatureResponseFormat } from "../../utils/passkey.js";
5
+ import { requestPasskeyAuthentication } from "../actions/passkey.js";
6
+ import { type ZksyncSsoPasskeyActions, zksyncSsoPasskeyActions } from "../decorators/passkey.js";
7
+ import { toSmartAccount } from "../smart-account.js";
8
+
9
+ export function createZksyncPasskeyClient<
10
+ transport extends Transport,
11
+ chain extends Chain,
12
+ rpcSchema extends RpcSchema | undefined = undefined,
13
+ >(_parameters: ZksyncSsoPasskeyClientConfig<transport, chain, rpcSchema>): ZksyncSsoPasskeyClient<transport, chain, rpcSchema> {
14
+ type WalletClientParameters = typeof _parameters;
15
+ const parameters: WalletClientParameters & {
16
+ key: NonNullable<WalletClientParameters["key"]>;
17
+ name: NonNullable<WalletClientParameters["name"]>;
18
+ } = {
19
+ ..._parameters,
20
+ address: getAddress(_parameters.address),
21
+ key: _parameters.key || "wallet",
22
+ name: _parameters.name || "ZKsync SSO Passkey Client",
23
+ };
24
+
25
+ const account = toSmartAccount({
26
+ address: parameters.address,
27
+ sign: async ({ hash }) => {
28
+ const passkeySignature = await requestPasskeyAuthentication({
29
+ challenge: hash,
30
+ credentialPublicKey: parameters.credentialPublicKey,
31
+ });
32
+
33
+ return passkeyHashSignatureResponseFormat(passkeySignature.passkeyAuthenticationResponse.response, parameters.contracts);
34
+ },
35
+ });
36
+ const client = createClient<transport, chain, Account, rpcSchema>({
37
+ ...parameters,
38
+ account,
39
+ type: "walletClient",
40
+ })
41
+ .extend(() => ({
42
+ credentialPublicKey: parameters.credentialPublicKey,
43
+ userName: parameters.userName,
44
+ userDisplayName: parameters.userDisplayName,
45
+ contracts: parameters.contracts,
46
+ paymasterAddress: parameters.paymasterAddress,
47
+ paymasterInput: parameters.paymasterInput,
48
+ }))
49
+ .extend(publicActions)
50
+ .extend(walletActions)
51
+ .extend(eip712WalletActions())
52
+ .extend(zksyncSsoPasskeyActions);
53
+ return client;
54
+ }
55
+
56
+ export type PasskeyRequiredContracts = {
57
+ session: Address; // Session, spend limit, etc.
58
+ passkey: Address; // Validator for passkey signature
59
+ accountFactory?: Address; // For account creation
60
+ };
61
+ type ZksyncSsoPasskeyData = {
62
+ credentialPublicKey: Uint8Array; // Public key of the passkey
63
+ userName: string; // Basically unique user id (which is called `userName` in webauthn)
64
+ userDisplayName: string; // Also option required for webauthn
65
+ contracts: PasskeyRequiredContracts;
66
+ paymasterAddress?: Address;
67
+ paymasterInput?: Hex;
68
+ };
69
+
70
+ export type ClientWithZksyncSsoPasskeyData<
71
+ transport extends Transport = Transport,
72
+ chain extends Chain = Chain,
73
+ > = Client<transport, chain, Account> & ZksyncSsoPasskeyData;
74
+
75
+ export type ZksyncSsoPasskeyClient<
76
+ transport extends Transport = Transport,
77
+ chain extends Chain = Chain,
78
+ rpcSchema extends RpcSchema | undefined = undefined,
79
+ account extends Account = Account,
80
+ > = Prettify<
81
+ Client<
82
+ transport,
83
+ chain,
84
+ account,
85
+ rpcSchema extends RpcSchema
86
+ ? [...PublicRpcSchema, ...WalletRpcSchema, ...rpcSchema]
87
+ : [...PublicRpcSchema, ...WalletRpcSchema],
88
+ PublicActions<transport, chain, account> & WalletActions<chain, account> & ZksyncSsoPasskeyActions
89
+ > & ZksyncSsoPasskeyData
90
+ >;
91
+
92
+ export interface ZksyncSsoPasskeyClientConfig<
93
+ transport extends Transport = Transport,
94
+ chain extends Chain = Chain,
95
+ rpcSchema extends RpcSchema | undefined = undefined,
96
+ > extends Omit<WalletClientConfig<transport, chain, Account, rpcSchema>, "account"> {
97
+ chain: NonNullable<chain>;
98
+ address: Address;
99
+ credentialPublicKey: Uint8Array;
100
+ userName: string;
101
+ userDisplayName: string;
102
+ contracts: PasskeyRequiredContracts;
103
+ paymasterAddress?: Address;
104
+ paymasterInput?: Hex;
105
+ key?: string;
106
+ name?: string;
107
+ }