UNPKG

ox

Version:

Ethereum Standard Library

231 lines (221 loc) 6.04 kB
import { describe, expect, test } from 'vp/test' import * as z_Transaction from '../Transaction.js' import * as z from 'zod/mini' const address = '0x0000000000000000000000000000000000000000' const hash = `0x${'11'.repeat(32)}` as const const r = `0x${'22'.repeat(32)}` as const const s = `0x${'33'.repeat(32)}` as const const baseRpc = { blockHash: hash, blockNumber: '0x1', chainId: '0x1', from: address, gas: '0x5208', hash, input: '0xdeadbeef', nonce: '0x2', r, s, to: address, transactionIndex: '0x0', value: '0x3', yParity: '0x1', } as const const base = { blockHash: hash, blockNumber: 1n, chainId: 1, from: address, gas: 21000n, hash, input: '0xdeadbeef', nonce: 2n, r, s, to: address, transactionIndex: 0, value: 3n, yParity: 1, } as const describe('Transaction', () => { test('decodes and encodes EIP-1559 transactions', () => { expect( z.decode(z_Transaction.Transaction, { ...baseRpc, accessList: [], gasPrice: '0x4', maxFeePerGas: '0x5', maxPriorityFeePerGas: '0x6', type: '0x2', }), ).toMatchInlineSnapshot(` { "accessList": [], "blockHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "blockNumber": 1n, "chainId": 1, "from": "0x0000000000000000000000000000000000000000", "gas": 21000n, "gasPrice": 4n, "hash": "0x1111111111111111111111111111111111111111111111111111111111111111", "input": "0xdeadbeef", "maxFeePerGas": 5n, "maxPriorityFeePerGas": 6n, "nonce": 2n, "r": "0x2222222222222222222222222222222222222222222222222222222222222222", "s": "0x3333333333333333333333333333333333333333333333333333333333333333", "to": "0x0000000000000000000000000000000000000000", "transactionIndex": 0, "type": "eip1559", "value": 3n, "yParity": 1, } `) expect( z.encode(z_Transaction.Transaction, { ...base, accessList: [], gasPrice: 4n, maxFeePerGas: 5n, maxPriorityFeePerGas: 6n, type: 'eip1559', }), ).toMatchInlineSnapshot(` { "accessList": [], "blockHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "blockNumber": "0x1", "chainId": "0x1", "from": "0x0000000000000000000000000000000000000000", "gas": "0x5208", "gasPrice": "0x4", "hash": "0x1111111111111111111111111111111111111111111111111111111111111111", "input": "0xdeadbeef", "maxFeePerGas": "0x5", "maxPriorityFeePerGas": "0x6", "nonce": "0x2", "r": "0x2222222222222222222222222222222222222222222222222222222222222222", "s": "0x3333333333333333333333333333333333333333333333333333333333333333", "to": "0x0000000000000000000000000000000000000000", "transactionIndex": "0x0", "type": "0x2", "value": "0x3", "yParity": "0x1", } `) }) test('TransactionToRpc accepts numberish encode inputs', () => { const decoded = { ...base, accessList: [], gasPrice: 4n, maxFeePerGas: 5n, maxPriorityFeePerGas: 6n, type: 'eip1559', } as const const expected = z.encode(z_Transaction.Transaction, decoded) expect( z.encode(z_Transaction.TransactionToRpc, { ...decoded, blockNumber: 1, gas: 21000, maxFeePerGas: 5, value: 3, }), ).toEqual(expected) expect( z.encode(z_Transaction.TransactionToRpc, { ...decoded, blockNumber: '0x1', gas: '0x5208', maxFeePerGas: '0x5', }), ).toEqual(expected) }) test('decodes legacy and pending transactions', () => { expect( z.decode(z_Transaction.Legacy, { ...baseRpc, chainId: '0x1', gasPrice: '0x4', type: '0x0', v: '0x1b', }), ).toMatchObject({ chainId: 1, gasPrice: 4n, type: 'legacy', v: 27 }) expect( z.decode(z_Transaction.Pending, { ...baseRpc, blockHash: null, blockNumber: null, gasPrice: '0x4', transactionIndex: null, type: '0x0', v: '0x1b', }), ).toMatchObject({ blockHash: null, blockNumber: null, transactionIndex: null, type: 'legacy', }) }) test('decodes other transaction variants', () => { expect( z.decode(z_Transaction.Eip2930, { ...baseRpc, accessList: [], gasPrice: '0x4', type: '0x1', }), ).toMatchObject({ gasPrice: 4n, type: 'eip2930' }) expect( z.decode(z_Transaction.Eip4844, { ...baseRpc, accessList: [], blobVersionedHashes: [hash], maxFeePerBlobGas: '0x4', maxFeePerGas: '0x5', maxPriorityFeePerGas: '0x6', type: '0x3', }), ).toMatchObject({ maxFeePerBlobGas: 4n, type: 'eip4844' }) expect( z.decode(z_Transaction.Eip7702, { ...baseRpc, accessList: [], authorizationList: [ { address, chainId: '0x1', nonce: '0x2', r, s, yParity: '0x1' }, ], maxFeePerGas: '0x5', maxPriorityFeePerGas: '0x6', type: '0x4', }), ).toMatchObject({ authorizationList: [{ chainId: 1, nonce: 2n }], type: 'eip7702', }) expect( z.decode(z_Transaction.Unknown, { ...baseRpc, type: '0x99', }), ).toMatchObject({ type: '0x99' }) }) test('rejects invalid variants', () => { expect( z.safeDecode(z_Transaction.Eip1559, { ...baseRpc, accessList: [], maxFeePerGas: '0x5', maxPriorityFeePerGas: '0x6', type: '0x1', } as never).success, ).toBe(false) expect( z.safeDecode(z_Transaction.Transaction, { ...baseRpc, type: '0x2', } as never).success, ).toBe(false) }) })