mirror of
https://github.com/logos-storage/nim-ethers.git
synced 2026-01-11 01:53:07 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
392eab04c4 | ||
|
|
b5710541ff | ||
|
|
483b789f22 | ||
|
|
ff3173986f |
31
Readme.md
31
Readme.md
@ -14,7 +14,7 @@ Use the [Nimble][2] package manager to add `ethers` to an existing
|
||||
project. Add the following to its .nimble file:
|
||||
|
||||
```nim
|
||||
requires "ethers >= 0.2.1 & < 0.3.0"
|
||||
requires "ethers >= 0.2.2 & < 0.3.0"
|
||||
```
|
||||
|
||||
Usage
|
||||
@ -106,6 +106,35 @@ type Transfer = object of Event
|
||||
Notice that `Transfer` inherits from `Event`, and that some event parameters are
|
||||
marked with `{.indexed.}` to match the definition in Solidity.
|
||||
|
||||
Note that valid types of indexed parameters are:
|
||||
```nim
|
||||
uint8 | uint16 | uint32 | uint64 | UInt256 | UInt128 |
|
||||
int8 | int16 | int32 | int64 | Int256 | Int128 |
|
||||
bool | Address | array[ 1..32, byte]
|
||||
```
|
||||
Distinct types of valid types are also supported for indexed fields, eg:
|
||||
```nim
|
||||
type
|
||||
DistinctAlias = distinct array[32, byte]
|
||||
MyEvent = object of Event
|
||||
a {.indexed.}: DistinctAlias
|
||||
b: DistinctAlias # also allowed for non-indexed fields
|
||||
|
||||
## The below funcs generally need to be included for ABI
|
||||
## encoding/decoding purposes when implementing distinct types.
|
||||
|
||||
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)
|
||||
```
|
||||
|
||||
You can now subscribe to Transfer events by calling `subscribe` on the contract
|
||||
instance.
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
author = "Nim Ethers Authors"
|
||||
description = "library for interacting with Ethereum"
|
||||
license = "MIT"
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import std/macros
|
||||
import std/typetraits
|
||||
import pkg/contractabi
|
||||
import ./basics
|
||||
import ./provider
|
||||
@ -33,6 +34,18 @@ func decode*[E: Event](decoder: var AbiDecoder, _: type E): ?!E =
|
||||
decoder.finishTuple()
|
||||
success event
|
||||
|
||||
func isSupported(T: type): bool =
|
||||
var supported = false
|
||||
# nim 1.2.x fails distinctBase checks on non-distinct types at compile time,
|
||||
# so we must separate with `when`
|
||||
when T is distinct:
|
||||
supported = T.distinctBase is ValueType or
|
||||
T.distinctBase is SmallByteArray
|
||||
else:
|
||||
supported = T is ValueType or
|
||||
T is SmallByteArray
|
||||
return supported
|
||||
|
||||
func decode*[E: Event](_: type E, data: seq[byte], topics: seq[Topic]): ?!E =
|
||||
var event = ?Abidecoder.decode(data, E)
|
||||
var i = 1
|
||||
@ -40,7 +53,7 @@ func decode*[E: Event](_: type E, data: seq[byte], topics: seq[Topic]): ?!E =
|
||||
if field.hasCustomPragma(indexed):
|
||||
if i >= topics.len:
|
||||
return failure "indexed event parameter not found"
|
||||
if typeof(field) is ValueType or typeof(field) is SmallByteArray:
|
||||
if typeof(field).isSupported:
|
||||
field = ?AbiDecoder.decode(@(topics[i]), typeof(field))
|
||||
inc i
|
||||
success event
|
||||
|
||||
@ -3,6 +3,26 @@ 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
|
||||
@ -25,6 +45,9 @@ suite "Events":
|
||||
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(
|
||||
@ -47,6 +70,14 @@ suite "Events":
|
||||
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]
|
||||
@ -71,6 +102,14 @@ suite "Events":
|
||||
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,) )
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user