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,
|
||||
transaction: Transaction): Future[TransactionResponse] {.async.} =
|
||||
convertError:
|
||||
signer.updateNonce(transaction.nonce)
|
||||
let
|
||||
client = await signer.provider.client
|
||||
hash = await client.eth_sendTransaction(transaction)
|
||||
|
|
|
@ -3,7 +3,10 @@ import ./provider
|
|||
|
||||
export basics
|
||||
|
||||
type Signer* = ref object of RootObj
|
||||
type
|
||||
Signer* = ref object of RootObj
|
||||
lastSeenNonce: ?UInt256
|
||||
|
||||
type SignerError* = object of EthersError
|
||||
|
||||
template raiseSignerError(message: string) =
|
||||
|
@ -41,6 +44,26 @@ method estimateGas*(signer: Signer,
|
|||
method getChainId*(signer: Signer): Future[UInt256] {.base, gcsafe.} =
|
||||
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,
|
||||
transaction: Transaction):
|
||||
Future[Transaction] {.base, async.} =
|
||||
|
@ -55,7 +78,7 @@ method populateTransaction*(signer: Signer,
|
|||
if transaction.sender.isNone:
|
||||
populated.sender = some(await signer.getAddress())
|
||||
if transaction.nonce.isNone:
|
||||
populated.nonce = some(await signer.getTransactionCount(BlockTag.pending))
|
||||
populated.nonce = some(await signer.getNonce())
|
||||
if transaction.chainId.isNone:
|
||||
populated.chainId = some(await signer.getChainId())
|
||||
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 &= "data: 0x" & $transaction.data.toHex
|
||||
if nonce =? transaction.nonce:
|
||||
result &= ", nonce: 0x" & $nonce.toHex
|
||||
result &= ", nonce: " & $nonce
|
||||
if chainId =? transaction.chainId:
|
||||
result &= ", chainId: " & $chainId
|
||||
if gasPrice =? transaction.gasPrice:
|
||||
result &= ", gasPrice: 0x" & $gasPrice.toHex
|
||||
result &= ", gasPrice: " & $gasPrice
|
||||
if gasLimit =? transaction.gasLimit:
|
||||
result &= ", gasLimit: 0x" & $gasLimit.toHex
|
||||
result &= ", gasLimit: " & $gasLimit
|
||||
result &= ")"
|
||||
|
|
|
@ -70,4 +70,5 @@ proc signTransaction*(wallet: Wallet,
|
|||
|
||||
method sendTransaction*(wallet: Wallet, transaction: Transaction): Future[TransactionResponse] {.async.} =
|
||||
let signed = await signTransaction(wallet, transaction)
|
||||
wallet.updateNonce(transaction.nonce)
|
||||
return await provider(wallet).sendTransaction(signed)
|
||||
|
|
|
@ -82,3 +82,24 @@ suite "JsonRpcSigner":
|
|||
transaction.chainId = 0xdeadbeef.u256.some
|
||||
expect SignerError:
|
||||
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