diff --git a/ethers/contract.nim b/ethers/contract.nim index e0620b6..cec9054 100644 --- a/ethers/contract.nim +++ b/ethers/contract.nim @@ -4,9 +4,11 @@ import pkg/contractabi import ./basics import ./provider import ./signer +import ./events export basics export provider +export events type Contract* = ref object of RootObj diff --git a/ethers/events.nim b/ethers/events.nim new file mode 100644 index 0000000..c481701 --- /dev/null +++ b/ethers/events.nim @@ -0,0 +1,34 @@ +import std/macros +import pkg/contractabi +import ./basics + +type + Event* = object of RootObj + Topic* = array[32, byte] + ValueType = uint8 | uint16 | uint32 | uint64 | UInt256 | UInt128 | + int8 | int16 | int32 | int64 | Int256 | Int128 | + bool | Address + +push: {.upraises: [].} + +template indexed* {.pragma.} + +func decode[E: Event](decoder: var AbiDecoder, _: type E): ?!E = + var event: E + for field in event.fields: + if not field.hasCustomPragma(indexed): + field = ?decoder.read(typeof(field)) + success event + +func decode*[E: Event](_: type E, data: seq[byte], topics: seq[Topic]): ?!E = + bind decode + var event = ?Abidecoder.decode(data, E) + var i = 1 + for field in event.fields: + if field.hasCustomPragma(indexed): + if i >= topics.len: + return failure "indexed event parameter not found" + if typeof(field) is ValueType: + field = ?AbiDecoder.decode(@(topics[i]), typeof(field)) + inc i + success event diff --git a/testmodule/test.nim b/testmodule/test.nim index 236088c..b374b52 100644 --- a/testmodule/test.nim +++ b/testmodule/test.nim @@ -1,5 +1,6 @@ import ./testJsonRpcProvider import ./testJsonRpcSigner import ./testContracts +import ./testEvents {.warning[UnusedImport]:off.} diff --git a/testmodule/testEvents.nim b/testmodule/testEvents.nim new file mode 100644 index 0000000..cbece26 --- /dev/null +++ b/testmodule/testEvents.nim @@ -0,0 +1,78 @@ +import pkg/asynctest +import pkg/ethers +import pkg/contractabi +import ./examples + +suite "Events": + + type + SimpleEvent = object of Event + a: UInt256 + b: Address + IndexedEvent = object of Event + a: UInt256 + b {.indexed.}: Address + c: Address + d {.indexed.}: UInt256 + ComplexIndexedEvent = object of Event + a {.indexed.}: array[42, UInt256] + b {.indexed.}: seq[UInt256] + c {.indexed.}: string + d {.indexed.}: seq[byte] + e {.indexed.}: (Address, UInt256) + + proc example(_: type SimpleEvent): SimpleEvent = + SimpleEvent( + a: UInt256.example, + b: Address.example + ) + + proc example(_: type IndexedEvent): IndexedEvent = + IndexedEvent( + a: UInt256.example, + b: Address.example, + c: Address.example, + d: UInt256.example + ) + + func encode[T](_: type Topic, value: T): Topic = + let encoded = AbiEncoder.encode(value) + result[0..