Skip to content

Commit ea69888

Browse files
committed
Change resimulation logic to simulate every 3 seconds
1 parent f3d5e31 commit ea69888

File tree

3 files changed

+96
-188
lines changed

3 files changed

+96
-188
lines changed

packages/transaction-controller/src/TransactionController.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -931,13 +931,6 @@ export class TransactionController extends BaseController<
931931
);
932932

933933
new ResimulateHelper({
934-
getBlockTracker: (networkClientId: NetworkClientId) => {
935-
const { blockTracker } = this.messagingSystem.call(
936-
`NetworkController:getNetworkClientById`,
937-
networkClientId,
938-
);
939-
return blockTracker;
940-
},
941934
updateSimulationData: this.#updateSimulationData.bind(this),
942935
onStateChange: (listener) => {
943936
this.messagingSystem.subscribe(

packages/transaction-controller/src/helpers/ResimulateHelper.test.ts

Lines changed: 64 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
RESIMULATE_PARAMS,
1515
shouldResimulate,
1616
VALUE_COMPARISON_PERCENT_THRESHOLD,
17+
RESIMULATE_INTERVAL_MS,
1718
} from './ResimulateHelper';
1819
import { CHAIN_IDS } from '../constants';
1920
import type {
@@ -87,10 +88,6 @@ const mockTransactionMeta = {
8788
jest.mock('../utils/utils');
8889

8990
describe('ResimulateHelper', () => {
90-
let blockTrackerMock: jest.Mocked<BlockTracker>;
91-
let getBlockTrackerMock: jest.Mock<
92-
(networkClientId: NetworkClientId) => BlockTracker
93-
>;
9491
let getTransactionsMock: jest.Mock<() => TransactionMeta[]>;
9592
let updateSimulationDataMock: jest.Mock<
9693
(transactionMeta: TransactionMeta) => void
@@ -99,166 +96,104 @@ describe('ResimulateHelper', () => {
9996

10097
let resimulateHelper: ResimulateHelper;
10198

102-
beforeEach(() => {
103-
blockTrackerMock = {
104-
on: jest.fn(),
105-
removeListener: jest.fn(),
106-
} as unknown as jest.Mocked<BlockTracker>;
99+
function triggerStateChange() {
100+
onStateChangeMock.mock.calls[0][0]();
101+
}
107102

108-
getBlockTrackerMock = jest.fn().mockReturnValue(blockTrackerMock);
103+
function mockGetTransactionsOnce(transactions: TransactionMeta[]) {
104+
getTransactionsMock.mockReturnValueOnce(
105+
transactions as unknown as ResimulateHelperOptions['getTransactions'],
106+
);
107+
}
108+
109+
beforeEach(() => {
110+
jest.useFakeTimers();
109111
getTransactionsMock = jest.fn();
110112
onStateChangeMock = jest.fn();
111113
updateSimulationDataMock = jest.fn();
112114

113115
resimulateHelper = new ResimulateHelper({
114-
getBlockTracker: getBlockTrackerMock,
115116
getTransactions: getTransactionsMock,
116117
onStateChange: onStateChangeMock,
117118
updateSimulationData: updateSimulationDataMock,
118119
} as unknown as ResimulateHelperOptions);
119120
});
120121

121-
it('assigns a block tracker listener to resimulate for a focused transaction', () => {
122-
resimulateHelper.start(mockTransactionMeta);
122+
it(`resimulates unapproved focused transaction every ${RESIMULATE_INTERVAL_MS} milliseconds`, () => {
123+
mockGetTransactionsOnce([mockTransactionMeta]);
124+
triggerStateChange();
123125

124-
expect(getBlockTrackerMock).toHaveBeenCalledWith(
125-
mockTransactionMeta.networkClientId,
126-
);
127-
expect(blockTrackerMock.on).toHaveBeenCalledWith(
128-
'latest',
129-
expect.any(Function),
130-
);
126+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS);
127+
128+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS);
129+
130+
expect(updateSimulationDataMock).toHaveBeenCalledWith(mockTransactionMeta);
131+
expect(updateSimulationDataMock).toHaveBeenCalledTimes(2);
131132
});
132133

133-
it('removes a block tracker listener for a transaction that is no longer focused', () => {
134-
resimulateHelper.start(mockTransactionMeta);
134+
it(`does not resimulate twice the same transaction even if state change is triggered twice`, () => {
135+
mockGetTransactionsOnce([mockTransactionMeta]);
136+
triggerStateChange();
135137

136-
const unfocusedTransactionMeta = {
137-
...mockTransactionMeta,
138-
isFocused: false,
139-
} as TransactionMeta;
138+
// Halfway through the interval
139+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS / 2);
140140

141-
resimulateHelper.stop(unfocusedTransactionMeta);
141+
// Assume state change is triggered again
142+
mockGetTransactionsOnce([mockTransactionMeta]);
143+
triggerStateChange();
142144

143-
expect(blockTrackerMock.removeListener).toHaveBeenCalledWith(
144-
'latest',
145-
expect.any(Function),
146-
);
145+
// Halfway through the interval
146+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS / 2);
147+
148+
expect(updateSimulationDataMock).toHaveBeenCalledTimes(1);
147149
});
148150

149-
it('does not add a block tracker listener for a transaction that is not focused', () => {
150-
resimulateHelper.start({
151-
...mockTransactionMeta,
152-
isFocused: false,
153-
});
151+
it('does not resimulate a transaction that is no longer focused', () => {
152+
mockGetTransactionsOnce([mockTransactionMeta]);
153+
triggerStateChange();
154154

155-
expect(blockTrackerMock.on).not.toHaveBeenCalled();
156-
});
155+
// Halfway through the interval
156+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS / 2);
157157

158-
it('does not add a block tracker listener for a transaction that is already resimulating', () => {
159-
resimulateHelper.start(mockTransactionMeta);
160-
resimulateHelper.start(mockTransactionMeta);
158+
const unfocusedTransactionMeta = {
159+
...mockTransactionMeta,
160+
isFocused: false,
161+
} as TransactionMeta;
161162

162-
expect(blockTrackerMock.on).toHaveBeenCalledTimes(1);
163-
});
163+
mockGetTransactionsOnce([unfocusedTransactionMeta]);
164+
triggerStateChange();
164165

165-
it('does not remove a block tracker listener for a transaction that is not resimulating', () => {
166-
resimulateHelper.stop(mockTransactionMeta);
166+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS / 2);
167167

168-
expect(blockTrackerMock.on).toHaveBeenCalledTimes(0);
168+
expect(updateSimulationDataMock).toHaveBeenCalledTimes(0);
169169
});
170170

171-
describe('on Transaction Controller state change', () => {
172-
it('start and stop resimulations depending on the isFocused state', async () => {
173-
const firstTransactionMeta = {
174-
...mockTransactionMeta,
175-
networkClientId: 'network1' as NetworkClientId,
176-
id: '1',
177-
} as TransactionMeta;
178-
179-
const secondTransactionMeta = {
180-
...mockTransactionMeta,
181-
networkClientId: 'network2' as NetworkClientId,
182-
id: '2',
183-
} as TransactionMeta;
184-
185-
// Assume both transactions are started to put them in the activeResimulations state
186-
resimulateHelper.start(firstTransactionMeta);
187-
resimulateHelper.start(secondTransactionMeta);
188-
189-
expect(getBlockTrackerMock).toHaveBeenCalledWith(
190-
firstTransactionMeta.networkClientId,
191-
);
192-
expect(getBlockTrackerMock).toHaveBeenCalledWith(
193-
secondTransactionMeta.networkClientId,
194-
);
171+
it('does not resimulate a transaction that is not focused', () => {
172+
const unfocusedTransactionMeta = {
173+
...mockTransactionMeta,
174+
isFocused: false,
175+
} as TransactionMeta;
195176

196-
// Assume both transactions are still in the transaction list but second is not focused anymore
197-
getTransactionsMock.mockReturnValueOnce([
198-
firstTransactionMeta,
199-
{
200-
...secondTransactionMeta,
201-
isFocused: false,
202-
},
203-
] as unknown as ResimulateHelperOptions['getTransactions']);
177+
mockGetTransactionsOnce([unfocusedTransactionMeta]);
178+
triggerStateChange();
204179

205-
// Manually trigger the state change listener
206-
onStateChangeMock.mock.calls[0][0]();
180+
jest.advanceTimersByTime(2 * RESIMULATE_INTERVAL_MS);
207181

208-
expect(blockTrackerMock.removeListener).toHaveBeenCalledWith(
209-
'latest',
210-
expect.any(Function),
211-
);
182+
expect(updateSimulationDataMock).toHaveBeenCalledTimes(0);
183+
});
212184

213-
// Manually trigger the block tracker listener
214-
const firstTransactionListener = blockTrackerMock.on.mock.calls[0][1];
215-
await firstTransactionListener();
185+
it('stops resimulating a transaction that is no longer in the transaction list', () => {
186+
mockGetTransactionsOnce([mockTransactionMeta]);
187+
triggerStateChange();
216188

217-
// Assert that first transaction is still in the activeResimulations state
218-
expect(updateSimulationDataMock).toHaveBeenCalledWith(
219-
firstTransactionMeta,
220-
);
221-
});
189+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS);
222190

223-
it('forces to stop resimulation for a transaction that is no longer in transaction list', async () => {
224-
const firstTransactionMeta = {
225-
...mockTransactionMeta,
226-
networkClientId: 'network1' as NetworkClientId,
227-
id: '1',
228-
} as TransactionMeta;
229-
230-
const secondTransactionMeta = {
231-
...mockTransactionMeta,
232-
networkClientId: 'network2' as NetworkClientId,
233-
id: '2',
234-
} as TransactionMeta;
235-
236-
// Assume both transactions are started to put them in the activeResimulations state
237-
resimulateHelper.start(firstTransactionMeta);
238-
resimulateHelper.start(secondTransactionMeta);
239-
240-
// On next state change, first transaction is still in the transaction list but second is not
241-
getTransactionsMock.mockReturnValueOnce([
242-
firstTransactionMeta,
243-
] as unknown as ResimulateHelperOptions['getTransactions']);
244-
245-
// Manually trigger the state change listener
246-
onStateChangeMock.mock.calls[0][0]();
247-
248-
expect(blockTrackerMock.removeListener).toHaveBeenCalledWith(
249-
'latest',
250-
expect.any(Function),
251-
);
191+
mockGetTransactionsOnce([]);
192+
triggerStateChange();
252193

253-
// Manually trigger the block tracker listener
254-
const firstTransactionListener = blockTrackerMock.on.mock.calls[0][1];
255-
await firstTransactionListener();
194+
jest.advanceTimersByTime(RESIMULATE_INTERVAL_MS);
256195

257-
// Assert that first transaction is still in the activeResimulations state
258-
expect(updateSimulationDataMock).toHaveBeenCalledWith(
259-
firstTransactionMeta,
260-
);
261-
});
196+
expect(updateSimulationDataMock).toHaveBeenCalledTimes(1);
262197
});
263198
});
264199

0 commit comments

Comments
 (0)