ox 0.9.16 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +4 -4
  3. package/TxEnvelope/package.json +6 -0
  4. package/TxEnvelopeEip1559/package.json +6 -0
  5. package/TxEnvelopeEip2930/package.json +6 -0
  6. package/TxEnvelopeEip4844/package.json +6 -0
  7. package/TxEnvelopeEip7702/package.json +6 -0
  8. package/TxEnvelopeLegacy/package.json +6 -0
  9. package/_cjs/core/{TransactionEnvelope.js → TxEnvelope.js} +1 -1
  10. package/_cjs/core/TxEnvelope.js.map +1 -0
  11. package/_cjs/core/{TransactionEnvelopeEip1559.js → TxEnvelopeEip1559.js} +2 -2
  12. package/_cjs/core/TxEnvelopeEip1559.js.map +1 -0
  13. package/_cjs/core/{TransactionEnvelopeEip2930.js → TxEnvelopeEip2930.js} +2 -2
  14. package/_cjs/core/TxEnvelopeEip2930.js.map +1 -0
  15. package/_cjs/core/{TransactionEnvelopeEip4844.js → TxEnvelopeEip4844.js} +4 -4
  16. package/_cjs/core/TxEnvelopeEip4844.js.map +1 -0
  17. package/_cjs/core/{TransactionEnvelopeEip7702.js → TxEnvelopeEip7702.js} +4 -4
  18. package/_cjs/core/TxEnvelopeEip7702.js.map +1 -0
  19. package/_cjs/core/{TransactionEnvelopeLegacy.js → TxEnvelopeLegacy.js} +2 -2
  20. package/_cjs/core/TxEnvelopeLegacy.js.map +1 -0
  21. package/_cjs/core/WebAuthnP256.js +1 -1
  22. package/_cjs/core/WebAuthnP256.js.map +1 -1
  23. package/_cjs/erc8021/Attribution.js +36 -6
  24. package/_cjs/erc8021/Attribution.js.map +1 -1
  25. package/_cjs/index.docs.js +1 -0
  26. package/_cjs/index.docs.js.map +1 -1
  27. package/_cjs/index.js +7 -7
  28. package/_cjs/index.js.map +1 -1
  29. package/_cjs/tempo/AuthorizationTempo.js +101 -0
  30. package/_cjs/tempo/AuthorizationTempo.js.map +1 -0
  31. package/_cjs/tempo/KeyAuthorization.js +123 -0
  32. package/_cjs/tempo/KeyAuthorization.js.map +1 -0
  33. package/_cjs/tempo/PoolId.js +10 -0
  34. package/_cjs/tempo/PoolId.js.map +1 -0
  35. package/_cjs/tempo/SignatureEnvelope.js +394 -0
  36. package/_cjs/tempo/SignatureEnvelope.js.map +1 -0
  37. package/_cjs/tempo/Tick.js +77 -0
  38. package/_cjs/tempo/Tick.js.map +1 -0
  39. package/_cjs/tempo/TokenId.js +28 -0
  40. package/_cjs/tempo/TokenId.js.map +1 -0
  41. package/_cjs/tempo/TokenRole.js +26 -0
  42. package/_cjs/tempo/TokenRole.js.map +1 -0
  43. package/_cjs/tempo/Transaction.js +80 -0
  44. package/_cjs/tempo/Transaction.js.map +1 -0
  45. package/_cjs/tempo/TransactionReceipt.js +26 -0
  46. package/_cjs/tempo/TransactionReceipt.js.map +1 -0
  47. package/_cjs/tempo/TransactionRequest.js +53 -0
  48. package/_cjs/tempo/TransactionRequest.js.map +1 -0
  49. package/_cjs/tempo/TxEnvelopeTempo.js +267 -0
  50. package/_cjs/tempo/TxEnvelopeTempo.js.map +1 -0
  51. package/_cjs/tempo/index.js +15 -0
  52. package/_cjs/tempo/index.js.map +1 -0
  53. package/_cjs/version.js +1 -1
  54. package/_esm/core/Blobs.js +8 -8
  55. package/_esm/core/{TransactionEnvelope.js → TxEnvelope.js} +11 -11
  56. package/_esm/core/TxEnvelope.js.map +1 -0
  57. package/_esm/core/{TransactionEnvelopeEip1559.js → TxEnvelopeEip1559.js} +42 -42
  58. package/_esm/core/TxEnvelopeEip1559.js.map +1 -0
  59. package/_esm/core/{TransactionEnvelopeEip2930.js → TxEnvelopeEip2930.js} +43 -43
  60. package/_esm/core/TxEnvelopeEip2930.js.map +1 -0
  61. package/_esm/core/{TransactionEnvelopeEip4844.js → TxEnvelopeEip4844.js} +42 -42
  62. package/_esm/core/TxEnvelopeEip4844.js.map +1 -0
  63. package/_esm/core/{TransactionEnvelopeEip7702.js → TxEnvelopeEip7702.js} +40 -40
  64. package/_esm/core/TxEnvelopeEip7702.js.map +1 -0
  65. package/_esm/core/{TransactionEnvelopeLegacy.js → TxEnvelopeLegacy.js} +42 -42
  66. package/_esm/core/TxEnvelopeLegacy.js.map +1 -0
  67. package/_esm/core/WebAuthnP256.js +1 -1
  68. package/_esm/core/WebAuthnP256.js.map +1 -1
  69. package/_esm/erc8021/Attribution.js +58 -13
  70. package/_esm/erc8021/Attribution.js.map +1 -1
  71. package/_esm/index.docs.js +1 -0
  72. package/_esm/index.docs.js.map +1 -1
  73. package/_esm/index.js +192 -192
  74. package/_esm/index.js.map +1 -1
  75. package/_esm/tempo/AuthorizationTempo.js +664 -0
  76. package/_esm/tempo/AuthorizationTempo.js.map +1 -0
  77. package/_esm/tempo/KeyAuthorization.js +426 -0
  78. package/_esm/tempo/KeyAuthorization.js.map +1 -0
  79. package/_esm/tempo/PoolId.js +28 -0
  80. package/_esm/tempo/PoolId.js.map +1 -0
  81. package/_esm/tempo/SignatureEnvelope.js +660 -0
  82. package/_esm/tempo/SignatureEnvelope.js.map +1 -0
  83. package/_esm/tempo/Tick.js +147 -0
  84. package/_esm/tempo/Tick.js.map +1 -0
  85. package/_esm/tempo/TokenId.js +71 -0
  86. package/_esm/tempo/TokenId.js.map +1 -0
  87. package/_esm/tempo/TokenRole.js +40 -0
  88. package/_esm/tempo/TokenRole.js.map +1 -0
  89. package/_esm/tempo/Transaction.js +167 -0
  90. package/_esm/tempo/Transaction.js.map +1 -0
  91. package/_esm/tempo/TransactionReceipt.js +138 -0
  92. package/_esm/tempo/TransactionReceipt.js.map +1 -0
  93. package/_esm/tempo/TransactionRequest.js +99 -0
  94. package/_esm/tempo/TransactionRequest.js.map +1 -0
  95. package/_esm/tempo/TxEnvelopeTempo.js +607 -0
  96. package/_esm/tempo/TxEnvelopeTempo.js.map +1 -0
  97. package/_esm/tempo/index.js +298 -0
  98. package/_esm/tempo/index.js.map +1 -0
  99. package/_esm/version.js +1 -1
  100. package/_types/core/Blobs.d.ts +8 -8
  101. package/_types/core/{TransactionEnvelope.d.ts → TxEnvelope.d.ts} +11 -11
  102. package/_types/core/TxEnvelope.d.ts.map +1 -0
  103. package/_types/core/{TransactionEnvelopeEip1559.d.ts → TxEnvelopeEip1559.d.ts} +54 -54
  104. package/_types/core/TxEnvelopeEip1559.d.ts.map +1 -0
  105. package/_types/core/{TransactionEnvelopeEip2930.d.ts → TxEnvelopeEip2930.d.ts} +55 -55
  106. package/_types/core/TxEnvelopeEip2930.d.ts.map +1 -0
  107. package/_types/core/{TransactionEnvelopeEip4844.d.ts → TxEnvelopeEip4844.d.ts} +54 -54
  108. package/_types/core/TxEnvelopeEip4844.d.ts.map +1 -0
  109. package/_types/core/{TransactionEnvelopeEip7702.d.ts → TxEnvelopeEip7702.d.ts} +49 -49
  110. package/_types/core/TxEnvelopeEip7702.d.ts.map +1 -0
  111. package/_types/core/{TransactionEnvelopeLegacy.d.ts → TxEnvelopeLegacy.d.ts} +54 -54
  112. package/_types/core/TxEnvelopeLegacy.d.ts.map +1 -0
  113. package/_types/core/WebAuthnP256.d.ts +1 -1
  114. package/_types/core/WebAuthnP256.d.ts.map +1 -1
  115. package/_types/erc8021/Attribution.d.ts +20 -6
  116. package/_types/erc8021/Attribution.d.ts.map +1 -1
  117. package/_types/index.d.ts +192 -192
  118. package/_types/index.d.ts.map +1 -1
  119. package/_types/index.docs.d.ts +1 -0
  120. package/_types/index.docs.d.ts.map +1 -1
  121. package/_types/tempo/AuthorizationTempo.d.ts +688 -0
  122. package/_types/tempo/AuthorizationTempo.d.ts.map +1 -0
  123. package/_types/tempo/KeyAuthorization.d.ts +437 -0
  124. package/_types/tempo/KeyAuthorization.d.ts.map +1 -0
  125. package/_types/tempo/PoolId.d.ts +33 -0
  126. package/_types/tempo/PoolId.d.ts.map +1 -0
  127. package/_types/tempo/SignatureEnvelope.d.ts +438 -0
  128. package/_types/tempo/SignatureEnvelope.d.ts.map +1 -0
  129. package/_types/tempo/Tick.d.ts +120 -0
  130. package/_types/tempo/Tick.d.ts.map +1 -0
  131. package/_types/tempo/TokenId.d.ts +55 -0
  132. package/_types/tempo/TokenId.d.ts.map +1 -0
  133. package/_types/tempo/TokenRole.d.ts +29 -0
  134. package/_types/tempo/TokenRole.d.ts.map +1 -0
  135. package/_types/tempo/Transaction.d.ts +208 -0
  136. package/_types/tempo/Transaction.d.ts.map +1 -0
  137. package/_types/tempo/TransactionReceipt.d.ts +165 -0
  138. package/_types/tempo/TransactionReceipt.d.ts.map +1 -0
  139. package/_types/tempo/TransactionRequest.d.ts +89 -0
  140. package/_types/tempo/TransactionRequest.d.ts.map +1 -0
  141. package/_types/tempo/TxEnvelopeTempo.d.ts +551 -0
  142. package/_types/tempo/TxEnvelopeTempo.d.ts.map +1 -0
  143. package/_types/tempo/index.d.ts +300 -0
  144. package/_types/tempo/index.d.ts.map +1 -0
  145. package/_types/version.d.ts +1 -1
  146. package/core/Blobs.ts +8 -8
  147. package/core/{TransactionEnvelope.ts → TxEnvelope.ts} +10 -10
  148. package/core/{TransactionEnvelopeEip1559.ts → TxEnvelopeEip1559.ts} +60 -69
  149. package/core/{TransactionEnvelopeEip2930.ts → TxEnvelopeEip2930.ts} +61 -72
  150. package/core/{TransactionEnvelopeEip4844.ts → TxEnvelopeEip4844.ts} +62 -71
  151. package/core/{TransactionEnvelopeEip7702.ts → TxEnvelopeEip7702.ts} +58 -67
  152. package/core/{TransactionEnvelopeLegacy.ts → TxEnvelopeLegacy.ts} +59 -68
  153. package/core/WebAuthnP256.ts +3 -1
  154. package/erc8021/Attribution.ts +77 -15
  155. package/index.docs.ts +1 -0
  156. package/index.ts +192 -195
  157. package/package.json +91 -31
  158. package/tempo/AuthorizationTempo/package.json +6 -0
  159. package/tempo/AuthorizationTempo.test.ts +1293 -0
  160. package/tempo/AuthorizationTempo.ts +884 -0
  161. package/tempo/KeyAuthorization/package.json +6 -0
  162. package/tempo/KeyAuthorization.test.ts +1373 -0
  163. package/tempo/KeyAuthorization.ts +622 -0
  164. package/tempo/PoolId/package.json +6 -0
  165. package/tempo/PoolId.test.ts +33 -0
  166. package/tempo/PoolId.ts +42 -0
  167. package/tempo/SignatureEnvelope/package.json +6 -0
  168. package/tempo/SignatureEnvelope.test.ts +1877 -0
  169. package/tempo/SignatureEnvelope.ts +973 -0
  170. package/tempo/Tick/package.json +6 -0
  171. package/tempo/Tick.test.ts +281 -0
  172. package/tempo/Tick.ts +186 -0
  173. package/tempo/TokenId/package.json +6 -0
  174. package/tempo/TokenId.test.ts +40 -0
  175. package/tempo/TokenId.ts +80 -0
  176. package/tempo/TokenRole/package.json +6 -0
  177. package/tempo/TokenRole.test.ts +16 -0
  178. package/tempo/TokenRole.ts +45 -0
  179. package/tempo/Transaction/package.json +6 -0
  180. package/tempo/Transaction.test.ts +523 -0
  181. package/tempo/Transaction.ts +339 -0
  182. package/tempo/TransactionReceipt/package.json +6 -0
  183. package/tempo/TransactionReceipt.ts +200 -0
  184. package/tempo/TransactionRequest/package.json +6 -0
  185. package/tempo/TransactionRequest.ts +160 -0
  186. package/tempo/TxEnvelopeTempo/package.json +6 -0
  187. package/tempo/TxEnvelopeTempo.test.ts +1371 -0
  188. package/tempo/TxEnvelopeTempo.ts +972 -0
  189. package/tempo/e2e.test.ts +1387 -0
  190. package/tempo/index.ts +308 -0
  191. package/tempo/package.json +6 -0
  192. package/version.ts +1 -1
  193. package/TransactionEnvelope/package.json +0 -6
  194. package/TransactionEnvelopeEip1559/package.json +0 -6
  195. package/TransactionEnvelopeEip2930/package.json +0 -6
  196. package/TransactionEnvelopeEip4844/package.json +0 -6
  197. package/TransactionEnvelopeEip7702/package.json +0 -6
  198. package/TransactionEnvelopeLegacy/package.json +0 -6
  199. package/_cjs/core/TransactionEnvelope.js.map +0 -1
  200. package/_cjs/core/TransactionEnvelopeEip1559.js.map +0 -1
  201. package/_cjs/core/TransactionEnvelopeEip2930.js.map +0 -1
  202. package/_cjs/core/TransactionEnvelopeEip4844.js.map +0 -1
  203. package/_cjs/core/TransactionEnvelopeEip7702.js.map +0 -1
  204. package/_cjs/core/TransactionEnvelopeLegacy.js.map +0 -1
  205. package/_esm/core/TransactionEnvelope.js.map +0 -1
  206. package/_esm/core/TransactionEnvelopeEip1559.js.map +0 -1
  207. package/_esm/core/TransactionEnvelopeEip2930.js.map +0 -1
  208. package/_esm/core/TransactionEnvelopeEip4844.js.map +0 -1
  209. package/_esm/core/TransactionEnvelopeEip7702.js.map +0 -1
  210. package/_esm/core/TransactionEnvelopeLegacy.js.map +0 -1
  211. package/_types/core/TransactionEnvelope.d.ts.map +0 -1
  212. package/_types/core/TransactionEnvelopeEip1559.d.ts.map +0 -1
  213. package/_types/core/TransactionEnvelopeEip2930.d.ts.map +0 -1
  214. package/_types/core/TransactionEnvelopeEip4844.d.ts.map +0 -1
  215. package/_types/core/TransactionEnvelopeEip7702.d.ts.map +0 -1
  216. package/_types/core/TransactionEnvelopeLegacy.d.ts.map +0 -1
