Polling block subscriptions for non-websocket connections
This commit is contained in:
parent
127c9c9b0d
commit
6a034870f8
|
@ -4,6 +4,7 @@ proc eth_blockNumber: UInt256
|
||||||
proc eth_call(transaction: Transaction, blockTag: BlockTag): seq[byte]
|
proc eth_call(transaction: Transaction, blockTag: BlockTag): seq[byte]
|
||||||
proc eth_gasPrice(): UInt256
|
proc eth_gasPrice(): UInt256
|
||||||
proc eth_getBlockByNumber(blockTag: BlockTag, includeTransactions: bool): ?Block
|
proc eth_getBlockByNumber(blockTag: BlockTag, includeTransactions: bool): ?Block
|
||||||
|
proc eth_getBlockByHash(hash: BlockHash, includeTransactions: bool): ?Block
|
||||||
proc eth_getTransactionCount(address: Address, blockTag: BlockTag): UInt256
|
proc eth_getTransactionCount(address: Address, blockTag: BlockTag): UInt256
|
||||||
proc eth_estimateGas(transaction: Transaction): UInt256
|
proc eth_estimateGas(transaction: Transaction): UInt256
|
||||||
proc eth_chainId(): UInt256
|
proc eth_chainId(): UInt256
|
||||||
|
@ -14,3 +15,6 @@ proc eth_sign(account: Address, message: seq[byte]): seq[byte]
|
||||||
proc eth_subscribe(name: string, filter: Filter): JsonNode
|
proc eth_subscribe(name: string, filter: Filter): JsonNode
|
||||||
proc eth_subscribe(name: string): JsonNode
|
proc eth_subscribe(name: string): JsonNode
|
||||||
proc eth_unsubscribe(id: JsonNode): bool
|
proc eth_unsubscribe(id: JsonNode): bool
|
||||||
|
proc eth_newBlockFilter(): JsonNode
|
||||||
|
proc eth_getFilterChanges(id: JsonNode): JsonNode
|
||||||
|
proc eth_uninstallFilter(id: JsonNode): bool
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import std/tables
|
import std/tables
|
||||||
|
import std/sequtils
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/json_rpc/rpcclient
|
import pkg/json_rpc/rpcclient
|
||||||
import ../../basics
|
import ../../basics
|
||||||
|
@ -97,6 +98,48 @@ method unsubscribe(subscriptions: WebSocketSubscriptions,
|
||||||
type
|
type
|
||||||
PollingSubscriptions = ref object of JsonRpcSubscriptions
|
PollingSubscriptions = ref object of JsonRpcSubscriptions
|
||||||
|
|
||||||
func new*(_: type JsonRpcSubscriptions,
|
proc new*(_: type JsonRpcSubscriptions,
|
||||||
client: RpcHttpClient): JsonRpcSubscriptions =
|
client: RpcHttpClient): JsonRpcSubscriptions =
|
||||||
PollingSubscriptions(client: client)
|
|
||||||
|
let subscriptions = PollingSubscriptions(client: client)
|
||||||
|
|
||||||
|
proc poll(id: JsonNode) {.async.} =
|
||||||
|
for change in await subscriptions.client.eth_getFilterChanges(id):
|
||||||
|
if callback =? subscriptions.getCallback(id):
|
||||||
|
callback(id, change)
|
||||||
|
|
||||||
|
proc poll {.async.} =
|
||||||
|
try:
|
||||||
|
while true:
|
||||||
|
for id in toSeq subscriptions.callbacks.keys:
|
||||||
|
await poll(id)
|
||||||
|
await sleepAsync(1.seconds)
|
||||||
|
except CancelledError:
|
||||||
|
raise
|
||||||
|
|
||||||
|
asyncSpawn poll()
|
||||||
|
|
||||||
|
subscriptions
|
||||||
|
|
||||||
|
method subscribeBlocks(subscriptions: PollingSubscriptions,
|
||||||
|
onBlock: BlockHandler):
|
||||||
|
Future[JsonRpcSubscription]
|
||||||
|
{.async.} =
|
||||||
|
|
||||||
|
proc getBlock(hash: BlockHash) {.async.} =
|
||||||
|
if blck =? (await subscriptions.client.eth_getBlockByHash(hash, false)):
|
||||||
|
await onBlock(blck)
|
||||||
|
|
||||||
|
proc callback(id, change: JsonNode) =
|
||||||
|
if hash =? BlockHash.fromJson(change).catch:
|
||||||
|
asyncSpawn getBlock(hash)
|
||||||
|
|
||||||
|
let id = await subscriptions.client.eth_newBlockFilter()
|
||||||
|
subscriptions.callbacks[id] = callback
|
||||||
|
return JsonRpcSubscription(subscriptions: subscriptions, id: id)
|
||||||
|
|
||||||
|
method unsubscribe(subscriptions: PollingSubscriptions,
|
||||||
|
id: JsonNode)
|
||||||
|
{.async.} =
|
||||||
|
subscriptions.callbacks.del(id)
|
||||||
|
discard await subscriptions.client.eth_uninstallFilter(id)
|
||||||
|
|
|
@ -36,3 +36,24 @@ suite "Web socket subscriptions":
|
||||||
check latestBlock.hash.isSome
|
check latestBlock.hash.isSome
|
||||||
check latestBlock.timestamp > 0.u256
|
check latestBlock.timestamp > 0.u256
|
||||||
await subscription.unsubscribe()
|
await subscription.unsubscribe()
|
||||||
|
|
||||||
|
suite "HTTP polling subscriptions":
|
||||||
|
|
||||||
|
var subscriptions: JsonRpcSubscriptions
|
||||||
|
var client: RpcHttpClient
|
||||||
|
|
||||||
|
setup:
|
||||||
|
client = newRpcHttpClient()
|
||||||
|
await client.connect("http://localhost:8545")
|
||||||
|
subscriptions = JsonRpcSubscriptions.new(client)
|
||||||
|
|
||||||
|
test "subscribes to new blocks":
|
||||||
|
var latestBlock: Block
|
||||||
|
proc callback(blck: Block) {.async.} =
|
||||||
|
latestBlock = blck
|
||||||
|
let subscription = await subscriptions.subscribeBlocks(callback)
|
||||||
|
discard await client.call("evm_mine", newJArray())
|
||||||
|
check eventually(latestBlock.number.isSome)
|
||||||
|
check latestBlock.hash.isSome
|
||||||
|
check latestBlock.timestamp > 0.u256
|
||||||
|
await subscription.unsubscribe()
|
||||||
|
|
Loading…
Reference in New Issue