Skip to content
Merged
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
8 changes: 8 additions & 0 deletions packages/assets-controllers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `Robinhood` in `SupportedTokenDetectionNetworks`
- Add Robinhood BalanceFetcher address in `SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID`

### Removed

- **BREAKING:** Revert Snap account-asset enrichment added in 109.3.0 ([#9454](https://github.com/MetaMask/core/pull/9454))
- `MultichainBalancesController` no longer fetches or stores `accountAssetInfo` on balance rows; enrichment is handled client-side by the unified assets controller.
- Remove exported types `AccountAssetInfo` and `MultichainAccountBalance`.
- Remove optional `accountAssetInfo` from selector `Asset` items.
- `MultichainAssetsController:accountAssetListUpdated` no longer includes a `refreshed` asset list for already-tracked snap adds;

## [109.4.1]

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -796,50 +796,6 @@ describe('MultichainAssetsController', () => {
});
});

it('publishes refreshed assets when snap reports adds that are already tracked', async () => {
const mockSolanaAccountId1 = 'account1';
const existingToken =
'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1/token:Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr' as CaipAssetType;
const { controller, messenger } = setupController({
state: {
accountsAssets: {
[mockSolanaAccountId1]: mockHandleRequestOnAssetsLookupReturnValue,
},
assetsMetadata: mockGetMetadataReturnValue,
allIgnoredAssets: {},
} as MultichainAssetsControllerState,
});

const eventListener = jest.fn();
messenger.subscribe(
'MultichainAssetsController:accountAssetListUpdated',
eventListener,
);

messenger.publish('AccountsController:accountAssetListUpdated', {
assets: {
[mockSolanaAccountId1]: {
added: [existingToken],
removed: [],
},
},
});
await jestAdvanceTime({ duration: 1 });

expect(
controller.state.accountsAssets[mockSolanaAccountId1],
).toStrictEqual(mockHandleRequestOnAssetsLookupReturnValue);
expect(eventListener).toHaveBeenCalledWith({
assets: {
[mockSolanaAccountId1]: {
added: [],
removed: [],
refreshed: [existingToken],
},
},
});
});

it('updates the assets list for an account when a an asset is removed', async () => {
const mockSolanaAccountId1 = 'account1';
const mockSolanaAccountId2 = 'account2';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,9 @@ export type AssetMetadataResponse = {
};
};

/**
* Per-account asset list delta published by {@link MultichainAssetsController}.
*/
export type MultichainAssetsControllerAccountAssetListDelta = {
added: CaipAssetType[];
removed: CaipAssetType[];
/**
* Snap-reported adds that are already tracked in MAC state. Downstream
* controllers should refresh balances and enrichment for these assets.
*/
refreshed?: CaipAssetType[];
};

export type MultichainAssetsControllerAccountAssetListUpdatedPayload = {
assets: Record<string, MultichainAssetsControllerAccountAssetListDelta>;
};

export type MultichainAssetsControllerAccountAssetListUpdatedEvent = {
type: `${typeof controllerName}:accountAssetListUpdated`;
payload: [MultichainAssetsControllerAccountAssetListUpdatedPayload];
payload: AccountsControllerAccountAssetListUpdatedEvent['payload'];
};

/**
Expand Down Expand Up @@ -468,9 +451,7 @@ export class MultichainAssetsController extends StaticIntervalPollingController<
this.#assertControllerMutexIsLocked();

const assetsForMetadataRefresh = new Set<CaipAssetType>([]);
const accountsAndAssetsForState: AccountAssetListUpdatedEventPayload['assets'] =
{};
const accountsAndAssetsToPublish: MultichainAssetsControllerAccountAssetListUpdatedPayload['assets'] =
const accountsAndAssetsToUpdate: AccountAssetListUpdatedEventPayload['assets'] =
{};
for (const [accountId, { added, removed }] of Object.entries(
event.assets,
Expand All @@ -487,13 +468,6 @@ export class MultichainAssetsController extends StaticIntervalPollingController<
!this.#isAssetIgnored(asset, accountId),
);

const refreshedAssets = added.filter(
(asset): asset is CaipAssetType =>
existing.includes(asset) &&
isCaipAssetType(asset) &&
!this.#isAssetIgnored(asset, accountId),
);

// Filter out tokens that cannot be verified or are flagged malicious
const filteredToBeAddedAssets =
await this.#filterBlockaidSpamTokensOnAdd(preFilteredToBeAddedAssets);
Expand All @@ -507,26 +481,12 @@ export class MultichainAssetsController extends StaticIntervalPollingController<
filteredToBeAddedAssets.length > 0 ||
filteredToBeRemovedAssets.length > 0
) {
accountsAndAssetsForState[accountId] = {
accountsAndAssetsToUpdate[accountId] = {
added: filteredToBeAddedAssets,
removed: filteredToBeRemovedAssets,
};
}

if (
filteredToBeAddedAssets.length > 0 ||
filteredToBeRemovedAssets.length > 0 ||
refreshedAssets.length > 0
) {
accountsAndAssetsToPublish[accountId] = {
added: filteredToBeAddedAssets,
removed: filteredToBeRemovedAssets,
...(refreshedAssets.length > 0
? { refreshed: refreshedAssets }
: {}),
};
}

for (const asset of existing) {
assetsForMetadataRefresh.add(asset);
}
Expand All @@ -541,7 +501,7 @@ export class MultichainAssetsController extends StaticIntervalPollingController<

this.update((state) => {
for (const [accountId, { added, removed }] of Object.entries(
accountsAndAssetsForState,
accountsAndAssetsToUpdate,
)) {
const assets = new Set([
...(state.accountsAssets[accountId] || []),
Expand All @@ -558,11 +518,9 @@ export class MultichainAssetsController extends StaticIntervalPollingController<
// Trigger fetching metadata for new assets
await this.#refreshAssetsMetadata(Array.from(assetsForMetadataRefresh));

if (Object.keys(accountsAndAssetsToPublish).length > 0) {
this.messenger.publish(`${controllerName}:accountAssetListUpdated`, {
assets: accountsAndAssetsToPublish,
});
}
this.messenger.publish(`${controllerName}:accountAssetListUpdated`, {
assets: accountsAndAssetsToUpdate,
});
}

/**
Expand Down
Loading