diff --git a/package.json b/package.json index 0779428d8c..0fd6f17bed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/core-monorepo", - "version": "245.0.0", + "version": "247.0.0", "private": true, "description": "Monorepo for packages shared between MetaMask clients", "repository": { diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 923f49ed9b..36747a51c2 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [43.1.1] + +### Changed + +- Fix a bug in `TokensController.addTokens` where tokens could be added from the wrong chain. ([#4924](https://github.com/MetaMask/core/pull/4924)) + +## [43.1.0] + +### Added + +- Add Solana to the polled exchange rates ([#4914](https://github.com/MetaMask/core/pull/4914)) + ## [43.0.0] ### Added @@ -1204,7 +1216,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845)) -[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@43.0.0...HEAD +[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@43.1.1...HEAD +[43.1.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@43.1.0...@metamask/assets-controllers@43.1.1 +[43.1.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@43.0.0...@metamask/assets-controllers@43.1.0 [43.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@42.0.0...@metamask/assets-controllers@43.0.0 [42.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@41.0.0...@metamask/assets-controllers@42.0.0 [41.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@40.0.0...@metamask/assets-controllers@41.0.0 diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index 61b73e747d..d02bc4883d 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/assets-controllers", - "version": "43.0.0", + "version": "43.1.1", "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)", "keywords": [ "MetaMask", diff --git a/packages/assets-controllers/src/RatesController/RatesController.test.ts b/packages/assets-controllers/src/RatesController/RatesController.test.ts index bf9d0fc193..f2fca24f76 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.test.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.test.ts @@ -100,8 +100,14 @@ describe('RatesController', () => { const { fiatCurrency, rates, cryptocurrencies } = ratesController.state; expect(ratesController).toBeDefined(); expect(fiatCurrency).toBe('usd'); - expect(Object.keys(rates)).toStrictEqual([Cryptocurrency.Btc]); - expect(cryptocurrencies).toStrictEqual([Cryptocurrency.Btc]); + expect(Object.keys(rates)).toStrictEqual([ + Cryptocurrency.Btc, + Cryptocurrency.Solana, + ]); + expect(cryptocurrencies).toStrictEqual([ + Cryptocurrency.Btc, + Cryptocurrency.Solana, + ]); }); }); @@ -119,11 +125,16 @@ describe('RatesController', () => { const publishActionSpy = jest.spyOn(messenger, 'publish'); jest.spyOn(global.Date, 'now').mockImplementation(() => getStubbedDate()); - const mockRateValue = 57715.42; + const mockBtcRateValue = 57715.42; + const mockSolRateValue = 200.48; + const fetchExchangeRateStub = jest.fn(() => { return Promise.resolve({ btc: { - eur: mockRateValue, + eur: mockBtcRateValue, + }, + sol: { + eur: mockSolRateValue, }, }); }); @@ -144,6 +155,10 @@ describe('RatesController', () => { conversionDate: 0, conversionRate: 0, }, + sol: { + conversionDate: 0, + conversionRate: 0, + }, }); await ratesController.start(); @@ -163,7 +178,11 @@ describe('RatesController', () => { expect(ratesPosUpdate).toStrictEqual({ btc: { conversionDate: MOCK_TIMESTAMP, - conversionRate: mockRateValue, + conversionRate: mockBtcRateValue, + }, + sol: { + conversionDate: MOCK_TIMESTAMP, + conversionRate: mockSolRateValue, }, }); @@ -326,7 +345,10 @@ describe('RatesController', () => { const cryptocurrencyListPreUpdate = ratesController.getCryptocurrencyList(); - expect(cryptocurrencyListPreUpdate).toStrictEqual([Cryptocurrency.Btc]); + expect(cryptocurrencyListPreUpdate).toStrictEqual([ + Cryptocurrency.Btc, + Cryptocurrency.Solana, + ]); // Just to make sure we're updating to something else than the default list expect(cryptocurrencyListPreUpdate).not.toStrictEqual( mockCryptocurrencyList, diff --git a/packages/assets-controllers/src/RatesController/RatesController.ts b/packages/assets-controllers/src/RatesController/RatesController.ts index 7abed73eed..16588ef0d0 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.ts @@ -12,8 +12,15 @@ import type { export const name = 'RatesController'; +/** + * Supported cryptocurrencies that can be used as a base currency. The value needs to be compatible + * with CryptoCompare's API which is the default source for the rates. + * + * See: https://min-api.cryptocompare.com/documentation?key=Price&cat=multipleSymbolsPriceEndpoint + */ export enum Cryptocurrency { Btc = 'btc', + Solana = 'sol', } const DEFAULT_INTERVAL = 180000; @@ -31,8 +38,12 @@ const defaultState = { conversionDate: 0, conversionRate: 0, }, + [Cryptocurrency.Solana]: { + conversionDate: 0, + conversionRate: 0, + }, }, - cryptocurrencies: [Cryptocurrency.Btc], + cryptocurrencies: [Cryptocurrency.Btc, Cryptocurrency.Solana], }; export class RatesController extends BaseController< diff --git a/packages/assets-controllers/src/TokensController.ts b/packages/assets-controllers/src/TokensController.ts index ba94bb2fb3..ddd7bd0295 100644 --- a/packages/assets-controllers/src/TokensController.ts +++ b/packages/assets-controllers/src/TokensController.ts @@ -462,16 +462,16 @@ export class TokensController extends BaseController< */ async addTokens(tokensToImport: Token[], networkClientId?: NetworkClientId) { const releaseLock = await this.#mutex.acquire(); - const { ignoredTokens, allDetectedTokens } = this.state; + const { allTokens, ignoredTokens, allDetectedTokens } = this.state; const importedTokensMap: { [key: string]: true } = {}; // Used later to dedupe imported tokens - const newTokensMap = Object.values(tokensToImport).reduce( - (output, token) => { - output[token.address] = token; - return output; - }, - {} as { [address: string]: Token }, - ); + const newTokensMap = [ + ...(allTokens[this.#chainId]?.[this.#getSelectedAccount().address] || []), + ...tokensToImport, + ].reduce((output, token) => { + output[token.address] = token; + return output; + }, {} as { [address: string]: Token }); try { tokensToImport.forEach((tokenToAdd) => { const { address, symbol, decimals, image, aggregators, name } =