Skip to content

Commit

Permalink
improve(TransactionClient): Track nonces on submitted transactions (#…
Browse files Browse the repository at this point in the history
…2108)

Track nonces internally within the TransactionClient as an attempt to
mitigate the high number of nonce collisions that are observed when a
chain is subject to a lot of fills.
  • Loading branch information
pxrl authored Feb 21, 2025
1 parent db49a9f commit 1d964b1
Showing 1 changed file with 6 additions and 6 deletions.
12 changes: 6 additions & 6 deletions src/clients/TransactionClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const { isError } = typeguards;
const DEFAULT_GASLIMIT_MULTIPLIER = 1.0;

export class TransactionClient {
readonly nonces: { [chainId: number]: number } = {};

// eslint-disable-next-line no-useless-constructor
constructor(readonly logger: winston.Logger) {}

Expand All @@ -53,7 +55,7 @@ export class TransactionClient {
return Promise.all(txns.map((txn: AugmentedTransaction) => this._simulate(txn)));
}

protected async _submit(txn: AugmentedTransaction, nonce: number | null = null): Promise<TransactionResponse> {
protected _submit(txn: AugmentedTransaction, nonce: number | null = null): Promise<TransactionResponse> {
const { contract, method, args, value, gasLimit } = txn;
return runTransaction(this.logger, contract, method, args, value, gasLimit, nonce);
}
Expand All @@ -70,17 +72,14 @@ export class TransactionClient {
// Transactions are submitted sequentially to avoid nonce collisions. More
// advanced nonce management may permit them to be submitted in parallel.
let mrkdwn = "";
let nonce: number | null = null;
for (let idx = 0; idx < txns.length; ++idx) {
const txn = txns[idx];

if (txn.chainId !== chainId) {
throw new Error(`chainId mismatch for method ${txn.method} (${txn.chainId} !== ${chainId})`);
}

if (nonce !== null) {
this.logger.debug({ at: "TransactionClient#submit", message: `Using nonce ${nonce}.` });
}
const nonce = this.nonces[chainId] ? this.nonces[chainId] + 1 : undefined;

// @dev It's assumed that nobody ever wants to discount the gasLimit.
const gasLimitMultiplier = txn.gasLimitMultiplier ?? DEFAULT_GASLIMIT_MULTIPLIER;
Expand All @@ -98,6 +97,7 @@ export class TransactionClient {
try {
response = await this._submit(txn, nonce);
} catch (error) {
delete this.nonces[chainId];
this.logger.info({
at: "TransactionClient#submit",
message: `Transaction ${idx + 1} submission on ${networkName} failed or timed out.`,
Expand All @@ -110,7 +110,7 @@ export class TransactionClient {
return txnResponses;
}

nonce = response.nonce + 1;
this.nonces[chainId] = response.nonce;
const blockExplorer = blockExplorerLink(response.hash, txn.chainId);
mrkdwn += ` ${idx + 1}. ${txn.message || "No message"} (${blockExplorer}): ${txn.mrkdwn || "No markdown"}\n`;
txnResponses.push(response);
Expand Down

0 comments on commit 1d964b1

Please sign in to comment.