@@ -0,0 +1,1373 @@
1
+ import { Hex, PublicKey, Secp256k1, Signature, Value, WebAuthnP256 } from 'ox'
2
+ import { describe, expect, test } from 'vitest'
3
+ import * as KeyAuthorization from './KeyAuthorization.js'
4
+ import * as SignatureEnvelope from './SignatureEnvelope.js'
5
+
6
+ const address = '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c'
7
+ const expiry = 1234567890
8
+ const token = '0x20c0000000000000000000000000000000000001'
9
+
10
+ const privateKey_secp256k1 =
11
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
12
+ const signature_secp256k1 = Secp256k1.sign({
13
+ payload: '0xdeadbeef',
14
+ privateKey: privateKey_secp256k1,
15
+ })
16
+
17
+ const publicKey_p256 = PublicKey.from({
18
+ prefix: 4,
19
+ x: 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
20
+ y: 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
21
+ })
22
+
23
+ const signature_p256_raw = Signature.from({
24
+ r: 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
25
+ s: 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
26
+ yParity: 0,
27
+ })
28
+
29
+ const signature_p256 = SignatureEnvelope.from({
30
+ signature: signature_p256_raw,
31
+ publicKey: publicKey_p256,
32
+ prehash: true,
33
+ })
34
+
35
+ const signature_webauthn = SignatureEnvelope.from({
36
+ signature: signature_p256_raw,
37
+ publicKey: publicKey_p256,
38
+ metadata: {
39
+ authenticatorData: WebAuthnP256.getAuthenticatorData({ rpId: 'localhost' }),
40
+ clientDataJSON: WebAuthnP256.getClientDataJSON({
41
+ challenge: '0xdeadbeef',
42
+ origin: 'http://localhost',
43
+ }),
44
+ },
45
+ })
46
+
47
+ describe('from', () => {
48
+ test('default', () => {
49
+ const authorization = KeyAuthorization.from({
50
+ address,
51
+ expiry,
52
+ type: 'secp256k1',
53
+ limits: [
54
+ {
55
+ token,
56
+ limit: Value.from('10', 6),
57
+ },
58
+ ],
59
+ })
60
+
61
+ expect(authorization).toMatchInlineSnapshot(`
62
+ {
63
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
64
+ "expiry": 1234567890,
65
+ "limits": [
66
+ {
67
+ "limit": 10000000n,
68
+ "token": "0x20c0000000000000000000000000000000000001",
69
+ },
70
+ ],
71
+ "type": "secp256k1",
72
+ }
73
+ `)
74
+ })
75
+
76
+ test('with signature (secp256k1)', () => {
77
+ const authorization = KeyAuthorization.from(
78
+ {
79
+ address,
80
+ expiry,
81
+ type: 'secp256k1',
82
+ limits: [
83
+ {
84
+ token,
85
+ limit: Value.from('10', 6),
86
+ },
87
+ ],
88
+ },
89
+ {
90
+ signature: signature_secp256k1,
91
+ },
92
+ )
93
+
94
+ expect(authorization).toMatchInlineSnapshot(`
95
+ {
96
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
97
+ "expiry": 1234567890,
98
+ "limits": [
99
+ {
100
+ "limit": 10000000n,
101
+ "token": "0x20c0000000000000000000000000000000000001",
102
+ },
103
+ ],
104
+ "signature": {
105
+ "signature": {
106
+ "r": 113291597329930009559670063131885256927775966057121513567941051428123344285399n,
107
+ "s": 54293712598725100598138577281441749550405991478212695085505730636505228583888n,
108
+ "yParity": 1,
109
+ },
110
+ "type": "secp256k1",
111
+ },
112
+ "type": "secp256k1",
113
+ }
114
+ `)
115
+ })
116
+
117
+ test('with signature (secp256k1)', () => {
118
+ const authorization = KeyAuthorization.from(
119
+ {
120
+ address,
121
+ expiry,
122
+ type: 'secp256k1',
123
+ limits: [
124
+ {
125
+ token,
126
+ limit: Value.from('10', 6),
127
+ },
128
+ ],
129
+ },
130
+ {
131
+ signature: SignatureEnvelope.from(signature_secp256k1),
132
+ },
133
+ )
134
+
135
+ expect(authorization).toMatchInlineSnapshot(`
136
+ {
137
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
138
+ "expiry": 1234567890,
139
+ "limits": [
140
+ {
141
+ "limit": 10000000n,
142
+ "token": "0x20c0000000000000000000000000000000000001",
143
+ },
144
+ ],
145
+ "signature": {
146
+ "signature": {
147
+ "r": 113291597329930009559670063131885256927775966057121513567941051428123344285399n,
148
+ "s": 54293712598725100598138577281441749550405991478212695085505730636505228583888n,
149
+ "yParity": 1,
150
+ },
151
+ "type": "secp256k1",
152
+ },
153
+ "type": "secp256k1",
154
+ }
155
+ `)
156
+ })
157
+
158
+ test('with signature (p256)', () => {
159
+ const authorization = KeyAuthorization.from(
160
+ {
161
+ address,
162
+ expiry,
163
+ type: 'p256',
164
+ limits: [
165
+ {
166
+ token,
167
+ limit: Value.from('10', 6),
168
+ },
169
+ ],
170
+ },
171
+ {
172
+ signature: signature_p256,
173
+ },
174
+ )
175
+
176
+ expect(authorization).toMatchInlineSnapshot(`
177
+ {
178
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
179
+ "expiry": 1234567890,
180
+ "limits": [
181
+ {
182
+ "limit": 10000000n,
183
+ "token": "0x20c0000000000000000000000000000000000001",
184
+ },
185
+ ],
186
+ "signature": {
187
+ "prehash": true,
188
+ "publicKey": {
189
+ "prefix": 4,
190
+ "x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
191
+ "y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
192
+ },
193
+ "signature": {
194
+ "r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
195
+ "s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
196
+ "yParity": 0,
197
+ },
198
+ "type": "p256",
199
+ },
200
+ "type": "p256",
201
+ }
202
+ `)
203
+ })
204
+
205
+ test('with signature (webAuthn)', () => {
206
+ const authorization = KeyAuthorization.from(
207
+ {
208
+ address,
209
+ expiry,
210
+ type: 'webAuthn',
211
+ limits: [
212
+ {
213
+ token,
214
+ limit: Value.from('10', 6),
215
+ },
216
+ ],
217
+ },
218
+ {
219
+ signature: signature_webauthn,
220
+ },
221
+ )
222
+
223
+ expect(authorization).toMatchInlineSnapshot(`
224
+ {
225
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
226
+ "expiry": 1234567890,
227
+ "limits": [
228
+ {
229
+ "limit": 10000000n,
230
+ "token": "0x20c0000000000000000000000000000000000001",
231
+ },
232
+ ],
233
+ "signature": {
234
+ "metadata": {
235
+ "authenticatorData": "0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000",
236
+ "clientDataJSON": "{"type":"webauthn.get","challenge":"3q2-7w","origin":"http://localhost","crossOrigin":false}",
237
+ },
238
+ "publicKey": {
239
+ "prefix": 4,
240
+ "x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
241
+ "y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
242
+ },
243
+ "signature": {
244
+ "r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
245
+ "s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
246
+ "yParity": 0,
247
+ },
248
+ "type": "webAuthn",
249
+ },
250
+ "type": "webAuthn",
251
+ }
252
+ `)
253
+ })
254
+
255
+ test('with inline signature (secp256k1)', () => {
256
+ const authorization = KeyAuthorization.from({
257
+ address,
258
+ expiry,
259
+ type: 'secp256k1',
260
+ limits: [
261
+ {
262
+ token,
263
+ limit: Value.from('10', 6),
264
+ },
265
+ ],
266
+ signature: SignatureEnvelope.from(signature_secp256k1),
267
+ })
268
+
269
+ expect(authorization).toMatchInlineSnapshot(`
270
+ {
271
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
272
+ "expiry": 1234567890,
273
+ "limits": [
274
+ {
275
+ "limit": 10000000n,
276
+ "token": "0x20c0000000000000000000000000000000000001",
277
+ },
278
+ ],
279
+ "signature": {
280
+ "signature": {
281
+ "r": 113291597329930009559670063131885256927775966057121513567941051428123344285399n,
282
+ "s": 54293712598725100598138577281441749550405991478212695085505730636505228583888n,
283
+ "yParity": 1,
284
+ },
285
+ "type": "secp256k1",
286
+ },
287
+ "type": "secp256k1",
288
+ }
289
+ `)
290
+ })
291
+
292
+ test('from rpc', () => {
293
+ const authorization = KeyAuthorization.from({
294
+ expiry: Hex.fromNumber(expiry),
295
+ keyId: address,
296
+ keyType: 'secp256k1',
297
+ limits: [{ token, limit: '0x989680' }],
298
+ signature: {
299
+ type: 'secp256k1',
300
+ r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
301
+ s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
302
+ yParity: '0x0',
303
+ },
304
+ })
305
+
306
+ expect(authorization).toMatchInlineSnapshot(`
307
+ {
308
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
309
+ "chainId": 0n,
310
+ "expiry": 1234567890,
311
+ "limits": [
312
+ {
313
+ "limit": 10000000n,
314
+ "token": "0x20c0000000000000000000000000000000000001",
315
+ },
316
+ ],
317
+ "signature": {
318
+ "signature": {
319
+ "r": 44944627813007772897391531230081695102703289123332187696115181104739239197517n,
320
+ "s": 36528503505192438307355164441104001310566505351980369085208178712678799181120n,
321
+ "yParity": 0,
322
+ },
323
+ "type": "secp256k1",
324
+ },
325
+ "type": "secp256k1",
326
+ }
327
+ `)
328
+ })
329
+
330
+ test('multiple limits', () => {
331
+ const authorization = KeyAuthorization.from({
332
+ address,
333
+ expiry,
334
+ type: 'secp256k1',
335
+ limits: [
336
+ {
337
+ token: '0x20c0000000000000000000000000000000000001',
338
+ limit: Value.from('10', 6),
339
+ },
340
+ {
341
+ token: '0x20c0000000000000000000000000000000000002',
342
+ limit: Value.from('20', 6),
343
+ },
344
+ ],
345
+ })
346
+
347
+ expect(authorization).toMatchInlineSnapshot(`
348
+ {
349
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
350
+ "expiry": 1234567890,
351
+ "limits": [
352
+ {
353
+ "limit": 10000000n,
354
+ "token": "0x20c0000000000000000000000000000000000001",
355
+ },
356
+ {
357
+ "limit": 20000000n,
358
+ "token": "0x20c0000000000000000000000000000000000002",
359
+ },
360
+ ],
361
+ "type": "secp256k1",
362
+ }
363
+ `)
364
+ })
365
+
366
+ test('zero expiry (never expires)', () => {
367
+ const authorization = KeyAuthorization.from({
368
+ address,
369
+ expiry: 0,
370
+ type: 'secp256k1',
371
+ limits: [
372
+ {
373
+ token,
374
+ limit: Value.from('10', 6),
375
+ },
376
+ ],
377
+ })
378
+
379
+ expect(authorization).toMatchInlineSnapshot(`
380
+ {
381
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
382
+ "expiry": 0,
383
+ "limits": [
384
+ {
385
+ "limit": 10000000n,
386
+ "token": "0x20c0000000000000000000000000000000000001",
387
+ },
388
+ ],
389
+ "type": "secp256k1",
390
+ }
391
+ `)
392
+ })
393
+ })
394
+
395
+ describe('fromRpc', () => {
396
+ test('secp256k1', () => {
397
+ const authorization = KeyAuthorization.fromRpc({
398
+ expiry: Hex.fromNumber(expiry),
399
+ keyId: address,
400
+ keyType: 'secp256k1',
401
+ limits: [{ token, limit: '0x989680' }],
402
+ signature: {
403
+ type: 'secp256k1',
404
+ r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
405
+ s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
406
+ yParity: '0x0',
407
+ },
408
+ })
409
+
410
+ expect(authorization).toMatchInlineSnapshot(`
411
+ {
412
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
413
+ "chainId": 0n,
414
+ "expiry": 1234567890,
415
+ "limits": [
416
+ {
417
+ "limit": 10000000n,
418
+ "token": "0x20c0000000000000000000000000000000000001",
419
+ },
420
+ ],
421
+ "signature": {
422
+ "signature": {
423
+ "r": 44944627813007772897391531230081695102703289123332187696115181104739239197517n,
424
+ "s": 36528503505192438307355164441104001310566505351980369085208178712678799181120n,
425
+ "yParity": 0,
426
+ },
427
+ "type": "secp256k1",
428
+ },
429
+ "type": "secp256k1",
430
+ }
431
+ `)
432
+ })
433
+
434
+ test('p256', () => {
435
+ const authorization = KeyAuthorization.fromRpc({
436
+ expiry: Hex.fromNumber(expiry),
437
+ keyId: address,
438
+ keyType: 'p256',
439
+ limits: [{ token, limit: '0x989680' }],
440
+ signature: {
441
+ type: 'p256',
442
+ prehash: true,
443
+ pubKeyX: Hex.fromNumber(publicKey_p256.x),
444
+ pubKeyY: Hex.fromNumber(publicKey_p256.y),
445
+ r: Hex.fromNumber(signature_p256_raw.r),
446
+ s: Hex.fromNumber(signature_p256_raw.s),
447
+ },
448
+ })
449
+
450
+ expect(authorization).toMatchInlineSnapshot(`
451
+ {
452
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
453
+ "chainId": 0n,
454
+ "expiry": 1234567890,
455
+ "limits": [
456
+ {
457
+ "limit": 10000000n,
458
+ "token": "0x20c0000000000000000000000000000000000001",
459
+ },
460
+ ],
461
+ "signature": {
462
+ "prehash": true,
463
+ "publicKey": {
464
+ "prefix": 4,
465
+ "x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
466
+ "y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
467
+ },
468
+ "signature": {
469
+ "r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
470
+ "s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
471
+ },
472
+ "type": "p256",
473
+ },
474
+ "type": "p256",
475
+ }
476
+ `)
477
+ })
478
+
479
+ test('webAuthn', () => {
480
+ const authorization = KeyAuthorization.fromRpc({
481
+ expiry: Hex.fromNumber(expiry),
482
+ keyId: address,
483
+ keyType: 'webAuthn',
484
+ limits: [{ token, limit: '0x989680' }],
485
+ signature: SignatureEnvelope.toRpc(signature_webauthn),
486
+ })
487
+
488
+ expect(authorization).toMatchInlineSnapshot(`
489
+ {
490
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
491
+ "chainId": 0n,
492
+ "expiry": 1234567890,
493
+ "limits": [
494
+ {
495
+ "limit": 10000000n,
496
+ "token": "0x20c0000000000000000000000000000000000001",
497
+ },
498
+ ],
499
+ "signature": {
500
+ "metadata": {
501
+ "authenticatorData": "0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000",
502
+ "clientDataJSON": "{"type":"webauthn.get","challenge":"3q2-7w","origin":"http://localhost","crossOrigin":false}",
503
+ },
504
+ "publicKey": {
505
+ "prefix": 4,
506
+ "x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
507
+ "y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
508
+ },
509
+ "signature": {
510
+ "r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
511
+ "s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
512
+ },
513
+ "type": "webAuthn",
514
+ },
515
+ "type": "webAuthn",
516
+ }
517
+ `)
518
+ })
519
+
520
+ test('multiple limits', () => {
521
+ const authorization = KeyAuthorization.fromRpc({
522
+ expiry: Hex.fromNumber(expiry),
523
+ keyId: address,
524
+ keyType: 'secp256k1',
525
+ limits: [
526
+ {
527
+ token: '0x20c0000000000000000000000000000000000001',
528
+ limit: '0x989680',
529
+ },
530
+ {
531
+ token: '0x20c0000000000000000000000000000000000002',
532
+ limit: '0x1312d00',
533
+ },
534
+ ],
535
+ signature: {
536
+ type: 'secp256k1',
537
+ r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
538
+ s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
539
+ yParity: '0x0',
540
+ },
541
+ })
542
+
543
+ expect(authorization).toMatchInlineSnapshot(`
544
+ {
545
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
546
+ "chainId": 0n,
547
+ "expiry": 1234567890,
548
+ "limits": [
549
+ {
550
+ "limit": 10000000n,
551
+ "token": "0x20c0000000000000000000000000000000000001",
552
+ },
553
+ {
554
+ "limit": 20000000n,
555
+ "token": "0x20c0000000000000000000000000000000000002",
556
+ },
557
+ ],
558
+ "signature": {
559
+ "signature": {
560
+ "r": 44944627813007772897391531230081695102703289123332187696115181104739239197517n,
561
+ "s": 36528503505192438307355164441104001310566505351980369085208178712678799181120n,
562
+ "yParity": 0,
563
+ },
564
+ "type": "secp256k1",
565
+ },
566
+ "type": "secp256k1",
567
+ }
568
+ `)
569
+ })
570
+
571
+ test('handles chainId "0x" as 0n', () => {
572
+ const authorization = KeyAuthorization.fromRpc({
573
+ chainId: '0x',
574
+ expiry: Hex.fromNumber(expiry),
575
+ keyId: address,
576
+ keyType: 'secp256k1',
577
+ limits: [{ token, limit: '0x989680' }],
578
+ signature: {
579
+ type: 'secp256k1',
580
+ r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
581
+ s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
582
+ yParity: '0x0',
583
+ },
584
+ })
585
+
586
+ expect(authorization.chainId).toBe(0n)
587
+ })
588
+ })
589
+
590
+ describe('fromTuple', () => {
591
+ test('default', () => {
592
+ const authorization = KeyAuthorization.fromTuple([
593
+ [
594
+ '0x00', // chainId
595
+ '0x00', // keyType (secp256k1)
596
+ address,
597
+ Hex.fromNumber(expiry),
598
+ [[token, '0x989680']],
599
+ ],
600
+ ])
601
+
602
+ expect(authorization).toMatchInlineSnapshot(`
603
+ {
604
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
605
+ "chainId": 0n,
606
+ "expiry": 1234567890,
607
+ "limits": [
608
+ {
609
+ "limit": 10000000n,
610
+ "token": "0x20c0000000000000000000000000000000000001",
611
+ },
612
+ ],
613
+ "type": "secp256k1",
614
+ }
615
+ `)
616
+ })
617
+
618
+ test('with signature (secp256k1)', () => {
619
+ const signature = SignatureEnvelope.serialize(
620
+ SignatureEnvelope.from(signature_secp256k1),
621
+ )
622
+
623
+ const authorization = KeyAuthorization.fromTuple([
624
+ [
625
+ '0x00', // chainId
626
+ '0x00', // keyType (secp256k1)
627
+ address,
628
+ Hex.fromNumber(expiry),
629
+ [[token, '0x989680']],
630
+ ],
631
+ signature,
632
+ ])
633
+
634
+ expect(authorization).toMatchInlineSnapshot(`
635
+ {
636
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
637
+ "chainId": 0n,
638
+ "expiry": 1234567890,
639
+ "limits": [
640
+ {
641
+ "limit": 10000000n,
642
+ "token": "0x20c0000000000000000000000000000000000001",
643
+ },
644
+ ],
645
+ "signature": {
646
+ "signature": {
647
+ "r": 113291597329930009559670063131885256927775966057121513567941051428123344285399n,
648
+ "s": 54293712598725100598138577281441749550405991478212695085505730636505228583888n,
649
+ "yParity": 1,
650
+ },
651
+ "type": "secp256k1",
652
+ },
653
+ "type": "secp256k1",
654
+ }
655
+ `)
656
+ })
657
+
658
+ test('with signature (p256)', () => {
659
+ const signature = SignatureEnvelope.serialize(signature_p256)
660
+
661
+ const authorization = KeyAuthorization.fromTuple([
662
+ [
663
+ '0x00', // chainId
664
+ '0x01', // keyType (p256)
665
+ address,
666
+ Hex.fromNumber(expiry),
667
+ [[token, '0x989680']],
668
+ ],
669
+ signature,
670
+ ])
671
+
672
+ expect(authorization).toMatchInlineSnapshot(`
673
+ {
674
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
675
+ "chainId": 0n,
676
+ "expiry": 1234567890,
677
+ "limits": [
678
+ {
679
+ "limit": 10000000n,
680
+ "token": "0x20c0000000000000000000000000000000000001",
681
+ },
682
+ ],
683
+ "signature": {
684
+ "prehash": true,
685
+ "publicKey": {
686
+ "prefix": 4,
687
+ "x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
688
+ "y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
689
+ },
690
+ "signature": {
691
+ "r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
692
+ "s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
693
+ },
694
+ "type": "p256",
695
+ },
696
+ "type": "p256",
697
+ }
698
+ `)
699
+ })
700
+
701
+ test('with signature (webAuthn)', () => {
702
+ const signature = SignatureEnvelope.serialize(signature_webauthn)
703
+
704
+ const authorization = KeyAuthorization.fromTuple([
705
+ [
706
+ '0x00', // chainId
707
+ '0x02', // keyType (webAuthn)
708
+ address,
709
+ Hex.fromNumber(expiry),
710
+ [[token, '0x989680']],
711
+ ],
712
+ signature,
713
+ ])
714
+
715
+ expect(authorization).toMatchInlineSnapshot(`
716
+ {
717
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
718
+ "chainId": 0n,
719
+ "expiry": 1234567890,
720
+ "limits": [
721
+ {
722
+ "limit": 10000000n,
723
+ "token": "0x20c0000000000000000000000000000000000001",
724
+ },
725
+ ],
726
+ "signature": {
727
+ "metadata": {
728
+ "authenticatorData": "0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000",
729
+ "clientDataJSON": "{"type":"webauthn.get","challenge":"3q2-7w","origin":"http://localhost","crossOrigin":false}",
730
+ },
731
+ "publicKey": {
732
+ "prefix": 4,
733
+ "x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
734
+ "y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
735
+ },
736
+ "signature": {
737
+ "r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
738
+ "s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
739
+ },
740
+ "type": "webAuthn",
741
+ },
742
+ "type": "webAuthn",
743
+ }
744
+ `)
745
+ })
746
+
747
+ test('multiple limits', () => {
748
+ const authorization = KeyAuthorization.fromTuple([
749
+ [
750
+ '0x00', // chainId
751
+ '0x00', // keyType (secp256k1)
752
+ address,
753
+ Hex.fromNumber(expiry),
754
+ [
755
+ ['0x20c0000000000000000000000000000000000001', '0x989680'],
756
+ ['0x20c0000000000000000000000000000000000002', '0x1312d00'],
757
+ ],
758
+ ],
759
+ ])
760
+
761
+ expect(authorization).toMatchInlineSnapshot(`
762
+ {
763
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
764
+ "chainId": 0n,
765
+ "expiry": 1234567890,
766
+ "limits": [
767
+ {
768
+ "limit": 10000000n,
769
+ "token": "0x20c0000000000000000000000000000000000001",
770
+ },
771
+ {
772
+ "limit": 20000000n,
773
+ "token": "0x20c0000000000000000000000000000000000002",
774
+ },
775
+ ],
776
+ "type": "secp256k1",
777
+ }
778
+ `)
779
+ })
780
+
781
+ test('with non-zero chainId', () => {
782
+ const authorization = KeyAuthorization.fromTuple([
783
+ [
784
+ Hex.fromNumber(123), // chainId
785
+ '0x00', // keyType (secp256k1)
786
+ address,
787
+ Hex.fromNumber(expiry),
788
+ [[token, '0x989680']],
789
+ ],
790
+ ])
791
+
792
+ expect(authorization).toMatchInlineSnapshot(`
793
+ {
794
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
795
+ "chainId": 123n,
796
+ "expiry": 1234567890,
797
+ "limits": [
798
+ {
799
+ "limit": 10000000n,
800
+ "token": "0x20c0000000000000000000000000000000000001",
801
+ },
802
+ ],
803
+ "type": "secp256k1",
804
+ }
805
+ `)
806
+ })
807
+
808
+ test('empty keyType treated as secp256k1', () => {
809
+ const authorization = KeyAuthorization.fromTuple([
810
+ [
811
+ '0x00', // chainId
812
+ '0x', // keyType (empty = secp256k1)
813
+ address,
814
+ Hex.fromNumber(expiry),
815
+ [[token, '0x989680']],
816
+ ],
817
+ ])
818
+
819
+ expect(authorization).toMatchInlineSnapshot(`
820
+ {
821
+ "address": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
822
+ "chainId": 0n,
823
+ "expiry": 1234567890,
824
+ "limits": [
825
+ {
826
+ "limit": 10000000n,
827
+ "token": "0x20c0000000000000000000000000000000000001",
828
+ },
829
+ ],
830
+ "type": "secp256k1",
831
+ }
832
+ `)
833
+ })
834
+ })
835
+
836
+ describe('getSignPayload', () => {
837
+ test('default', () => {
838
+ const authorization = KeyAuthorization.from({
839
+ address,
840
+ expiry,
841
+ type: 'secp256k1',
842
+ limits: [
843
+ {
844
+ token,
845
+ limit: Value.from('10', 6),
846
+ },
847
+ ],
848
+ })
849
+
850
+ const payload = KeyAuthorization.getSignPayload(authorization)
851
+
852
+ expect(payload).toMatchInlineSnapshot(
853
+ `"0x6d56b62bb5e94ca0206340e4bc1ece5a35e7ad31c30c6b98074d146d5c5de993"`,
854
+ )
855
+ })
856
+
857
+ test('with signature (signature should be ignored)', () => {
858
+ const authorization = KeyAuthorization.from({
859
+ address,
860
+ expiry,
861
+ type: 'secp256k1',
862
+ limits: [
863
+ {
864
+ token,
865
+ limit: Value.from('10', 6),
866
+ },
867
+ ],
868
+ signature: SignatureEnvelope.from(signature_secp256k1),
869
+ })
870
+
871
+ const payload = KeyAuthorization.getSignPayload(authorization)
872
+
873
+ // Should be same as without signature
874
+ expect(payload).toMatchInlineSnapshot(
875
+ `"0x6d56b62bb5e94ca0206340e4bc1ece5a35e7ad31c30c6b98074d146d5c5de993"`,
876
+ )
877
+ })
878
+
879
+ test('different key types', () => {
880
+ const auth_secp256k1 = KeyAuthorization.from({
881
+ address,
882
+ expiry,
883
+ type: 'secp256k1',
884
+ limits: [{ token, limit: Value.from('10', 6) }],
885
+ })
886
+
887
+ const auth_p256 = KeyAuthorization.from({
888
+ address,
889
+ expiry,
890
+ type: 'p256',
891
+ limits: [{ token, limit: Value.from('10', 6) }],
892
+ })
893
+
894
+ const auth_webauthn = KeyAuthorization.from({
895
+ address,
896
+ expiry,
897
+ type: 'webAuthn',
898
+ limits: [{ token, limit: Value.from('10', 6) }],
899
+ })
900
+
901
+ const payload_secp256k1 = KeyAuthorization.getSignPayload(auth_secp256k1)
902
+ const payload_p256 = KeyAuthorization.getSignPayload(auth_p256)
903
+ const payload_webauthn = KeyAuthorization.getSignPayload(auth_webauthn)
904
+
905
+ // Payloads should be different for different key types
906
+ expect(payload_secp256k1).not.toBe(payload_p256)
907
+ expect(payload_secp256k1).not.toBe(payload_webauthn)
908
+ expect(payload_p256).not.toBe(payload_webauthn)
909
+
910
+ expect(payload_secp256k1).toMatchInlineSnapshot(
911
+ `"0x6d56b62bb5e94ca0206340e4bc1ece5a35e7ad31c30c6b98074d146d5c5de993"`,
912
+ )
913
+ expect(payload_p256).toMatchInlineSnapshot(
914
+ `"0x70f1d02570bd5ec14701306f7c3fadf405911fcd585136d1d60f2e4eb689f602"`,
915
+ )
916
+ expect(payload_webauthn).toMatchInlineSnapshot(
917
+ `"0xb69543e8899a3d0a0186e347df6589f47ea194b6bc3ac935225411b1ef2d4627"`,
918
+ )
919
+ })
920
+ })
921
+
922
+ describe('hash', () => {
923
+ test('default', () => {
924
+ const authorization = KeyAuthorization.from({
925
+ address,
926
+ expiry,
927
+ type: 'secp256k1',
928
+ limits: [
929
+ {
930
+ token,
931
+ limit: Value.from('10', 6),
932
+ },
933
+ ],
934
+ })
935
+
936
+ const hash = KeyAuthorization.hash(authorization)
937
+
938
+ expect(hash).toMatchInlineSnapshot(
939
+ `"0x6d56b62bb5e94ca0206340e4bc1ece5a35e7ad31c30c6b98074d146d5c5de993"`,
940
+ )
941
+ })
942
+ })
943
+
944
+ describe('toRpc', () => {
945
+ test('secp256k1', () => {
946
+ const authorization = KeyAuthorization.from({
947
+ address,
948
+ expiry,
949
+ type: 'secp256k1',
950
+ limits: [
951
+ {
952
+ token,
953
+ limit: Value.from('10', 6),
954
+ },
955
+ ],
956
+ signature: SignatureEnvelope.from({
957
+ r: 44944627813007772897391531230081695102703289123332187696115181104739239197517n,
958
+ s: 36528503505192438307355164441104001310566505351980369085208178712678799181120n,
959
+ yParity: 0,
960
+ }),
961
+ })
962
+
963
+ const rpc = KeyAuthorization.toRpc(authorization)
964
+
965
+ expect(rpc).toMatchInlineSnapshot(`
966
+ {
967
+ "chainId": "0x",
968
+ "expiry": "0x499602d2",
969
+ "keyId": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
970
+ "keyType": "secp256k1",
971
+ "limits": [
972
+ {
973
+ "limit": "0x989680",
974
+ "token": "0x20c0000000000000000000000000000000000001",
975
+ },
976
+ ],
977
+ "signature": {
978
+ "r": "0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d",
979
+ "s": "0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540",
980
+ "type": "secp256k1",
981
+ "yParity": "0x0",
982
+ },
983
+ }
984
+ `)
985
+ })
986
+
987
+ test('p256', () => {
988
+ const authorization = KeyAuthorization.from({
989
+ address,
990
+ expiry,
991
+ type: 'p256',
992
+ limits: [
993
+ {
994
+ token,
995
+ limit: Value.from('10', 6),
996
+ },
997
+ ],
998
+ signature: signature_p256,
999
+ })
1000
+
1001
+ const rpc = KeyAuthorization.toRpc(authorization)
1002
+
1003
+ expect(rpc).toMatchInlineSnapshot(`
1004
+ {
1005
+ "chainId": "0x",
1006
+ "expiry": "0x499602d2",
1007
+ "keyId": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1008
+ "keyType": "p256",
1009
+ "limits": [
1010
+ {
1011
+ "limit": "0x989680",
1012
+ "token": "0x20c0000000000000000000000000000000000001",
1013
+ },
1014
+ ],
1015
+ "signature": {
1016
+ "prehash": true,
1017
+ "pubKeyX": "0xad8ac16e167d6992c3e120d7f17d2376bc1cbcf30c46ba6dd00ce07303e742f5",
1018
+ "pubKeyY": "0x11edf6ce1c32de66846f56afa7be1cbd729bc35750b6d0cdcf3ec9d75461aba0",
1019
+ "r": "0xccbb3485d4726235f13cb15ef394fb7158179fb7b1925eccec0147671090c52e",
1020
+ "s": "0x77c3c53373cc1e3b05e7c23f609deb17cea8fe097300c45411237e9fe4166b35",
1021
+ "type": "p256",
1022
+ },
1023
+ }
1024
+ `)
1025
+ })
1026
+
1027
+ test('webAuthn', () => {
1028
+ const authorization = KeyAuthorization.from({
1029
+ address,
1030
+ expiry,
1031
+ type: 'webAuthn',
1032
+ limits: [
1033
+ {
1034
+ token,
1035
+ limit: Value.from('10', 6),
1036
+ },
1037
+ ],
1038
+ signature: signature_webauthn,
1039
+ })
1040
+
1041
+ const rpc = KeyAuthorization.toRpc(authorization)
1042
+
1043
+ expect(rpc).toMatchInlineSnapshot(`
1044
+ {
1045
+ "chainId": "0x",
1046
+ "expiry": "0x499602d2",
1047
+ "keyId": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1048
+ "keyType": "webAuthn",
1049
+ "limits": [
1050
+ {
1051
+ "limit": "0x989680",
1052
+ "token": "0x20c0000000000000000000000000000000000001",
1053
+ },
1054
+ ],
1055
+ "signature": {
1056
+ "pubKeyX": "0xad8ac16e167d6992c3e120d7f17d2376bc1cbcf30c46ba6dd00ce07303e742f5",
1057
+ "pubKeyY": "0x11edf6ce1c32de66846f56afa7be1cbd729bc35750b6d0cdcf3ec9d75461aba0",
1058
+ "r": "0xccbb3485d4726235f13cb15ef394fb7158179fb7b1925eccec0147671090c52e",
1059
+ "s": "0x77c3c53373cc1e3b05e7c23f609deb17cea8fe097300c45411237e9fe4166b35",
1060
+ "type": "webAuthn",
1061
+ "webauthnData": "0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d976305000000007b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a223371322d3777222c226f726967696e223a22687474703a2f2f6c6f63616c686f7374222c2263726f73734f726967696e223a66616c73657d",
1062
+ },
1063
+ }
1064
+ `)
1065
+ })
1066
+
1067
+ test('multiple limits', () => {
1068
+ const authorization = KeyAuthorization.from({
1069
+ address,
1070
+ expiry,
1071
+ type: 'secp256k1',
1072
+ limits: [
1073
+ {
1074
+ token: '0x20c0000000000000000000000000000000000001',
1075
+ limit: Value.from('10', 6),
1076
+ },
1077
+ {
1078
+ token: '0x20c0000000000000000000000000000000000002',
1079
+ limit: Value.from('20', 6),
1080
+ },
1081
+ ],
1082
+ signature: SignatureEnvelope.from(signature_secp256k1),
1083
+ })
1084
+
1085
+ const rpc = KeyAuthorization.toRpc(authorization)
1086
+
1087
+ expect(rpc).toMatchInlineSnapshot(`
1088
+ {
1089
+ "chainId": "0x",
1090
+ "expiry": "0x499602d2",
1091
+ "keyId": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1092
+ "keyType": "secp256k1",
1093
+ "limits": [
1094
+ {
1095
+ "limit": "0x989680",
1096
+ "token": "0x20c0000000000000000000000000000000000001",
1097
+ },
1098
+ {
1099
+ "limit": "0x1312d00",
1100
+ "token": "0x20c0000000000000000000000000000000000002",
1101
+ },
1102
+ ],
1103
+ "signature": {
1104
+ "r": "0xfa78c5905fb0b9d6066ef531f962a62bc6ef0d5eb59ecb134056d206f75aaed7",
1105
+ "s": "0x780926ff2601a935c2c79707d9e1799948c9f19dcdde1e090e903b19a07923d0",
1106
+ "type": "secp256k1",
1107
+ "yParity": "0x1",
1108
+ },
1109
+ }
1110
+ `)
1111
+ })
1112
+
1113
+ test('with non-zero chainId', () => {
1114
+ const authorization = KeyAuthorization.from({
1115
+ address,
1116
+ chainId: 123n,
1117
+ expiry,
1118
+ type: 'secp256k1',
1119
+ limits: [
1120
+ {
1121
+ token,
1122
+ limit: Value.from('10', 6),
1123
+ },
1124
+ ],
1125
+ signature: SignatureEnvelope.from(signature_secp256k1),
1126
+ })
1127
+
1128
+ const rpc = KeyAuthorization.toRpc(authorization)
1129
+
1130
+ expect(rpc).toMatchInlineSnapshot(`
1131
+ {
1132
+ "chainId": "0x7b",
1133
+ "expiry": "0x499602d2",
1134
+ "keyId": "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1135
+ "keyType": "secp256k1",
1136
+ "limits": [
1137
+ {
1138
+ "limit": "0x989680",
1139
+ "token": "0x20c0000000000000000000000000000000000001",
1140
+ },
1141
+ ],
1142
+ "signature": {
1143
+ "r": "0xfa78c5905fb0b9d6066ef531f962a62bc6ef0d5eb59ecb134056d206f75aaed7",
1144
+ "s": "0x780926ff2601a935c2c79707d9e1799948c9f19dcdde1e090e903b19a07923d0",
1145
+ "type": "secp256k1",
1146
+ "yParity": "0x1",
1147
+ },
1148
+ }
1149
+ `)
1150
+ })
1151
+
1152
+ test('round-trip: toRpc -> fromRpc', () => {
1153
+ const authorization = KeyAuthorization.from({
1154
+ address,
1155
+ chainId: 0n,
1156
+ expiry,
1157
+ type: 'secp256k1',
1158
+ limits: [
1159
+ {
1160
+ token,
1161
+ limit: Value.from('10', 6),
1162
+ },
1163
+ ],
1164
+ signature: SignatureEnvelope.from(signature_secp256k1),
1165
+ })
1166
+
1167
+ const rpc = KeyAuthorization.toRpc(authorization)
1168
+ const restored = KeyAuthorization.fromRpc(rpc)
1169
+
1170
+ expect(restored).toEqual(authorization)
1171
+ })
1172
+ })
1173
+
1174
+ describe('toTuple', () => {
1175
+ test('default', () => {
1176
+ const authorization = KeyAuthorization.from({
1177
+ address,
1178
+ type: 'secp256k1',
1179
+ })
1180
+
1181
+ const tuple = KeyAuthorization.toTuple(authorization)
1182
+
1183
+ expect(tuple).toMatchInlineSnapshot(`
1184
+ [
1185
+ [
1186
+ "0x",
1187
+ "0x",
1188
+ "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1189
+ ],
1190
+ ]
1191
+ `)
1192
+ })
1193
+
1194
+ test('with signature (secp256k1)', () => {
1195
+ const authorization = KeyAuthorization.from({
1196
+ address,
1197
+ expiry,
1198
+ type: 'secp256k1',
1199
+ limits: [
1200
+ {
1201
+ token,
1202
+ limit: Value.from('10', 6),
1203
+ },
1204
+ ],
1205
+ signature: SignatureEnvelope.from(signature_secp256k1),
1206
+ })
1207
+
1208
+ const tuple = KeyAuthorization.toTuple(authorization)
1209
+
1210
+ expect(tuple).toMatchInlineSnapshot(`
1211
+ [
1212
+ [
1213
+ "0x",
1214
+ "0x",
1215
+ "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1216
+ "0x499602d2",
1217
+ [
1218
+ [
1219
+ "0x20c0000000000000000000000000000000000001",
1220
+ "0x989680",
1221
+ ],
1222
+ ],
1223
+ ],
1224
+ "0xfa78c5905fb0b9d6066ef531f962a62bc6ef0d5eb59ecb134056d206f75aaed7780926ff2601a935c2c79707d9e1799948c9f19dcdde1e090e903b19a07923d01c",
1225
+ ]
1226
+ `)
1227
+ })
1228
+
1229
+ test('with signature (p256)', () => {
1230
+ const authorization = KeyAuthorization.from({
1231
+ address,
1232
+ expiry,
1233
+ type: 'p256',
1234
+ limits: [
1235
+ {
1236
+ token,
1237
+ limit: Value.from('10', 6),
1238
+ },
1239
+ ],
1240
+ signature: signature_p256,
1241
+ })
1242
+
1243
+ const tuple = KeyAuthorization.toTuple(authorization)
1244
+
1245
+ expect(tuple).toMatchInlineSnapshot(`
1246
+ [
1247
+ [
1248
+ "0x",
1249
+ "0x01",
1250
+ "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1251
+ "0x499602d2",
1252
+ [
1253
+ [
1254
+ "0x20c0000000000000000000000000000000000001",
1255
+ "0x989680",
1256
+ ],
1257
+ ],
1258
+ ],
1259
+ "0x01ccbb3485d4726235f13cb15ef394fb7158179fb7b1925eccec0147671090c52e77c3c53373cc1e3b05e7c23f609deb17cea8fe097300c45411237e9fe4166b35ad8ac16e167d6992c3e120d7f17d2376bc1cbcf30c46ba6dd00ce07303e742f511edf6ce1c32de66846f56afa7be1cbd729bc35750b6d0cdcf3ec9d75461aba001",
1260
+ ]
1261
+ `)
1262
+ })
1263
+
1264
+ test('with signature (webAuthn)', () => {
1265
+ const authorization = KeyAuthorization.from({
1266
+ address,
1267
+ expiry,
1268
+ type: 'webAuthn',
1269
+ limits: [
1270
+ {
1271
+ token,
1272
+ limit: Value.from('10', 6),
1273
+ },
1274
+ ],
1275
+ signature: signature_webauthn,
1276
+ })
1277
+
1278
+ const tuple = KeyAuthorization.toTuple(authorization)
1279
+
1280
+ expect(tuple).toMatchInlineSnapshot(`
1281
+ [
1282
+ [
1283
+ "0x",
1284
+ "0x02",
1285
+ "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1286
+ "0x499602d2",
1287
+ [
1288
+ [
1289
+ "0x20c0000000000000000000000000000000000001",
1290
+ "0x989680",
1291
+ ],
1292
+ ],
1293
+ ],
1294
+ "0x0249960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d976305000000007b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a223371322d3777222c226f726967696e223a22687474703a2f2f6c6f63616c686f7374222c2263726f73734f726967696e223a66616c73657dccbb3485d4726235f13cb15ef394fb7158179fb7b1925eccec0147671090c52e77c3c53373cc1e3b05e7c23f609deb17cea8fe097300c45411237e9fe4166b35ad8ac16e167d6992c3e120d7f17d2376bc1cbcf30c46ba6dd00ce07303e742f511edf6ce1c32de66846f56afa7be1cbd729bc35750b6d0cdcf3ec9d75461aba0",
1295
+ ]
1296
+ `)
1297
+ })
1298
+
1299
+ test('multiple limits', () => {
1300
+ const authorization = KeyAuthorization.from({
1301
+ address,
1302
+ expiry,
1303
+ type: 'secp256k1',
1304
+ limits: [
1305
+ {
1306
+ token: '0x20c0000000000000000000000000000000000001',
1307
+ limit: Value.from('10', 6),
1308
+ },
1309
+ {
1310
+ token: '0x20c0000000000000000000000000000000000002',
1311
+ limit: Value.from('20', 6),
1312
+ },
1313
+ ],
1314
+ })
1315
+
1316
+ const tuple = KeyAuthorization.toTuple(authorization)
1317
+
1318
+ expect(tuple).toMatchInlineSnapshot(`
1319
+ [
1320
+ [
1321
+ "0x",
1322
+ "0x",
1323
+ "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1324
+ "0x499602d2",
1325
+ [
1326
+ [
1327
+ "0x20c0000000000000000000000000000000000001",
1328
+ "0x989680",
1329
+ ],
1330
+ [
1331
+ "0x20c0000000000000000000000000000000000002",
1332
+ "0x1312d00",
1333
+ ],
1334
+ ],
1335
+ ],
1336
+ ]
1337
+ `)
1338
+ })
1339
+
1340
+ test('with non-zero chainId', () => {
1341
+ const authorization = KeyAuthorization.from({
1342
+ address,
1343
+ chainId: 123n,
1344
+ expiry,
1345
+ type: 'secp256k1',
1346
+ limits: [
1347
+ {
1348
+ token,
1349
+ limit: Value.from('10', 6),
1350
+ },
1351
+ ],
1352
+ })
1353
+
1354
+ const tuple = KeyAuthorization.toTuple(authorization)
1355
+
1356
+ expect(tuple).toMatchInlineSnapshot(`
1357
+ [
1358
+ [
1359
+ "0x7b",
1360
+ "0x",
1361
+ "0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
1362
+ "0x499602d2",
1363
+ [
1364
+ [
1365
+ "0x20c0000000000000000000000000000000000001",
1366
+ "0x989680",
1367
+ ],
1368
+ ],
1369
+ ],
1370
+ ]
1371
+ `)
1372
+ })
1373
+ })