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,152 @@
1
+ import { errorValues, standardErrorCodes } from "./constants.js";
2
+
3
+ const FALLBACK_MESSAGE = "Unspecified error message.";
4
+
5
+ const JSON_RPC_SERVER_ERROR_MESSAGE = "Unspecified server error.";
6
+
7
+ type ErrorValueKey = keyof typeof errorValues;
8
+
9
+ /**
10
+ * Gets the message for a given code, or a fallback message if the code has
11
+ * no corresponding message.
12
+ */
13
+ export function getMessageFromCode(
14
+ code: number | undefined,
15
+ fallbackMessage: string = FALLBACK_MESSAGE,
16
+ ): string {
17
+ if (code && Number.isInteger(code)) {
18
+ const codeString = code.toString();
19
+
20
+ if (hasKey(errorValues, codeString)) {
21
+ return errorValues[codeString as ErrorValueKey].message;
22
+ }
23
+ if (isJsonRpcServerError(code)) {
24
+ return JSON_RPC_SERVER_ERROR_MESSAGE;
25
+ }
26
+ }
27
+ return fallbackMessage;
28
+ }
29
+
30
+ /**
31
+ * Returns whether the given code is valid.
32
+ * A code is only valid if it has a message.
33
+ */
34
+ export function isValidCode(code: number): boolean {
35
+ if (!Number.isInteger(code)) {
36
+ return false;
37
+ }
38
+
39
+ const codeString = code.toString();
40
+ if (errorValues[codeString as ErrorValueKey]) {
41
+ return true;
42
+ }
43
+
44
+ if (isJsonRpcServerError(code)) {
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+
50
+ /**
51
+ * Returns the error code from an error object.
52
+ */
53
+ export function getErrorCode(error: unknown): number | undefined {
54
+ if (typeof error === "number") {
55
+ return error;
56
+ } else if (isErrorWithCode(error)) {
57
+ return error.code ?? error.errorCode;
58
+ }
59
+
60
+ return undefined;
61
+ }
62
+
63
+ interface ErrorWithCode {
64
+ code?: number;
65
+ errorCode?: number;
66
+ }
67
+
68
+ function isErrorWithCode(error: unknown): error is ErrorWithCode {
69
+ return (
70
+ typeof error === "object"
71
+ && error !== null
72
+ && (typeof (error as ErrorWithCode).code === "number"
73
+ || typeof (error as ErrorWithCode).errorCode === "number")
74
+ );
75
+ }
76
+
77
+ /**
78
+ * Serializes the given error to an Ethereum JSON RPC-compatible error object.
79
+ * Merely copies the given error's values if it is already compatible.
80
+ * If the given error is not fully compatible, it will be preserved on the
81
+ * returned object's data.originalError property.
82
+ */
83
+
84
+ export interface SerializedEthereumRpcError {
85
+ code: number; // must be an integer
86
+ message: string;
87
+ data?: unknown;
88
+ stack?: string;
89
+ }
90
+
91
+ export function serialize(
92
+ error: unknown,
93
+ { shouldIncludeStack = false } = {},
94
+ ): SerializedEthereumRpcError {
95
+ const serialized: Partial<SerializedEthereumRpcError> = {};
96
+
97
+ if (
98
+ error
99
+ && typeof error === "object"
100
+ && !Array.isArray(error)
101
+ && hasKey(error as Record<string, unknown>, "code")
102
+ && isValidCode((error as SerializedEthereumRpcError).code)
103
+ ) {
104
+ const _error = error as Partial<SerializedEthereumRpcError>;
105
+ serialized.code = _error.code;
106
+
107
+ if (_error.message && typeof _error.message === "string") {
108
+ serialized.message = _error.message;
109
+
110
+ if (hasKey(_error, "data")) {
111
+ serialized.data = _error.data;
112
+ }
113
+ } else {
114
+ serialized.message = getMessageFromCode((serialized as SerializedEthereumRpcError).code);
115
+
116
+ serialized.data = { originalError: assignOriginalError(error) };
117
+ }
118
+ } else {
119
+ serialized.code = standardErrorCodes.rpc.internal;
120
+
121
+ serialized.message = hasStringProperty(error, "message") ? error.message : FALLBACK_MESSAGE;
122
+ serialized.data = { originalError: assignOriginalError(error) };
123
+ }
124
+
125
+ if (shouldIncludeStack) {
126
+ serialized.stack = hasStringProperty(error, "stack") ? error.stack : undefined;
127
+ }
128
+ return serialized as SerializedEthereumRpcError;
129
+ }
130
+
131
+ // Internal
132
+
133
+ function isJsonRpcServerError(code: number): boolean {
134
+ return code >= -32099 && code <= -32000;
135
+ }
136
+
137
+ function assignOriginalError(error: unknown): unknown {
138
+ if (error && typeof error === "object" && !Array.isArray(error)) {
139
+ return Object.assign({}, error);
140
+ }
141
+ return error;
142
+ }
143
+
144
+ function hasKey(obj: Record<string, unknown>, key: string) {
145
+ return Object.prototype.hasOwnProperty.call(obj, key);
146
+ }
147
+
148
+ function hasStringProperty<T>(obj: unknown, prop: keyof T): obj is T {
149
+ return (
150
+ typeof obj === "object" && obj !== null && prop in obj && typeof (obj as T)[prop] === "string"
151
+ );
152
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export type { AppMetadata, ProviderInterface } from "./client-auth-server/interface.js";
2
+ export type { SessionPreferences } from "./client-auth-server/session.js";
3
+ export { WalletProvider, type WalletProviderConstructorOptions } from "./client-auth-server/WalletProvider.js";
@@ -0,0 +1,9 @@
1
+ import { type Address } from "viem";
2
+
3
+ export type ChainData = {
4
+ id: number;
5
+ capabilities: Record<string, unknown>;
6
+ contracts: {
7
+ session: Address; // Session, spend limit, etc.
8
+ };
9
+ };
@@ -0,0 +1,36 @@
1
+ import { type Address, encodeAbiParameters, encodeFunctionData, type Hash, type Hex, parseAbiParameters, toHex } from "viem";
2
+
3
+ import { SessionKeyModuleAbi } from "../abi/SessionKeyModule.js";
4
+ import type { SessionConfig } from "../utils/session.js";
5
+
6
+ export const encodeSession = (sessionConfig: SessionConfig) => {
7
+ const callData = encodeFunctionData({
8
+ abi: SessionKeyModuleAbi,
9
+ functionName: "createSession",
10
+ args: [sessionConfig],
11
+ });
12
+ const selector = callData.slice(0, "0x".length + 8) as Hex; // first 4 bytes for function selector
13
+ const args = `0x${callData.slice(selector.length, callData.length)}` as Hex; // the rest is the arguments
14
+ return args;
15
+ };
16
+
17
+ export const encodePasskeyModuleParameters = (passkey: { passkeyPublicKey: [Buffer, Buffer]; expectedOrigin: string }) => {
18
+ return encodeAbiParameters(
19
+ [
20
+ { type: "bytes32[2]", name: "xyPublicKeys" },
21
+ { type: "string", name: "expectedOrigin" },
22
+ ],
23
+ [
24
+ [toHex(passkey.passkeyPublicKey[0]), toHex(passkey.passkeyPublicKey[1])],
25
+ passkey.expectedOrigin,
26
+ ],
27
+ );
28
+ };
29
+
30
+ export const encodeModuleData = (moduleData: { address: Address; parameters: Hash }) => {
31
+ const moduleParams = parseAbiParameters("address, bytes");
32
+ return encodeAbiParameters(
33
+ moduleParams,
34
+ [moduleData.address, moduleData.parameters],
35
+ );
36
+ };
@@ -0,0 +1,43 @@
1
+ export function getWebsiteName(): string | null {
2
+ const fullTitle = document.title;
3
+ if (!fullTitle) return null;
4
+
5
+ const delimiters = [" - ", " | ", " : ", " · ", " — "];
6
+
7
+ // Find the first delimiter that splits the title
8
+ for (const delimiter of delimiters) {
9
+ const parts = fullTitle.split(delimiter);
10
+ if (parts.length > 1) {
11
+ return parts[0]!.trim();
12
+ }
13
+ }
14
+
15
+ return fullTitle.trim();
16
+ }
17
+
18
+ export function getFavicon(): string | null {
19
+ const el = document.querySelector(
20
+ "link[sizes=\"192x192\"], link[sizes=\"180x180\"], link[rel=\"icon\"], link[rel=\"shortcut icon\"]",
21
+ );
22
+ const href = el?.getAttribute("href");
23
+ if (!href) return null;
24
+
25
+ try {
26
+ const url = new URL(href, document.location.href);
27
+ // Make sure no malicious URLs are returned like "javascript:..."
28
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
29
+ return null;
30
+ }
31
+ return url.href;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ export function noThrow<T>(fn: () => T): T | null {
38
+ try {
39
+ return fn();
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./encoding.js";
2
+ export * from "./passkey.js";
3
+ export * from "./session.js";
@@ -0,0 +1,344 @@
1
+ import { ECDSASigValue } from "@peculiar/asn1-ecc";
2
+ import { AsnParser } from "@peculiar/asn1-schema";
3
+ import { bigintToBuf, bufToBigint } from "bigint-conversion";
4
+ import { Buffer } from "buffer";
5
+ import { type Address, encodeAbiParameters, type Hex, toHex } from "viem";
6
+
7
+ enum COSEKEYS {
8
+ kty = 1, // Key Type
9
+ alg = 3, // Algorithm
10
+ crv = -1, // Curve for EC keys
11
+ x = -2, // X coordinate for EC keys
12
+ y = -3, // Y coordinate for EC keys
13
+ }
14
+
15
+ type COSEPublicKeyMap = Map<COSEKEYS, number | Buffer>;
16
+
17
+ // Encode an integer in CBOR format
18
+ function encodeInt(int: number): Buffer {
19
+ if (int >= 0 && int <= 23) {
20
+ // Small positive integer (0–23)
21
+ return Buffer.from([int]);
22
+ } else if (int >= 24 && int <= 255) {
23
+ // 1-byte positive integer
24
+ return Buffer.from([0x18, int]);
25
+ } else if (int >= 256 && int <= 65535) {
26
+ // 2-byte positive integer
27
+ const buf = Buffer.alloc(3);
28
+ buf[0] = 0x19;
29
+ buf.writeUInt16BE(int, 1);
30
+ return buf;
31
+ } else if (int < 0 && int >= -24) {
32
+ // Small negative integer (-1 to -24)
33
+ return Buffer.from([0x20 - (int + 1)]);
34
+ } else if (int < -24 && int >= -256) {
35
+ // 1-byte negative integer
36
+ return Buffer.from([0x38, -int - 1]);
37
+ } else if (int < -256 && int >= -65536) {
38
+ // 2-byte negative integer
39
+ const buf = Buffer.alloc(3);
40
+ buf[0] = 0x39;
41
+ buf.writeUInt16BE(-int - 1, 1);
42
+ return buf;
43
+ } else {
44
+ throw new Error("Unsupported integer range");
45
+ }
46
+ }
47
+
48
+ // Encode a byte array in CBOR format
49
+ function encodeBytes(bytes: Buffer): Buffer {
50
+ if (bytes.length <= 23) {
51
+ return Buffer.concat([Buffer.from([0x40 + bytes.length]), bytes]); // Byte array with small length
52
+ } else if (bytes.length < 256) {
53
+ return Buffer.concat([Buffer.from([0x58, bytes.length]), bytes]); // Byte array with 1-byte length prefix
54
+ } else {
55
+ throw new Error("Unsupported byte array length");
56
+ }
57
+ }
58
+
59
+ // Encode a map in CBOR format
60
+ function encodeMap(map: COSEPublicKeyMap): Buffer {
61
+ const encodedItems: Buffer[] = [];
62
+
63
+ // CBOR map header, assuming the map size fits within small integer encoding
64
+ const mapHeader = 0xA0 | map.size;
65
+ encodedItems.push(Buffer.from([mapHeader]));
66
+
67
+ map.forEach((value, key) => {
68
+ // Encode the key
69
+ encodedItems.push(encodeInt(key));
70
+
71
+ // Encode the value based on its type (Buffer or number)
72
+ if (Buffer.isBuffer(value)) {
73
+ encodedItems.push(encodeBytes(value));
74
+ } else {
75
+ encodedItems.push(encodeInt(value));
76
+ }
77
+ });
78
+
79
+ return Buffer.concat(encodedItems);
80
+ }
81
+
82
+ function decodeMap(buffer: Buffer): COSEPublicKeyMap {
83
+ const map = new Map<COSEKEYS, number | Buffer>();
84
+ let offset = 1; // Start after the map header
85
+
86
+ const mapHeader = buffer[0];
87
+ const mapSize = mapHeader & 0x1F; // Number of pairs
88
+
89
+ for (let i = 0; i < mapSize; i++) {
90
+ const [key, keyLength] = decodeInt(buffer, offset);
91
+ offset += keyLength;
92
+
93
+ const [value, valueLength] = decodeValue(buffer, offset);
94
+ offset += valueLength;
95
+
96
+ map.set(key as COSEKEYS, value);
97
+ }
98
+
99
+ return map;
100
+ }
101
+
102
+ function decodeInt(buffer: Buffer, offset: number): [number, number] {
103
+ const intByte = buffer[offset];
104
+
105
+ if (intByte < 24) {
106
+ // Small positive integer (0–23)
107
+ return [intByte, 1];
108
+ } else if (intByte === 0x18) {
109
+ // 1-byte unsigned integer
110
+ return [buffer[offset + 1], 2];
111
+ } else if (intByte === 0x19) {
112
+ // 2-byte unsigned integer
113
+ return [buffer.readUInt16BE(offset + 1), 3];
114
+ } else if (intByte >= 0x20 && intByte <= 0x37) {
115
+ // Small negative integer (-1 to -24)
116
+ return [-(intByte - 0x20) - 1, 1];
117
+ } else if (intByte === 0x38) {
118
+ // 1-byte negative integer
119
+ return [-1 - buffer[offset + 1], 2];
120
+ } else if (intByte === 0x39) {
121
+ // 2-byte negative integer
122
+ return [-1 - buffer.readUInt16BE(offset + 1), 3];
123
+ } else {
124
+ throw new Error("Unsupported integer format");
125
+ }
126
+ }
127
+
128
+ function decodeBytes(buffer: Buffer, offset: number): [Buffer, number] {
129
+ const lengthByte = buffer[offset];
130
+ if (lengthByte >= 0x40 && lengthByte <= 0x57) {
131
+ const length = lengthByte - 0x40;
132
+ return [buffer.slice(offset + 1, offset + 1 + length), length + 1];
133
+ } else if (lengthByte === 0x58) { // Byte array with 1-byte length prefix
134
+ const length = buffer[offset + 1];
135
+ return [buffer.slice(offset + 2, offset + 2 + length), length + 2];
136
+ } else {
137
+ throw new Error("Unsupported byte format");
138
+ }
139
+ }
140
+
141
+ function decodeValue(buffer: Buffer, offset: number): [number | Buffer, number] {
142
+ const type = buffer[offset];
143
+ if (type >= 0x40 && type <= 0x5F) { // Byte array
144
+ return decodeBytes(buffer, offset);
145
+ } else {
146
+ return decodeInt(buffer, offset);
147
+ }
148
+ }
149
+
150
+ export const getPublicKeyBytesFromPasskeySignature = (publicPasskey: Uint8Array): [Buffer, Buffer] => {
151
+ const cosePublicKey = decodeMap(Buffer.from(publicPasskey)); // Decodes CBOR-encoded COSE key
152
+ const x = cosePublicKey.get(COSEKEYS.x) as Buffer;
153
+ const y = cosePublicKey.get(COSEKEYS.y) as Buffer;
154
+
155
+ return [Buffer.from(x), Buffer.from(y)];
156
+ };
157
+
158
+ export const getPasskeySignatureFromPublicKeyBytes = (coordinates: [Hex, Hex]): Uint8Array => {
159
+ const [xHex, yHex] = coordinates;
160
+ const x = Buffer.from(xHex.slice(2), "hex");
161
+ const y = Buffer.from(yHex.slice(2), "hex");
162
+
163
+ const cosePublicKey: COSEPublicKeyMap = new Map();
164
+ cosePublicKey.set(COSEKEYS.kty, 2); // Type 2 for EC keys
165
+ cosePublicKey.set(COSEKEYS.alg, -7); // -7 for ES256 algorithm
166
+ cosePublicKey.set(COSEKEYS.crv, 1); // Curve ID (1 for P-256)
167
+ cosePublicKey.set(COSEKEYS.x, x);
168
+ cosePublicKey.set(COSEKEYS.y, y);
169
+
170
+ const encodedPublicKey = encodeMap(cosePublicKey);
171
+ return new Uint8Array(encodedPublicKey);
172
+ };
173
+
174
+ /**
175
+ * Return 2 32byte words for the R & S for the EC2 signature, 0 l-trimmed
176
+ * @param signature
177
+ * @returns r & s bytes sequentially
178
+ */
179
+ export function unwrapEC2Signature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {
180
+ const parsedSignature = AsnParser.parse(signature, ECDSASigValue);
181
+ let rBytes = new Uint8Array(parsedSignature.r);
182
+ let sBytes = new Uint8Array(parsedSignature.s);
183
+
184
+ if (shouldRemoveLeadingZero(rBytes)) {
185
+ rBytes = rBytes.slice(1);
186
+ }
187
+
188
+ if (shouldRemoveLeadingZero(sBytes)) {
189
+ sBytes = sBytes.slice(1);
190
+ }
191
+
192
+ return {
193
+ r: rBytes,
194
+ s: normalizeS(sBytes),
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Normalizes the 's' value of an ECDSA signature to prevent signature malleability.
200
+ *
201
+ * @param {Uint8Array} sBuf - The 's' value of the signature as a Uint8Array.
202
+ * @returns {Uint8Array} The normalized 's' value as a Uint8Array.
203
+ *
204
+ * @description
205
+ * This function implements the process of normalizing the 's' value in an ECDSA signature.
206
+ * It ensures that the 's' value is always in the lower half of the curve's order,
207
+ * which helps prevent signature malleability attacks.
208
+ *
209
+ * The function uses the curve order 'n' for secp256k1:
210
+ * n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
211
+ *
212
+ * If 's' is greater than half of 'n', it is subtracted from 'n' to get the lower value.
213
+ */
214
+ export function normalizeS(sBuf: Uint8Array): Uint8Array {
215
+ const n = BigInt("0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
216
+ const halfN = n / BigInt(2);
217
+ const sNumber: bigint = bufToBigint(sBuf);
218
+
219
+ if (sNumber / halfN) {
220
+ return new Uint8Array(bigintToBuf(n - sNumber));
221
+ } else {
222
+ return sBuf;
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Determine if the DER-specific `00` byte at the start of an ECDSA signature byte sequence
228
+ * should be removed based on the following logic:
229
+ *
230
+ * "If the leading byte is 0x0, and the the high order bit on the second byte is not set to 0,
231
+ * then remove the leading 0x0 byte"
232
+ */
233
+ function shouldRemoveLeadingZero(bytes: Uint8Array): boolean {
234
+ return bytes[0] === 0x0 && (bytes[1] & (1 << 7)) !== 0;
235
+ }
236
+
237
+ /**
238
+ * Decode from a Base64URL-encoded string to an ArrayBuffer. Best used when converting a
239
+ * credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
240
+ * excludeCredentials.
241
+ *
242
+ * @param buffer Value to decode from base64
243
+ * @param to (optional) The decoding to use, in case it's desirable to decode from base64 instead
244
+ */
245
+ export function base64UrlToUint8Array(base64urlString: string, isUrl: boolean = true): Uint8Array {
246
+ const _buffer = toArrayBuffer(base64urlString, isUrl);
247
+ return new Uint8Array(_buffer);
248
+ }
249
+
250
+ function toArrayBuffer(data: string, isUrl: boolean) {
251
+ const
252
+ // Regular base64 characters
253
+ chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
254
+
255
+ // Base64url characters
256
+ charsUrl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
257
+
258
+ genLookup = (target: string) => {
259
+ const lookupTemp = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);
260
+ const len = chars.length;
261
+ for (let i = 0; i < len; i++) {
262
+ lookupTemp[target.charCodeAt(i)] = i;
263
+ }
264
+ return lookupTemp;
265
+ },
266
+
267
+ // Use a lookup table to find the index.
268
+ lookup = genLookup(chars),
269
+ lookupUrl = genLookup(charsUrl);
270
+
271
+ const
272
+ len = data.length;
273
+ let bufferLength = data.length * 0.75,
274
+ i,
275
+ p = 0,
276
+ encoded1,
277
+ encoded2,
278
+ encoded3,
279
+ encoded4;
280
+
281
+ if (data[data.length - 1] === "=") {
282
+ bufferLength--;
283
+ if (data[data.length - 2] === "=") {
284
+ bufferLength--;
285
+ }
286
+ }
287
+
288
+ const
289
+ arraybuffer = new ArrayBuffer(bufferLength),
290
+ bytes = new Uint8Array(arraybuffer),
291
+ target = isUrl ? lookupUrl : lookup;
292
+
293
+ for (i = 0; i < len; i += 4) {
294
+ encoded1 = target[data.charCodeAt(i)];
295
+ encoded2 = target[data.charCodeAt(i + 1)];
296
+ encoded3 = target[data.charCodeAt(i + 2)];
297
+ encoded4 = target[data.charCodeAt(i + 3)];
298
+
299
+ bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
300
+ bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
301
+ bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
302
+ }
303
+
304
+ return arraybuffer;
305
+ };
306
+
307
+ export function passkeyHashSignatureResponseFormat(
308
+ passkeyResponse: {
309
+ authenticatorData: string;
310
+ clientDataJSON: string;
311
+ signature: string;
312
+ },
313
+ contracts: {
314
+ passkey: Address;
315
+ },
316
+ ) {
317
+ const signature = unwrapEC2Signature(base64UrlToUint8Array(passkeyResponse.signature));
318
+ const fatSignature = encodeAbiParameters(
319
+ [
320
+ { type: "bytes" }, // authData
321
+ { type: "bytes" }, // clientDataJson
322
+ { type: "bytes32[2]" }, // signature (two elements)
323
+ ],
324
+ [
325
+ toHex(base64UrlToUint8Array(passkeyResponse.authenticatorData)),
326
+ toHex(base64UrlToUint8Array(passkeyResponse.clientDataJSON)),
327
+ [toHex(signature.r), toHex(signature.s)],
328
+ ],
329
+ );
330
+ const fullFormattedSig = encodeAbiParameters(
331
+ [
332
+ { type: "bytes" }, // fat signature
333
+ { type: "address" }, // validator address
334
+ { type: "bytes[]" }, // validator data
335
+ ],
336
+ [
337
+ fatSignature,
338
+ contracts.passkey,
339
+ ["0x"], // FIXME: this is assuming there are no other hooks
340
+ ],
341
+ );
342
+
343
+ return fullFormattedSig;
344
+ }
@@ -0,0 +1,103 @@
1
+ import { type Address, type Hash } from "viem";
2
+
3
+ export enum LimitType {
4
+ Unlimited = 0,
5
+ Lifetime = 1,
6
+ Allowance = 2,
7
+ }
8
+
9
+ /**
10
+ * Limit is the value tracked either for a lifetime or a period on-chain
11
+ * @member limitType - Used to validate limit & period values (unlimited has no limit, lifetime has no period, allowance has both!)
12
+ * @member limit - The limit is exceeded if the tracked value is greater than this over the provided period
13
+ * @member period - The block.timestamp divisor for the limit to be enforced (eg: 60 for a minute, 86400 for a day, 604800 for a week, unset for lifetime)
14
+ */
15
+ export type Limit = {
16
+ limitType: LimitType;
17
+ limit: bigint;
18
+ period: bigint;
19
+ };
20
+
21
+ export const LimitUnlimited = {
22
+ limitType: LimitType.Unlimited,
23
+ limit: 0n,
24
+ period: 0n,
25
+ };
26
+
27
+ export const LimitZero = {
28
+ limitType: LimitType.Lifetime,
29
+ limit: 0n,
30
+ period: 0n,
31
+ };
32
+
33
+ /**
34
+ * Common logic operators to used combine multiple constraints
35
+ */
36
+ export enum ConstraintCondition {
37
+ Unconstrained = 0,
38
+ Equal = 1,
39
+ Greater = 2,
40
+ Less = 3,
41
+ GreaterEqual = 4,
42
+ LessEqual = 5,
43
+ NotEqual = 6,
44
+ }
45
+
46
+ /**
47
+ * Constraint allows performing logic checks on any binary word (bytes32) in the transaction.
48
+ * This can let you set spend limits against functions on specific contracts
49
+ * @member index - The location of the start of the data in the transaction. This is not the index of the constraint within the containing array!
50
+ * @member condition - The kind of check to perform (None, =, >, <, >=, <=, !=)
51
+ * @member refValue - The value to compare against (as bytes32)
52
+ * @member limit - The limit to enforce on the parsed value (from index)
53
+ */
54
+ export type Constraint = {
55
+ index: bigint;
56
+ condition: ConstraintCondition;
57
+ refValue: Hash;
58
+ limit: Limit;
59
+ };
60
+
61
+ /**
62
+ * CallPolicy is a policy for a specific contract (address/function) call.
63
+ * @member target - Only one policy per target per session (unique mapping)
64
+ * @member selector - Solidity function selector (the selector directly), also unique mapping with target
65
+ * @member maxValuePerUse - Will reject transaction if value is set above this amount (for transfer or call)
66
+ * @member valueLimit - If not set, unlimited. If a number or a limit without a period, converts to a lifetime value. Also rejects transactions that have cumulative value greater than what's set here
67
+ * @member constraints - Array of conditions with specific limits for performing range and logic checks (e.g. 5 > x >= 30) on the transaction data (not value!)
68
+ */
69
+ export type CallPolicy = {
70
+ target: Address;
71
+ valueLimit: Limit;
72
+ maxValuePerUse: bigint;
73
+ selector: Hash;
74
+ constraints: Constraint[];
75
+ };
76
+
77
+ /**
78
+ * Simplified CallPolicy for transactions with less than 4 bytes of data
79
+ * @member target - Only one policy per target per session (unique mapping from CallPolicies)
80
+ * @member maxValuePerUse - Will reject transaction if value is set above this amount
81
+ * @member valueLimit - Validated from value
82
+ */
83
+ export type TransferPolicy = {
84
+ target: Address;
85
+ maxValuePerUse: bigint;
86
+ valueLimit: Limit;
87
+ };
88
+
89
+ /**
90
+ * SessionConfig is a set of policies and metadata to validate a transaction
91
+ * @member signer - The address that signs the transaction (session public key)
92
+ * @member expiresAt - The block.timestamp at which the session is no longer valid
93
+ * @member feeLimit - The maximum fee that can be paid for the transaction (maxFeePerGas * gasLimit)
94
+ * @member callPolicies - Used to validate the transaction data, has complex calldata parsing logic
95
+ * @member transferPolicies - Used to validate the transaction value when there's no additional data
96
+ */
97
+ export type SessionConfig = {
98
+ signer: Address;
99
+ expiresAt: bigint;
100
+ feeLimit: Limit;
101
+ callPolicies: CallPolicy[];
102
+ transferPolicies: TransferPolicy[];
103
+ };