@0xsequence/wallet-primitives 0.0.0-20250520201059

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 (96) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +7 -0
  3. package/LICENSE +202 -0
  4. package/dist/address.d.ts +5 -0
  5. package/dist/address.d.ts.map +1 -0
  6. package/dist/address.js +7 -0
  7. package/dist/address.js.map +1 -0
  8. package/dist/attestation.d.ts +24 -0
  9. package/dist/attestation.d.ts.map +1 -0
  10. package/dist/attestation.js +77 -0
  11. package/dist/attestation.js.map +1 -0
  12. package/dist/config.d.ts +85 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +381 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/constants.d.ts +173 -0
  17. package/dist/constants.d.ts.map +1 -0
  18. package/dist/constants.js +31 -0
  19. package/dist/constants.js.map +1 -0
  20. package/dist/context.d.ts +9 -0
  21. package/dist/context.d.ts.map +1 -0
  22. package/dist/context.js +8 -0
  23. package/dist/context.js.map +1 -0
  24. package/dist/erc-6492.d.ts +19 -0
  25. package/dist/erc-6492.d.ts.map +1 -0
  26. package/dist/erc-6492.js +64 -0
  27. package/dist/erc-6492.js.map +1 -0
  28. package/dist/extensions/index.d.ts +9 -0
  29. package/dist/extensions/index.d.ts.map +1 -0
  30. package/dist/extensions/index.js +7 -0
  31. package/dist/extensions/index.js.map +1 -0
  32. package/dist/extensions/passkeys.d.ts +31 -0
  33. package/dist/extensions/passkeys.d.ts.map +1 -0
  34. package/dist/extensions/passkeys.js +224 -0
  35. package/dist/extensions/passkeys.js.map +1 -0
  36. package/dist/extensions/recovery.d.ts +310 -0
  37. package/dist/extensions/recovery.d.ts.map +1 -0
  38. package/dist/extensions/recovery.js +444 -0
  39. package/dist/extensions/recovery.js.map +1 -0
  40. package/dist/generic-tree.d.ts +14 -0
  41. package/dist/generic-tree.d.ts.map +1 -0
  42. package/dist/generic-tree.js +34 -0
  43. package/dist/generic-tree.js.map +1 -0
  44. package/dist/index.d.ts +16 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +16 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/network.d.ts +15 -0
  49. package/dist/network.d.ts.map +1 -0
  50. package/dist/network.js +24 -0
  51. package/dist/network.js.map +1 -0
  52. package/dist/payload.d.ts +108 -0
  53. package/dist/payload.d.ts.map +1 -0
  54. package/dist/payload.js +627 -0
  55. package/dist/payload.js.map +1 -0
  56. package/dist/permission.d.ts +73 -0
  57. package/dist/permission.d.ts.map +1 -0
  58. package/dist/permission.js +188 -0
  59. package/dist/permission.js.map +1 -0
  60. package/dist/session-config.d.ts +113 -0
  61. package/dist/session-config.d.ts.map +1 -0
  62. package/dist/session-config.js +554 -0
  63. package/dist/session-config.js.map +1 -0
  64. package/dist/session-signature.d.ts +24 -0
  65. package/dist/session-signature.d.ts.map +1 -0
  66. package/dist/session-signature.js +141 -0
  67. package/dist/session-signature.js.map +1 -0
  68. package/dist/signature.d.ts +108 -0
  69. package/dist/signature.d.ts.map +1 -0
  70. package/dist/signature.js +1079 -0
  71. package/dist/signature.js.map +1 -0
  72. package/dist/utils.d.ts +45 -0
  73. package/dist/utils.d.ts.map +1 -0
  74. package/dist/utils.js +100 -0
  75. package/dist/utils.js.map +1 -0
  76. package/eslint.config.mjs +4 -0
  77. package/package.json +27 -0
  78. package/src/address.ts +19 -0
  79. package/src/attestation.ts +114 -0
  80. package/src/config.ts +521 -0
  81. package/src/constants.ts +39 -0
  82. package/src/context.ts +16 -0
  83. package/src/erc-6492.ts +97 -0
  84. package/src/extensions/index.ts +14 -0
  85. package/src/extensions/passkeys.ts +283 -0
  86. package/src/extensions/recovery.ts +542 -0
  87. package/src/generic-tree.ts +55 -0
  88. package/src/index.ts +15 -0
  89. package/src/network.ts +37 -0
  90. package/src/payload.ts +825 -0
  91. package/src/permission.ts +252 -0
  92. package/src/session-config.ts +681 -0
  93. package/src/session-signature.ts +197 -0
  94. package/src/signature.ts +1398 -0
  95. package/src/utils.ts +114 -0
  96. package/tsconfig.json +10 -0
