Skip to content
Draft
4 changes: 4 additions & 0 deletions packages/assets-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump `@metamask/network-enablement-controller` from `^5.2.0` to `^5.3.0` ([#9003](https://github.com/MetaMask/core/pull/9003))

### Removed

- **BREAKING:** Remove `TransactionController:incomingTransactionsReceived` from `AssetsController` allowed events and `RpcDataSourceAllowedEvents`; remove associated balance refresh on incoming transactions ([#9012](https://github.com/MetaMask/core/pull/9012))

## [8.3.2]

### Changed
Expand Down
2 changes: 0 additions & 2 deletions packages/assets-controller/src/AssetsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import type {
SnapControllerSnapInstalledEvent,
} from '@metamask/snaps-controllers';
import type {
TransactionControllerIncomingTransactionsReceivedEvent,
TransactionControllerTransactionConfirmedEvent,
TransactionControllerUnapprovedTransactionAddedEvent,
TransactionMeta,
Expand Down Expand Up @@ -333,7 +332,6 @@ type AllowedEvents =
| NetworkControllerNetworkAddedEvent
| NetworkControllerNetworkRemovedEvent
| TransactionControllerTransactionConfirmedEvent
| TransactionControllerIncomingTransactionsReceivedEvent
// StakedBalanceDataSource
| NetworkEnablementControllerEvents
// SnapDataSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export function createMockAssetControllerMessenger(): {
// RpcDataSource, StakedBalanceDataSource
'NetworkController:stateChange',
'TransactionController:transactionConfirmed',
'TransactionController:incomingTransactionsReceived',
// StakedBalanceDataSource
'NetworkEnablementController:stateChange',
// SnapDataSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1904,42 +1904,6 @@ describe('RpcDataSource', () => {
expect(true).toBe(true);
});
});

it('refreshes balance when incoming transactions received', async () => {
await withController(async ({ controller, rootMessenger }) => {
await controller.subscribe({
request: createDataRequest(),
subscriptionId: 'test-sub',
isUpdate: false,
onAssetsUpdate: jest.fn(),
});

rootMessenger.publish(
'TransactionController:incomingTransactionsReceived',
[{ chainId: MOCK_CHAIN_ID_HEX }] as unknown as TransactionMeta[],
);
await new Promise(process.nextTick);
expect(controller).toBeDefined();
});
});

it('refreshes all active chains when incoming transactions empty', async () => {
await withController(async ({ controller, rootMessenger }) => {
await controller.subscribe({
request: createDataRequest(),
subscriptionId: 'test-sub',
isUpdate: false,
onAssetsUpdate: jest.fn(),
});

rootMessenger.publish(
'TransactionController:incomingTransactionsReceived',
[] as TransactionMeta[],
);
await new Promise(process.nextTick);
expect(controller).toBeDefined();
});
});
});

describe('network state change', () => {
Expand Down
32 changes: 1 addition & 31 deletions packages/assets-controller/src/data-sources/RpcDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
NetworkStatus,
} from '@metamask/network-controller';
import type {
TransactionControllerIncomingTransactionsReceivedEvent,
TransactionControllerTransactionConfirmedEvent,
TransactionMeta,
} from '@metamask/transaction-controller';
Expand Down Expand Up @@ -78,8 +77,7 @@ export type RpcDataSourceAllowedActions =
// Allowed events that RpcDataSource can subscribe to
export type RpcDataSourceAllowedEvents =
| NetworkControllerStateChangeEvent
| TransactionControllerTransactionConfirmedEvent
| TransactionControllerIncomingTransactionsReceivedEvent;
| TransactionControllerTransactionConfirmedEvent;

/** Network status for each chain */
export type ChainStatus = {
Expand Down Expand Up @@ -234,8 +232,6 @@ export class RpcDataSource extends AbstractDataSource<

#unsubscribeTransactionConfirmed: (() => void) | undefined = undefined;

#unsubscribeIncomingTransactions: (() => void) | undefined = undefined;

// Rpc-datasource components
readonly #multicallClient: MulticallClient;

Expand Down Expand Up @@ -637,13 +633,6 @@ export class RpcDataSource extends AbstractDataSource<
);
this.#unsubscribeTransactionConfirmed =
typeof unsubConfirmed === 'function' ? unsubConfirmed : undefined;

const unsubIncoming = this.#messenger.subscribe(
'TransactionController:incomingTransactionsReceived',
this.#onIncomingTransactions.bind(this),
);
this.#unsubscribeIncomingTransactions =
typeof unsubIncoming === 'function' ? unsubIncoming : undefined;
}

#onTransactionConfirmed(payload: TransactionMeta): void {
Expand All @@ -657,24 +646,6 @@ export class RpcDataSource extends AbstractDataSource<
});
}

#onIncomingTransactions(payload: TransactionMeta[]): void {
const chainIds = Array.from(
new Set(
(payload ?? [])
.map((item) => item?.chainId)
.filter((id): id is Hex => Boolean(id)),
),
);
const caipChainIds = chainIds.map(
(hexChainId) => `eip155:${parseInt(hexChainId, 16)}` as ChainId,
);
const toRefresh =
caipChainIds.length > 0 ? caipChainIds : [...this.#activeChains];
this.#refreshBalanceForChains(toRefresh).catch((error) => {
log('Failed to refresh balance after incoming transactions', { error });
});
}

