Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,11 @@ describe('TransactionController', () => {
},
],
});

const testProvider = MAINNET_PROVIDER;
const testBlockTracker = buildMockBlockTracker('0x102833C');
controller.delayedInit(testProvider, testBlockTracker);

const registry = await controller.handleMethodData('0xf39b5b9b');

expect(registry.parsedRegistryMethod).toStrictEqual({
Expand Down Expand Up @@ -2109,6 +2114,10 @@ describe('TransactionController', () => {
],
});

const testProvider = MAINNET_PROVIDER;
const testBlockTracker = buildMockBlockTracker('0x102833C');
controller.delayedInit(testProvider, testBlockTracker);

await controller.handleMethodData('0xf39b5b9b');

const registryLookup = jest.spyOn<TransactionController, never>(
Expand Down
79 changes: 67 additions & 12 deletions packages/transaction-controller/src/TransactionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ import {
validateTransactionOrigin,
validateTxParams,
} from './utils/validation';
import { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';
import { ProxyWithAccessibleTarget } from '@metamask/network-controller/src/create-auto-managed-network-client';

export const HARDFORK = Hardfork.London;

Expand Down Expand Up @@ -329,15 +331,15 @@ export class TransactionController extends BaseControllerV1<

private readonly inProcessOfSigning: Set<string> = new Set();

private readonly nonceTracker: NonceTracker;
private nonceTracker!: NonceTracker;

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private readonly registry: any;

private readonly mutex = new Mutex();

private readonly gasFeeFlows: GasFeeFlow[];
private gasFeeFlows!: GasFeeFlow[];

private readonly getSavedGasFees: (chainId: Hex) => SavedGasFees | undefined;

Expand All @@ -364,13 +366,23 @@ export class TransactionController extends BaseControllerV1<

readonly #incomingTransactionOptions: IncomingTransactionOptions;

private readonly incomingTransactionHelper: IncomingTransactionHelper;
private incomingTransactionHelper!: IncomingTransactionHelper;

private readonly securityProviderRequest?: SecurityProviderRequest;

readonly #pendingTransactionOptions: PendingTransactionOptions;

private readonly pendingTransactionTracker: PendingTransactionTracker;
private pendingTransactionTracker!: PendingTransactionTracker;

readonly #onNetworkStateChange: (
listener: (state: NetworkState) => void,
) => void;

readonly #isMultichainEnabled: boolean;

readonly #incomingTransactions: IncomingTransactionOptions;

readonly #getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];

private readonly signAbortCallbacks: Map<string, () => void> = new Map();

Expand Down Expand Up @@ -427,7 +439,7 @@ export class TransactionController extends BaseControllerV1<
return { registryMethod, parsedRegistryMethod };
}

#multichainTrackingHelper: MultichainTrackingHelper;
#multichainTrackingHelper!: MultichainTrackingHelper;

/**
* EventEmitter instance used to listen to specific transactional events
Expand Down Expand Up @@ -492,8 +504,7 @@ export class TransactionController extends BaseControllerV1<
this.isSendFlowHistoryDisabled = disableSendFlowHistory ?? false;
this.isHistoryDisabled = disableHistory ?? false;
this.isSwapsDisabled = disableSwaps ?? false;
// @ts-expect-error the type in eth-method-registry is inappropriate and should be changed
this.registry = new MethodRegistry({ provider });

this.getSavedGasFees = getSavedGasFees ?? ((_chainId) => undefined);
this.getCurrentAccountEIP1559Compatibility =
getCurrentAccountEIP1559Compatibility ?? (() => Promise.resolve(true));
Expand Down Expand Up @@ -521,16 +532,36 @@ export class TransactionController extends BaseControllerV1<
this.publish =
hooks?.publish ?? (() => Promise.resolve({ transactionHash: undefined }));

this.#onNetworkStateChange = onNetworkStateChange;
this.#isMultichainEnabled = isMultichainEnabled;
this.#incomingTransactions = incomingTransactions;
this.#getNetworkClientRegistry = getNetworkClientRegistry;
}

/**
* Initializes `registry`, `nonceTracker`, `#multichainTrackingHelper`,
* `incomingTransactionHelper`, `pendingTransactionTracker`, and passes a
* callback to `onNetworkStateChange`.
*
* This relies on the provider and block tracker being defined which may not
* have been the case at the time the Transaction Controller was instantiated.
*/
initialization() {
const { provider, blockTracker } = this.getProviderAndBlockTracker()

// @ts-expect-error the type in eth-method-registry is inappropriate and should be changed
this.registry = new MethodRegistry({ provider });

this.nonceTracker = this.#createNonceTracker({
provider,
blockTracker,
});

this.#multichainTrackingHelper = new MultichainTrackingHelper({
isMultichainEnabled,
isMultichainEnabled: this.#isMultichainEnabled,
provider,
nonceTracker: this.nonceTracker,
incomingTransactionOptions: incomingTransactions,
incomingTransactionOptions: this.#incomingTransactions,
findNetworkClientIdByChainId: (chainId: Hex) => {
return this.messagingSystem.call(
`NetworkController:findNetworkClientIdByChainId`,
Expand All @@ -543,7 +574,7 @@ export class TransactionController extends BaseControllerV1<
networkClientId,
);
}) as NetworkController['getNetworkClientById'],
getNetworkClientRegistry,
getNetworkClientRegistry: this.#getNetworkClientRegistry,
removeIncomingTransactionHelperListeners:
this.#removeIncomingTransactionHelperListeners.bind(this),
removePendingTransactionTrackerListeners:
Expand All @@ -564,7 +595,7 @@ export class TransactionController extends BaseControllerV1<

const etherscanRemoteTransactionSource =
new EtherscanRemoteTransactionSource({
includeTokenTransfers: incomingTransactions.includeTokenTransfers,
includeTokenTransfers: this.#incomingTransactions.includeTokenTransfers,
});

this.incomingTransactionHelper = this.#createIncomingTransactionHelper({
Expand Down Expand Up @@ -604,7 +635,7 @@ export class TransactionController extends BaseControllerV1<

// TODO once v2 is merged make sure this only runs when
// selectedNetworkClientId changes
onNetworkStateChange(() => {
this.#onNetworkStateChange(() => {
log('Detected network change', this.getChainId());
this.pendingTransactionTracker.startIfPendingTransactions();
this.onBootCleanup();
Expand All @@ -613,6 +644,30 @@ export class TransactionController extends BaseControllerV1<
this.onBootCleanup();
}

/**
* Get the relevant provider and blockTracker instance.
*
* @returns Provider and BlockTracker instances.
*/
getProviderAndBlockTracker(): { provider: Provider, blockTracker: BlockTracker } {
const selectedNetworkClientId = this.getNetworkState().selectedNetworkClientId;
const networkClient = this.messagingSystem.call(
`NetworkController:getNetworkClientById`,
selectedNetworkClientId,
)
const provider = networkClient.provider;

if (provider === undefined) {
const MISSING_PROVIDER_ERROR = 'TransactionController failed to set the provider correctly. A provider must be set for this method to be available';

throw new Error(MISSING_PROVIDER_ERROR);
}

const blockTracker = networkClient.blockTracker;

return { provider, blockTracker };
}

/**
* Stops polling and removes listeners to prepare the controller for garbage collection.
*/
Expand Down