fix(async): propagate async cancellation (#105)

* fix(async): propagate CancelledErrors

* remove CatchableError from contract macro async raises list

* remove mistakenly added ContractError
This commit is contained in:
Eric 2025-02-17 20:31:24 +11:00 committed by GitHub
parent 26342d3e27
commit d2b11a8657
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 199 additions and 185 deletions

View File

@ -19,6 +19,8 @@ export events
export errors.SolidityError
export errors.errors
{.push raises: [].}
logScope:
topics = "ethers contract"
@ -48,10 +50,10 @@ func new*(ContractType: type Contract,
func new*(ContractType: type Contract,
address: Address,
signer: Signer): ContractType =
signer: Signer): ContractType {.raises: [SignerError].} =
ContractType(signer: some signer, provider: signer.provider, address: address)
func connect*[T: Contract](contract: T, provider: Provider | Signer): T =
func connect*[T: Contract](contract: T, provider: Provider | Signer): T {.raises: [SignerError].} =
T.new(contract.address, provider)
func provider*(contract: Contract): Provider =
@ -83,24 +85,25 @@ proc createTransaction(contract: Contract,
gasLimit: overrides.gasLimit,
)
proc decodeResponse(T: type, bytes: seq[byte]): T =
proc decodeResponse(T: type, bytes: seq[byte]): T {.raises: [ContractError].} =
without decoded =? AbiDecoder.decode(bytes, T):
raiseContractError "unable to decode return value as " & $T
return decoded
proc call(provider: Provider,
transaction: Transaction,
overrides: TransactionOverrides): Future[seq[byte]] {.async: (raises: [ProviderError]).} =
if overrides of CallOverrides and
blockTag =? CallOverrides(overrides).blockTag:
proc call(
provider: Provider, transaction: Transaction, overrides: TransactionOverrides
): Future[seq[byte]] {.async: (raises: [ProviderError, CancelledError]).} =
if overrides of CallOverrides and blockTag =? CallOverrides(overrides).blockTag:
await provider.call(transaction, blockTag)
else:
await provider.call(transaction)
proc call(contract: Contract,
function: string,
parameters: tuple,
overrides = TransactionOverrides()) {.async: (raises: [ProviderError, SignerError]).} =
proc call(
contract: Contract,
function: string,
parameters: tuple,
overrides = TransactionOverrides(),
) {.async: (raises: [ProviderError, SignerError, CancelledError]).} =
var transaction = createTransaction(contract, function, parameters, overrides)
if signer =? contract.signer and transaction.sender.isNone:
@ -108,11 +111,15 @@ proc call(contract: Contract,
discard await contract.provider.call(transaction, overrides)
proc call(contract: Contract,
function: string,
parameters: tuple,
ReturnType: type,
overrides = TransactionOverrides()): Future[ReturnType] {.async: (raises: [ProviderError, SignerError, ContractError]).} =
proc call(
contract: Contract,
function: string,
parameters: tuple,
ReturnType: type,
overrides = TransactionOverrides(),
): Future[ReturnType] {.
async: (raises: [ProviderError, SignerError, ContractError, CancelledError])
.} =
var transaction = createTransaction(contract, function, parameters, overrides)
if signer =? contract.signer and transaction.sender.isNone:
@ -126,7 +133,7 @@ proc send(
function: string,
parameters: tuple,
overrides = TransactionOverrides()
): Future[?TransactionResponse] {.async: (raises: [AsyncLockError, CancelledError, CatchableError]).} =
): Future[?TransactionResponse] {.async: (raises: [AsyncLockError, SignerError, ProviderError, CancelledError]).} =
if signer =? contract.signer:
withLock(signer):
@ -263,10 +270,22 @@ func addAsyncPragma(procedure: var NimNode) =
let pragmas = procedure[4]
if pragmas.kind == nnkEmpty:
procedure[4] = newNimNode(nnkPragma)
procedure[4].add ident("async")
macro contract*(procedure: untyped{nkProcDef|nkMethodDef}): untyped =
procedure[4].add nnkExprColonExpr.newTree(
newIdentNode("async"),
nnkTupleConstr.newTree(
nnkExprColonExpr.newTree(
newIdentNode("raises"),
nnkBracket.newTree(
newIdentNode("CancelledError"),
newIdentNode("ProviderError"),
newIdentNode("EthersError"),
newIdentNode("AsyncLockError"),
),
)
),
)
macro contract*(procedure: untyped{nkProcDef | nkMethodDef}): untyped =
let parameters = procedure[3]
let body = procedure[6]

View File

@ -102,96 +102,85 @@ func toTransaction*(past: PastTransaction): Transaction =
)
method getBlockNumber*(
provider: Provider): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
provider: Provider
): Future[UInt256] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method getBlock*(
provider: Provider,
tag: BlockTag): Future[?Block] {.base, async: (raises:[ProviderError]).} =
provider: Provider, tag: BlockTag
): Future[?Block] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method call*(
provider: Provider,
tx: Transaction,
blockTag = BlockTag.latest): Future[seq[byte]] {.base, async: (raises:[ProviderError]).} =
provider: Provider, tx: Transaction, blockTag = BlockTag.latest
): Future[seq[byte]] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method getGasPrice*(
provider: Provider): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
provider: Provider
): Future[UInt256] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method getTransactionCount*(
provider: Provider,
address: Address,
blockTag = BlockTag.latest): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
provider: Provider, address: Address, blockTag = BlockTag.latest
): Future[UInt256] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method getTransaction*(
provider: Provider,
txHash: TransactionHash): Future[?PastTransaction] {.base, async: (raises:[ProviderError]).} =
provider: Provider, txHash: TransactionHash
): Future[?PastTransaction] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method getTransactionReceipt*(
provider: Provider,
txHash: TransactionHash): Future[?TransactionReceipt] {.base, async: (raises:[ProviderError]).} =
provider: Provider, txHash: TransactionHash
): Future[?TransactionReceipt] {.
base, async: (raises: [ProviderError, CancelledError])
.} =
doAssert false, "not implemented"
method sendTransaction*(
provider: Provider,
rawTransaction: seq[byte]): Future[TransactionResponse] {.base, async: (raises:[ProviderError]).} =
provider: Provider, rawTransaction: seq[byte]
): Future[TransactionResponse] {.
base, async: (raises: [ProviderError, CancelledError])
.} =
doAssert false, "not implemented"
method getLogs*(
provider: Provider,
filter: EventFilter): Future[seq[Log]] {.base, async: (raises:[ProviderError]).} =
provider: Provider, filter: EventFilter
): Future[seq[Log]] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method estimateGas*(
provider: Provider,
transaction: Transaction,
blockTag = BlockTag.latest): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
provider: Provider, transaction: Transaction, blockTag = BlockTag.latest
): Future[UInt256] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method getChainId*(
provider: Provider): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
provider: Provider
): Future[UInt256] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method subscribe*(
provider: Provider,
filter: EventFilter,
callback: LogHandler): Future[Subscription] {.base, async: (raises:[ProviderError]).} =
provider: Provider, filter: EventFilter, callback: LogHandler
): Future[Subscription] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method subscribe*(
provider: Provider,
callback: BlockHandler): Future[Subscription] {.base, async: (raises:[ProviderError]).} =
provider: Provider, callback: BlockHandler
): Future[Subscription] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method unsubscribe*(
subscription: Subscription) {.base, async: (raises:[ProviderError]).} =
subscription: Subscription
) {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
method isSyncing*(provider: Provider): Future[bool] {.base, async.} =
method isSyncing*(provider: Provider): Future[bool] {.base, async: (raises: [ProviderError, CancelledError]).} =
doAssert false, "not implemented"
proc replay*(
provider: Provider,
tx: Transaction,
blockNumber: UInt256) {.async: (raises:[ProviderError]).} =
provider: Provider, tx: Transaction, blockNumber: UInt256
) {.async: (raises: [ProviderError, CancelledError]).} =
# Replay transaction at block. Useful for fetching revert reasons, which will
# be present in the raised error message. The replayed block number should
# include the state of the chain in the block previous to the block in which
@ -203,8 +192,8 @@ proc replay*(
discard await provider.call(tx, BlockTag.init(blockNumber))
proc ensureSuccess(
provider: Provider,
receipt: TransactionReceipt) {.async: (raises: [ProviderError]).} =
provider: Provider, receipt: TransactionReceipt
) {.async: (raises: [ProviderError, CancelledError]).} =
## If the receipt.status is Failed, the tx is replayed to obtain a revert
## reason, after which a ProviderError with the revert reason is raised.
## If no revert reason was obtained
@ -252,7 +241,7 @@ proc confirm*(
if number > blockNumber:
blockNumber = number
blockEvent.fire()
except ProviderError:
except ProviderError, CancelledError:
# there's nothing we can do here
discard
@ -312,5 +301,7 @@ proc confirm*(
let txResp = await tx
return await txResp.confirm(confirmations, timeout)
method close*(provider: Provider) {.base, async: (raises:[ProviderError]).} =
method close*(
provider: Provider
) {.base, async: (raises: [ProviderError, CancelledError]).} =
discard

View File

@ -56,7 +56,7 @@ proc new*(
var client: RpcClient
var subscriptions: JsonRpcSubscriptions
proc initialize {.async: (raises:[JsonRpcProviderError]).} =
proc initialize() {.async: (raises: [JsonRpcProviderError, CancelledError]).} =
convertError:
case parseUri(url).scheme
of "ws", "wss":
@ -72,12 +72,16 @@ proc new*(
pollingInterval = pollingInterval)
subscriptions.start()
proc awaitClient: Future[RpcClient] {.async:(raises:[JsonRpcProviderError]).} =
proc awaitClient(): Future[RpcClient] {.
async: (raises: [JsonRpcProviderError, CancelledError])
.} =
convertError:
await initialized
return client
proc awaitSubscriptions: Future[JsonRpcSubscriptions] {.async:(raises:[JsonRpcProviderError]).} =
proc awaitSubscriptions(): Future[JsonRpcSubscriptions] {.
async: (raises: [JsonRpcProviderError, CancelledError])
.} =
convertError:
await initialized
return subscriptions
@ -86,29 +90,29 @@ proc new*(
return JsonRpcProvider(client: awaitClient(), subscriptions: awaitSubscriptions())
proc callImpl(
client: RpcClient,
call: string,
args: JsonNode): Future[JsonNode] {.async: (raises: [JsonRpcProviderError]).} =
without response =? (await client.call(call, %args)).catch, error:
client: RpcClient, call: string, args: JsonNode
): Future[JsonNode] {.async: (raises: [JsonRpcProviderError, CancelledError]).} =
try:
let response = await client.call(call, %args)
without json =? JsonNode.fromJson(response.string), error:
raiseJsonRpcProviderError "Failed to parse response '" & response.string & "': " &
error.msg
return json
except CancelledError as error:
raise error
except CatchableError as error:
raiseJsonRpcProviderError error.msg
without json =? JsonNode.fromJson(response.string), error:
raiseJsonRpcProviderError "Failed to parse response: " & error.msg
json
proc send*(
provider: JsonRpcProvider,
call: string,
arguments: seq[JsonNode] = @[]): Future[JsonNode]
{.async: (raises: [JsonRpcProviderError]).} =
provider: JsonRpcProvider, call: string, arguments: seq[JsonNode] = @[]
): Future[JsonNode] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.callImpl(call, %arguments)
proc listAccounts*(provider: JsonRpcProvider): Future[seq[Address]]
{.async: (raises: [JsonRpcProviderError]).} =
proc listAccounts*(
provider: JsonRpcProvider
): Future[seq[Address]] {.async: (raises: [JsonRpcProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_accounts()
@ -120,73 +124,66 @@ proc getSigner*(provider: JsonRpcProvider, address: Address): JsonRpcSigner =
JsonRpcSigner(provider: provider, address: some address)
method getBlockNumber*(
provider: JsonRpcProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider
): Future[UInt256] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_blockNumber()
method getBlock*(
provider: JsonRpcProvider,
tag: BlockTag): Future[?Block] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, tag: BlockTag
): Future[?Block] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_getBlockByNumber(tag, false)
method call*(
provider: JsonRpcProvider,
tx: Transaction,
blockTag = BlockTag.latest): Future[seq[byte]] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, tx: Transaction, blockTag = BlockTag.latest
): Future[seq[byte]] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_call(tx, blockTag)
method getGasPrice*(
provider: JsonRpcProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider
): Future[UInt256] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_gasPrice()
method getTransactionCount*(
provider: JsonRpcProvider,
address: Address,
blockTag = BlockTag.latest): Future[UInt256] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, address: Address, blockTag = BlockTag.latest
): Future[UInt256] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_getTransactionCount(address, blockTag)
method getTransaction*(
provider: JsonRpcProvider,
txHash: TransactionHash): Future[?PastTransaction] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, txHash: TransactionHash
): Future[?PastTransaction] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_getTransactionByHash(txHash)
method getTransactionReceipt*(
provider: JsonRpcProvider,
txHash: TransactionHash): Future[?TransactionReceipt] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, txHash: TransactionHash
): Future[?TransactionReceipt] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
return await client.eth_getTransactionReceipt(txHash)
method getLogs*(
provider: JsonRpcProvider,
filter: EventFilter): Future[seq[Log]] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, filter: EventFilter
): Future[seq[Log]] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
let logsJson = if filter of Filter:
await client.eth_getLogs(Filter(filter))
elif filter of FilterByBlockHash:
await client.eth_getLogs(FilterByBlockHash(filter))
else:
await client.eth_getLogs(filter)
let logsJson =
if filter of Filter:
await client.eth_getLogs(Filter(filter))
elif filter of FilterByBlockHash:
await client.eth_getLogs(FilterByBlockHash(filter))
else:
await client.eth_getLogs(filter)
var logs: seq[Log] = @[]
for logJson in logsJson.getElems:
@ -196,10 +193,10 @@ method getLogs*(
return logs
method estimateGas*(
provider: JsonRpcProvider,
transaction: Transaction,
blockTag = BlockTag.latest): Future[UInt256] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider,
transaction: Transaction,
blockTag = BlockTag.latest,
): Future[UInt256] {.async: (raises: [ProviderError, CancelledError]).} =
try:
convertError:
let client = await provider.client
@ -209,24 +206,24 @@ method estimateGas*(
msg: "Estimate gas failed: " & error.msg,
data: error.data,
transaction: transaction,
parent: error
parent: error,
)
method getChainId*(
provider: JsonRpcProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider
): Future[UInt256] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
try:
return await client.eth_chainId()
except CancelledError as error:
raise error
except CatchableError:
return parse(await client.net_version(), UInt256)
method sendTransaction*(
provider: JsonRpcProvider,
rawTransaction: seq[byte]): Future[TransactionResponse]
{.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, rawTransaction: seq[byte]
): Future[TransactionResponse] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let
client = await provider.client
@ -235,41 +232,40 @@ method sendTransaction*(
return TransactionResponse(hash: hash, provider: provider)
method subscribe*(
provider: JsonRpcProvider,
filter: EventFilter,
onLog: LogHandler): Future[Subscription] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, filter: EventFilter, onLog: LogHandler
): Future[Subscription] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let subscriptions = await provider.subscriptions
let id = await subscriptions.subscribeLogs(filter, onLog)
return JsonRpcSubscription(subscriptions: subscriptions, id: id)
method subscribe*(
provider: JsonRpcProvider,
onBlock: BlockHandler): Future[Subscription] {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider, onBlock: BlockHandler
): Future[Subscription] {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let subscriptions = await provider.subscriptions
let id = await subscriptions.subscribeBlocks(onBlock)
return JsonRpcSubscription(subscriptions: subscriptions, id: id)
method unsubscribe*(
subscription: JsonRpcSubscription) {.async: (raises:[ProviderError]).} =
subscription: JsonRpcSubscription
) {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let subscriptions = subscription.subscriptions
let id = subscription.id
await subscriptions.unsubscribe(id)
method isSyncing*(provider: JsonRpcProvider): Future[bool] {.async.} =
method isSyncing*(
provider: JsonRpcProvider
): Future[bool] {.async: (raises: [ProviderError, CancelledError]).} =
let response = await provider.send("eth_syncing")
if response.kind == JsonNodeKind.JObject:
return true
return response.getBool()
method close*(
provider: JsonRpcProvider) {.async: (raises:[ProviderError]).} =
provider: JsonRpcProvider
) {.async: (raises: [ProviderError, CancelledError]).} =
convertError:
let client = await provider.client
let subscriptions = await provider.subscriptions
@ -290,6 +286,8 @@ proc raiseJsonRpcSignerError(
template convertSignerError(body) =
try:
body
except CancelledError as error:
raise error
except JsonRpcError as error:
raiseJsonRpcSignerError(error.msg)
except CatchableError as error:
@ -301,9 +299,8 @@ method provider*(signer: JsonRpcSigner): Provider
signer.provider
method getAddress*(
signer: JsonRpcSigner): Future[Address]
{.async: (raises:[ProviderError, SignerError]).} =
signer: JsonRpcSigner
): Future[Address] {.async: (raises: [ProviderError, SignerError, CancelledError]).} =
if address =? signer.address:
return address
@ -314,19 +311,18 @@ method getAddress*(
raiseJsonRpcSignerError "no address found"
method signMessage*(
signer: JsonRpcSigner,
message: seq[byte]): Future[seq[byte]] {.async: (raises:[SignerError]).} =
signer: JsonRpcSigner, message: seq[byte]
): Future[seq[byte]] {.async: (raises: [SignerError, CancelledError]).} =
convertSignerError:
let client = await signer.provider.client
let address = await signer.getAddress()
return await client.personal_sign(message, address)
method sendTransaction*(
signer: JsonRpcSigner,
transaction: Transaction): Future[TransactionResponse]
{.async: (raises:[SignerError, ProviderError]).} =
signer: JsonRpcSigner, transaction: Transaction
): Future[TransactionResponse] {.
async: (raises: [SignerError, ProviderError, CancelledError])
.} =
convertError:
let
client = await signer.provider.client

View File

@ -40,6 +40,8 @@ proc raiseJsonRpcProviderError*(
template convertError*(body) =
try:
body
except CancelledError as error:
raise error
except JsonRpcError as error:
raiseJsonRpcProviderError(error.msg)
except CatchableError as error:

View File

@ -18,6 +18,8 @@ template raiseSignerError*(message: string, parent: ref ProviderError = nil) =
template convertError(body) =
try:
body
except CancelledError as error:
raise error
except ProviderError as error:
raise error # do not convert provider errors
except CatchableError as error:
@ -28,59 +30,61 @@ method provider*(
doAssert false, "not implemented"
method getAddress*(
signer: Signer): Future[Address]
{.base, async: (raises:[ProviderError, SignerError]).} =
signer: Signer
): Future[Address] {.
base, async: (raises: [ProviderError, SignerError, CancelledError])
.} =
doAssert false, "not implemented"
method signMessage*(
signer: Signer,
message: seq[byte]): Future[seq[byte]]
{.base, async: (raises: [SignerError]).} =
signer: Signer, message: seq[byte]
): Future[seq[byte]] {.base, async: (raises: [SignerError, CancelledError]).} =
doAssert false, "not implemented"
method sendTransaction*(
signer: Signer,
transaction: Transaction): Future[TransactionResponse]
{.base, async: (raises:[SignerError, ProviderError]).} =
signer: Signer, transaction: Transaction
): Future[TransactionResponse] {.
base, async: (raises: [SignerError, ProviderError, CancelledError])
.} =
doAssert false, "not implemented"
method getGasPrice*(
signer: Signer): Future[UInt256]
{.base, async: (raises: [ProviderError, SignerError]).} =
signer: Signer
): Future[UInt256] {.
base, async: (raises: [ProviderError, SignerError, CancelledError])
.} =
return await signer.provider.getGasPrice()
method getTransactionCount*(
signer: Signer,
blockTag = BlockTag.latest): Future[UInt256]
{.base, async: (raises:[SignerError, ProviderError]).} =
signer: Signer, blockTag = BlockTag.latest
): Future[UInt256] {.
base, async: (raises: [SignerError, ProviderError, CancelledError])
.} =
convertError:
let address = await signer.getAddress()
return await signer.provider.getTransactionCount(address, blockTag)
method estimateGas*(
signer: Signer,
transaction: Transaction,
blockTag = BlockTag.latest): Future[UInt256]
{.base, async: (raises:[SignerError, ProviderError]).} =
signer: Signer, transaction: Transaction, blockTag = BlockTag.latest
): Future[UInt256] {.
base, async: (raises: [SignerError, ProviderError, CancelledError])
.} =
var transaction = transaction
transaction.sender = some(await signer.getAddress())
return await signer.provider.estimateGas(transaction, blockTag)
method getChainId*(
signer: Signer): Future[UInt256]
{.base, async: (raises: [ProviderError, SignerError]).} =
signer: Signer
): Future[UInt256] {.
base, async: (raises: [SignerError, ProviderError, CancelledError])
.} =
return await signer.provider.getChainId()
method getNonce(
signer: Signer): Future[UInt256] {.base, async: (raises: [SignerError, ProviderError]).} =
signer: Signer
): Future[UInt256] {.
base, async: (raises: [SignerError, ProviderError, CancelledError])
.} =
return await signer.getTransactionCount(BlockTag.pending)
template withLock*(signer: Signer, body: untyped) =

View File

@ -69,7 +69,7 @@ method provider*(wallet: Wallet): Provider {.gcsafe, raises: [SignerError].} =
method getAddress*(
wallet: Wallet): Future[Address]
{.async: (raises:[ProviderError, SignerError]).} =
{.async: (raises:[ProviderError, SignerError, CancelledError]).} =
return wallet.address
@ -83,7 +83,7 @@ proc signTransaction*(wallet: Wallet,
method sendTransaction*(
wallet: Wallet,
transaction: Transaction): Future[TransactionResponse]
{.async: (raises:[SignerError, ProviderError]).} =
{.async: (raises:[SignerError, ProviderError, CancelledError]).} =
let signed = await signTransaction(wallet, transaction)
return await provider(wallet).sendTransaction(signed)

View File

@ -9,5 +9,7 @@ func raiseWalletError*(message: string) {.raises: [WalletError].}=
template convertError*(body) =
try:
body
except CancelledError as error:
raise error
except CatchableError as error:
raiseWalletError(error.msg)

View File

@ -13,13 +13,13 @@ method provider*(signer: MockSigner): Provider =
method getAddress*(
signer: MockSigner): Future[Address]
{.async: (raises:[ProviderError, SignerError]).} =
{.async: (raises:[ProviderError, SignerError, CancelledError]).} =
return signer.address
method sendTransaction*(
signer: MockSigner,
transaction: Transaction): Future[TransactionResponse]
{.async: (raises:[SignerError, ProviderError]).} =
{.async: (raises:[SignerError, ProviderError, CancelledError]).} =
signer.transactions.add(transaction)