/**
* Fetch balances for the given chains across all active subscriptions and
* push updates to the controller.
Expand Down Expand Up @@ -1502,7 +1473,6 @@ export class RpcDataSource extends AbstractDataSource<
log('Destroying RpcDataSource');

this.#unsubscribeTransactionConfirmed?.();
this.#unsubscribeIncomingTransactions?.();

// Stop all polling
this.#balanceFetcher.stopAllPolling();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,6 @@ describe('StakedBalanceDataSource', () => {
'TransactionController:transactionConfirmed',
expect.any(Function),
);
expect(mockMessengerSubscribe).toHaveBeenCalledWith(
'TransactionController:incomingTransactionsReceived',
expect.any(Function),
);
expect(mockMessengerSubscribe).toHaveBeenCalledWith(
'NetworkController:stateChange',
expect.any(Function),
Expand Down Expand Up @@ -492,64 +488,6 @@ describe('StakedBalanceDataSource', () => {
expect(onAssetsUpdate).toHaveBeenCalledTimes(1);
});
});

it('refreshes when incomingTransactionsReceived includes tx involving staking contract', async () => {
await withController(async ({ controller, rootMessenger }) => {
// Arrange
const onAssetsUpdate = await arrange({ controller });

// Act
rootMessenger.publish(
'TransactionController:incomingTransactionsReceived',
[
{
id: '1',
networkClientId: 'mainnet',
status: TransactionStatus.confirmed,
time: Date.now(),
chainId: MAINNET_CHAIN_ID_HEX,
txParams: {
to: STAKING_CONTRACT_MAINNET,
from: '0x0000000000000000000000000000000000000000',
},
},
],
);

// Assert
await new Promise((resolve) => setTimeout(resolve, 300));
expect(onAssetsUpdate).toHaveBeenCalledTimes(1);
});
});

it('does not refresh when incomingTransactionsReceived has no tx involving staking contract', async () => {
await withController(async ({ controller, rootMessenger }) => {
// Arrange
const onAssetsUpdate = await arrange({ controller });

// Act
rootMessenger.publish(
'TransactionController:incomingTransactionsReceived',
[
{
id: '1',
networkClientId: 'mainnet',
status: TransactionStatus.confirmed,
time: Date.now(),
chainId: MAINNET_CHAIN_ID_HEX,
txParams: {
to: '0x1234567890123456789012345678901234567890',
from: '0x0000000000000000000000000000000000000000',
},
},
],
);

// Assert
await new Promise((resolve) => setTimeout(resolve, 100));
expect(onAssetsUpdate).not.toHaveBeenCalled();
});
});
});

describe('refreshStakedBalance', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ export class StakedBalanceDataSource extends AbstractDataSource<
this.#onTransactionConfirmed.bind(this),
);

this.#messenger.subscribe(
'TransactionController:incomingTransactionsReceived',
this.#onIncomingTransactions.bind(this),
);

this.#messenger.subscribe(
'NetworkController:stateChange',
this.#onNetworkStateChange.bind(this),
Expand Down Expand Up @@ -312,43 +307,6 @@ export class StakedBalanceDataSource extends AbstractDataSource<
}
}

/**
* When incoming transactions are received, refresh staked balance only for
* chains where at least one transaction is from or to the staking contract.
*
* @param payload - From TransactionController:incomingTransactionsReceived (array of { chainId?, txParams? }).
*/
#onIncomingTransactions(
payload: { chainId?: string; txParams?: { from?: string; to?: string } }[],
): void {
if (!this.#enabled) {
return;
}
const chainIdsToRefresh = new Set<string>();
for (const item of payload ?? []) {
if (!item?.chainId) {
continue;
}
if (this.#isTransactionInvolvingStakingContract(item)) {
chainIdsToRefresh.add(item.chainId);
}
}
const caipChainIds = [...chainIdsToRefresh].map(
(hexChainId) => `eip155:${parseInt(hexChainId, 16)}` as ChainId,
);
if (caipChainIds.length === 0) {
return;
}
const toRefresh = this.#getToRefreshForChains(caipChainIds);
if (toRefresh.length > 0) {
this.#refreshStakedBalanceAfterTransaction(toRefresh).catch((error) => {
log('Failed to refresh staked balance after incoming transactions', {
error,
});
});
}
}