@@ -0,0 +1,14 @@
1
+ import { Address } from 'ox'
2
+
3
+ export type Extensions = {
4
+ passkeys: Address.Address
5
+ recovery: Address.Address
6
+ }
7
+
8
+ export const Dev1: Extensions = {
9
+ passkeys: '0x8f26281dB84C18aAeEa8a53F94c835393229d296',
10
+ recovery: '0xd98da48C4FF9c19742eA5856A277424557C863a6',
11
+ }
12
+
13
+ export * as Passkeys from './passkeys.js'
14
+ export * as Recovery from './recovery.js'
@@ -0,0 +1,283 @@
1
+ import { Bytes, Hex, WebAuthnP256 } from 'ox'
2
+ import * as GenericTree from '../generic-tree.js'
3
+
4
+ export type PasskeyMetadata = {
5
+ credentialId: string
6
+ }
7
+
8
+ export type PublicKey = {
9
+ requireUserVerification: boolean
10
+ x: Hex.Hex
11
+ y: Hex.Hex
12
+ metadata?: PasskeyMetadata | Hex.Hex
13
+ }
14
+
15
+ export function metadataTree(metadata: Required<PublicKey>['metadata']): GenericTree.Tree {
16
+ if (typeof metadata === 'object') {
17
+ return {
18
+ type: 'leaf',
19
+ value: Bytes.fromString(metadata.credentialId),
20
+ }
21
+ } else {
22
+ return metadata
23
+ }
24
+ }
25
+
26
+ export function metadataNode(metadata: Required<PublicKey>['metadata']): GenericTree.Node {
27
+ return GenericTree.hash(metadataTree(metadata))
28
+ }
29
+
30
+ export function toTree(publicKey: PublicKey): GenericTree.Tree {
31
+ const a = Hex.padLeft(publicKey.x, 32)
32
+ const b = Hex.padLeft(publicKey.y, 32)
33
+ const c = Hex.padLeft(publicKey.requireUserVerification ? '0x01' : '0x00', 32)
34
+
35
+ if (publicKey.metadata) {
36
+ return [
37
+ [a, b],
38
+ [c, metadataTree(publicKey.metadata)],
39
+ ]
40
+ } else {
41
+ return [
42
+ [a, b],
43
+ [c, Hex.padLeft('0x00', 32)],
44
+ ]
45
+ }
46
+ }
47
+
48
+ export function fromTree(tree: GenericTree.Tree): PublicKey {
49
+ if (!GenericTree.isBranch(tree) || tree.length !== 2) {
50
+ throw new Error('Invalid tree')
51
+ }
52
+ const [p1, p2] = tree
53
+ if (!GenericTree.isBranch(p1) || p1.length !== 2) {
54
+ throw new Error('Invalid tree for x,y')
55
+ }
56
+
57
+ const [x, y] = p1
58
+ if (!GenericTree.isNode(x)) {
59
+ throw new Error('Invalid x bytes')
60
+ }
61
+ if (!GenericTree.isNode(y)) {
62
+ throw new Error('Invalid y bytes')
63
+ }
64
+
65
+ let requireUserVerification = false
66
+ let metadata: PublicKey['metadata']
67
+
68
+ if (GenericTree.isBranch(p2)) {
69
+ if (p2.length !== 2) {
70
+ throw new Error('Invalid tree for c,metadata')
71
+ }
72
+
73
+ const [c, meta] = p2
74
+ if (!GenericTree.isNode(c) || c.length !== 32) {
75
+ throw new Error('Invalid c bytes')
76
+ }
77
+ const cBytes = Hex.toBytes(c)
78
+ requireUserVerification = cBytes[31] === 1
79
+
80
+ if (GenericTree.isBranch(meta)) {
81
+ if (meta.length !== 2) {
82
+ throw new Error('Invalid metadata tree')
83
+ }
84
+
85
+ const [credLeaf, sub] = meta
86
+ if (!GenericTree.isLeaf(credLeaf)) {
87
+ throw new Error('Invalid credentialId leaf')
88
+ }
89
+ const credentialId = new TextDecoder().decode(credLeaf.value)
90
+
91
+ if (!GenericTree.isBranch(sub) || sub.length !== 2) {
92
+ throw new Error('Invalid sub-branch for name and createdAt')
93
+ }
94
+
95
+ const [nameLeaf, createdAtLeaf] = sub
96
+ if (!GenericTree.isLeaf(nameLeaf) || !GenericTree.isLeaf(createdAtLeaf)) {
97
+ throw new Error('Invalid metadata leaves')
98
+ }
99
+
100
+ metadata = { credentialId }
101
+ } else if (GenericTree.isNode(meta) && meta.length === 32) {
102
+ metadata = meta
103
+ } else {
104
+ throw new Error('Invalid metadata node')
105
+ }
106
+ } else {
107
+ if (!GenericTree.isNode(p2) || p2.length !== 32) {
108
+ throw new Error('Invalid c bytes')
109
+ }
110
+ const p2Bytes = Hex.toBytes(p2)
111
+ requireUserVerification = p2Bytes[31] === 1
112
+ }
113
+
114
+ return { requireUserVerification, x, y, metadata }
115
+ }
116
+
117
+ export function rootFor(publicKey: PublicKey): Hex.Hex {
118
+ return GenericTree.hash(toTree(publicKey))
119
+ }
120
+
121
+ export type DecodedSignature = {
122
+ publicKey: PublicKey
123
+ r: Bytes.Bytes
124
+ s: Bytes.Bytes
125
+ authenticatorData: Bytes.Bytes
126
+ clientDataJSON: string
127
+ embedMetadata?: boolean
128
+ }
129
+
130
+ export function encode(decoded: DecodedSignature): Bytes.Bytes {
131
+ const challengeIndex = decoded.clientDataJSON.indexOf('"challenge"')
132
+ const typeIndex = decoded.clientDataJSON.indexOf('"type"')
133
+
134
+ const authDataSize = decoded.authenticatorData.length
135
+ const clientDataJSONSize = decoded.clientDataJSON.length
136
+
137
+ if (authDataSize > 65535) {
138
+ throw new Error('Authenticator data size is too large')
139
+ }
140
+ if (clientDataJSONSize > 65535) {
141
+ throw new Error('Client data JSON size is too large')
142
+ }
143
+
144
+ const bytesAuthDataSize = authDataSize <= 255 ? 1 : 2
145
+ const bytesClientDataJSONSize = clientDataJSONSize <= 255 ? 1 : 2
146
+ const bytesChallengeIndex = challengeIndex <= 255 ? 1 : 2
147
+ const bytesTypeIndex = typeIndex <= 255 ? 1 : 2
148
+
149
+ let flags = 0
150
+
151
+ flags |= decoded.publicKey.requireUserVerification ? 1 : 0 // 0x01 bit
152
+ flags |= (bytesAuthDataSize - 1) << 1 // 0x02 bit
153
+ flags |= (bytesClientDataJSONSize - 1) << 2 // 0x04 bit
154
+ flags |= (bytesChallengeIndex - 1) << 3 // 0x08 bit
155
+ flags |= (bytesTypeIndex - 1) << 4 // 0x10 bit
156
+
157
+ // Set metadata flag if metadata exists
158
+ if (decoded.embedMetadata) {
159
+ flags |= 1 << 6 // 0x40 bit
160
+ }
161
+
162
+ let result: Bytes.Bytes = Bytes.from([flags])
163
+
164
+ // Add metadata if it exists
165
+ if (decoded.embedMetadata) {
166
+ if (!decoded.publicKey.metadata) {
167
+ throw new Error('Metadata is not present in the public key')
168
+ }
169
+ result = Bytes.concat(result, Hex.toBytes(metadataNode(decoded.publicKey.metadata)))
170
+ }
171
+
172
+ result = Bytes.concat(result, Bytes.padLeft(Bytes.fromNumber(authDataSize), bytesAuthDataSize))
173
+ result = Bytes.concat(result, decoded.authenticatorData)
174
+
175
+ result = Bytes.concat(result, Bytes.padLeft(Bytes.fromNumber(decoded.clientDataJSON.length), bytesClientDataJSONSize))
176
+ result = Bytes.concat(result, Bytes.from(new TextEncoder().encode(decoded.clientDataJSON)))
177
+
178
+ result = Bytes.concat(result, Bytes.padLeft(Bytes.fromNumber(challengeIndex), bytesChallengeIndex))
179
+ result = Bytes.concat(result, Bytes.padLeft(Bytes.fromNumber(typeIndex), bytesTypeIndex))
180
+
181
+ result = Bytes.concat(result, Bytes.padLeft(decoded.r, 32))
182
+ result = Bytes.concat(result, Bytes.padLeft(decoded.s, 32))
183
+
184
+ result = Bytes.concat(result, Bytes.fromHex(decoded.publicKey.x))
185
+ result = Bytes.concat(result, Bytes.fromHex(decoded.publicKey.y))
186
+
187
+ return result
188
+ }
189
+
190
+ export function isValidSignature(challenge: Hex.Hex, decoded: DecodedSignature): boolean {
191
+ return WebAuthnP256.verify({
192
+ challenge,
193
+ publicKey: {
194
+ x: Hex.toBigInt(decoded.publicKey.x),
195
+ y: Hex.toBigInt(decoded.publicKey.y),
196
+ prefix: 4,
197
+ },
198
+ metadata: {
199
+ authenticatorData: Hex.fromBytes(decoded.authenticatorData),
200
+ challengeIndex: decoded.clientDataJSON.indexOf('"challenge"'),
201
+ clientDataJSON: decoded.clientDataJSON,
202
+ typeIndex: decoded.clientDataJSON.indexOf('"type"'),
203
+ userVerificationRequired: decoded.publicKey.requireUserVerification,
204
+ },
205
+ signature: {
206
+ r: Bytes.toBigInt(decoded.r),
207
+ s: Bytes.toBigInt(decoded.s),
208
+ },
209
+ })
210
+ }
211
+
212
+ export function decode(data: Bytes.Bytes): Required<DecodedSignature> & { challengeIndex: number; typeIndex: number } {
213
+ let offset = 0
214
+
215
+ const flags = data[0]
216
+ offset += 1
217
+
218
+ if (flags === undefined) {
219
+ throw new Error('Invalid flags')
220
+ }
221
+
222
+ const requireUserVerification = (flags & 0x01) !== 0x00
223
+ const bytesAuthDataSize = ((flags >> 1) & 0x01) + 1
224
+ const bytesClientDataJSONSize = ((flags >> 2) & 0x01) + 1
225
+ const bytesChallengeIndex = ((flags >> 3) & 0x01) + 1
226
+ const bytesTypeIndex = ((flags >> 4) & 0x01) + 1
227
+ const hasMetadata = ((flags >> 6) & 0x01) === 0x01
228
+
229
+ // Check if fallback to abi decode is needed
230
+ if ((flags & 0x20) !== 0) {
231
+ throw new Error('Fallback to abi decode is not supported in this implementation')
232
+ }
233
+
234
+ let metadata: Hex.Hex | undefined
235
+
236
+ // Read metadata if present
237
+ if (hasMetadata) {
238
+ const metadataBytes = Bytes.slice(data, offset, offset + 32)
239
+ metadata = Hex.fromBytes(metadataBytes)
240
+ offset += 32
241
+ }
242
+
243
+ const authDataSize = Bytes.toNumber(Bytes.slice(data, offset, offset + bytesAuthDataSize))
244
+ offset += bytesAuthDataSize
245
+ const authenticatorData = Bytes.slice(data, offset, offset + authDataSize)
246
+ offset += authDataSize
247
+
248
+ const clientDataJSONSize = Bytes.toNumber(Bytes.slice(data, offset, offset + bytesClientDataJSONSize))
249
+ offset += bytesClientDataJSONSize
250
+ const clientDataJSONBytes = Bytes.slice(data, offset, offset + clientDataJSONSize)
251
+ offset += clientDataJSONSize
252
+ const clientDataJSON = new TextDecoder().decode(clientDataJSONBytes)
253
+
254
+ const challengeIndex = Bytes.toNumber(Bytes.slice(data, offset, offset + bytesChallengeIndex))
255
+ offset += bytesChallengeIndex
256
+ const typeIndex = Bytes.toNumber(Bytes.slice(data, offset, offset + bytesTypeIndex))
257
+ offset += bytesTypeIndex
258
+
259
+ const r = Bytes.slice(data, offset, offset + 32)
260
+ offset += 32
261
+ const s = Bytes.slice(data, offset, offset + 32)
262
+ offset += 32
263
+
264
+ const xBytes = Bytes.slice(data, offset, offset + 32)
265
+ offset += 32
266
+ const yBytes = Bytes.slice(data, offset, offset + 32)
267
+
268
+ return {
269
+ publicKey: {
270
+ requireUserVerification,
271
+ x: Hex.fromBytes(xBytes),
272
+ y: Hex.fromBytes(yBytes),
273
+ metadata,
274
+ },
275
+ r,
276
+ s,
277
+ authenticatorData,
278
+ clientDataJSON,
279
+ challengeIndex,
280
+ typeIndex,
281
+ embedMetadata: hasMetadata,
282
+ }
283
+ }