Increment nonce count when populating transaction (#54)
Increment nonce count when populating transaction Co-authored-by: markspanbroek <mark@spanbroek.net>
This commit is contained in:
parent
8fff63102a
commit
f0303473f6
|
@ -240,6 +240,7 @@ method signMessage*(signer: JsonRpcSigner,
|
||||||
method sendTransaction*(signer: JsonRpcSigner,
|
method sendTransaction*(signer: JsonRpcSigner,
|
||||||
transaction: Transaction): Future[TransactionResponse] {.async.} =
|
transaction: Transaction): Future[TransactionResponse] {.async.} =
|
||||||
convertError:
|
convertError:
|
||||||
|
signer.updateNonce(transaction.nonce)
|
||||||
let
|
let
|
||||||
client = await signer.provider.client
|
client = await signer.provider.client
|
||||||
hash = await client.eth_sendTransaction(transaction)
|
hash = await client.eth_sendTransaction(transaction)
|
||||||
|
|
|
@ -3,7 +3,10 @@ import ./provider
|
||||||
|
|
||||||
export basics
|
export basics
|
||||||
|
|
||||||
type Signer* = ref object of RootObj
|
type
|
||||||
|
Signer* = ref object of RootObj
|
||||||
|
lastSeenNonce: ?UInt256
|
||||||
|
|
||||||
type SignerError* = object of EthersError
|
type SignerError* = object of EthersError
|
||||||
|
|
||||||
template raiseSignerError(message: string) =
|
template raiseSignerError(message: string) =
|
||||||
|
@ -41,6 +44,26 @@ method estimateGas*(signer: Signer,
|
||||||
method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} =
|
method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} =
|
||||||
signer.provider.getChainId()
|
signer.provider.getChainId()
|
||||||
|
|
||||||
|
method getNonce(signer: Signer): Future[UInt256] {.base, gcsafe, async.} =
|
||||||
|
var nonce = await signer.getTransactionCount(BlockTag.pending)
|
||||||
|
|
||||||
|
if lastSeen =? signer.lastSeenNonce and lastSeen >= nonce:
|
||||||
|
nonce = (lastSeen + 1.u256)
|
||||||
|
signer.lastSeenNonce = some nonce
|
||||||
|
|
||||||
|
return nonce
|
||||||
|
|
||||||
|
method updateNonce*(signer: Signer, nonce: ?UInt256) {.base, gcsafe.} =
|
||||||
|
without nonce =? nonce:
|
||||||
|
return
|
||||||
|
|
||||||
|
without lastSeen =? signer.lastSeenNonce:
|
||||||
|
signer.lastSeenNonce = some nonce
|
||||||
|
return
|
||||||
|
|
||||||
|
if nonce > lastSeen:
|
||||||
|
signer.lastSeenNonce = some nonce
|
||||||
|
|
||||||
method populateTransaction*(signer: Signer,
|
method populateTransaction*(signer: Signer,
|
||||||
transaction: Transaction):
|
transaction: Transaction):
|
||||||
Future[Transaction] {.base, async.} =
|
Future[Transaction] {.base, async.} =
|
||||||
|
@ -55,7 +78,7 @@ method populateTransaction*(signer: Signer,
|
||||||
if transaction.sender.isNone:
|
if transaction.sender.isNone:
|
||||||
populated.sender = some(await signer.getAddress())
|
populated.sender = some(await signer.getAddress())
|
||||||
if transaction.nonce.isNone:
|
if transaction.nonce.isNone:
|
||||||
populated.nonce = some(await signer.getTransactionCount(BlockTag.pending))
|
populated.nonce = some(await signer.getNonce())
|
||||||
if transaction.chainId.isNone:
|
if transaction.chainId.isNone:
|
||||||
populated.chainId = some(await signer.getChainId())
|
populated.chainId = some(await signer.getChainId())
|
||||||
if transaction.gasPrice.isNone and (transaction.maxFee.isNone or transaction.maxPriorityFee.isNone):
|
if transaction.gasPrice.isNone and (transaction.maxFee.isNone or transaction.maxPriorityFee.isNone):
|
||||||
|
|
|
@ -21,11 +21,11 @@ func `$`*(transaction: Transaction): string =
|
||||||
result &= "value: " & $transaction.value & ", "
|
result &= "value: " & $transaction.value & ", "
|
||||||
result &= "data: 0x" & $transaction.data.toHex
|
result &= "data: 0x" & $transaction.data.toHex
|
||||||
if nonce =? transaction.nonce:
|
if nonce =? transaction.nonce:
|
||||||
result &= ", nonce: 0x" & $nonce.toHex
|
result &= ", nonce: " & $nonce
|
||||||
if chainId =? transaction.chainId:
|
if chainId =? transaction.chainId:
|
||||||
result &= ", chainId: " & $chainId
|
result &= ", chainId: " & $chainId
|
||||||
if gasPrice =? transaction.gasPrice:
|
if gasPrice =? transaction.gasPrice:
|
||||||
result &= ", gasPrice: 0x" & $gasPrice.toHex
|
result &= ", gasPrice: " & $gasPrice
|
||||||
if gasLimit =? transaction.gasLimit:
|
if gasLimit =? transaction.gasLimit:
|
||||||
result &= ", gasLimit: 0x" & $gasLimit.toHex
|
result &= ", gasLimit: " & $gasLimit
|
||||||
result &= ")"
|
result &= ")"
|
||||||
|
|
|
@ -70,4 +70,5 @@ proc signTransaction*(wallet: Wallet,
|
||||||
|
|
||||||
method sendTransaction*(wallet: Wallet, transaction: Transaction): Future[TransactionResponse] {.async.} =
|
method sendTransaction*(wallet: Wallet, transaction: Transaction): Future[TransactionResponse] {.async.} =
|
||||||
let signed = await signTransaction(wallet, transaction)
|
let signed = await signTransaction(wallet, transaction)
|
||||||
|
wallet.updateNonce(transaction.nonce)
|
||||||
return await provider(wallet).sendTransaction(signed)
|
return await provider(wallet).sendTransaction(signed)
|
||||||
|
|
|
@ -82,3 +82,24 @@ suite "JsonRpcSigner":
|
||||||
transaction.chainId = 0xdeadbeef.u256.some
|
transaction.chainId = 0xdeadbeef.u256.some
|
||||||
expect SignerError:
|
expect SignerError:
|
||||||
discard await signer.populateTransaction(transaction)
|
discard await signer.populateTransaction(transaction)
|
||||||
|
|
||||||
|
test "concurrent populate calls increment nonce":
|
||||||
|
let signer = provider.getSigner()
|
||||||
|
let count = await signer.getTransactionCount(BlockTag.pending)
|
||||||
|
var transaction1 = Transaction.example
|
||||||
|
var transaction2 = Transaction.example
|
||||||
|
var transaction3 = Transaction.example
|
||||||
|
|
||||||
|
let populated = await allFinished(
|
||||||
|
signer.populateTransaction(transaction1),
|
||||||
|
signer.populateTransaction(transaction2),
|
||||||
|
signer.populateTransaction(transaction3)
|
||||||
|
)
|
||||||
|
|
||||||
|
transaction1 = await populated[0]
|
||||||
|
transaction2 = await populated[1]
|
||||||
|
transaction3 = await populated[2]
|
||||||
|
|
||||||
|
check !transaction1.nonce == count
|
||||||
|
check !transaction2.nonce == count + 1.u256
|
||||||
|
check !transaction3.nonce == count + 2.u256
|
||||||
|
|
Loading…
Reference in New Issue