From 8e95dee8d22307de07d1e3f5303789c5329cdc8a Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 27 Oct 2020 08:46:26 -0230 Subject: [PATCH 1/5] CurrencyController can be configured to always fetch usd rate in addition to currentCurrency rate --- src/assets/CurrencyRateController.ts | 38 ++++++++++++++++++++++------ tests/CurrencyRateController.test.ts | 37 ++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/assets/CurrencyRateController.ts b/src/assets/CurrencyRateController.ts index eff85ef5ac9..62b1f092d06 100644 --- a/src/assets/CurrencyRateController.ts +++ b/src/assets/CurrencyRateController.ts @@ -11,11 +11,13 @@ const { Mutex } = require('await-semaphore'); * @property currentCurrency - Currently-active ISO 4217 currency code * @property interval - Polling interval used to fetch new currency rate * @property nativeCurrency - Symbol for the base asset used for conversion + * @property includeUSDRate - Whether to include the usd rate in addition to the currentCurrency */ export interface CurrencyRateConfig extends BaseConfig { currentCurrency: string; interval: number; nativeCurrency: string; + includeUSDRate?: boolean; } /** @@ -27,12 +29,14 @@ export interface CurrencyRateConfig extends BaseConfig { * @property conversionRate - Conversion rate from current base asset to the current currency * @property currentCurrency - Currently-active ISO 4217 currency code * @property nativeCurrency - Symbol for the base asset used for conversion + * @property usdConversionRate - Conversion rate from usd to the current currency */ export interface CurrencyRateState extends BaseState { conversionDate: number; conversionRate: number; currentCurrency: string; nativeCurrency: string; + usdConversionRate?: number; } /** @@ -40,6 +44,9 @@ export interface CurrencyRateState extends BaseState { * asset to the current currency */ export class CurrencyRateController extends BaseController { + /* Optional config to include conversion to usd in all price url fetches and on state */ + includeUSDRate?: boolean; + private activeCurrency = ''; private activeNativeCurrency = ''; @@ -52,10 +59,11 @@ export class CurrencyRateController extends BaseController { - const json = await handleFetch(this.getPricingURL(currency, nativeCurrency)); + async fetchExchangeRate(currency: string, nativeCurrency = this.activeNativeCurrency, includeUSDRate?: boolean): Promise { + const json = await handleFetch(this.getPricingURL(currency, nativeCurrency, includeUSDRate)); const conversionRate = Number(json[currency.toUpperCase()]); - + const usdConversionRate = Number(json.USD); if (!Number.isFinite(conversionRate)) { throw new Error(`Invalid response for ${currency.toUpperCase()}: ${json[currency.toUpperCase()]}`); } + if (includeUSDRate && !Number.isFinite(usdConversionRate)) { + throw new Error(`Invalid response for usdConversionRate: ${json.USD}`); + } return { conversionDate: Date.now() / 1000, conversionRate, currentCurrency: currency, nativeCurrency, + usdConversionRate, }; } @@ -157,16 +174,21 @@ export class CurrencyRateController extends BaseController { beforeEach(() => { - fetchMock.mock('*', () => new Response(JSON.stringify({ USD: 1337 }))).spy(); + fetchMock + .mock(/XYZ,USD/u, () => new Response(JSON.stringify({ XYZ: 123, USD: 456 }))) + .mock(/DEF,USD/u, () => new Response(JSON.stringify({ DEF: 123 }))) + .mock('*', () => new Response(JSON.stringify({ USD: 1337 }))) + .spy(); }); afterEach(() => { @@ -29,6 +33,7 @@ describe('CurrencyRateController', () => { disabled: false, interval: 180000, nativeCurrency: 'ETH', + includeUSDRate: false, }); }); @@ -40,6 +45,7 @@ describe('CurrencyRateController', () => { disabled: false, interval: 180000, nativeCurrency: 'ETH', + includeUSDRate: false, }); }); @@ -89,6 +95,13 @@ describe('CurrencyRateController', () => { expect(controller.state.conversionRate).toBeGreaterThan(0); }); + it('should add usd rate to state when includeUSDRate is configured true', async () => { + const controller = new CurrencyRateController({ includeUSDRate: true, currentCurrency: 'xyz' }); + expect(controller.state.usdConversionRate).toEqual(0); + await controller.updateExchangeRate(); + expect(controller.state.usdConversionRate).toEqual(456); + }); + it('should use default base asset', async () => { const nativeCurrency = 'FOO'; const controller = new CurrencyRateController({ nativeCurrency }); @@ -96,6 +109,28 @@ describe('CurrencyRateController', () => { expect(fetchMock.calls()[0][0]).toContain(nativeCurrency); }); + it('should add usd rate to state fetches when configured', async () => { + const controller = new CurrencyRateController({ includeUSDRate: true }); + const result = await controller.fetchExchangeRate('xyz', 'FOO', true); + expect(fetchMock.calls()[0][0]).toContain('XYZ,USD'); + expect(result.usdConversionRate).toEqual(456); + expect(result.conversionRate).toEqual(123); + }); + + it('should throw correctly when configured to return usd but receives an invalid response for currentCurrency rate', async () => { + const controller = new CurrencyRateController({ includeUSDRate: true }); + await expect(controller.fetchExchangeRate('abc', 'FOO', true)).rejects.toThrow( + 'Invalid response for ABC: undefined', + ); + }); + + it('should throw correctly when configured to return usd but receives an invalid response for usdConversionRate', async () => { + const controller = new CurrencyRateController({ includeUSDRate: true }); + await expect(controller.fetchExchangeRate('def', 'FOO', true)).rejects.toThrow( + 'Invalid response for usdConversionRate: undefined', + ); + }); + describe('#fetchExchangeRate', () => { it('should handle a valid symbol in the API response', async () => { const controller = new CurrencyRateController({ nativeCurrency: 'usd' }); From 7bd881be81372c26857458e36ecd3e39c103f085 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 3 Nov 2020 16:55:35 -0330 Subject: [PATCH 2/5] Update src/assets/CurrencyRateController.ts Co-authored-by: Mark Stacey --- src/assets/CurrencyRateController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/CurrencyRateController.ts b/src/assets/CurrencyRateController.ts index 62b1f092d06..13739c8ca27 100644 --- a/src/assets/CurrencyRateController.ts +++ b/src/assets/CurrencyRateController.ts @@ -63,7 +63,7 @@ export class CurrencyRateController extends BaseController Date: Tue, 3 Nov 2020 16:56:05 -0330 Subject: [PATCH 3/5] Update src/assets/CurrencyRateController.ts Co-authored-by: Mark Stacey --- src/assets/CurrencyRateController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/assets/CurrencyRateController.ts b/src/assets/CurrencyRateController.ts index 13739c8ca27..e1ba385d097 100644 --- a/src/assets/CurrencyRateController.ts +++ b/src/assets/CurrencyRateController.ts @@ -92,10 +92,8 @@ export class CurrencyRateController extends BaseController Date: Tue, 3 Nov 2020 16:56:35 -0330 Subject: [PATCH 4/5] Update src/assets/CurrencyRateController.ts Co-authored-by: Mark Stacey --- src/assets/CurrencyRateController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/assets/CurrencyRateController.ts b/src/assets/CurrencyRateController.ts index e1ba385d097..184731b88e6 100644 --- a/src/assets/CurrencyRateController.ts +++ b/src/assets/CurrencyRateController.ts @@ -182,10 +182,8 @@ export class CurrencyRateController extends BaseController Date: Fri, 6 Nov 2020 00:15:19 -0330 Subject: [PATCH 5/5] Update unit tests --- tests/ComposableController.test.ts | 3 +++ tests/CurrencyRateController.test.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/tests/ComposableController.test.ts b/tests/ComposableController.test.ts index 7d76753801d..cbed12ee5a2 100644 --- a/tests/ComposableController.test.ts +++ b/tests/ComposableController.test.ts @@ -40,6 +40,7 @@ describe('ComposableController', () => { conversionRate: 0, currentCurrency: 'usd', nativeCurrency: 'ETH', + usdConversionRate: 0, }, EnsController: { ensEntries: {}, @@ -96,6 +97,7 @@ describe('ComposableController', () => { selectedAddress: '', suggestedAssets: [], tokens: [], + usdConversionRate: 0, }); }); @@ -149,6 +151,7 @@ describe('ComposableController', () => { selectedAddress: '', suggestedAssets: [], tokens: [], + usdConversionRate: 0, }); }); diff --git a/tests/CurrencyRateController.test.ts b/tests/CurrencyRateController.test.ts index e143950359f..6de969e2ce3 100644 --- a/tests/CurrencyRateController.test.ts +++ b/tests/CurrencyRateController.test.ts @@ -23,6 +23,7 @@ describe('CurrencyRateController', () => { conversionRate: 0, currentCurrency: 'usd', nativeCurrency: 'ETH', + usdConversionRate: 0, }); });