refactor(subscriptions): cleanup tx.confirm()

This commit is contained in:
Mark Spanbroek 2025-09-10 10:18:10 +02:00
parent ca30aa7e4d
commit c4b3130213

View File

@ -235,69 +235,40 @@ proc confirm*(
assert confirmations > 0
var blockNumber: UInt256
## We need initialized succesfull Result, because the first iteration of the `while` loop
## bellow is triggered "manually" by calling `await updateBlockNumber` and not by block
## subscription. If left uninitialized then the Result is in error state and error is raised.
## This result is not used for block value, but for block subscription errors.
var blockSubscriptionResult: ?!Block = success(Block(number: UInt256.none, timestamp: 0.u256, hash: BlockHash.none))
var blockNumber = await tx.provider.getBlockNumber()
let blockEvent = newAsyncEvent()
proc updateBlockNumber {.async: (raises: []).} =
try:
let number = await tx.provider.getBlockNumber()
if number > blockNumber:
blockNumber = number
blockEvent.fire()
except ProviderError, CancelledError:
# there's nothing we can do here
discard
blockEvent.fire()
proc onBlock(blckResult: ?!Block) =
blockSubscriptionResult = blckResult
if blckResult.isErr:
if blck =? blckResult and number =? blck.number:
blockNumber = number
blockEvent.fire()
return
# ignore block parameter; hardhat may call this with pending blocks
asyncSpawn updateBlockNumber()
await updateBlockNumber()
let subscription = await tx.provider.subscribe(onBlock)
let finish = blockNumber + timeout.u256
var receipt: ?TransactionReceipt
while true:
await blockEvent.wait()
blockEvent.clear()
try:
var receipt: ?TransactionReceipt
if blockSubscriptionResult.isErr:
let error = blockSubscriptionResult.error()
while true:
await blockEvent.wait()
blockEvent.clear()
if error of SubscriptionError:
raise (ref SubscriptionError)(error)
elif error of CancelledError:
raise (ref CancelledError)(error)
else:
raise error.toErr(ProviderError)
if blockNumber >= finish:
raise newException(EthersError, "tx not mined before timeout")
if blockNumber >= finish:
await subscription.unsubscribe()
raise newException(EthersError, "tx not mined before timeout")
if receipt.?blockNumber.isNone:
receipt = await tx.provider.getTransactionReceipt(tx.hash)
if receipt.?blockNumber.isNone:
receipt = await tx.provider.getTransactionReceipt(tx.hash)
without receipt =? receipt and txBlockNumber =? receipt.blockNumber:
continue
without receipt =? receipt and txBlockNumber =? receipt.blockNumber:
continue
if txBlockNumber + confirmations.u256 <= blockNumber + 1:
await subscription.unsubscribe()
await tx.provider.ensureSuccess(receipt)
return receipt
if txBlockNumber + confirmations.u256 <= blockNumber + 1:
await tx.provider.ensureSuccess(receipt)
return receipt
finally:
await subscription.unsubscribe()
proc confirm*(
tx: Future[TransactionResponse],