Add convenience API for obtaining logs from a smart contract event
This commit is contained in:
parent
6927cd08a2
commit
270fd64620
|
@ -119,6 +119,11 @@ proc test() {.async.} =
|
|||
|
||||
echo "sendCoin: ", await ns.sendCoin(accounts[1], 100.u256).send()
|
||||
|
||||
echo "transfers: ", await ns.getJsonLogs(
|
||||
Transfer,
|
||||
fromBlock = some(blockId(deployedAtBlock)),
|
||||
toBlock = some(blockId(1000'u64)))
|
||||
|
||||
await notifFut
|
||||
|
||||
await s.unsubscribe()
|
||||
|
|
40
web3.nim
40
web3.nim
|
@ -636,7 +636,8 @@ macro contract*(cname: untyped, body: untyped): untyped =
|
|||
call.add argument
|
||||
callWithRawData.add argument
|
||||
let
|
||||
cbident = ident obj.eventObject.name
|
||||
eventName = obj.eventObject.name
|
||||
cbident = ident eventName
|
||||
procTy = nnkProcTy.newTree(params, newEmptyNode())
|
||||
signature = getSignature(obj.eventObject)
|
||||
|
||||
|
@ -654,20 +655,49 @@ macro contract*(cname: untyped, body: untyped): untyped =
|
|||
|
||||
result.add quote do:
|
||||
type `cbident` = object
|
||||
proc subscribe(s: Sender[`cname`], t: typedesc[`cbident`], options: JsonNode, `callbackIdent`: `procTy`): Future[Subscription] =
|
||||
let options = addAddressAndSignatureToOptions(options, s.contractAddress, "0x" & toLowerAscii($keccak256.digest(`signature`)))
|
||||
|
||||
template eventTopic(T: type `cbident`): string =
|
||||
"0x" & toLowerAscii($keccak256.digest(`signature`))
|
||||
|
||||
proc subscribe(s: Sender[`cname`],
|
||||
t: type `cbident`,
|
||||
options: JsonNode,
|
||||
`callbackIdent`: `procTy`): Future[Subscription] =
|
||||
let options = addAddressAndSignatureToOptions(options, s.contractAddress, eventTopic(`cbident`))
|
||||
|
||||
s.web3.subscribeToLogs(options) do(`jsonIdent`: JsonNode):
|
||||
`argParseBody`
|
||||
`call`
|
||||
|
||||
proc subscribe(s: Sender[`cname`], t: typedesc[`cbident`], options: JsonNode, `callbackIdent`: `procTyWithRawData`): Future[Subscription] =
|
||||
let options = addAddressAndSignatureToOptions(options, s.contractAddress, "0x" & toLowerAscii($keccak256.digest(`signature`)))
|
||||
proc subscribe(s: Sender[`cname`],
|
||||
t: type `cbident`,
|
||||
options: JsonNode,
|
||||
`callbackIdent`: `procTyWithRawData`): Future[Subscription] =
|
||||
let options = addAddressAndSignatureToOptions(options, s.contractAddress, eventTopic(`cbident`))
|
||||
|
||||
s.web3.subscribeToLogs(options) do(`jsonIdent`: JsonNode):
|
||||
`argParseBody`
|
||||
`callWithRawData`
|
||||
|
||||
proc getJsonLogs(s: Sender[`cname`],
|
||||
t: type `cbident`,
|
||||
fromBlock, toBlock = none(RtBlockIdentifier),
|
||||
blockHash = none(BlockHash)): Future[JsonNode] =
|
||||
var options = newJObject()
|
||||
options["address"] = %s.contractAddress
|
||||
var topics = newJArray()
|
||||
topics.elems.insert(%eventTopic(`cbident`), 0)
|
||||
options["topics"] = topics
|
||||
if blockHash.isSome:
|
||||
doAssert fromBlock.isNone and toBlock.isNone
|
||||
options["blockhash"] = %blockHash.unsafeGet
|
||||
else:
|
||||
if fromBlock.isSome:
|
||||
options["fromBlock"] = %fromBlock.unsafeGet
|
||||
if toBlock.isSome:
|
||||
options["toBlock"] = %toBlock.unsafeGet
|
||||
|
||||
s.web3.provider.eth_getLogs(options)
|
||||
else:
|
||||
discard
|
||||
|
||||
|
|
|
@ -110,3 +110,9 @@ proc `%`*(x: FilterOptions): JsonNode =
|
|||
result["address"] = %x.address.unsafeGet
|
||||
if x.topics.isSome:
|
||||
result["topics"] = %x.topics.unsafeGet
|
||||
|
||||
proc `%`*(x: RtBlockIdentifier): JsonNode =
|
||||
case x.kind
|
||||
of BlockIdentifierKind.number: %x.number
|
||||
of BlockIdentifierKind.alias: %x.alias
|
||||
|
||||
|
|
|
@ -16,6 +16,17 @@ type
|
|||
BlockNumber* = uint64
|
||||
BlockIdentifier* = string|BlockNumber
|
||||
|
||||
BlockIdentifierKind* = enum
|
||||
number
|
||||
alias
|
||||
|
||||
RtBlockIdentifier* = object
|
||||
case kind*: BlockIdentifierKind
|
||||
of BlockIdentifierKind.number:
|
||||
number*: BlockNumber
|
||||
of BlockIdentifierKind.alias:
|
||||
alias*: string
|
||||
|
||||
Quantity* = distinct uint64
|
||||
|
||||
EthSend* = object
|
||||
|
@ -117,6 +128,7 @@ type
|
|||
toBlock*: Option[string] # (optional, default: "latest") integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.
|
||||
address*: Option[Address] # (optional) contract address or a list of addresses from which logs should originate.
|
||||
topics*: Option[seq[string]]#Option[seq[FilterData]] # (optional) list of DATA topics. Topics are order-dependent. Each topic can also be a list of DATA with "or" options.
|
||||
blockhash*: Option[BlockHash]
|
||||
|
||||
LogObject* = object
|
||||
#removed*: bool # true when the log was removed, due to a chain reorganization. false if its a valid log.
|
||||
|
@ -171,3 +183,10 @@ proc `==`*[N](a, b: DynamicBytes[N]): bool {.inline.} =
|
|||
|
||||
proc `==`*(a, b: Address): bool {.inline.} =
|
||||
array[20, byte](a) == array[20, byte](b)
|
||||
|
||||
func blockId*(n: BlockNumber): RtBlockIdentifier =
|
||||
RtBlockIdentifier(kind: BlockIdentifierKind.number, number: n)
|
||||
|
||||
func blockId*(a: string): RtBlockIdentifier =
|
||||
RtBlockIdentifier(kind: BlockIdentifierKind.alias, alias: a)
|
||||
|
||||
|
|
Loading…
Reference in New Issue