Update exceptions

Use {.async: (raises: [...].} where needed
Annotate provider with {.push raises:[].}
Format signatures
This commit is contained in:
Eric 2024-01-24 14:36:53 +11:00
parent ad1fe90492
commit f6f0dbc07b
No known key found for this signature in database
7 changed files with 182 additions and 116 deletions

View File

@ -5,7 +5,7 @@ license = "MIT"
requires "nim >= 1.6.0" requires "nim >= 1.6.0"
requires "chronicles >= 0.10.3 & < 0.11.0" requires "chronicles >= 0.10.3 & < 0.11.0"
requires "chronos >= 3.0.0 & < 4.0.0" requires "chronos#f0a2d4df61302d24baa6c0f1c257f92045c9ee57"
requires "contractabi >= 0.6.0 & < 0.7.0" requires "contractabi >= 0.6.0 & < 0.7.0"
requires "questionable >= 0.10.2 & < 0.11.0" requires "questionable >= 0.10.2 & < 0.11.0"
requires "json_rpc" requires "json_rpc"

View File

@ -97,68 +97,94 @@ func toTransaction*(past: PastTransaction): Transaction =
chainId: past.chainId chainId: past.chainId
) )
method getBlockNumber*(provider: Provider): Future[UInt256] {.base, gcsafe.} = method getBlockNumber*(
provider: Provider): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getBlock*(provider: Provider, tag: BlockTag): Future[?Block] {.base, gcsafe.} = method getBlock*(
provider: Provider,
tag: BlockTag): Future[?Block] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method call*(provider: Provider, method call*(
tx: Transaction, provider: Provider,
blockTag = BlockTag.latest): Future[seq[byte]] {.base, gcsafe.} = tx: Transaction,
blockTag = BlockTag.latest): Future[seq[byte]] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getGasPrice*(provider: Provider): Future[UInt256] {.base, gcsafe.} = method getGasPrice*(
provider: Provider): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getTransactionCount*(provider: Provider, method getTransactionCount*(
address: Address, provider: Provider,
blockTag = BlockTag.latest): address: Address,
Future[UInt256] {.base, gcsafe.} = blockTag = BlockTag.latest): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getTransaction*(provider: Provider, method getTransaction*(
txHash: TransactionHash): provider: Provider,
Future[?PastTransaction] {.base, gcsafe.} = txHash: TransactionHash): Future[?PastTransaction] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getTransactionReceipt*(provider: Provider, method getTransactionReceipt*(
txHash: TransactionHash): provider: Provider,
Future[?TransactionReceipt] {.base, gcsafe.} = txHash: TransactionHash): Future[?TransactionReceipt] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method sendTransaction*(provider: Provider, method sendTransaction*(
rawTransaction: seq[byte]): provider: Provider,
Future[TransactionResponse] {.base, gcsafe.} = rawTransaction: seq[byte]): Future[TransactionResponse] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getLogs*(provider: Provider, method getLogs*(
filter: EventFilter): Future[seq[Log]] {.base, gcsafe.} = provider: Provider,
filter: EventFilter): Future[seq[Log]] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method estimateGas*(provider: Provider, method estimateGas*(
transaction: Transaction, provider: Provider,
blockTag = BlockTag.latest): Future[UInt256] {.base, gcsafe.} = transaction: Transaction,
blockTag = BlockTag.latest): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getChainId*(provider: Provider): Future[UInt256] {.base, gcsafe.} = method getChainId*(
provider: Provider): Future[UInt256] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method subscribe*(provider: Provider, method subscribe*(
filter: EventFilter, provider: Provider,
callback: LogHandler): filter: EventFilter,
Future[Subscription] {.base, gcsafe.} = callback: LogHandler): Future[Subscription] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method subscribe*(provider: Provider, method subscribe*(
callback: BlockHandler): provider: Provider,
Future[Subscription] {.base, gcsafe.} = callback: BlockHandler): Future[Subscription] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method unsubscribe*(subscription: Subscription) {.base, async.} = method unsubscribe*(
subscription: Subscription) {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
proc replay*(provider: Provider, tx: Transaction, blockNumber: UInt256) {.async.} = proc replay*(
provider: Provider,
tx: Transaction,
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
@ -172,8 +198,7 @@ proc replay*(provider: Provider, tx: Transaction, blockNumber: UInt256) {.async.
method getRevertReason*( method getRevertReason*(
provider: Provider, provider: Provider,
hash: TransactionHash, hash: TransactionHash,
blockNumber: UInt256 blockNumber: UInt256): Future[?string] {.base, async: (raises: [ProviderError]).} =
): Future[?string] {.base, async.} =
without pastTx =? await provider.getTransaction(hash): without pastTx =? await provider.getTransaction(hash):
return none string return none string
@ -187,8 +212,7 @@ method getRevertReason*(
method getRevertReason*( method getRevertReason*(
provider: Provider, provider: Provider,
receipt: TransactionReceipt receipt: TransactionReceipt): Future[?string] {.base, async: (raises: [ProviderError]).} =
): Future[?string] {.base, async.} =
if receipt.status != TransactionStatus.Failure: if receipt.status != TransactionStatus.Failure:
return none string return none string
@ -200,8 +224,7 @@ method getRevertReason*(
proc ensureSuccess( proc ensureSuccess(
provider: Provider, provider: Provider,
receipt: TransactionReceipt receipt: TransactionReceipt) {.async: (raises: [ProviderError]).} =
) {.async, raises: [ProviderError].} =
## 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
@ -220,11 +243,10 @@ proc ensureSuccess(
trace "transaction replay completed, no revert reason obtained" trace "transaction replay completed, no revert reason obtained"
raiseProviderError("Transaction reverted with unknown reason") raiseProviderError("Transaction reverted with unknown reason")
proc confirm*(tx: TransactionResponse, proc confirm*(
confirmations = EthersDefaultConfirmations, tx: TransactionResponse,
timeout = EthersReceiptTimeoutBlks): confirmations = EthersDefaultConfirmations,
Future[TransactionReceipt] timeout = EthersReceiptTimeoutBlks): Future[TransactionReceipt] {.async: (raises: [CancelledError, ProviderError, EthersError]).} =
{.async, raises: [ProviderError, EthersError].} =
## Waits for a transaction to be mined and for the specified number of blocks ## Waits for a transaction to be mined and for the specified number of blocks
## to pass since it was mined (confirmations). ## to pass since it was mined (confirmations).
## A timeout, in blocks, can be specified that will raise an error if too many ## A timeout, in blocks, can be specified that will raise an error if too many
@ -266,10 +288,10 @@ proc confirm*(tx: TransactionResponse,
await tx.provider.ensureSuccess(receipt) await tx.provider.ensureSuccess(receipt)
return receipt return receipt
proc confirm*(tx: Future[TransactionResponse], proc confirm*(
confirmations: int = EthersDefaultConfirmations, tx: Future[TransactionResponse],
timeout: int = EthersReceiptTimeoutBlks): confirmations: int = EthersDefaultConfirmations,
Future[TransactionReceipt] {.async.} = timeout: int = EthersReceiptTimeoutBlks): Future[TransactionReceipt] {.async.} =
## Convenience method that allows wait to be chained to a sendTransaction ## Convenience method that allows wait to be chained to a sendTransaction
## call, eg: ## call, eg:
## `await signer.sendTransaction(populated).confirm(3)` ## `await signer.sendTransaction(populated).confirm(3)`
@ -277,5 +299,5 @@ proc confirm*(tx: Future[TransactionResponse],
let txResp = await tx let txResp = await tx
return await txResp.confirm(confirmations, timeout) return await txResp.confirm(confirmations, timeout)
method close*(provider: Provider) {.async, base.} = method close*(provider: Provider) {.base, async: (raises:[ProviderError]).} =
discard discard

View File

@ -49,9 +49,7 @@ template convertError(body) =
body body
except JsonRpcError as error: except JsonRpcError as error:
raiseJsonRpcProviderError(error.msg) raiseJsonRpcProviderError(error.msg)
# Catch all ValueErrors for now, at least until JsonRpcError is actually except CatchableError as error:
# raised. PR created: https://github.com/status-im/nim-json-rpc/pull/151
except ValueError as error:
raiseJsonRpcProviderError(error.msg) raiseJsonRpcProviderError(error.msg)
# Provider # Provider
@ -62,9 +60,11 @@ const defaultPollingInterval = 4.seconds
proc jsonHeaders: seq[(string, string)] = proc jsonHeaders: seq[(string, string)] =
@[("Content-Type", "application/json")] @[("Content-Type", "application/json")]
proc new*(_: type JsonRpcProvider, proc new*(
url=defaultUrl, _: type JsonRpcProvider,
pollingInterval=defaultPollingInterval): JsonRpcProvider = url=defaultUrl,
pollingInterval=defaultPollingInterval): JsonRpcProvider {.raises: [JsonRpcProviderError].} =
var initialized: Future[void] var initialized: Future[void]
var client: RpcClient var client: RpcClient
var subscriptions: JsonRpcSubscriptions var subscriptions: JsonRpcSubscriptions
@ -82,19 +82,21 @@ proc new*(_: type JsonRpcProvider,
client = http client = http
subscriptions = JsonRpcSubscriptions.new(http, subscriptions = JsonRpcSubscriptions.new(http,
pollingInterval = pollingInterval) pollingInterval = pollingInterval)
subscriptions.init()
proc awaitClient: Future[RpcClient] {.async.} = proc awaitClient: Future[RpcClient] {.async:(raises:[JsonRpcProviderError]).} =
convertError: convertError:
await initialized await initialized
return client return client
proc awaitSubscriptions: Future[JsonRpcSubscriptions] {.async.} = proc awaitSubscriptions: Future[JsonRpcSubscriptions] {.async:(raises:[JsonRpcProviderError]).} =
convertError: convertError:
await initialized await initialized
return subscriptions return subscriptions
initialized = initialize() convertError:
JsonRpcProvider(client: awaitClient(), subscriptions: awaitSubscriptions()) initialized = initialize()
return JsonRpcProvider(client: awaitClient(), subscriptions: awaitSubscriptions())
proc callImpl( proc callImpl(
client: RpcClient, client: RpcClient,
@ -116,7 +118,6 @@ proc send*(
arguments: seq[JsonNode] = @[]): Future[JsonNode] {.async.} = arguments: seq[JsonNode] = @[]): Future[JsonNode] {.async.} =
convertError: convertError:
let client = await provider.client let client = await provider.client
return await client.call(call, %arguments)
return await client.callImpl(call, %arguments) return await client.callImpl(call, %arguments)
proc listAccounts*(provider: JsonRpcProvider): Future[seq[Address]] {.async.} = proc listAccounts*(provider: JsonRpcProvider): Future[seq[Address]] {.async.} =
@ -130,54 +131,66 @@ proc getSigner*(provider: JsonRpcProvider): JsonRpcSigner =
proc getSigner*(provider: JsonRpcProvider, address: Address): JsonRpcSigner = proc getSigner*(provider: JsonRpcProvider, address: Address): JsonRpcSigner =
JsonRpcSigner(provider: provider, address: some address) JsonRpcSigner(provider: provider, address: some address)
method getBlockNumber*(provider: JsonRpcProvider): Future[UInt256] {.async.} = method getBlockNumber*(
provider: JsonRpcProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
convertError: convertError:
let client = await provider.client let client = await provider.client
return await client.eth_blockNumber() return await client.eth_blockNumber()
method getBlock*(provider: JsonRpcProvider, method getBlock*(
tag: BlockTag): Future[?Block] {.async.} = provider: JsonRpcProvider,
tag: BlockTag): Future[?Block] {.async: (raises:[ProviderError]).} =
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*(provider: JsonRpcProvider, method call*(
tx: Transaction, provider: JsonRpcProvider,
blockTag = BlockTag.latest): Future[seq[byte]] {.async.} = tx: Transaction,
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*(provider: JsonRpcProvider): Future[UInt256] {.async.} = method getGasPrice*(
provider: JsonRpcProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
convertError: convertError:
let client = await provider.client let client = await provider.client
return await client.eth_gasPrice() return await client.eth_gasPrice()
method getTransactionCount*(provider: JsonRpcProvider, method getTransactionCount*(
address: Address, provider: JsonRpcProvider,
blockTag = BlockTag.latest): address: Address,
Future[UInt256] {.async.} = 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*(provider: JsonRpcProvider, method getTransaction*(
txHash: TransactionHash): provider: JsonRpcProvider,
Future[?PastTransaction] {.async.} = txHash: TransactionHash): Future[?PastTransaction] {.async: (raises:[ProviderError]).} =
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*(provider: JsonRpcProvider, method getTransactionReceipt*(
txHash: TransactionHash): provider: JsonRpcProvider,
Future[?TransactionReceipt] {.async.} = txHash: TransactionHash): Future[?TransactionReceipt] {.async: (raises:[ProviderError]).} =
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*(provider: JsonRpcProvider, method getLogs*(
filter: EventFilter): provider: JsonRpcProvider,
Future[seq[Log]] {.async.} = filter: EventFilter): Future[seq[Log]] {.async: (raises:[ProviderError]).} =
convertError: convertError:
let client = await provider.client let client = await provider.client
let logsJson = if filter of Filter: let logsJson = if filter of Filter:
@ -189,19 +202,23 @@ method getLogs*(provider: JsonRpcProvider,
var logs: seq[Log] = @[] var logs: seq[Log] = @[]
for logJson in logsJson.getElems: for logJson in logsJson.getElems:
if log =? Log.fromJson(logJson).catch: if log =? Log.fromJson(logJson):
logs.add log logs.add log
return logs return logs
method estimateGas*(provider: JsonRpcProvider, method estimateGas*(
transaction: Transaction, provider: JsonRpcProvider,
blockTag = BlockTag.latest): Future[UInt256] {.async.} = transaction: Transaction,
blockTag = BlockTag.latest): Future[UInt256] {.async: (raises:[ProviderError]).} =
convertError: convertError:
let client = await provider.client let client = await provider.client
return await client.eth_estimateGas(transaction, blockTag) return await client.eth_estimateGas(transaction, blockTag)
method getChainId*(provider: JsonRpcProvider): Future[UInt256] {.async.} = method getChainId*(
provider: JsonRpcProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
convertError: convertError:
let client = await provider.client let client = await provider.client
try: try:
@ -209,7 +226,10 @@ method getChainId*(provider: JsonRpcProvider): Future[UInt256] {.async.} =
except CatchableError: except CatchableError:
return parse(await client.net_version(), UInt256) return parse(await client.net_version(), UInt256)
method sendTransaction*(provider: JsonRpcProvider, rawTransaction: seq[byte]): Future[TransactionResponse] {.async.} = method sendTransaction*(
provider: JsonRpcProvider,
rawTransaction: seq[byte]): Future[TransactionResponse] {.async: (raises:[ProviderError]).} =
convertError: convertError:
let let
client = await provider.client client = await provider.client
@ -217,33 +237,42 @@ method sendTransaction*(provider: JsonRpcProvider, rawTransaction: seq[byte]): F
return TransactionResponse(hash: hash, provider: provider) return TransactionResponse(hash: hash, provider: provider)
method subscribe*(provider: JsonRpcProvider, method subscribe*(
filter: EventFilter, provider: JsonRpcProvider,
onLog: LogHandler): filter: EventFilter,
Future[Subscription] {.async.} = 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*(provider: JsonRpcProvider, method subscribe*(
onBlock: BlockHandler): provider: JsonRpcProvider,
Future[Subscription] {.async.} = onBlock: BlockHandler): Future[Subscription] {.async: (raises:[ProviderError]).} =
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(subscription: JsonRpcSubscription) {.async.} = method unsubscribe*(
subscription: JsonRpcSubscription) {.async: (raises:[ProviderError]).} =
convertError: convertError:
let subscriptions = subscription.subscriptions let subscriptions = subscription.subscriptions
let id = subscription.id let id = subscription.id
echo "[jsonrpc.unsubscribe] subscription id: ", $id
await subscriptions.unsubscribe(id) await subscriptions.unsubscribe(id)
method close*(provider: JsonRpcProvider) {.async.} = method close*(
provider: JsonRpcProvider) {.async: (raises:[ProviderError]).} =
convertError: convertError:
echo "[JsonRpcProvider.close]"
let client = await provider.client let client = await provider.client
let subscriptions = await provider.subscriptions let subscriptions = await provider.subscriptions
echo "[JsonRpcProvider.closing subscriptions]"
await subscriptions.close() await subscriptions.close()
await client.close() await client.close()
@ -252,25 +281,32 @@ method close*(provider: JsonRpcProvider) {.async.} =
method provider*(signer: JsonRpcSigner): Provider = method provider*(signer: JsonRpcSigner): Provider =
signer.provider signer.provider
method getAddress*(signer: JsonRpcSigner): Future[Address] {.async.} = method getAddress*(
signer: JsonRpcSigner): Future[Address] {.async: (raises:[ProviderError]).} =
if address =? signer.address: if address =? signer.address:
return address return address
let accounts = await signer.provider.listAccounts() convertError:
if accounts.len > 0: let accounts = await signer.provider.listAccounts()
return accounts[0] if accounts.len > 0:
return accounts[0]
raiseJsonRpcProviderError "no address found" raiseJsonRpcProviderError "no address found"
method signMessage*(signer: JsonRpcSigner, method signMessage*(
message: seq[byte]): Future[seq[byte]] {.async.} = signer: JsonRpcSigner,
message: seq[byte]): Future[seq[byte]] {.async: (raises:[JsonRpcProviderError]).} =
convertError: convertError:
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.eth_sign(address, message) return await client.eth_sign(address, message)
method sendTransaction*(signer: JsonRpcSigner, method sendTransaction*(
transaction: Transaction): Future[TransactionResponse] {.async.} = signer: JsonRpcSigner,
transaction: Transaction): Future[TransactionResponse] {.async: (raises:[JsonRpcProviderError]).} =
convertError: convertError:
if nonce =? transaction.nonce: if nonce =? transaction.nonce:
signer.updateNonce(nonce) signer.updateNonce(nonce)

View File

@ -2,5 +2,5 @@ template untilCancelled*(body) =
try: try:
while true: while true:
body body
except CancelledError: except CancelledError as e:
raise raise e

View File

@ -3,6 +3,8 @@ import ./provider
export basics export basics
{.push raises: [].}
type type
Signer* = ref object of RootObj Signer* = ref object of RootObj
lastSeenNonce: ?UInt256 lastSeenNonce: ?UInt256
@ -19,17 +21,18 @@ template raiseSignerError(message: string, parent: ref ProviderError = nil) =
proc raiseEstimateGasError( proc raiseEstimateGasError(
transaction: Transaction, transaction: Transaction,
parent: ref ProviderError = nil parent: ref ProviderError = nil
) = ) {.raises: [EstimateGasError] .} =
let e = (ref EstimateGasError)( let e = (ref EstimateGasError)(
msg: "Estimate gas failed", msg: "Estimate gas failed",
transaction: transaction, transaction: transaction,
parent: parent) parent: parent)
raise e raise e
method provider*(signer: Signer): Provider {.base, gcsafe.} = method provider*(signer: Signer):
Provider {.base, gcsafe, raises: [EthersError].} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getAddress*(signer: Signer): Future[Address] {.base, gcsafe.} = method getAddress*(signer: Signer): Future[Address] {.base, async: (raises:[ProviderError]).} =
doAssert false, "not implemented" doAssert false, "not implemented"
method signMessage*(signer: Signer, method signMessage*(signer: Signer,
@ -40,7 +43,8 @@ method sendTransaction*(signer: Signer,
transaction: Transaction): Future[TransactionResponse] {.base, async.} = transaction: Transaction): Future[TransactionResponse] {.base, async.} =
doAssert false, "not implemented" doAssert false, "not implemented"
method getGasPrice*(signer: Signer): Future[UInt256] {.base, gcsafe.} = method getGasPrice*(signer: Signer):
Future[UInt256] {.base, gcsafe, raises: [EthersError].} =
signer.provider.getGasPrice() signer.provider.getGasPrice()
method getTransactionCount*(signer: Signer, method getTransactionCount*(signer: Signer,
@ -59,7 +63,8 @@ method estimateGas*(signer: Signer,
except ProviderError as e: except ProviderError as e:
raiseEstimateGasError transaction, e raiseEstimateGasError transaction, e
method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} = method getChainId*(signer: Signer):
Future[UInt256] {.base, gcsafe, raises: [EthersError].} =
signer.provider.getChainId() signer.provider.getChainId()
method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} = method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} =
@ -91,6 +96,7 @@ method populateTransaction*(signer: Signer,
transaction: Transaction): transaction: Transaction):
Future[Transaction] {.base, async.} = Future[Transaction] {.base, async.} =
echo "[signer.populatetransaction] signer type: ", typeof signer
if sender =? transaction.sender and sender != await signer.getAddress(): if sender =? transaction.sender and sender != await signer.getAddress():
raiseSignerError("from address mismatch") raiseSignerError("from address mismatch")
if chainId =? transaction.chainId and chainId != await signer.getChainId(): if chainId =? transaction.chainId and chainId != await signer.getChainId():
@ -119,8 +125,10 @@ method populateTransaction*(signer: Signer,
populated.nonce = some(await signer.getNonce()) populated.nonce = some(await signer.getNonce())
try: try:
populated.gasLimit = some(await signer.estimateGas(populated)) populated.gasLimit = some(await signer.estimateGas(populated))
except ProviderError, EstimateGasError: except ProviderError as e:
let e = getCurrentException() signer.decreaseNonce()
raise e
except EstimateGasError as e:
signer.decreaseNonce() signer.decreaseNonce()
raise e raise e

View File

@ -54,7 +54,7 @@ proc createRandom*(_: type Wallet, provider: Provider): Wallet =
result.address = Address.init(result.publicKey.toCanonicalAddress()) result.address = Address.init(result.publicKey.toCanonicalAddress())
result.provider = some provider result.provider = some provider
method provider*(wallet: Wallet): Provider = method provider*(wallet: Wallet): Provider {.raises: [WalletError].} =
without provider =? wallet.provider: without provider =? wallet.provider:
raiseWalletError "Wallet has no provider" raiseWalletError "Wallet has no provider"
provider provider

View File

@ -3,5 +3,5 @@ import ../basics
type type
WalletError* = object of EthersError WalletError* = object of EthersError
func raiseWalletError*(message: string) = func raiseWalletError*(message: string) {.raises: [WalletError].}=
raise newException(WalletError, message) raise newException(WalletError, message)