diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index d6b2a09..6498c33 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -1,4 +1,5 @@ import { + AccessList, accessListify, AccessListish, assertArgument, @@ -54,6 +55,10 @@ export enum TxTypeToPrefix { eip1559 = 0x02, } +function formatAccessList(value: AccessListish): Array<[ string, Array ]> { + return accessListify(value).map((set) => [ set.address, set.storageKeys ]); +} + interface Field { maxLength?: number; length?: number; @@ -106,6 +111,7 @@ export const celoTransactionFields: Record = { maxFeePerGas: { maxLength: 32, numeric: true } as Field, maxPriorityFeePerGas: { maxLength: 32, numeric: true } as Field, maxFeeInFeeCurrency: { maxLength: 32, numeric: true } as Field, + } as const; function formatCeloField(name: CeloFieldName, value: any) { @@ -170,8 +176,7 @@ function prepareEncodeTx(tx: CeloTransaction, signature?: Signature): RlpStructu tx.to || "0x", tx.value ? toBeHex(tx.value) : "0x", tx.data || "0x", - // @ts-expect-error - tx.accessList || [], + formatAccessList(tx.accessList || []), (tx as CeloTransactionCip66).feeCurrency || "0x", (tx as CeloTransactionCip66).maxFeeInFeeCurrency ? toBeHex((tx as CeloTransactionCip66).maxFeeInFeeCurrency) : "0x", ]; @@ -188,8 +193,7 @@ function prepareEncodeTx(tx: CeloTransaction, signature?: Signature): RlpStructu tx.to || "0x", tx.value ? toBeHex(tx.value) : "0x", tx.data || "0x", - // @ts-expect-error - tx.accessList || [], + formatAccessList(tx.accessList || []), (tx as CeloTransactionCip64).feeCurrency || "0x", ]; break; @@ -205,8 +209,7 @@ function prepareEncodeTx(tx: CeloTransaction, signature?: Signature): RlpStructu tx.to || "0x", tx.value ? toBeHex(tx.value) : "0x", tx.data || "0x", - // @ts-expect-error - tx.accessList || [], + formatAccessList(tx.accessList || []), ]; break; default: @@ -258,6 +261,8 @@ export function serializeCeloTransaction( if (fieldName in celoTransactionFields) { // @ts-expect-error txArgs[fieldName as CeloFieldName] = formatCeloField(fieldName as CeloFieldName, fieldValue); + } else if (fieldName === 'accessList') { + txArgs[fieldName] = fieldValue } }); @@ -339,7 +344,7 @@ export function parseCeloTransaction(rawTransaction: BytesLike): CeloTransaction to: handleAddress(transaction[5] as string), value: handleBigInt(transaction[6] as string), data: transaction[7] as string, - accessList: handleAccessList(transaction[8] as string), + accessList: handleAccessList(transaction[8]), feeCurrency: handleAddress(transaction[9] as string), maxFeeInFeeCurrency: handleBigInt(transaction[10] as string), } as CeloTransactionCip66; @@ -469,12 +474,12 @@ function handleBigInt(value: string): bigint { return getBigInt(value); } -function handleAccessList(value: string): AccessListish | "0x" { +function handleAccessList(value: any): AccessList { if (value === "0x") { return accessListify([]); } // TODO: use value - return accessListify([]); + return accessListify(value); } const baseTxLengths = { diff --git a/tests/transactions.unit.test.ts b/tests/transactions.unit.test.ts index 7c0a76c..195f0c9 100644 --- a/tests/transactions.unit.test.ts +++ b/tests/transactions.unit.test.ts @@ -17,6 +17,34 @@ describe('serializeCeloTransaction', () => { expect(serializeCeloTransaction(tx)).toMatchInlineSnapshot(`"0x7af84b82a4ec01847735940084773594008094f653a42ef024d174bb4be98b67690e5886d01f5f880de0b6b3a764000080c094765de816845861e75a25fca122bb6898b8b1282a860b3a4b56fa00"`); }); + it('can handle accessList', () => { + const transaction = serializeCeloTransaction({ + to: "0xF653A42ef024d174Bb4bE98B67690E5886d01F5F", + chainId: 42220, + nonce: 1, + accessList: [ + { + address: '0x0000000000000000000000000000000000000000', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000001', + '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe', + ], + }, + ], + }) + expect(transaction).toMatchInlineSnapshot(`"0x02f87b82a4ec0180808094f653a42ef024d174bb4be98b67690e5886d01f5f8080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000001a060fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe"`) + expect(parseCeloTransaction(transaction).accessList).toMatchInlineSnapshot(` +[ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe", + ], + }, +] +`) + }) }); describe('parseCeloTransaction', () => { it('serializes CIP-66 transaction', () => {