diff --git a/ethers/contract.nim b/ethers/contract.nim index 20704ac..c590313 100644 --- a/ethers/contract.nim +++ b/ethers/contract.nim @@ -3,13 +3,11 @@ import std/macros import std/sequtils import pkg/chronos import pkg/contractabi -import pkg/stew/byteutils import ./basics import ./provider import ./signer import ./events import ./fields -import ./exceptions export basics export provider diff --git a/ethers/exceptions.nim b/ethers/exceptions.nim deleted file mode 100644 index b7f3b72..0000000 --- a/ethers/exceptions.nim +++ /dev/null @@ -1,7 +0,0 @@ -import ./basics - -func msgStack*(error: ref EthersError): string = - var msg = error.msg - if not error.parent.isNil: - msg &= " -- Parent exception: " & error.parent.msg - return msg diff --git a/ethers/providers/jsonrpc.nim b/ethers/providers/jsonrpc.nim index 315ae2e..505944d 100644 --- a/ethers/providers/jsonrpc.nim +++ b/ethers/providers/jsonrpc.nim @@ -3,7 +3,6 @@ import std/tables import std/uri import pkg/json_rpc/rpcclient import pkg/json_rpc/errors -import pkg/stew/byteutils import ../basics import ../provider import ../signer diff --git a/ethers/signer.nim b/ethers/signer.nim index 38a7171..089600c 100644 --- a/ethers/signer.nim +++ b/ethers/signer.nim @@ -1,12 +1,7 @@ import ./basics import ./provider -import pkg/chronicles export basics -export chronicles - -logScope: - topics = "ethers signer" type Signer* = ref object of RootObj @@ -91,35 +86,6 @@ method decreaseNonce*(signer: Signer) {.base, gcsafe.} = if lastSeen =? signer.lastSeenNonce and lastSeen > 0: signer.lastSeenNonce = some lastSeen - 1 -proc ensureNonceSequence( - signer: Signer, - tx: Transaction -): Future[Transaction] {.async.} = - ## Ensures that once the nonce is incremented, if estimate gas fails, the - ## nonce is decremented. Disallows concurrent calls by use of AsyncLock. - ## Immediately returns if tx already has a nonce or gasLimit. - - if not (tx.nonce.isNone and tx.gasLimit.isNone): - return tx - - var populated = tx - if signer.populateLock.isNil: - signer.populateLock = newAsyncLock() - - await signer.populateLock.acquire() - - try: - populated.nonce = some(await signer.getNonce()) - populated.gasLimit = some(await signer.estimateGas(populated)) - except ProviderError, EstimateGasError: - let e = getCurrentException() - signer.decreaseNonce() - raise e - finally: - signer.populateLock.release() - - return populated - method populateTransaction*(signer: Signer, transaction: Transaction): Future[Transaction] {.base, async.} = @@ -129,18 +95,40 @@ method populateTransaction*(signer: Signer, if chainId =? transaction.chainId and chainId != await signer.getChainId(): raiseSignerError("chain id mismatch") - var populated = await signer.ensureNonceSequence(transaction) + if signer.populateLock.isNil: + signer.populateLock = newAsyncLock() - if populated.sender.isNone: + await signer.populateLock.acquire() + + var populated = transaction + + if transaction.sender.isNone: populated.sender = some(await signer.getAddress()) - if populated.chainId.isNone: + if transaction.chainId.isNone: populated.chainId = some(await signer.getChainId()) - if populated.gasPrice.isNone and (populated.maxFee.isNone or populated.maxPriorityFee.isNone): + if transaction.gasPrice.isNone and (populated.maxFee.isNone or populated.maxPriorityFee.isNone): populated.gasPrice = some(await signer.getGasPrice()) - if populated.nonce.isNone: - populated.nonce = some(await signer.getNonce()) - if populated.gasLimit.isNone: - populated.gasLimit = some(await signer.estimateGas(populated)) + + if transaction.nonce.isNone and transaction.gasLimit.isNone: + # when both nonce and gasLimit are not populated, we must ensure getNonce is + # followed by an estimateGas so we can determine if there was an error. If + # there is an error, the nonce must be deprecated to prevent nonce gaps and + # stuck transactions + try: + populated.nonce = some(await signer.getNonce()) + populated.gasLimit = some(await signer.estimateGas(populated)) + except ProviderError, EstimateGasError: + let e = getCurrentException() + signer.decreaseNonce() + raise e + finally: + signer.populateLock.release() + + else: + if transaction.nonce.isNone: + populated.nonce = some(await signer.getNonce()) + if transaction.gasLimit.isNone: + populated.gasLimit = some(await signer.estimateGas(populated)) return populated