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
4 changes: 4 additions & 0 deletions packages/assets-controllers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add optional `rwaData` support when adding tokens in `TokensController` ([#7804](https://github.com/MetaMask/core/pull/7804)).

### Changed

- Bump `@metamask/profile-sync-controller` from `^27.0.0` to `^27.1.0` ([#7849](https://github.com/MetaMask/core/pull/7849))
Expand Down
164 changes: 164 additions & 0 deletions packages/assets-controllers/src/TokensController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { v1 as uuidV1 } from 'uuid';
import { ERC20Standard } from './Standards/ERC20Standard';
import { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standard';
import { TOKEN_END_POINT_API } from './token-service';
import type { TokenRwaData } from './token-service';
import type { Token } from './TokenRatesController';
import { TokensController } from './TokensController';
import type {
Expand Down Expand Up @@ -1881,6 +1882,115 @@ describe('TokensController', () => {
},
);
});

it('overwrites rwaData when re-adding tokens via addTokens', async () => {
await withController(async ({ controller }) => {
const existingRwaData: TokenRwaData = {
ticker: 'OLD',
};
const updatedRwaData: TokenRwaData = {
ticker: 'NEW',
};

await controller.addTokens(
[
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
rwaData: existingRwaData,
},
],
'mainnet',
);

await controller.addTokens(
[
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
rwaData: updatedRwaData,
},
],
'mainnet',
);

expect(
controller.state.allTokens[ChainId.mainnet][
defaultMockInternalAccount.address
],
).toStrictEqual([
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
rwaData: updatedRwaData,
},
]);
});
});

it('clears rwaData when re-adding tokens without rwaData', async () => {
await withController(async ({ controller }) => {
const existingRwaData: TokenRwaData = {
ticker: 'OLD',
};

await controller.addTokens(
[
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
rwaData: existingRwaData,
},
],
'mainnet',
);

await controller.addTokens(
[
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
},
],
'mainnet',
);

expect(
controller.state.allTokens[ChainId.mainnet][
defaultMockInternalAccount.address
],
).toStrictEqual([
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
},
]);
});
});
});

describe('watchAsset', () => {
Expand Down Expand Up @@ -3221,6 +3331,60 @@ describe('TokensController', () => {
});
});
});

it('overwrites rwaData for tokens with cached rwaData', async () => {
await withController(async ({ controller, messenger }) => {
ContractMock.mockReturnValue(
buildMockEthersERC721Contract({ supportsInterface: false }),
);

await controller.addTokens(
[
{
address: '0x01',
symbol: 'bar',
decimals: 2,
aggregators: [],
image: undefined,
name: undefined,
rwaData: { ticker: 'OLD' },
},
],
'mainnet',
);

messenger.publish(
'TokenListController:stateChange',
{
tokensChainsCache: {
[ChainId.mainnet]: {
timestamp: 1,
data: {
'0x01': {
address: '0x01',
symbol: 'bar',
decimals: 2,
occurrences: 1,
name: 'BarName',
iconUrl:
'https://static.cx.metamask.io/api/v1/tokenIcons/1/0x01.png',
aggregators: ['Aave'],
rwaData: { ticker: 'NEW' },
},
},
},
},
},
[],
);

expect(
controller.state.allTokens[ChainId.mainnet][
defaultMockInternalAccount.address
][0].rwaData,
).toStrictEqual({ ticker: 'NEW' });
});
});
});

describe('when selectedAccountId is not set or account not found', () => {
Expand Down
14 changes: 11 additions & 3 deletions packages/assets-controllers/src/TokensController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { ERC1155Standard } from './Standards/NftStandards/ERC1155/ERC1155Standar
import {
fetchTokenMetadata,
TOKEN_METADATA_NO_SUPPORT_ERROR,
TokenRwaData,
} from './token-service';
import type {
TokenListStateChange,
Expand Down Expand Up @@ -284,10 +285,13 @@ export class TokensController extends BaseController<
const tokens = updatedAllTokens[chainId as Hex][selectedAddress];

for (const [, token] of Object.entries(tokens)) {
const cachedToken = chainData[token.address];
const cachedToken = chainData[token.address.toLowerCase()];
if (cachedToken && cachedToken.name && !token.name) {
token.name = cachedToken.name; // Update the token name
}
if (cachedToken?.rwaData) {
token.rwaData = cachedToken.rwaData; // Update the token RWA data
}
}
}
}
Expand Down Expand Up @@ -416,6 +420,7 @@ export class TokensController extends BaseController<
* @param options.image - Image of the token.
* @param options.interactingAddress - The address of the account to add a token to.
* @param options.networkClientId - Network Client ID.
* @param options.rwaData - Optional RWA data for the token.
* @returns Current token list.
*/
async addToken({
Expand All @@ -426,6 +431,7 @@ export class TokensController extends BaseController<
image,
interactingAddress,
networkClientId,
rwaData,
}: {
address: string;
symbol: string;
Expand All @@ -434,6 +440,7 @@ export class TokensController extends BaseController<
image?: string;
interactingAddress?: string;
networkClientId: NetworkClientId;
rwaData?: TokenRwaData;
}): Promise<Token[]> {
const releaseLock = await this.#mutex.acquire();
const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;
Expand Down Expand Up @@ -473,7 +480,7 @@ export class TokensController extends BaseController<
isERC721,
aggregators: formatAggregatorNames(tokenMetadata?.aggregators ?? []),
name,
...(tokenMetadata?.rwaData && { rwaData: tokenMetadata.rwaData }),
...(rwaData !== undefined && { rwaData }),
};
const previousIndex = newTokens.findIndex(
(token) => token.address.toLowerCase() === address.toLowerCase(),
Expand Down Expand Up @@ -986,7 +993,7 @@ export class TokensController extends BaseController<

await this.#requestApproval(suggestedAssetMeta);

const { address, symbol, decimals, name, image } = asset;
const { address, symbol, decimals, name, image, rwaData } = asset;
await this.addToken({
address,
symbol,
Expand All @@ -995,6 +1002,7 @@ export class TokensController extends BaseController<
image,
interactingAddress: suggestedAssetMeta.interactingAddress,
networkClientId,
rwaData,
});
}

Expand Down
Loading