nim-ethers/testmodule/testEvents.nim

137 lines
4.0 KiB
Nim

import pkg/asynctest
import pkg/ethers
import pkg/contractabi
import ./examples
## Define outside the scope of the suite to allow for exporting
## To use custom distinct types, these procs will generally need
## to be defined in the application code anyway, to support ABI
## encoding/decoding
type
DistinctAlias = distinct array[32, byte]
proc `==`*(x, y: DistinctAlias): bool {.borrow.}
func toArray(value: DistinctAlias): array[32, byte] =
array[32, byte](value)
func encode*(encoder: var AbiEncoder, value: DistinctAlias) =
encoder.write(value.toArray)
func decode*(decoder: var AbiDecoder,
T: type DistinctAlias): ?!T =
let d = ?decoder.read(type array[32, byte])
success DistinctAlias(d)
suite "Events":
type
SimpleEvent = object of Event
a: UInt256
b: Address
DynamicSizeEvent = object of Event
a: array[32, byte]
b: seq[byte]
IndexedEvent = object of Event
a: UInt256
b {.indexed.}: Address
c: Address
d {.indexed.}: UInt256
e {.indexed.}: array[32, byte]
ComplexIndexedEvent = object of Event
a {.indexed.}: array[42, UInt256]
b {.indexed.}: seq[UInt256]
c {.indexed.}: string
d {.indexed.}: seq[byte]
e {.indexed.}: (Address, UInt256)
f {.indexed.}: array[33, byte]
IndexedWithDistinctType = object of Event
a {.indexed.}: DistinctAlias
b: DistinctAlias
proc example(_: type SimpleEvent): SimpleEvent =
SimpleEvent(
a: UInt256.example,
b: Address.example
)
proc example(_: type DynamicSizeEvent): DynamicSizeEvent =
DynamicSizeEvent(
a: array[32, byte].example,
b: seq[byte].example
)
proc example(_: type IndexedEvent): IndexedEvent =
IndexedEvent(
a: UInt256.example,
b: Address.example,
c: Address.example,
d: UInt256.example,
e: array[32, byte].example
)
proc example(_: type IndexedWithDistinctType): IndexedWithDistinctType =
IndexedWithDistinctType(
a: DistinctAlias(array[32, byte].example)
)
func encode(_: type AbiEncoder, value: DistinctAlias): seq[byte] =
@(value.toArray)
func encode[T](_: type Topic, value: T): Topic =
let encoded = AbiEncoder.encode(value)
result[0..<Topic.len] = encoded[0..<Topic.len]
test "decodes event fields":
let event = SimpleEvent.example
let data = AbiEncoder.encode( (event.a, event.b) )
check SimpleEvent.decode(data, @[]) == success event
test "decodes dynamically sized fields":
let event = DynamicSizeEvent.example
let data = AbiEncoder.encode( (event.a, event.b) )
check DynamicSizeEvent.decode(data, @[]) == success event
test "decodes indexed fields":
let event = IndexedEvent.example
var topics: seq[Topic]
topics.add Topic.default
topics.add Topic.encode(event.b)
topics.add Topic.encode(event.d)
topics.add Topic.encode(event.e)
let data = AbiEncoder.encode( (event.a, event.c) )
check IndexedEvent.decode(data, topics) == success event
test "decodes indexed fields with distinct types":
let event = IndexedWithDistinctType.example
var topics: seq[Topic]
topics.add Topic.default
topics.add Topic.encode(event.a)
let data = AbiEncoder.encode( (event.b,) )
check IndexedWithDistinctType.decode(data, topics) == success event
test "fails when data is incomplete":
let event = SimpleEvent.example
let invalid = AbiEncoder.encode( (event.a,) )
check SimpleEvent.decode(invalid, @[]).isFailure
test "fails when topics are incomplete":
let event = IndexedEvent.example
var invalid: seq[Topic]
invalid.add Topic.default
invalid.add Topic.encode(event.b)
let data = AbiEncoder.encode( (event.a, event.c) )
check IndexedEvent.decode(data, invalid).isFailure
test "ignores indexed complex arguments":
let topics = @[
Topic.default,
Topic.example,
Topic.example,
Topic.example,
Topic.example,
Topic.example,
Topic.example
]
check ComplexIndexedEvent.decode(@[], topics) == success ComplexIndexedEvent()