diff --git a/evm/evm-codec/src/abi-components/event.ts b/evm/evm-codec/src/abi-components/event.ts deleted file mode 100644 index 42cc72ec6..000000000 --- a/evm/evm-codec/src/abi-components/event.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { bytes32 } from "../codecs/primitives"; -import { Src } from "../src"; -import { Codec, StructTypes } from "../codec"; -import type { Pretty } from "../utils"; - -export interface EventRecord { - topics: string[]; - data: string; -} - -export type EventParams> = T extends AbiEvent - ? StructTypes> - : never; - -type EventArgs = { - [key: string]: Pretty & { indexed?: boolean }>; -}; - -export type IndexedCodecs = Pretty<{ - [K in keyof T]: T[K] extends { indexed: true; isDynamic: true } - ? typeof bytes32 & { indexed: true } - : T[K]; -}>; - -export class AbiEvent { - public readonly params: any; - constructor(public readonly topic: string, args: T) { - const entries = Object.entries(args); - this.params = Object.fromEntries( - entries.map( - ([key, arg]) => - [ - key, - arg.indexed && arg.isDynamic - ? { - ...bytes32, - isDynamic: true, - indexed: true, - } - : arg, - ] as const - ) - ) as IndexedCodecs; - } - - is(rec: EventRecord): boolean { - return rec.topics[0] === this.topic; - } - - decode(rec: EventRecord): StructTypes> { - const src = new Src(Buffer.from(rec.data.slice(2), "hex")); - const result = {} as any; - let topicCounter = 1; - for (let i in this.params) { - if (this.params[i].indexed) { - const topic = rec.topics[topicCounter++]; - const topicSrc = new Src(Buffer.from(topic.slice(2), "hex")); - result[i] = this.params[i].decode(topicSrc); - } else { - result[i] = this.params[i].decode(src); - } - } - return result; - } -} diff --git a/evm/evm-codec/src/abi-components/function.ts b/evm/evm-codec/src/abi-components/function.ts deleted file mode 100644 index 424633265..000000000 --- a/evm/evm-codec/src/abi-components/function.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Codec, Struct, StructTypes } from "../codec"; -import { Sink } from "../sink"; -import { slotsCount } from "../utils"; -import { Src } from "../src"; -import assert from "node:assert"; - -export type FunctionArguments> = - F extends AbiFunction ? StructTypes : never; - -export type FunctionReturn> = - F extends AbiFunction ? ReturnType : never; - -type ReturnType = T extends Codec - ? U - : T extends Struct - ? StructTypes - : void; - -export class AbiFunction< - const T extends Struct, - const R extends Codec | Struct | void = void -> { - readonly #selector: Buffer; - private readonly slotsCount: number; - - constructor( - public selector: string, - public readonly args: T, - public readonly returnType?: R - ) { - assert(selector.startsWith("0x"), "selector must start with 0x"); - assert(selector.length === 10, "selector must be 4 bytes long"); - this.#selector = Buffer.from(selector.slice(2), "hex"); - this.args = args; - this.slotsCount = slotsCount(Object.values(args)); - } - - is(calldata: string) { - return calldata.startsWith(this.selector); - } - - encode(args: StructTypes) { - const sink = new Sink(this.slotsCount); - for (let i in this.args) { - this.args[i].encode(sink, args[i]); - } - return `0x${Buffer.concat([this.#selector, sink.result()]).toString( - "hex" - )}`; - } - - decode(calldata: string): StructTypes { - assert( - this.is(calldata), - `unexpected function signature: ${calldata.slice(0, 10)}` - ); - const src = new Src(Buffer.from(calldata.slice(10), "hex")); - const result = {} as any; - for (let i in this.args) { - result[i] = this.args[i].decode(src); - } - return result; - } - - private isCodecs(value: any): value is Codec { - return "decode" in value && "encode" in value; - } - - decodeResult(output: string): ReturnType { - if (!this.returnType) { - return undefined as any; - } - const src = new Src(Buffer.from(output.slice(2), "hex")); - if (this.isCodecs(this.returnType)) { - return this.returnType.decode(src) as any; - } - const result = {} as any; - for (let i in this.returnType) { - const codec = this.returnType[i] as Codec; - result[i] = codec.decode(src); - } - return result; - } -} diff --git a/evm/evm-codec/test/event.test.ts b/evm/evm-codec/test/event.test.ts deleted file mode 100644 index f466dd635..000000000 --- a/evm/evm-codec/test/event.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { encodeAbiParameters, encodeEventTopics, parseAbiItem } from "viem"; -import { - bool, - bytes, - indexed, - string, - struct, - uint256, - event as _event, -} from "../src"; - -describe("Event", () => { - it("decodes simple args", () => { - const topics = encodeEventTopics({ - abi: [parseAbiItem("event Test(uint256 indexed a, uint256 b)")], - eventName: "Test", - args: { a: 123n }, - }); - const event = _event(topics[0], { - a: indexed(uint256), - b: uint256, - }); - const decoded = event.decode({ - topics, - data: encodeAbiParameters([{ type: "uint256" }], [100n]), - }); - expect(decoded).toEqual({ a: 123n, b: 100n }); - }); - - it("decodes complex args", () => { - const topics = encodeEventTopics({ - abi: [ - parseAbiItem( - "event Test(string indexed a, string b, bytes c, (uint256, string) d, bool indexed e)" - ), - ], - eventName: "Test", - args: { a: "xdxdxd", e: true }, - }); - const event = _event(topics[0], { - a: indexed(string), - b: string, - c: bytes, - d: struct({ _0: uint256, _1: string }), - e: indexed(bool), - }); - const decoded = event.decode({ - topics, - data: encodeAbiParameters( - [ - { type: "string" }, - { type: "bytes" }, - { - type: "tuple", - components: [{ type: "uint256" }, { type: "string" }], - }, - ], - ["hello", "0x1234", [100n, "world"]] - ), - }); - expect(decoded).toEqual({ - a: Buffer.from(topics[1].slice(2), "hex"), - b: "hello", - c: Buffer.from([0x12, 0x34]), - d: { _0: 100n, _1: "world" }, - e: true, - }); - }); -}); diff --git a/evm/evm-codec/test/function.test.ts b/evm/evm-codec/test/function.test.ts deleted file mode 100644 index 8c821b5de..000000000 --- a/evm/evm-codec/test/function.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { encodeFunctionData, encodeFunctionResult, parseAbiItem } from "viem"; -import { - array, - bool, - bytes4, - fixedArray, - fun, - int32, - Sink, - string, - struct, - uint256, -} from "../src"; - -describe("Function", () => { - it("encodes/decodes simple args", () => { - const simpleFunction = fun("0x12345678", { - foo: uint256, - _1: int32, - _2: bool, - }); - const calldata = simpleFunction.encode({ - foo: 100n, - _1: -420, - _2: true, - }); - expect(calldata).toBe( - "0x123456780000000000000000000000000000000000000000000000000000000000000064fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe5c0000000000000000000000000000000000000000000000000000000000000001" - ); - - const decoded = simpleFunction.decode(calldata); - expect(decoded).toStrictEqual({ - foo: 100n, - _1: -420, - _2: true, - }); - }); - - it("encodes/decodes dynamic args", () => { - const staticStruct = struct({ - foo: uint256, - bar: bytes4, - }); - const dynamicFunction = fun("0x423917ce", { - arg1: array(uint256), - arg2: fixedArray(array(uint256), 10), - arg3: struct({ - foo: uint256, - bar: array(uint256), - str: staticStruct, - }), - arg4: staticStruct, - }); - const args = { - arg1: [100n, 2n], - arg2: [[], [1n], [], [], [100n, 2n, 3n], [], [], [1337n], [], []], - arg3: { - foo: 100n, - bar: [1n, 2n, 3n], - str: { - foo: 123n, - bar: Buffer.from([0x12, 0x34, 0x56, 0x78]), - }, - }, - arg4: { - foo: 100n, - bar: Buffer.from([0x12, 0x34, 0x56, 0x78]), - }, - }; - const viemArgs = [ - [100n, 2n], - [[], [1n], [], [], [100n, 2n, 3n], [], [], [1337n], [], []], - { - foo: 100n, - bar: [1n, 2n, 3n], - str: { - foo: 123n, - bar: "0x12345678", - }, - }, - { - foo: 100n, - bar: "0x12345678", - }, - ] as const; - - const calldata = dynamicFunction.encode(args); - const expected = encodeFunctionData({ - abi: [ - { - name: "foo", - type: "function", - inputs: [ - { name: "arg1", type: "uint256[]" }, - { name: "arg2", type: "uint256[][10]" }, - { - name: "arg3", - type: "tuple", - components: [ - { name: "foo", type: "uint256" }, - { name: "bar", type: "uint256[]" }, - { - name: "str", - type: "tuple", - components: [ - { name: "foo", type: "uint256" }, - { name: "bar", type: "bytes4" }, - ], - }, - ], - }, - { - name: "arg4", - type: "tuple", - components: [ - { name: "foo", type: "uint256" }, - { name: "bar", type: "bytes4" }, - ], - }, - ], - }, - ], - functionName: "foo", - args: viemArgs, - }); - expect(calldata).toBe(expected); - - expect(dynamicFunction.decode(calldata)).toStrictEqual(args); - }); - - it("return simple type", () => { - const simpleFunction = fun( - "0x12345678", - { - foo: uint256, - }, - int32 - ); - const sink = new Sink(1); - int32.encode(sink, -420); - sink.toString(); - const output = simpleFunction.decodeResult(sink.toString()); - expect(output).toBe(-420); - }); - - it("return tuple", () => { - const data = encodeFunctionResult({ - abi: [ - parseAbiItem( - "function foo() external returns (uint256, string memory b)" - ), - ], - functionName: "foo", - result: [100n, "hello"], - }); - const _fun = fun("0x12345678", {}, { _0: uint256, b: string }); - expect(_fun.decodeResult(data)).toStrictEqual({ _0: 100n, b: "hello" }); - }); -});