/**
* Build toRefresh list for subscribed (account, chainId) pairs for the given chains.
*
Expand Down
4 changes: 4 additions & 0 deletions packages/assets-controllers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump `@metamask/network-enablement-controller` from `^5.2.0` to `^5.3.0` ([#9003](https://github.com/MetaMask/core/pull/9003))

### Removed

- **BREAKING:** Remove `TransactionController:incomingTransactionsReceived` from `TokenBalancesControllerMessenger` allowed events ([#9012](https://github.com/MetaMask/core/pull/9012))

## [108.5.0]

### Added
Expand Down
17 changes: 0 additions & 17 deletions packages/assets-controllers/src/TokenBalancesController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ const setupController = ({
'AccountActivityService:statusChanged',
'AccountsController:selectedEvmAccountChange',
'TransactionController:transactionConfirmed',
'TransactionController:incomingTransactionsReceived',
],
});

Expand Down Expand Up @@ -6129,22 +6128,6 @@ describe('TokenBalancesController', () => {
});
});

it('should handle TransactionController:incomingTransactionsReceived event', async () => {
const { controller, messenger } = setupController();
const updateBalancesSpy = jest.spyOn(controller, 'updateBalances');

messenger.publish('TransactionController:incomingTransactionsReceived', [
{ chainId: '0x1' },
{ chainId: '0x89' },
] as unknown as TransactionMeta[]);

await jest.advanceTimersByTimeAsync(0);

expect(updateBalancesSpy).toHaveBeenCalledWith({
chainIds: ['0x1', '0x89'],
});
});

it('should handle errors from #onTokensChanged gracefully', async () => {
const warnSpy = jest.spyOn(console, 'warn').mockImplementation();
const { controller, messenger } = setupController();
Expand Down
19 changes: 2 additions & 17 deletions packages/assets-controllers/src/TokenBalancesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ import type {
PreferencesControllerStateChangeEvent,
} from '@metamask/preferences-controller';
import type { AuthenticationController } from '@metamask/profile-sync-controller';
import type {
TransactionControllerIncomingTransactionsReceivedEvent,
TransactionControllerTransactionConfirmedEvent,
} from '@metamask/transaction-controller';
import type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';
import type { Hex } from '@metamask/utils';
import {
isCaipAssetType,
Expand Down Expand Up @@ -195,8 +192,7 @@ export type AllowedEvents =
| AccountActivityServiceBalanceUpdatedEvent
| AccountActivityServiceStatusChangedEvent
| AccountsControllerSelectedEvmAccountChangeEvent
| TransactionControllerTransactionConfirmedEvent
| TransactionControllerIncomingTransactionsReceivedEvent;
| TransactionControllerTransactionConfirmedEvent;

export type TokenBalancesControllerMessenger = Messenger<
typeof CONTROLLER,
Expand Down Expand Up @@ -495,17 +491,6 @@ export class TokenBalancesController extends StaticIntervalPollingController<{
});
},
);

this.messenger.subscribe(
'TransactionController:incomingTransactionsReceived',
(incomingTransactions) => {
this.updateBalances({
chainIds: incomingTransactions.map((tx) => tx.chainId),
}).catch(() => {
// Silently handle balance update errors
});
},
);
}

/**
Expand Down
13 changes: 13 additions & 0 deletions packages/transaction-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- `TransactionController` can now be constructed before `NetworkController` is registered on the messenger ([#9012](https://github.com/MetaMask/core/pull/9012))
- Network client tracking initializes automatically once `NetworkController` becomes available; no explicit call required from the consumer.
- Transaction history trimming is skipped when the history limit feature flag is unavailable.
- **BREAKING:** Remove deprecated `TransactionController` constructor options and unused hooks, and replace them with direct messenger calls ([#8983](https://github.com/MetaMask/core/pull/8983))
- Removed options: `disableHistory`, `disableSendFlowHistory`, `getCurrentAccountEIP1559Compatibility`, `getCurrentNetworkEIP1559Compatibility`, `getExternalPendingTransactions`, `getGasFeeEstimates`, `getNetworkClientRegistry`, `getNetworkState`, `pendingTransactions`, `securityProviderRequest`, `sign`, `transactionHistoryLimit`
- Removed hooks: `afterSign`, `afterSimulate`, `getAdditionalSignArguments`
Expand All @@ -17,6 +20,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added required `AllowedActions`: `GasFeeController:fetchGasFeeEstimates`, `KeyringController:signTransaction`, `NetworkController:getEIP1559Compatibility`, `NetworkController:getNetworkClientRegistry`, `NetworkController:getState`
- Removed resubmit logic from `PendingTransactionTracker`

### Removed

- **BREAKING:** Remove incoming transaction support from `TransactionController` ([#9012](https://github.com/MetaMask/core/pull/9012))
- Removed constructor option `incomingTransactions`.
- Removed public methods `startIncomingTransactionPolling`, `stopIncomingTransactionPolling`, `updateIncomingTransactions`.
- Removed event `TransactionController:incomingTransactionsReceived`.
- Removed exported constant `INCOMING_TRANSACTIONS_SUPPORTED_CHAIN_IDS`.
- Removed exported types `TransactionControllerIncomingTransactionsReceivedEvent`, `TransactionControllerStartIncomingTransactionPollingAction`, `TransactionControllerStopIncomingTransactionPollingAction`, `TransactionControllerUpdateIncomingTransactionsAction`, `TransactionResponse`, `GetAccountTransactionsRequest`, `GetAccountTransactionsResponse`.
- Fields on `TransactionMeta` related to incoming transactions are preserved.

## [66.0.1]

### Changed
Expand Down
Loading
Loading