Skip to content

Commit 0203cbb

Browse files
committed
Update implementation
1 parent 34afeb0 commit 0203cbb

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

packages/transaction-controller/src/helpers/PendingTransactionTracker.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import { createModuleLogger, projectLogger } from '../logger';
1515
import type { TransactionControllerMessenger } from '../TransactionController';
1616
import type { TransactionMeta, TransactionReceipt } from '../types';
1717
import { TransactionStatus, TransactionType } from '../types';
18-
import { getTimeoutAttempts } from '../utils/feature-flags';
18+
import {
19+
getAcceleratedPollingParams,
20+
getTimeoutAttempts,
21+
} from '../utils/feature-flags';
1922

2023
/**
2124
* We wait this many blocks before emitting a 'transaction-dropped' event
@@ -88,6 +91,8 @@ export class PendingTransactionTracker {
8891

8992
readonly #isResubmitEnabled: () => boolean;
9093

94+
readonly #lastSeenTimestampByHash: Map<string, number>;
95+
9196
// TODO: Replace `any` with type
9297
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9398
readonly #listener: any;
@@ -103,8 +108,6 @@ export class PendingTransactionTracker {
103108

104109
#running: boolean;
105110

106-
readonly #timeoutCountByHash: Map<string, number>;
107-
108111
readonly #transactionPoller: TransactionPoller;
109112

110113
#transactionToForcePoll: TransactionMeta | undefined;
@@ -150,11 +153,11 @@ export class PendingTransactionTracker {
150153
this.#getNetworkClientId = getNetworkClientId;
151154
this.#getTransactions = getTransactions;
152155
this.#isResubmitEnabled = isResubmitEnabled ?? ((): boolean => true);
156+
this.#lastSeenTimestampByHash = new Map();
153157
this.#listener = this.#onLatestBlock.bind(this);
154158
this.#messenger = messenger;
155159
this.#publishTransaction = publishTransaction;
156160
this.#running = false;
157-
this.#timeoutCountByHash = new Map();
158161
this.#transactionToForcePoll = undefined;
159162

160163
this.#transactionPoller = new TransactionPoller({
@@ -529,6 +532,7 @@ export class PendingTransactionTracker {
529532
chainId,
530533
hash,
531534
id: transactionId,
535+
submittedTime,
532536
txParams: { nonce },
533537
} = txMeta;
534538

@@ -564,36 +568,54 @@ export class PendingTransactionTracker {
564568
// Check if transaction exists on the network
565569
const transaction = await this.#getTransactionByHash(hash);
566570

567-
// If transaction exists, reset the counter
571+
// If transaction exists, record the timestamp
568572
if (transaction !== null) {
573+
const currentTimestamp = Date.now();
574+
575+
this.#log(
576+
'Transaction found on network, recording timestamp',
577+
transactionId,
578+
);
579+
580+
this.#lastSeenTimestampByHash.set(hash, currentTimestamp);
581+
return false;
582+
}
583+
584+
const lastSeenTimestamp =
585+
this.#lastSeenTimestampByHash.get(hash) ?? submittedTime;
586+
587+
if (!lastSeenTimestamp) {
569588
this.#log(
570-
'Transaction found on network, resetting timeout counter',
589+
'Transaction not yet seen on network and has no submitted time, skipping timeout check',
571590
transactionId,
572591
);
573592

574-
this.#timeoutCountByHash.delete(hash);
575593
return false;
576594
}
577595

578-
// Transaction doesn't exist, increment counter
579-
let attempts = this.#timeoutCountByHash.get(hash);
596+
const { blockTime } = getAcceleratedPollingParams(
597+
chainId,
598+
this.#messenger,
599+
);
580600

581-
attempts ??= 0;
582-
attempts += 1;
583-
this.#timeoutCountByHash.set(hash, attempts);
601+
const currentTimestamp = Date.now();
602+
const durationSinceLastSeen = currentTimestamp - lastSeenTimestamp;
603+
const timeoutDuration = blockTime * threshold;
584604

585-
this.#log('Incrementing timeout counter', {
605+
this.#log('Checking timeout duration', {
586606
transactionId,
587-
attempts,
607+
durationSinceLastSeen,
608+
timeoutDuration,
588609
threshold,
610+
blockTime,
589611
});
590612

591-
if (attempts < threshold) {
613+
if (durationSinceLastSeen < timeoutDuration) {
592614
return false;
593615
}
594616

595-
this.#log('Hit timeout threshold', transactionId);
596-
this.#timeoutCountByHash.delete(hash);
617+
this.#log('Hit timeout duration threshold', transactionId);
618+
this.#lastSeenTimestampByHash.delete(hash);
597619

598620
this.#failTransaction(
599621
txMeta,

packages/transaction-controller/src/utils/feature-flags.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { TransactionControllerMessenger } from '../TransactionController';
99
const DEFAULT_BATCH_SIZE_LIMIT = 10;
1010
const DEFAULT_ACCELERATED_POLLING_COUNT_MAX = 10;
1111
const DEFAULT_ACCELERATED_POLLING_INTERVAL_MS = 3 * 1000;
12+
const DEFAULT_BLOCK_TIME = 12 * 1000;
1213
const DEFAULT_GAS_ESTIMATE_FALLBACK_BLOCK_PERCENT = 35;
1314
const DEFAULT_GAS_ESTIMATE_BUFFER = 1;
1415
const DEFAULT_INCOMING_TRANSACTIONS_POLLING_INTERVAL_MS = 1000 * 60 * 4; // 4 Minutes
@@ -116,6 +117,11 @@ export type TransactionControllerFeatureFlags = {
116117
/** Accelerated polling parameters on a per-chain basis. */
117118
perChainConfig?: {
118119
[chainId: Hex]: {
120+
/**
121+
* Block time in milliseconds.
122+
*/
123+
blockTime?: number;
124+
119125
/**
120126
* Maximum number of polling requests that can be made in a row, before
121127
* the normal polling resumes.
@@ -264,7 +270,7 @@ export function getBatchSizeLimit(
264270
export function getAcceleratedPollingParams(
265271
chainId: Hex,
266272
messenger: TransactionControllerMessenger,
267-
): { countMax: number; intervalMs: number } {
273+
): { blockTime: number; countMax: number; intervalMs: number } {
268274
const featureFlags = getFeatureFlags(messenger);
269275

270276
const acceleratedPollingParams =
@@ -280,7 +286,11 @@ export function getAcceleratedPollingParams(
280286
acceleratedPollingParams?.defaultIntervalMs ??
281287
DEFAULT_ACCELERATED_POLLING_INTERVAL_MS;
282288

283-
return { countMax, intervalMs };
289+
const blockTime =
290+
acceleratedPollingParams?.perChainConfig?.[chainId]?.blockTime ??
291+
DEFAULT_BLOCK_TIME;
292+
293+
return { blockTime, countMax, intervalMs };
284294
}
285295

286296
/**

0 commit comments

Comments
 (0)