tempo.ts 0.0.0 → 0.0.2

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 (153) hide show
  1. package/README.md +92 -0
  2. package/dist/chains.d.ts +1477 -0
  3. package/dist/chains.d.ts.map +1 -0
  4. package/dist/chains.js +43 -0
  5. package/dist/chains.js.map +1 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/internal/types.d.ts +284 -0
  11. package/dist/internal/types.d.ts.map +1 -0
  12. package/dist/internal/types.js +2 -0
  13. package/dist/internal/types.js.map +1 -0
  14. package/dist/ox/TokenId.d.ts +18 -0
  15. package/dist/ox/TokenId.d.ts.map +1 -0
  16. package/dist/ox/TokenId.js +29 -0
  17. package/dist/ox/TokenId.js.map +1 -0
  18. package/dist/ox/TokenRole.d.ts +11 -0
  19. package/dist/ox/TokenRole.d.ts.map +1 -0
  20. package/dist/ox/TokenRole.js +22 -0
  21. package/dist/ox/TokenRole.js.map +1 -0
  22. package/dist/ox/Transaction.d.ts +161 -0
  23. package/dist/ox/Transaction.d.ts.map +1 -0
  24. package/dist/ox/Transaction.js +117 -0
  25. package/dist/ox/Transaction.js.map +1 -0
  26. package/dist/ox/TransactionEnvelopeFeeToken.d.ts +393 -0
  27. package/dist/ox/TransactionEnvelopeFeeToken.d.ts.map +1 -0
  28. package/dist/ox/TransactionEnvelopeFeeToken.js +452 -0
  29. package/dist/ox/TransactionEnvelopeFeeToken.js.map +1 -0
  30. package/dist/ox/TransactionRequest.d.ts +62 -0
  31. package/dist/ox/TransactionRequest.d.ts.map +1 -0
  32. package/dist/ox/TransactionRequest.js +66 -0
  33. package/dist/ox/TransactionRequest.js.map +1 -0
  34. package/dist/ox/index.d.ts +5 -0
  35. package/dist/ox/index.d.ts.map +1 -0
  36. package/dist/ox/index.js +5 -0
  37. package/dist/ox/index.js.map +1 -0
  38. package/dist/prool/Instance.d.ts +92 -0
  39. package/dist/prool/Instance.d.ts.map +1 -0
  40. package/dist/prool/Instance.js +96 -0
  41. package/dist/prool/Instance.js.map +1 -0
  42. package/dist/prool/index.d.ts +2 -0
  43. package/dist/prool/index.d.ts.map +1 -0
  44. package/dist/prool/index.js +2 -0
  45. package/dist/prool/index.js.map +1 -0
  46. package/dist/viem/abis.d.ts +2058 -0
  47. package/dist/viem/abis.d.ts.map +1 -0
  48. package/dist/viem/abis.js +1599 -0
  49. package/dist/viem/abis.js.map +1 -0
  50. package/dist/viem/actions/amm.d.ts +2091 -0
  51. package/dist/viem/actions/amm.d.ts.map +1 -0
  52. package/dist/viem/actions/amm.js +876 -0
  53. package/dist/viem/actions/amm.js.map +1 -0
  54. package/dist/viem/actions/fee.d.ts +727 -0
  55. package/dist/viem/actions/fee.d.ts.map +1 -0
  56. package/dist/viem/actions/fee.js +230 -0
  57. package/dist/viem/actions/fee.js.map +1 -0
  58. package/dist/viem/actions/index.d.ts +5 -0
  59. package/dist/viem/actions/index.d.ts.map +1 -0
  60. package/dist/viem/actions/index.js +5 -0
  61. package/dist/viem/actions/index.js.map +1 -0
  62. package/dist/viem/actions/policy.d.ts +1900 -0
  63. package/dist/viem/actions/policy.d.ts.map +1 -0
  64. package/dist/viem/actions/policy.js +841 -0
  65. package/dist/viem/actions/policy.js.map +1 -0
  66. package/dist/viem/actions/token.d.ts +13759 -0
  67. package/dist/viem/actions/token.d.ts.map +1 -0
  68. package/dist/viem/actions/token.js +2579 -0
  69. package/dist/viem/actions/token.js.map +1 -0
  70. package/dist/viem/addresses.d.ts +8 -0
  71. package/dist/viem/addresses.d.ts.map +1 -0
  72. package/dist/viem/addresses.js +8 -0
  73. package/dist/viem/addresses.js.map +1 -0
  74. package/dist/viem/chain.d.ts +341 -0
  75. package/dist/viem/chain.d.ts.map +1 -0
  76. package/dist/viem/chain.js +22 -0
  77. package/dist/viem/chain.js.map +1 -0
  78. package/dist/viem/client.d.ts +27 -0
  79. package/dist/viem/client.d.ts.map +1 -0
  80. package/dist/viem/client.js +28 -0
  81. package/dist/viem/client.js.map +1 -0
  82. package/dist/viem/decorator.d.ts +1636 -0
  83. package/dist/viem/decorator.d.ts.map +1 -0
  84. package/dist/viem/decorator.js +95 -0
  85. package/dist/viem/decorator.js.map +1 -0
  86. package/dist/viem/formatters.d.ts +4 -0
  87. package/dist/viem/formatters.d.ts.map +1 -0
  88. package/dist/viem/formatters.js +69 -0
  89. package/dist/viem/formatters.js.map +1 -0
  90. package/dist/viem/index.d.ts +10 -0
  91. package/dist/viem/index.d.ts.map +1 -0
  92. package/dist/viem/index.js +10 -0
  93. package/dist/viem/index.js.map +1 -0
  94. package/dist/viem/transaction.d.ts +54 -0
  95. package/dist/viem/transaction.d.ts.map +1 -0
  96. package/dist/viem/transaction.js +108 -0
  97. package/dist/viem/transaction.js.map +1 -0
  98. package/dist/viem/transport.d.ts +16 -0
  99. package/dist/viem/transport.d.ts.map +1 -0
  100. package/dist/viem/transport.js +33 -0
  101. package/dist/viem/transport.js.map +1 -0
  102. package/dist/viem/types.d.ts +10 -0
  103. package/dist/viem/types.d.ts.map +1 -0
  104. package/dist/viem/types.js +2 -0
  105. package/dist/viem/types.js.map +1 -0
  106. package/dist/viem/utils.d.ts +8 -0
  107. package/dist/viem/utils.d.ts.map +1 -0
  108. package/dist/viem/utils.js +9 -0
  109. package/dist/viem/utils.js.map +1 -0
  110. package/package.json +100 -2
  111. package/src/chains.ts +46 -0
  112. package/src/index.ts +1 -0
  113. package/src/internal/types.ts +414 -0
  114. package/src/ox/TokenId.test.ts +29 -0
  115. package/src/ox/TokenId.ts +35 -0
  116. package/src/ox/TokenRole.test.ts +20 -0
  117. package/src/ox/TokenRole.ts +27 -0
  118. package/src/ox/Transaction.test.ts +257 -0
  119. package/src/ox/Transaction.ts +247 -0
  120. package/src/ox/TransactionEnvelopeFeeToken.test.ts +1119 -0
  121. package/src/ox/TransactionEnvelopeFeeToken.ts +717 -0
  122. package/src/ox/TransactionRequest.ts +100 -0
  123. package/src/ox/index.ts +4 -0
  124. package/src/prool/Instance.test.ts +43 -0
  125. package/src/prool/Instance.ts +190 -0
  126. package/src/prool/index.ts +1 -0
  127. package/src/prool/internal/chain.json +106 -0
  128. package/src/prool/internal/consensus.toml +32 -0
  129. package/src/viem/abis.ts +1606 -0
  130. package/src/viem/actions/amm.test.ts +425 -0
  131. package/src/viem/actions/amm.ts +1308 -0
  132. package/src/viem/actions/fee.test.ts +281 -0
  133. package/src/viem/actions/fee.ts +362 -0
  134. package/src/viem/actions/index.ts +4 -0
  135. package/src/viem/actions/policy.test.ts +514 -0
  136. package/src/viem/actions/policy.ts +1284 -0
  137. package/src/viem/actions/token.test.ts +2172 -0
  138. package/src/viem/actions/token.ts +3830 -0
  139. package/src/viem/addresses.ts +10 -0
  140. package/src/viem/chain.ts +27 -0
  141. package/src/viem/client.bench-d.ts +8 -0
  142. package/src/viem/client.test.ts +152 -0
  143. package/src/viem/client.ts +91 -0
  144. package/src/viem/decorator.bench-d.ts +11 -0
  145. package/src/viem/decorator.test.ts +35 -0
  146. package/src/viem/decorator.ts +1914 -0
  147. package/src/viem/e2e.test.ts +410 -0
  148. package/src/viem/formatters.ts +100 -0
  149. package/src/viem/index.ts +9 -0
  150. package/src/viem/transaction.ts +253 -0
  151. package/src/viem/transport.ts +47 -0
  152. package/src/viem/types.ts +55 -0
  153. package/src/viem/utils.ts +37 -0
