diff --git a/ethers/providers/jsonrpc/looping.nim b/ethers/providers/jsonrpc/looping.nim index f0bb7a8..31a8957 100644 --- a/ethers/providers/jsonrpc/looping.nim +++ b/ethers/providers/jsonrpc/looping.nim @@ -2,5 +2,5 @@ template untilCancelled*(body) = try: while true: body - except CancelledError: - raise + except CancelledError as exc: + raise exc diff --git a/ethers/providers/jsonrpc/subscriptions.nim b/ethers/providers/jsonrpc/subscriptions.nim index 142c9cc..d919f3c 100644 --- a/ethers/providers/jsonrpc/subscriptions.nim +++ b/ethers/providers/jsonrpc/subscriptions.nim @@ -14,6 +14,14 @@ type callbacks: Table[JsonNode, SubscriptionCallback] SubscriptionCallback = proc(id, arguments: JsonNode) {.gcsafe, raises:[].} +# FIXME Nim 1.6.XX seems to have issues tracking exception effects and will see +# ghost unlisted Exceptions with table operations. In a smaller example +# (https://forum.nim-lang.org/t/10749), using {.experimental:"strictEffects".} +# would fix it, but it doesn't work here for some reason I yet don't +# understand. For now, therefore, I'm simply using a mitigation which is to +# tell the compiler the truth. +template mitigateEffectsBug(body) = {.cast(raises: []).}: body + method subscribeBlocks*(subscriptions: JsonRpcSubscriptions, onBlock: BlockHandler): Future[JsonNode] @@ -70,7 +78,7 @@ method subscribeBlocks(subscriptions: WebSocketSubscriptions, if blck =? Block.fromJson(arguments["result"]).catch: onBlock(blck) let id = await subscriptions.client.eth_subscribe("newHeads") - subscriptions.callbacks[id] = callback + mitigateEffectsBug: subscriptions.callbacks[id] = callback return id method subscribeLogs(subscriptions: WebSocketSubscriptions, @@ -82,13 +90,13 @@ method subscribeLogs(subscriptions: WebSocketSubscriptions, if log =? Log.fromJson(arguments["result"]).catch: onLog(log) let id = await subscriptions.client.eth_subscribe("logs", filter) - subscriptions.callbacks[id] = callback + mitigateEffectsBug: subscriptions.callbacks[id] = callback return id method unsubscribe(subscriptions: WebSocketSubscriptions, id: JsonNode) {.async.} = - subscriptions.callbacks.del(id) + mitigateEffectsBug: subscriptions.callbacks.del(id) discard await subscriptions.client.eth_unsubscribe(id) # Polling @@ -144,7 +152,7 @@ method subscribeBlocks(subscriptions: PollingSubscriptions, asyncSpawn getBlock(hash) let id = await subscriptions.client.eth_newBlockFilter() - subscriptions.callbacks[id] = callback + mitigateEffectsBug: subscriptions.callbacks[id] = callback return id method subscribeLogs(subscriptions: PollingSubscriptions, @@ -158,11 +166,11 @@ method subscribeLogs(subscriptions: PollingSubscriptions, onLog(log) let id = await subscriptions.client.eth_newFilter(filter) - subscriptions.callbacks[id] = callback + mitigateEffectsBug: subscriptions.callbacks[id] = callback return id method unsubscribe(subscriptions: PollingSubscriptions, id: JsonNode) {.async.} = - subscriptions.callbacks.del(id) + mitigateEffectsBug: subscriptions.callbacks.del(id) discard await subscriptions.client.eth_uninstallFilter(id) diff --git a/ethers/signer.nim b/ethers/signer.nim index eaca26c..1962055 100644 --- a/ethers/signer.nim +++ b/ethers/signer.nim @@ -26,10 +26,12 @@ proc raiseEstimateGasError( parent: parent) raise e -method provider*(signer: Signer): Provider {.base, gcsafe.} = +method provider*(signer: Signer): + Provider {.base, gcsafe, raises: [CatchableError].} = doAssert false, "not implemented" -method getAddress*(signer: Signer): Future[Address] {.base, gcsafe.} = +method getAddress*(signer: Signer): + Future[Address] {.base, gcsafe, raises: [CatchableError].} = doAssert false, "not implemented" method signMessage*(signer: Signer, @@ -40,7 +42,8 @@ method sendTransaction*(signer: Signer, transaction: Transaction): Future[TransactionResponse] {.base, async.} = doAssert false, "not implemented" -method getGasPrice*(signer: Signer): Future[UInt256] {.base, gcsafe.} = +method getGasPrice*(signer: Signer): + Future[UInt256] {.base, gcsafe, raises: [CatchableError].} = signer.provider.getGasPrice() method getTransactionCount*(signer: Signer, @@ -59,7 +62,8 @@ method estimateGas*(signer: Signer, except ProviderError as e: raiseEstimateGasError transaction, e -method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} = +method getChainId*(signer: Signer): + Future[UInt256] {.base, gcsafe, raises: [CatchableError].} = signer.provider.getChainId() method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} = @@ -74,7 +78,7 @@ method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} = method updateNonce*( signer: Signer, nonce: UInt256 -) {.base, gcsafe.} = +) {.base, gcsafe, raises: [CatchableError].} = without lastSeen =? signer.lastSeenNonce: signer.lastSeenNonce = some nonce @@ -83,7 +87,7 @@ method updateNonce*( if nonce > lastSeen: signer.lastSeenNonce = some nonce -method decreaseNonce*(signer: Signer) {.base, gcsafe.} = +method decreaseNonce*(signer: Signer) {.base, gcsafe, raises: [CatchableError].} = if lastSeen =? signer.lastSeenNonce and lastSeen > 0: signer.lastSeenNonce = some lastSeen - 1 @@ -119,10 +123,12 @@ method populateTransaction*(signer: Signer, populated.nonce = some(await signer.getNonce()) try: populated.gasLimit = some(await signer.estimateGas(populated)) - except ProviderError, EstimateGasError: - let e = getCurrentException() + except ProviderError as exc: signer.decreaseNonce() - raise e + raise exc + except EstimateGasError as exc: + signer.decreaseNonce() + raise exc else: if transaction.nonce.isNone: diff --git a/ethers/wallet.nim b/ethers/wallet.nim index 85305f6..045935b 100644 --- a/ethers/wallet.nim +++ b/ethers/wallet.nim @@ -54,7 +54,7 @@ proc createRandom*(_: type Wallet, provider: Provider): Wallet = result.address = Address.init(result.publicKey.toCanonicalAddress()) result.provider = some provider -method provider*(wallet: Wallet): Provider = +method provider*(wallet: Wallet): Provider {.raises: [CatchableError].} = without provider =? wallet.provider: raiseWalletError "Wallet has no provider" provider diff --git a/testmodule/hardhat.nim b/testmodule/hardhat.nim index 55bd79f..f5efc83 100644 --- a/testmodule/hardhat.nim +++ b/testmodule/hardhat.nim @@ -1,10 +1,12 @@ +import std/os import std/json import pkg/ethers/basics type Deployment* = object json: JsonNode -const defaultFile = "../testnode/deployment.json" +const defaultFile = currentSourcePath.parentDir.parentDir / + "testnode" / "deployment.json" ## Reads deployment information from a json file. It expects a file that has ## been exported with Hardhat deploy. See also: