fix(async): propagate CancelledErrors

This commit is contained in:
Eric 2025-02-12 21:52:55 +11:00
parent 26342d3e27
commit f088cde27f
No known key found for this signature in database
8 changed files with 194 additions and 181 deletions

View File

@ -88,19 +88,20 @@ proc decodeResponse(T: type, bytes: seq[byte]): T =
raiseContractError "unable to decode return value as " & $T raiseContractError "unable to decode return value as " & $T
return decoded return decoded
proc call(provider: Provider, proc call(
transaction: Transaction, provider: Provider, transaction: Transaction, overrides: TransactionOverrides
overrides: TransactionOverrides): Future[seq[byte]] {.async: (raises: [ProviderError]).} = ): Future[seq[byte]] {.async: (raises: [ProviderError, CancelledError]).} =
if overrides of CallOverrides and if overrides of CallOverrides and blockTag =? CallOverrides(overrides).blockTag:
blockTag =? CallOverrides(overrides).blockTag:
await provider.call(transaction, blockTag) await provider.call(transaction, blockTag)
else: else:
await provider.call(transaction) await provider.call(transaction)
proc call(contract: Contract, proc call(
function: string, contract: Contract,
parameters: tuple, function: string,
overrides = TransactionOverrides()) {.async: (raises: [ProviderError, SignerError]).} = parameters: tuple,
overrides = TransactionOverrides(),
) {.async: (raises: [ProviderError, SignerError, CancelledError]).} =
var transaction = createTransaction(contract, function, parameters, overrides) var transaction = createTransaction(contract, function, parameters, overrides)
if signer =? contract.signer and transaction.sender.isNone: if signer =? contract.signer and transaction.sender.isNone:
@ -108,11 +109,15 @@ proc call(contract: Contract,
discard await contract.provider.call(transaction, overrides) discard await contract.provider.call(transaction, overrides)
proc call(contract: Contract, proc call(
function: string, contract: Contract,
parameters: tuple, function: string,
ReturnType: type, parameters: tuple,
overrides = TransactionOverrides()): Future[ReturnType] {.async: (raises: [ProviderError, SignerError, ContractError]).} = ReturnType: type,
overrides = TransactionOverrides(),
): Future[ReturnType] {.
async: (raises: [ProviderError, SignerError, ContractError, CancelledError])
.} =
var transaction = createTransaction(contract, function, parameters, overrides) var transaction = createTransaction(contract, function, parameters, overrides)
if signer =? contract.signer and transaction.sender.isNone: if signer =? contract.signer and transaction.sender.isNone:
@ -263,10 +268,23 @@ func addAsyncPragma(procedure: var NimNode) =
let pragmas = procedure[4] let pragmas = procedure[4]
if pragmas.kind == nnkEmpty: if pragmas.kind == nnkEmpty:
procedure[4] = newNimNode(nnkPragma) procedure[4] = newNimNode(nnkPragma)
procedure[4].add ident("async") procedure[4].add nnkExprColonExpr.newTree(
newIdentNode("async"),
macro contract*(procedure: untyped{nkProcDef|nkMethodDef}): untyped = nnkTupleConstr.newTree(
nnkExprColonExpr.newTree(
newIdentNode("raises"),
nnkBracket.newTree(
newIdentNode("CancelledError"),
newIdentNode("ProviderError"),
newIdentNode("EthersError"),
newIdentNode("AsyncLockError"),
newIdentNode("CatchableError"),
),
)
),
)
macro contract*(procedure: untyped{nkProcDef | nkMethodDef}): untyped =
let parameters = procedure[3] let parameters = procedure[3]
let body = procedure[6] let body = procedure[6]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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