@@ -0,0 +1,1119 @@
1
+ import { Authorization, Hex, Rlp, RpcTransport, Secp256k1, Value } from 'ox'
2
+ import { TransactionEnvelopeFeeToken } from 'tempo.ts/ox'
3
+ import { Instance } from 'tempo.ts/prool'
4
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest'
5
+
6
+ const privateKey =
7
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
8
+ const privateKey2 =
9
+ '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d'
10
+
11
+ describe('assert', () => {
12
+ test('invalid chainId', () => {
13
+ expect(() =>
14
+ TransactionEnvelopeFeeToken.assert({
15
+ authorizationList: [
16
+ {
17
+ address: '0x0000000000000000000000000000000000000000',
18
+ chainId: -1,
19
+ nonce: 0n,
20
+ r: 0n,
21
+ s: 0n,
22
+ yParity: 0,
23
+ },
24
+ ],
25
+ chainId: 1,
26
+ }),
27
+ ).toThrowErrorMatchingInlineSnapshot(
28
+ `[TransactionEnvelope.InvalidChainIdError: Chain ID "-1" is invalid.]`,
29
+ )
30
+ })
31
+
32
+ test('invalid address', () => {
33
+ expect(() =>
34
+ TransactionEnvelopeFeeToken.assert({
35
+ authorizationList: [
36
+ {
37
+ address: '0x000000000000000000000000000000000000000z',
38
+ chainId: 0,
39
+ nonce: 0n,
40
+ r: 0n,
41
+ s: 0n,
42
+ yParity: 0,
43
+ },
44
+ ],
45
+ chainId: 1,
46
+ }),
47
+ ).toThrowErrorMatchingInlineSnapshot(
48
+ `
49
+ [Address.InvalidAddressError: Address "0x000000000000000000000000000000000000000z" is invalid.
50
+
51
+ Details: Address is not a 20 byte (40 hexadecimal character) value.]
52
+ `,
53
+ )
54
+ })
55
+
56
+ test('fee cap too high', () => {
57
+ expect(() =>
58
+ TransactionEnvelopeFeeToken.assert({
59
+ authorizationList: [
60
+ {
61
+ address: '0x0000000000000000000000000000000000000000',
62
+ chainId: 1,
63
+ nonce: 0n,
64
+ r: 0n,
65
+ s: 0n,
66
+ yParity: 0,
67
+ },
68
+ ],
69
+ maxFeePerGas: 2n ** 256n - 1n + 1n,
70
+ chainId: 1,
71
+ }),
72
+ ).toThrowErrorMatchingInlineSnapshot(
73
+ `[TransactionEnvelope.FeeCapTooHighError: The fee cap (\`maxFeePerGas\`/\`maxPriorityFeePerGas\` = 115792089237316195423570985008687907853269984665640564039457584007913.129639936 gwei) cannot be higher than the maximum allowed value (2^256-1).]`,
74
+ )
75
+ })
76
+ })
77
+
78
+ describe('deserialize', () => {
79
+ const transaction = TransactionEnvelopeFeeToken.from({
80
+ chainId: 1,
81
+ nonce: 785n,
82
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
83
+ value: Value.fromEther('1'),
84
+ maxFeePerGas: Value.fromGwei('2'),
85
+ maxPriorityFeePerGas: Value.fromGwei('2'),
86
+ })
87
+
88
+ test('default', () => {
89
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction)
90
+ const deserialized = TransactionEnvelopeFeeToken.deserialize(serialized)
91
+ expect(deserialized).toEqual(transaction)
92
+ })
93
+
94
+ test('minimal', () => {
95
+ const transaction = TransactionEnvelopeFeeToken.from({
96
+ chainId: 1,
97
+ nonce: 0n,
98
+ })
99
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction)
100
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
101
+ transaction,
102
+ )
103
+ })
104
+
105
+ test('authorizationList', () => {
106
+ const authorization = Authorization.from({
107
+ address: '0x0000000000000000000000000000000000000000',
108
+ chainId: 0,
109
+ nonce: 0n,
110
+ })
111
+
112
+ const signature = Secp256k1.sign({
113
+ payload: Authorization.getSignPayload(authorization),
114
+ privateKey,
115
+ })
116
+
117
+ const authorizationList = [Authorization.from(authorization, { signature })]
118
+
119
+ const transaction_authorizationList = TransactionEnvelopeFeeToken.from({
120
+ ...transaction,
121
+ authorizationList,
122
+ })
123
+ const serialized = TransactionEnvelopeFeeToken.serialize(
124
+ transaction_authorizationList,
125
+ )
126
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
127
+ transaction_authorizationList,
128
+ )
129
+ })
130
+
131
+ test('gas', () => {
132
+ const transaction_gas = TransactionEnvelopeFeeToken.from({
133
+ ...transaction,
134
+ gas: 21001n,
135
+ })
136
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction_gas)
137
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
138
+ transaction_gas,
139
+ )
140
+ })
141
+
142
+ test('accessList', () => {
143
+ const transaction_accessList = TransactionEnvelopeFeeToken.from({
144
+ ...transaction,
145
+ accessList: [
146
+ {
147
+ address: '0x0000000000000000000000000000000000000000',
148
+ storageKeys: [
149
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
150
+ '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe',
151
+ ],
152
+ },
153
+ ],
154
+ })
155
+ const serialized = TransactionEnvelopeFeeToken.serialize(
156
+ transaction_accessList,
157
+ )
158
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
159
+ transaction_accessList,
160
+ )
161
+ })
162
+
163
+ test('data', () => {
164
+ const transaction_data = TransactionEnvelopeFeeToken.from({
165
+ ...transaction,
166
+ data: '0x1234',
167
+ })
168
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction_data)
169
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
170
+ transaction_data,
171
+ )
172
+ })
173
+
174
+ test('signature', () => {
175
+ const signature = Secp256k1.sign({
176
+ payload: TransactionEnvelopeFeeToken.getSignPayload(transaction),
177
+ privateKey,
178
+ })
179
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction, {
180
+ signature,
181
+ })
182
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual({
183
+ ...transaction,
184
+ ...signature,
185
+ })
186
+ })
187
+
188
+ describe('raw', () => {
189
+ test('default', () => {
190
+ const serialized = `0x77${Rlp.fromHex([
191
+ Hex.fromNumber(1), // chainId
192
+ Hex.fromNumber(0), // nonce
193
+ Hex.fromNumber(1), // maxPriorityFeePerGas
194
+ Hex.fromNumber(1), // maxFeePerGas
195
+ Hex.fromNumber(1), // gas
196
+ '0x0000000000000000000000000000000000000000', // to
197
+ Hex.fromNumber(0), // value
198
+ '0x', // data
199
+ '0x', // accessList
200
+ '0x', // authorizationList
201
+ '0x', // feeToken
202
+ '0x', // feePayerSignature
203
+ ]).slice(2)}` as const
204
+ expect(
205
+ TransactionEnvelopeFeeToken.deserialize(serialized),
206
+ ).toMatchInlineSnapshot(`
207
+ {
208
+ "chainId": 1,
209
+ "gas": 1n,
210
+ "maxFeePerGas": 1n,
211
+ "maxPriorityFeePerGas": 1n,
212
+ "nonce": 0n,
213
+ "to": "0x0000000000000000000000000000000000000000",
214
+ "type": "feeToken",
215
+ "value": 0n,
216
+ }
217
+ `)
218
+ })
219
+
220
+ test('empty sig', () => {
221
+ const serialized = `0x77${Rlp.fromHex([
222
+ Hex.fromNumber(1), // chainId
223
+ Hex.fromNumber(0), // nonce
224
+ Hex.fromNumber(1), // maxPriorityFeePerGas
225
+ Hex.fromNumber(1), // maxFeePerGas
226
+ Hex.fromNumber(1), // gas
227
+ '0x0000000000000000000000000000000000000000', // to
228
+ Hex.fromNumber(0), // value
229
+ '0x', // data
230
+ '0x', // accessList
231
+ '0x', // authorizationList
232
+ '0x', // feeToken
233
+ '0x', // feePayerSignature
234
+ '0x', // r
235
+ '0x', // v
236
+ '0x', // s
237
+ ]).slice(2)}` as const
238
+ expect(
239
+ TransactionEnvelopeFeeToken.deserialize(serialized),
240
+ ).toMatchInlineSnapshot(`
241
+ {
242
+ "chainId": 1,
243
+ "gas": 1n,
244
+ "maxFeePerGas": 1n,
245
+ "maxPriorityFeePerGas": 1n,
246
+ "nonce": 0n,
247
+ "r": 0n,
248
+ "s": 0n,
249
+ "to": "0x0000000000000000000000000000000000000000",
250
+ "type": "feeToken",
251
+ "value": 0n,
252
+ "yParity": 0,
253
+ }
254
+ `)
255
+ })
256
+
257
+ test('low sig coords', () => {
258
+ const serialized = `0x77${Rlp.fromHex([
259
+ Hex.fromNumber(1), // chainId
260
+ Hex.fromNumber(0), // nonce
261
+ Hex.fromNumber(1), // maxPriorityFeePerGas
262
+ Hex.fromNumber(1), // maxFeePerGas
263
+ Hex.fromNumber(1), // gas
264
+ '0x0000000000000000000000000000000000000000', // to
265
+ Hex.fromNumber(0), // value
266
+ '0x', // data
267
+ '0x', // accessList
268
+ '0x', // authorizationList
269
+ '0x', // feeToken
270
+ '0x', // feePayerSignature
271
+ '0x', // r
272
+ Hex.fromNumber(69), // v
273
+ Hex.fromNumber(420), // s
274
+ ]).slice(2)}` as const
275
+ expect(
276
+ TransactionEnvelopeFeeToken.deserialize(serialized),
277
+ ).toMatchInlineSnapshot(`
278
+ {
279
+ "chainId": 1,
280
+ "gas": 1n,
281
+ "maxFeePerGas": 1n,
282
+ "maxPriorityFeePerGas": 1n,
283
+ "nonce": 0n,
284
+ "r": 69n,
285
+ "s": 420n,
286
+ "to": "0x0000000000000000000000000000000000000000",
287
+ "type": "feeToken",
288
+ "value": 0n,
289
+ "yParity": 0,
290
+ }
291
+ `)
292
+ })
293
+ })
294
+
295
+ describe('errors', () => {
296
+ test('invalid access list (invalid address)', () => {
297
+ expect(() =>
298
+ TransactionEnvelopeFeeToken.deserialize(
299
+ `0x77${Rlp.fromHex([
300
+ Hex.fromNumber(1), // chainId
301
+ Hex.fromNumber(0), // nonce
302
+ Hex.fromNumber(1), // maxPriorityFeePerGas
303
+ Hex.fromNumber(1), // maxFeePerGas
304
+ Hex.fromNumber(1), // gas
305
+ '0x0000000000000000000000000000000000000000', // to
306
+ Hex.fromNumber(0), // value
307
+ '0x', // data
308
+ [
309
+ [
310
+ '0x',
311
+ [
312
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
313
+ ],
314
+ ],
315
+ ], // accessList
316
+ '0x', // authorizationList
317
+ ]).slice(2)}`,
318
+ ),
319
+ ).toThrowErrorMatchingInlineSnapshot(`
320
+ [TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "feeToken" was provided.
321
+
322
+ Serialized Transaction: "0x77f84201000101019400000000000000000000000000000000000000000080e4e380e1a0000000000000000000000000000000000000000000000000000000000000000180"
323
+ Missing Attributes: feeToken, feePayerSignatureOrSender, yParity, r, s]
324
+ `)
325
+
326
+ expect(() =>
327
+ TransactionEnvelopeFeeToken.deserialize(
328
+ `0x77${Rlp.fromHex([
329
+ Hex.fromNumber(1), // chainId
330
+ Hex.fromNumber(0), // nonce
331
+ Hex.fromNumber(1), // maxPriorityFeePerGas
332
+ Hex.fromNumber(1), // maxFeePerGas
333
+ Hex.fromNumber(1), // gas
334
+ '0x0000000000000000000000000000000000000000', // to
335
+ Hex.fromNumber(0), // value
336
+ '0x', // data
337
+ [['0x123456', ['0x0']]], // accessList
338
+ '0x', // authorizationList
339
+ ]).slice(2)}`,
340
+ ),
341
+ ).toThrowErrorMatchingInlineSnapshot(`
342
+ [TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "feeToken" was provided.
343
+
344
+ Serialized Transaction: "0x77e501000101019400000000000000000000000000000000000000000080c7c683123456c10080"
345
+ Missing Attributes: feeToken, feePayerSignatureOrSender, yParity, r, s]
346
+ `)
347
+ })
348
+
349
+ test('invalid transaction (all missing)', () => {
350
+ expect(() =>
351
+ TransactionEnvelopeFeeToken.deserialize(
352
+ `0x77${Rlp.fromHex([]).slice(2)}`,
353
+ ),
354
+ ).toThrowErrorMatchingInlineSnapshot(`
355
+ [TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "feeToken" was provided.
356
+
357
+ Serialized Transaction: "0x77c0"
358
+ Missing Attributes: chainId, nonce, feeToken, maxPriorityFeePerGas, maxFeePerGas, gas, to, value, data, accessList, authorizationList, feePayerSignatureOrSender]
359
+ `)
360
+ })
361
+
362
+ test('invalid transaction (some missing)', () => {
363
+ expect(() =>
364
+ TransactionEnvelopeFeeToken.deserialize(
365
+ `0x77${Rlp.fromHex(['0x00', '0x01']).slice(2)}`,
366
+ ),
367
+ ).toThrowErrorMatchingInlineSnapshot(`
368
+ [TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "feeToken" was provided.
369
+
370
+ Serialized Transaction: "0x77c20001"
371
+ Missing Attributes: feeToken, maxPriorityFeePerGas, maxFeePerGas, gas, to, value, data, accessList, authorizationList, feePayerSignatureOrSender]
372
+ `)
373
+ })
374
+
375
+ test('invalid transaction (missing signature)', () => {
376
+ expect(() =>
377
+ TransactionEnvelopeFeeToken.deserialize(
378
+ `0x77${Rlp.fromHex([
379
+ '0x',
380
+ '0x',
381
+ '0x',
382
+ '0x',
383
+ '0x',
384
+ '0x',
385
+ '0x',
386
+ '0x',
387
+ '0x',
388
+ '0x',
389
+ '0x',
390
+ '0x',
391
+ '0x',
392
+ ]).slice(2)}`,
393
+ ),
394
+ ).toThrowErrorMatchingInlineSnapshot(`
395
+ [TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "feeToken" was provided.
396
+
397
+ Serialized Transaction: "0x77cd80808080808080808080808080"
398
+ Missing Attributes: r, s]
399
+ `)
400
+ })
401
+ })
402
+ })
403
+
404
+ describe('from', () => {
405
+ test('default', () => {
406
+ {
407
+ const envelope = TransactionEnvelopeFeeToken.from({
408
+ chainId: 1,
409
+ nonce: 0n,
410
+ })
411
+ expect(envelope).toMatchInlineSnapshot(`
412
+ {
413
+ "chainId": 1,
414
+ "nonce": 0n,
415
+ "type": "feeToken",
416
+ }
417
+ `)
418
+ const serialized = TransactionEnvelopeFeeToken.serialize(envelope)
419
+ const envelope2 = TransactionEnvelopeFeeToken.from(serialized)
420
+ expect(envelope2).toEqual(envelope)
421
+ }
422
+
423
+ {
424
+ const envelope = TransactionEnvelopeFeeToken.from({
425
+ chainId: 1,
426
+ nonce: 0n,
427
+ r: 0n,
428
+ s: 1n,
429
+ yParity: 0,
430
+ })
431
+ expect(envelope).toMatchInlineSnapshot(`
432
+ {
433
+ "chainId": 1,
434
+ "nonce": 0n,
435
+ "r": 0n,
436
+ "s": 1n,
437
+ "type": "feeToken",
438
+ "yParity": 0,
439
+ }
440
+ `)
441
+ const serialized = TransactionEnvelopeFeeToken.serialize(envelope)
442
+ const envelope2 = TransactionEnvelopeFeeToken.from(serialized)
443
+ expect(envelope2).toEqual(envelope)
444
+ }
445
+ })
446
+
447
+ test('options: signature', () => {
448
+ const envelope = TransactionEnvelopeFeeToken.from(
449
+ {
450
+ chainId: 1,
451
+ nonce: 0n,
452
+ },
453
+ {
454
+ signature: {
455
+ r: 0n,
456
+ s: 1n,
457
+ yParity: 0,
458
+ },
459
+ },
460
+ )
461
+ expect(envelope).toMatchInlineSnapshot(`
462
+ {
463
+ "chainId": 1,
464
+ "nonce": 0n,
465
+ "r": 0n,
466
+ "s": 1n,
467
+ "type": "feeToken",
468
+ "yParity": 0,
469
+ }
470
+ `)
471
+ const serialized = TransactionEnvelopeFeeToken.serialize(envelope)
472
+ const envelope2 = TransactionEnvelopeFeeToken.from(serialized)
473
+ expect(envelope2).toEqual(envelope)
474
+ })
475
+
476
+ test('options: feePayerSignature', () => {
477
+ const envelope = TransactionEnvelopeFeeToken.from(
478
+ {
479
+ chainId: 1,
480
+ nonce: 0n,
481
+ r: 1n,
482
+ s: 2n,
483
+ yParity: 0,
484
+ },
485
+ {
486
+ feePayerSignature: {
487
+ r: 0n,
488
+ s: 1n,
489
+ yParity: 0,
490
+ },
491
+ },
492
+ )
493
+ expect(envelope).toMatchInlineSnapshot(`
494
+ {
495
+ "chainId": 1,
496
+ "feePayerSignature": {
497
+ "r": 0n,
498
+ "s": 1n,
499
+ "yParity": 0,
500
+ },
501
+ "nonce": 0n,
502
+ "r": 1n,
503
+ "s": 2n,
504
+ "type": "feeToken",
505
+ "yParity": 0,
506
+ }
507
+ `)
508
+ const serialized = TransactionEnvelopeFeeToken.serialize(envelope)
509
+ const envelope2 = TransactionEnvelopeFeeToken.from(serialized)
510
+ expect(envelope2).toEqual(envelope)
511
+ })
512
+ })
513
+
514
+ describe('getSignPayload', () => {
515
+ test('default', () => {
516
+ const authorization = Authorization.from({
517
+ address: '0x0000000000000000000000000000000000000000',
518
+ chainId: 1,
519
+ nonce: 785n,
520
+ })
521
+ const signature_auth = Secp256k1.sign({
522
+ payload: Authorization.getSignPayload(authorization),
523
+ privateKey,
524
+ })
525
+
526
+ const envelope = TransactionEnvelopeFeeToken.from({
527
+ authorizationList: [
528
+ Authorization.from(authorization, { signature: signature_auth }),
529
+ ],
530
+ chainId: 1,
531
+ gas: 21000n,
532
+ maxFeePerGas: 13000000000n,
533
+ maxPriorityFeePerGas: 1000000000n,
534
+ nonce: 665n,
535
+ value: 1000000000000000000n,
536
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
537
+ })
538
+
539
+ const signature = Secp256k1.sign({
540
+ payload: TransactionEnvelopeFeeToken.getSignPayload(envelope),
541
+ privateKey,
542
+ })
543
+
544
+ const envelope_signed = TransactionEnvelopeFeeToken.from(envelope, {
545
+ signature,
546
+ })
547
+
548
+ expect(envelope_signed).toMatchInlineSnapshot(`
549
+ {
550
+ "authorizationList": [
551
+ {
552
+ "address": "0x0000000000000000000000000000000000000000",
553
+ "chainId": 1,
554
+ "nonce": 785n,
555
+ "r": 45905576947909600150892513825393874260108741328435165924126757974077129494832n,
556
+ "s": 48243644890612770021063037464756173394424732895207796335842780877380370396087n,
557
+ "yParity": 0,
558
+ },
559
+ ],
560
+ "chainId": 1,
561
+ "gas": 21000n,
562
+ "maxFeePerGas": 13000000000n,
563
+ "maxPriorityFeePerGas": 1000000000n,
564
+ "nonce": 665n,
565
+ "r": 2197655434111937974218303607195887458649942608682485837450202937256281617344n,
566
+ "s": 45514547126785856401831290616133478750134795595263686266026091483746271601472n,
567
+ "to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
568
+ "type": "feeToken",
569
+ "value": 1000000000000000000n,
570
+ "yParity": 0,
571
+ }
572
+ `)
573
+ })
574
+ })
575
+
576
+ describe('hash', () => {
577
+ test('default', () => {
578
+ const envelope = TransactionEnvelopeFeeToken.from({
579
+ authorizationList: [],
580
+ chainId: 1,
581
+ gas: 21000n,
582
+ maxFeePerGas: 13000000000n,
583
+ maxPriorityFeePerGas: 1000000000n,
584
+ nonce: 665n,
585
+ value: 1000000000000000000n,
586
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
587
+ r: BigInt(
588
+ '0xacf664dcd984d082b68c434feb66ac684711babdeefe6f101bf8df88fc367a37',
589
+ ),
590
+ s: BigInt(
591
+ '0x5e0800058a9b5c2250bed60ee969a45b7445e562a8298c2d222d114e6dfbfcb9',
592
+ ),
593
+ yParity: 0,
594
+ })
595
+
596
+ const hash = TransactionEnvelopeFeeToken.hash(envelope)
597
+ expect(hash).toMatchInlineSnapshot(
598
+ `"0x28ff6c475c6bc8e5ac460a9fa89ef29c3de20e35f128e5c2b36946a67df572c9"`,
599
+ )
600
+ })
601
+
602
+ test('behavior: presign', () => {
603
+ const envelope = TransactionEnvelopeFeeToken.from({
604
+ authorizationList: [],
605
+ chainId: 1,
606
+ gas: 21000n,
607
+ maxFeePerGas: 13000000000n,
608
+ maxPriorityFeePerGas: 1000000000n,
609
+ nonce: 665n,
610
+ value: 1000000000000000000n,
611
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
612
+ r: BigInt(
613
+ '0xacf664dcd984d082b68c434feb66ac684711babdeefe6f101bf8df88fc367a37',
614
+ ),
615
+ s: BigInt(
616
+ '0x5e0800058a9b5c2250bed60ee969a45b7445e562a8298c2d222d114e6dfbfcb9',
617
+ ),
618
+ yParity: 0,
619
+ })
620
+
621
+ const hash = TransactionEnvelopeFeeToken.hash(envelope, { presign: true })
622
+ expect(hash).toMatchInlineSnapshot(
623
+ `"0x19c3cd0e89bbd10237160f3d6b28c5bc41494ea31dc54ceb7d6cad9a48fae7b4"`,
624
+ )
625
+ })
626
+ })
627
+
628
+ describe('serialize', () => {
629
+ const transaction = TransactionEnvelopeFeeToken.from({
630
+ chainId: 1,
631
+ nonce: 785n,
632
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
633
+ value: Value.fromEther('1'),
634
+ maxFeePerGas: Value.fromGwei('2'),
635
+ maxPriorityFeePerGas: Value.fromGwei('2'),
636
+ })
637
+
638
+ test('default', () => {
639
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction)
640
+ expect(serialized).toMatchInlineSnapshot(
641
+ `"0x77f20182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c08080"`,
642
+ )
643
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
644
+ transaction,
645
+ )
646
+ })
647
+
648
+ test('default (all zeros)', () => {
649
+ const transaction = TransactionEnvelopeFeeToken.from({
650
+ to: undefined,
651
+ nonce: 0n,
652
+ chainId: 1,
653
+ maxFeePerGas: 0n,
654
+ maxPriorityFeePerGas: 0n,
655
+ value: 0n,
656
+ })
657
+
658
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction)
659
+
660
+ expect(serialized).toMatchInlineSnapshot(`"0x77cc0180808080808080c0c08080"`)
661
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual({
662
+ chainId: 1,
663
+ nonce: 0n,
664
+ type: 'feeToken',
665
+ })
666
+ })
667
+
668
+ test('minimal (w/ type)', () => {
669
+ const transaction = TransactionEnvelopeFeeToken.from({
670
+ chainId: 1,
671
+ nonce: 0n,
672
+ })
673
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction)
674
+ expect(serialized).toMatchInlineSnapshot(`"0x77cc0180808080808080c0c08080"`)
675
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
676
+ transaction,
677
+ )
678
+ })
679
+
680
+ test('minimal (w/ maxFeePerGas)', () => {
681
+ const transaction = TransactionEnvelopeFeeToken.from({
682
+ chainId: 1,
683
+ maxFeePerGas: 1n,
684
+ nonce: 0n,
685
+ })
686
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction)
687
+ expect(serialized).toMatchInlineSnapshot(`"0x77cc0180800180808080c0c08080"`)
688
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
689
+ transaction,
690
+ )
691
+ })
692
+
693
+ test('authorizationList', () => {
694
+ const authorization = Authorization.from({
695
+ address: '0x0000000000000000000000000000000000000000',
696
+ chainId: 0,
697
+ nonce: 0n,
698
+ })
699
+
700
+ const signature = Secp256k1.sign({
701
+ payload: Authorization.getSignPayload(authorization),
702
+ privateKey,
703
+ })
704
+
705
+ const authorizationList = [Authorization.from(authorization, { signature })]
706
+
707
+ const transaction_authorizationList = TransactionEnvelopeFeeToken.from({
708
+ ...transaction,
709
+ authorizationList,
710
+ })
711
+ const serialized = TransactionEnvelopeFeeToken.serialize(
712
+ transaction_authorizationList,
713
+ )
714
+ expect(serialized).toMatchInlineSnapshot(
715
+ `"0x77f88f0182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0f85cf85a809400000000000000000000000000000000000000008001a0aa64791de483fa82224c2beeba9ee4c89323db0d1a39c24bcfa555b8d3c31aa9a03cdeba27b1c512236967597d1352b6d71239bebde01237ca72b26d6fd218cb978080"`,
716
+ )
717
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
718
+ transaction_authorizationList,
719
+ )
720
+ })
721
+
722
+ test('gas', () => {
723
+ const transaction_gas = TransactionEnvelopeFeeToken.from({
724
+ ...transaction,
725
+ gas: 21001n,
726
+ })
727
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction_gas)
728
+ expect(serialized).toMatchInlineSnapshot(
729
+ `"0x77f401820311847735940084773594008252099470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c08080"`,
730
+ )
731
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
732
+ transaction_gas,
733
+ )
734
+ })
735
+
736
+ test('feeToken', () => {
737
+ const transaction_feeToken = TransactionEnvelopeFeeToken.from({
738
+ ...transaction,
739
+ feeToken: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
740
+ })
741
+ const serialized =
742
+ TransactionEnvelopeFeeToken.serialize(transaction_feeToken)
743
+ expect(serialized).toMatchInlineSnapshot(
744
+ `"0x77f8460182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c094deadbeefdeadbeefdeadbeefdeadbeefdeadbeef80"`,
745
+ )
746
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
747
+ transaction_feeToken,
748
+ )
749
+ })
750
+
751
+ test('accessList', () => {
752
+ const transaction_accessList = TransactionEnvelopeFeeToken.from({
753
+ ...transaction,
754
+ accessList: [
755
+ {
756
+ address: '0x0000000000000000000000000000000000000000',
757
+ storageKeys: [
758
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
759
+ '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe',
760
+ ],
761
+ },
762
+ ],
763
+ })
764
+ const serialized = TransactionEnvelopeFeeToken.serialize(
765
+ transaction_accessList,
766
+ )
767
+ expect(serialized).toMatchInlineSnapshot(
768
+ `"0x77f88e0182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000001a060fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fec08080"`,
769
+ )
770
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
771
+ transaction_accessList,
772
+ )
773
+ })
774
+
775
+ test('data', () => {
776
+ const transaction_data = TransactionEnvelopeFeeToken.from({
777
+ ...transaction,
778
+ data: '0x1234',
779
+ })
780
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction_data)
781
+ expect(serialized).toMatchInlineSnapshot(
782
+ `"0x77f40182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a7640000821234c0c08080"`,
783
+ )
784
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual(
785
+ transaction_data,
786
+ )
787
+ })
788
+
789
+ test('options: signature', async () => {
790
+ const signature = Secp256k1.sign({
791
+ payload: TransactionEnvelopeFeeToken.getSignPayload(transaction),
792
+ privateKey,
793
+ })
794
+ const serialized = TransactionEnvelopeFeeToken.serialize(transaction, {
795
+ signature,
796
+ })
797
+ expect(serialized).toMatchInlineSnapshot(
798
+ `"0x77f8750182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c0808001a069cf330f0a61a4d7712f2cbbb933eafc1ed6be732cf49b7269c782bb301c727ea0474916716fd0000d30e69a7b629697f04b542cc6abcb3c4e61dfdf3e9541dcc7"`,
799
+ )
800
+ expect(TransactionEnvelopeFeeToken.deserialize(serialized)).toEqual({
801
+ ...transaction,
802
+ ...signature,
803
+ })
804
+ })
805
+
806
+ test('options: signature', () => {
807
+ expect(
808
+ TransactionEnvelopeFeeToken.serialize(transaction, {
809
+ signature: {
810
+ r: BigInt(
811
+ '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe',
812
+ ),
813
+ s: BigInt(
814
+ '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe',
815
+ ),
816
+ yParity: 1,
817
+ },
818
+ }),
819
+ ).toMatchInlineSnapshot(
820
+ `"0x77f8750182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c0808001a060fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fea060fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe"`,
821
+ )
822
+
823
+ expect(
824
+ TransactionEnvelopeFeeToken.serialize(transaction, {
825
+ signature: {
826
+ r: BigInt(
827
+ '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe',
828
+ ),
829
+ s: BigInt(
830
+ '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe',
831
+ ),
832
+ yParity: 0,
833
+ },
834
+ }),
835
+ ).toMatchInlineSnapshot(
836
+ `"0x77f8750182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c0808080a060fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fea060fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe"`,
837
+ )
838
+
839
+ expect(
840
+ TransactionEnvelopeFeeToken.serialize(transaction, {
841
+ signature: {
842
+ r: 0n,
843
+ s: 0n,
844
+ yParity: 0,
845
+ },
846
+ }),
847
+ ).toMatchInlineSnapshot(
848
+ `"0x77f50182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c08080808080"`,
849
+ )
850
+ })
851
+
852
+ test('options: feePayerSignature', async () => {
853
+ const signature = Secp256k1.sign({
854
+ payload: TransactionEnvelopeFeeToken.getSignPayload(transaction),
855
+ privateKey,
856
+ })
857
+ const transaction_signed = TransactionEnvelopeFeeToken.from(transaction, {
858
+ signature,
859
+ })
860
+
861
+ const sender = Secp256k1.recoverAddress({
862
+ payload: TransactionEnvelopeFeeToken.getSignPayload(transaction),
863
+ signature,
864
+ })
865
+
866
+ const feePayerSignature = Secp256k1.sign({
867
+ payload: TransactionEnvelopeFeeToken.getFeePayerSignPayload(
868
+ transaction_signed,
869
+ {
870
+ sender,
871
+ },
872
+ ),
873
+ privateKey: privateKey2,
874
+ })
875
+ const serialized_feePayer = TransactionEnvelopeFeeToken.serialize(
876
+ transaction_signed,
877
+ {
878
+ feePayerSignature,
879
+ },
880
+ )
881
+
882
+ expect(serialized_feePayer).toMatchInlineSnapshot(
883
+ `"0x77f8b90182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0c080f84380a0e64a93976c4cfd0ab07d40d58ef3f80f8c9dcc71c78c78b063654c7cab16326ba0090430ef7278d4d0ca33832eab5f92161cbf05e0b8b4db309ef9b5fe0b2a31ef01a069cf330f0a61a4d7712f2cbbb933eafc1ed6be732cf49b7269c782bb301c727ea0474916716fd0000d30e69a7b629697f04b542cc6abcb3c4e61dfdf3e9541dcc7"`,
884
+ )
885
+ expect(
886
+ TransactionEnvelopeFeeToken.deserialize(serialized_feePayer),
887
+ ).toEqual({
888
+ ...transaction,
889
+ ...signature,
890
+ feePayerSignature,
891
+ })
892
+ })
893
+ })
894
+
895
+ describe('validate', () => {
896
+ test('default', () => {
897
+ expect(
898
+ TransactionEnvelopeFeeToken.validate({
899
+ authorizationList: [],
900
+ chainId: 1,
901
+ }),
902
+ ).toBe(true)
903
+ expect(
904
+ TransactionEnvelopeFeeToken.validate({
905
+ authorizationList: [],
906
+ maxFeePerGas: 2n ** 257n,
907
+ chainId: 1,
908
+ }),
909
+ ).toBe(false)
910
+ })
911
+ })
912
+
913
+ test('exports', () => {
914
+ expect(Object.keys(TransactionEnvelopeFeeToken)).toMatchInlineSnapshot(`
915
+ [
916
+ "feePayerMagic",
917
+ "serializedType",
918
+ "type",
919
+ "assert",
920
+ "deserialize",
921
+ "from",
922
+ "getFeePayerSignPayload",
923
+ "getSignPayload",
924
+ "hash",
925
+ "serialize",
926
+ "validate",
927
+ ]
928
+ `)
929
+ })
930
+
931
+ describe('e2e', () => {
932
+ const node = Instance.tempo({ port: 3000 })
933
+ beforeEach(() => node.start())
934
+ afterEach(() => node.stop())
935
+
936
+ test('behavior: default', async () => {
937
+ const address = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
938
+ const privateKey =
939
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
940
+
941
+ const transport = RpcTransport.fromHttp('http://localhost:3000')
942
+
943
+ const nonce = await transport.request({
944
+ method: 'eth_getTransactionCount',
945
+ params: [address, 'pending'],
946
+ })
947
+
948
+ const transaction = TransactionEnvelopeFeeToken.from({
949
+ chainId: 1337,
950
+ feeToken: '0x20c0000000000000000000000000000000000000',
951
+ nonce: BigInt(nonce),
952
+ gas: 21000n,
953
+ to: '0x0000000000000000000000000000000000000000',
954
+ value: Value.fromEther('1'),
955
+ maxFeePerGas: Value.fromGwei('20'),
956
+ maxPriorityFeePerGas: Value.fromGwei('10'),
957
+ })
958
+
959
+ const signature = Secp256k1.sign({
960
+ payload: TransactionEnvelopeFeeToken.getSignPayload(transaction),
961
+ privateKey,
962
+ })
963
+
964
+ const serialized_signed = TransactionEnvelopeFeeToken.serialize(
965
+ transaction,
966
+ {
967
+ signature,
968
+ },
969
+ )
970
+
971
+ const receipt = await transport.request({
972
+ method: 'eth_sendRawTransactionSync',
973
+ params: [serialized_signed],
974
+ })
975
+
976
+ expect(receipt).toBeDefined()
977
+
978
+ {
979
+ const response = await transport.request({
980
+ method: 'eth_getTransactionByHash',
981
+ params: [receipt.transactionHash],
982
+ })
983
+ if (!response) throw new Error()
984
+
985
+ const { blockNumber, blockHash, ...rest } = response
986
+
987
+ expect(blockNumber).toBeDefined()
988
+ expect(blockHash).toBeDefined()
989
+ expect(rest).toMatchInlineSnapshot(`
990
+ {
991
+ "accessList": [],
992
+ "authorizationList": [],
993
+ "chainId": "0x539",
994
+ "feePayerSignature": null,
995
+ "feeToken": "0x20c0000000000000000000000000000000000000",
996
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
997
+ "gas": "0x5208",
998
+ "gasPrice": "0x2540be42c",
999
+ "hash": "0xffec2c3aee1b7ce955120c950286eb3d4f758685e440855a220ff341d6d665d7",
1000
+ "input": "0x",
1001
+ "maxFeePerGas": "0x4a817c800",
1002
+ "maxPriorityFeePerGas": "0x2540be400",
1003
+ "nonce": "0x0",
1004
+ "r": "0xa95419f113415ccb9d7f0041e6989d09e031dc21a1605849edaddd72cff286ea",
1005
+ "s": "0x56b4faf46d2b07c294c4efa2db09e669a50b018d51b94529987d53ff011e09ee",
1006
+ "to": "0x0000000000000000000000000000000000000000",
1007
+ "transactionIndex": "0x0",
1008
+ "type": "0x77",
1009
+ "v": "0x1",
1010
+ "value": "0xde0b6b3a7640000",
1011
+ "yParity": "0x1",
1012
+ }
1013
+ `)
1014
+ }
1015
+
1016
+ const { blockNumber, blockHash, ...rest } = receipt
1017
+
1018
+ expect(blockNumber).toBeDefined()
1019
+ expect(blockHash).toBeDefined()
1020
+ expect(rest).toMatchInlineSnapshot(`
1021
+ {
1022
+ "contractAddress": null,
1023
+ "cumulativeGasUsed": "0x5208",
1024
+ "effectiveGasPrice": "0x2540be42c",
1025
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
1026
+ "gasUsed": "0x5208",
1027
+ "logs": [],
1028
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
1029
+ "status": "0x0",
1030
+ "to": "0x0000000000000000000000000000000000000000",
1031
+ "transactionHash": "0xffec2c3aee1b7ce955120c950286eb3d4f758685e440855a220ff341d6d665d7",
1032
+ "transactionIndex": "0x0",
1033
+ "type": "0x77",
1034
+ }
1035
+ `)
1036
+ })
1037
+
1038
+ test('behavior: feePayerSignature (user → feePayer)', async () => {
1039
+ const feePayer = {
1040
+ address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
1041
+ privateKey:
1042
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
1043
+ } as const
1044
+ const sender = {
1045
+ address: '0x0a275bEE91B39092Dfd57089Dee0EB0539020B90',
1046
+ privateKey:
1047
+ '0xfe24691eff5297c76e847dc78a8966b96cf65a44140b9a0d3f5100ce71d74a59',
1048
+ } as const
1049
+
1050
+ const transport = RpcTransport.fromHttp('http://localhost:3000')
1051
+
1052
+ const nonce = await transport.request({
1053
+ method: 'eth_getTransactionCount',
1054
+ params: [sender.address, 'pending'],
1055
+ })
1056
+
1057
+ const transaction = TransactionEnvelopeFeeToken.from({
1058
+ chainId: 1337,
1059
+ feePayerSignature: null,
1060
+ nonce: BigInt(nonce),
1061
+ gas: 21000n,
1062
+ to: '0x0000000000000000000000000000000000000000',
1063
+ value: 0n,
1064
+ maxFeePerGas: Hex.toBigInt('0x59'),
1065
+ maxPriorityFeePerGas: Hex.toBigInt('0x59'),
1066
+ })
1067
+
1068
+ const signature = Secp256k1.sign({
1069
+ payload: TransactionEnvelopeFeeToken.getSignPayload(transaction),
1070
+ // unfunded PK
1071
+ privateKey: sender.privateKey,
1072
+ })
1073
+
1074
+ const transaction_signed = TransactionEnvelopeFeeToken.from(transaction, {
1075
+ signature,
1076
+ })
1077
+
1078
+ const feePayerSignature = Secp256k1.sign({
1079
+ payload: TransactionEnvelopeFeeToken.getFeePayerSignPayload(
1080
+ transaction_signed,
1081
+ { sender: sender.address },
1082
+ ),
1083
+ privateKey: feePayer.privateKey,
1084
+ })
1085
+
1086
+ const serialized_signed = TransactionEnvelopeFeeToken.serialize(
1087
+ transaction_signed,
1088
+ {
1089
+ feePayerSignature,
1090
+ },
1091
+ )
1092
+
1093
+ const receipt = await transport.request({
1094
+ method: 'eth_sendRawTransactionSync',
1095
+ params: [serialized_signed],
1096
+ })
1097
+
1098
+ const { blockNumber, blockHash, ...rest } = receipt
1099
+
1100
+ expect(blockNumber).toBeDefined()
1101
+ expect(blockHash).toBeDefined()
1102
+ expect(rest).toMatchInlineSnapshot(`
1103
+ {
1104
+ "contractAddress": null,
1105
+ "cumulativeGasUsed": "0x5208",
1106
+ "effectiveGasPrice": "0x59",
1107
+ "from": "0x0a275bee91b39092dfd57089dee0eb0539020b90",
1108
+ "gasUsed": "0x5208",
1109
+ "logs": [],
1110
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
1111
+ "status": "0x1",
1112
+ "to": "0x0000000000000000000000000000000000000000",
1113
+ "transactionHash": "0x872e61efb1d53706b955f7a0dfc14de5a060bffb1237b32ca7ace529329d3ffd",
1114
+ "transactionIndex": "0x0",
1115
+ "type": "0x77",
1116
+ }
1117
+ `)
1118
+ })
1119
+ })