From 8ddf205363498c8c9a6a0ff80ae55bb5bdc25dbc Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Mon, 18 Mar 2024 12:11:26 +0100 Subject: [PATCH 1/9] Use hardcoded infura api urls --- .../src/GasFeeController.test.ts | 98 ++++++++----------- .../src/GasFeeController.ts | 32 ++++-- .../src/determineGasFeeCalculations.test.ts | 3 + .../src/determineGasFeeCalculations.ts | 12 ++- .../gas-fee-controller/src/gas-util.test.ts | 50 ++++++++-- packages/gas-fee-controller/src/gas-util.ts | 15 ++- 6 files changed, 134 insertions(+), 76 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.test.ts b/packages/gas-fee-controller/src/GasFeeController.test.ts index d198f4b983a..604d82196da 100644 --- a/packages/gas-fee-controller/src/GasFeeController.test.ts +++ b/packages/gas-fee-controller/src/GasFeeController.test.ts @@ -25,7 +25,11 @@ import { fetchEthGasPriceEstimate, calculateTimeEstimate, } from './gas-util'; -import { GAS_ESTIMATE_TYPES, GasFeeController } from './GasFeeController'; +import { + GAS_API_BASE_URL, + GAS_ESTIMATE_TYPES, + GasFeeController, +} from './GasFeeController'; import type { GasFeeState, GasFeeStateChange, @@ -218,21 +222,21 @@ describe('GasFeeController', () => { * GasFeeController. * @param options.getCurrentNetworkLegacyGasAPICompatibility - Sets * getCurrentNetworkLegacyGasAPICompatibility on the GasFeeController. - * @param options.legacyAPIEndpoint - Sets legacyAPIEndpoint on the GasFeeController. - * @param options.EIP1559APIEndpoint - Sets EIP1559APIEndpoint on the GasFeeController. * @param options.clientId - Sets clientId on the GasFeeController. * @param options.networkControllerState - State object to initialize * NetworkController with. * @param options.interval - The polling interval. * @param options.state - The initial GasFeeController state + * @param options.infuraAPIKey - The Infura API key. + * @param options.infuraAPIKeySecret - The Infura API key secret. */ async function setupGasFeeController({ getIsEIP1559Compatible = jest.fn().mockResolvedValue(true), getCurrentNetworkLegacyGasAPICompatibility = jest .fn() .mockReturnValue(false), - legacyAPIEndpoint = 'http://legacy.endpoint/', - EIP1559APIEndpoint = 'http://eip-1559.endpoint/', + infuraAPIKey = 'INFURA_API_KEY', + infuraAPIKeySecret = 'INFURA_API_KEY_SECRET', clientId, getChainId, networkControllerState = {}, @@ -242,12 +246,12 @@ describe('GasFeeController', () => { getChainId?: jest.Mock; getIsEIP1559Compatible?: jest.Mock>; getCurrentNetworkLegacyGasAPICompatibility?: jest.Mock; - legacyAPIEndpoint?: string; - EIP1559APIEndpoint?: string; clientId?: string; networkControllerState?: Partial; state?: GasFeeState; interval?: number; + infuraAPIKey?: string; + infuraAPIKeySecret?: string; } = {}) { const controllerMessenger = getControllerMessenger(); networkController = await setupNetworkController({ @@ -262,11 +266,11 @@ describe('GasFeeController', () => { messenger, getCurrentNetworkLegacyGasAPICompatibility, getCurrentNetworkEIP1559Compatibility: getIsEIP1559Compatible, // change this for networkDetails.state.networkDetails.isEIP1559Compatible ??? - legacyAPIEndpoint, - EIP1559APIEndpoint, state, clientId, interval, + infuraAPIKey, + infuraAPIKeySecret, }); } @@ -319,8 +323,6 @@ describe('GasFeeController', () => { getCurrentNetworkLegacyGasAPICompatibility: jest .fn() .mockReturnValue(true), - legacyAPIEndpoint: 'https://some-legacy-endpoint/', - EIP1559APIEndpoint: 'https://some-eip-1559-endpoint/', networkControllerState: { providerConfig: { type: NetworkType.rpc, @@ -338,15 +340,15 @@ describe('GasFeeController', () => { isEIP1559Compatible: false, isLegacyGasAPICompatible: true, fetchGasEstimates, - fetchGasEstimatesUrl: 'https://some-eip-1559-endpoint/1337', + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/suggestedGasFees`, fetchGasEstimatesViaEthFeeHistory, fetchLegacyGasPriceEstimates, - fetchLegacyGasPriceEstimatesUrl: - 'https://some-legacy-endpoint/1337', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/gasPrices`, fetchEthGasPriceEstimate, calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), + infuraAuthToken: expect.any(String), }); }); @@ -375,8 +377,6 @@ describe('GasFeeController', () => { getCurrentNetworkLegacyGasAPICompatibility: jest .fn() .mockReturnValue(true), - legacyAPIEndpoint: 'https://some-legacy-endpoint/', - EIP1559APIEndpoint: 'https://some-eip-1559-endpoint/', networkControllerState: { providerConfig: { type: NetworkType.rpc, @@ -396,15 +396,15 @@ describe('GasFeeController', () => { isEIP1559Compatible: false, isLegacyGasAPICompatible: true, fetchGasEstimates, - fetchGasEstimatesUrl: 'https://some-eip-1559-endpoint/1337', + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/suggestedGasFees`, fetchGasEstimatesViaEthFeeHistory, fetchLegacyGasPriceEstimates, - fetchLegacyGasPriceEstimatesUrl: - 'https://some-legacy-endpoint/1337', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/gasPrices`, fetchEthGasPriceEstimate, calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), + infuraAuthToken: expect.any(String), }); }); @@ -686,8 +686,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations correctly', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - legacyAPIEndpoint: 'https://some-legacy-endpoint/', - EIP1559APIEndpoint: 'https://some-eip-1559-endpoint/', networkControllerState: { providerConfig: { type: NetworkType.rpc, @@ -705,14 +703,15 @@ describe('GasFeeController', () => { isEIP1559Compatible: false, isLegacyGasAPICompatible: true, fetchGasEstimates, - fetchGasEstimatesUrl: 'https://some-eip-1559-endpoint/1337', + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/suggestedGasFees`, fetchGasEstimatesViaEthFeeHistory, fetchLegacyGasPriceEstimates, - fetchLegacyGasPriceEstimatesUrl: 'https://some-legacy-endpoint/1337', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/gasPrices`, fetchEthGasPriceEstimate, calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), + infuraAuthToken: expect.any(String), }); }); @@ -737,7 +736,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations correctly when getChainId returns a number input', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - legacyAPIEndpoint: 'http://legacy.endpoint/', getChainId: jest.fn().mockReturnValue(1), }); @@ -745,7 +743,7 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenCalledWith( expect.objectContaining({ - fetchLegacyGasPriceEstimatesUrl: 'http://legacy.endpoint/1', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1/gasPrices`, }), ); }); @@ -753,7 +751,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations correctly when getChainId returns a hexstring input', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - legacyAPIEndpoint: 'http://legacy.endpoint/', getChainId: jest.fn().mockReturnValue('0x1'), }); @@ -761,7 +758,7 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenCalledWith( expect.objectContaining({ - fetchLegacyGasPriceEstimatesUrl: 'http://legacy.endpoint/1', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1/gasPrices`, }), ); }); @@ -769,7 +766,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations correctly when getChainId returns a numeric string input', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - legacyAPIEndpoint: 'http://legacy.endpoint/', getChainId: jest.fn().mockReturnValue('1'), }); @@ -777,7 +773,7 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenCalledWith( expect.objectContaining({ - fetchLegacyGasPriceEstimatesUrl: 'http://legacy.endpoint/1', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1/gasPrices`, }), ); }); @@ -798,8 +794,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations correctly', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - legacyAPIEndpoint: 'https://some-legacy-endpoint/', - EIP1559APIEndpoint: 'https://some-eip-1559-endpoint/', networkControllerState: { providerConfig: { type: NetworkType.rpc, @@ -817,14 +811,15 @@ describe('GasFeeController', () => { isEIP1559Compatible: true, isLegacyGasAPICompatible: false, fetchGasEstimates, - fetchGasEstimatesUrl: 'https://some-eip-1559-endpoint/1337', + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/suggestedGasFees`, fetchGasEstimatesViaEthFeeHistory, fetchLegacyGasPriceEstimates, - fetchLegacyGasPriceEstimatesUrl: 'https://some-legacy-endpoint/1337', + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/1337/gasPrices`, fetchEthGasPriceEstimate, calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), + infuraAuthToken: expect.any(String), }); }); @@ -849,7 +844,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations with a URL that contains the chain ID', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - EIP1559APIEndpoint: 'http://eip-1559.endpoint/', getChainId: jest.fn().mockReturnValue('0x1'), }); @@ -857,7 +851,7 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenCalledWith( expect.objectContaining({ - fetchGasEstimatesUrl: 'http://eip-1559.endpoint/1', + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/1/suggestedGasFees`, }), ); }); @@ -899,8 +893,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations correctly', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - legacyAPIEndpoint: 'https://some-legacy-endpoint/', - EIP1559APIEndpoint: 'https://some-eip-1559-endpoint/', clientId: '99999', }); @@ -912,16 +904,19 @@ describe('GasFeeController', () => { isEIP1559Compatible: true, isLegacyGasAPICompatible: false, fetchGasEstimates, - fetchGasEstimatesUrl: 'https://some-eip-1559-endpoint/5', + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/${convertHexToDecimal( + ChainId.goerli, + )}/suggestedGasFees`, fetchGasEstimatesViaEthFeeHistory, fetchLegacyGasPriceEstimates, - fetchLegacyGasPriceEstimatesUrl: `https://some-legacy-endpoint/${convertHexToDecimal( + fetchLegacyGasPriceEstimatesUrl: `${GAS_API_BASE_URL}/networks/${convertHexToDecimal( ChainId.goerli, - )}`, + )}/gasPrices`, fetchEthGasPriceEstimate, calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), + infuraAuthToken: expect.any(String), }); }); @@ -931,10 +926,6 @@ describe('GasFeeController', () => { await gasFeeController.fetchGasFeeEstimates({ networkClientId: 'goerli', }); - console.log( - 'gasFeeController.state.gasFeeEstimatesByChainId: ', - gasFeeController.state.gasFeeEstimatesByChainId, - ); expect( gasFeeController.state.gasFeeEstimatesByChainId?.[ChainId.goerli], @@ -954,7 +945,6 @@ describe('GasFeeController', () => { it('should call determineGasFeeCalculations with a URL that contains the chain ID', async () => { await setupGasFeeController({ ...defaultConstructorOptions, - EIP1559APIEndpoint: 'http://eip-1559.endpoint/', }); await gasFeeController.fetchGasFeeEstimates({ @@ -963,9 +953,9 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenCalledWith( expect.objectContaining({ - fetchGasEstimatesUrl: `http://eip-1559.endpoint/${convertHexToDecimal( + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/${convertHexToDecimal( ChainId.sepolia, - )}`, + )}/suggestedGasFees`, }), ); }); @@ -980,8 +970,6 @@ describe('GasFeeController', () => { getCurrentNetworkLegacyGasAPICompatibility: jest .fn() .mockReturnValue(true), - legacyAPIEndpoint: 'https://some-legacy-endpoint/', - EIP1559APIEndpoint: 'https://some-eip-1559-endpoint/', networkControllerState: { networksMetadata: { goerli: { @@ -1007,9 +995,9 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenNthCalledWith( 1, expect.objectContaining({ - fetchGasEstimatesUrl: `https://some-eip-1559-endpoint/${convertHexToDecimal( + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/${convertHexToDecimal( ChainId.goerli, - )}`, + )}/suggestedGasFees`, }), ); await clock.tickAsync(pollingInterval / 2); @@ -1018,9 +1006,9 @@ describe('GasFeeController', () => { expect(mockedDetermineGasFeeCalculations).toHaveBeenNthCalledWith( 2, expect.objectContaining({ - fetchGasEstimatesUrl: `https://some-eip-1559-endpoint/${convertHexToDecimal( + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/${convertHexToDecimal( ChainId.goerli, - )}`, + )}/suggestedGasFees`, }), ); expect( @@ -1031,9 +1019,9 @@ describe('GasFeeController', () => { await clock.tickAsync(pollingInterval); expect(mockedDetermineGasFeeCalculations).toHaveBeenCalledWith( expect.objectContaining({ - fetchGasEstimatesUrl: `https://some-eip-1559-endpoint/${convertHexToDecimal( + fetchGasEstimatesUrl: `${GAS_API_BASE_URL}/networks/${convertHexToDecimal( ChainId.sepolia, - )}`, + )}/suggestedGasFees`, }), ); }); diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index ecb397e6078..7f8d38435e0 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -31,7 +31,7 @@ import { calculateTimeEstimate, } from './gas-util'; -export const LEGACY_GAS_PRICES_API_URL = `https://api.metaswap.codefi.network/gasPrices`; +export const GAS_API_BASE_URL = 'https://gas.api.infura.io'; export type unknownString = 'unknown'; @@ -274,6 +274,8 @@ export class GasFeeController extends StaticIntervalPollingController< private readonly getCurrentAccountEIP1559Compatibility; + private readonly infuraAuthToken: string; + private currentChainId; private ethQuery?: EthQuery; @@ -299,11 +301,10 @@ export class GasFeeController extends StaticIntervalPollingController< * @param options.getProvider - Returns a network provider for the current network. * @param options.onNetworkDidChange - A function for registering an event handler for the * network state change event. - * @param options.legacyAPIEndpoint - The legacy gas price API URL. This option is primarily for - * testing purposes. - * @param options.EIP1559APIEndpoint - The EIP-1559 gas price API URL. * @param options.clientId - The client ID used to identify to the gas estimation API who is * asking for estimates. + * @param options.infuraAPIKey - The Infura API key used for infura API requests. + * @param options.infuraAPIKeySecret - The Infura API key secret used for infura API requests. */ constructor({ interval = 15000, @@ -315,9 +316,9 @@ export class GasFeeController extends StaticIntervalPollingController< getCurrentNetworkLegacyGasAPICompatibility, getProvider, onNetworkDidChange, - legacyAPIEndpoint = LEGACY_GAS_PRICES_API_URL, - EIP1559APIEndpoint, clientId, + infuraAPIKey, + infuraAPIKeySecret, }: { interval?: number; messenger: GasFeeMessenger; @@ -328,9 +329,9 @@ export class GasFeeController extends StaticIntervalPollingController< getChainId?: () => Hex; getProvider: () => ProviderProxy; onNetworkDidChange?: (listener: (state: NetworkState) => void) => void; - legacyAPIEndpoint?: string; - EIP1559APIEndpoint: string; clientId?: string; + infuraAPIKey: string; + infuraAPIKeySecret: string; }) { super({ name, @@ -348,9 +349,13 @@ export class GasFeeController extends StaticIntervalPollingController< this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility; this.#getProvider = getProvider; + const { EIP1559APIEndpoint, legacyAPIEndpoint } = this.#getAPIEndpoints(); this.EIP1559APIEndpoint = EIP1559APIEndpoint; this.legacyAPIEndpoint = legacyAPIEndpoint; this.clientId = clientId; + this.infuraAuthToken = Buffer.from( + `${infuraAPIKey}:${infuraAPIKeySecret}`, + ).toString('base64'); this.ethQuery = new EthQuery(this.#getProvider()); @@ -473,6 +478,7 @@ export class GasFeeController extends StaticIntervalPollingController< calculateTimeEstimate, clientId: this.clientId, ethQuery, + infuraAuthToken: this.infuraAuthToken, }); if (shouldUpdateState) { @@ -589,6 +595,16 @@ export class GasFeeController extends StaticIntervalPollingController< this.currentChainId = newChainId; } } + + #getAPIEndpoints() { + const EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks//suggestedGasFees`; + const legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks//gasPrices`; + + return { + EIP1559APIEndpoint, + legacyAPIEndpoint, + }; + } } export default GasFeeController; diff --git a/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts b/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts index 1bff2582a7f..04ac3c7700b 100644 --- a/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts +++ b/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts @@ -40,6 +40,8 @@ const mockedFetchGasEstimatesViaEthFeeHistory = Parameters >; +const INFURA_AUTH_TOKEN_MOCK = 'test'; + /** * Builds mock data for the `fetchGasEstimates` function. All of the data here is filled in to make * the gas fee estimation code function in a way that represents a reasonably happy path; it does @@ -132,6 +134,7 @@ describe('determineGasFeeCalculations', () => { calculateTimeEstimate: mockedCalculateTimeEstimate, clientId: 'some-client-id', ethQuery: {}, + infuraAuthToken: INFURA_AUTH_TOKEN_MOCK, }; describe('when isEIP1559Compatible is true', () => { diff --git a/packages/gas-fee-controller/src/determineGasFeeCalculations.ts b/packages/gas-fee-controller/src/determineGasFeeCalculations.ts index f62ee4a7e28..5d324ce6651 100644 --- a/packages/gas-fee-controller/src/determineGasFeeCalculations.ts +++ b/packages/gas-fee-controller/src/determineGasFeeCalculations.ts @@ -31,6 +31,7 @@ import { GAS_ESTIMATE_TYPES } from './GasFeeController'; * @param args.calculateTimeEstimate - A function that determine time estimate bounds. * @param args.clientId - An identifier that an API can use to know who is asking for estimates. * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly. + * @param args.infuraAuthToken - Infura auth token to use for the requests. * @returns The gas fee calculations. */ export default async function determineGasFeeCalculations({ @@ -45,11 +46,13 @@ export default async function determineGasFeeCalculations({ calculateTimeEstimate, clientId, ethQuery, + infuraAuthToken, }: { isEIP1559Compatible: boolean; isLegacyGasAPICompatible: boolean; fetchGasEstimates: ( url: string, + infuraAuthToken: string, clientId?: string, ) => Promise; fetchGasEstimatesUrl: string; @@ -60,6 +63,7 @@ export default async function determineGasFeeCalculations({ ) => Promise; fetchLegacyGasPriceEstimates: ( url: string, + infuraAuthToken: string, clientId?: string, ) => Promise; fetchLegacyGasPriceEstimatesUrl: string; @@ -75,12 +79,17 @@ export default async function determineGasFeeCalculations({ // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any ethQuery: any; + infuraAuthToken: string; }): Promise { try { if (isEIP1559Compatible) { let estimates: GasFeeEstimates; try { - estimates = await fetchGasEstimates(fetchGasEstimatesUrl, clientId); + estimates = await fetchGasEstimates( + fetchGasEstimatesUrl, + infuraAuthToken, + clientId, + ); } catch { estimates = await fetchGasEstimatesViaEthFeeHistory(ethQuery); } @@ -99,6 +108,7 @@ export default async function determineGasFeeCalculations({ } else if (isLegacyGasAPICompatible) { const estimates = await fetchLegacyGasPriceEstimates( fetchLegacyGasPriceEstimatesUrl, + infuraAuthToken, clientId, ); return { diff --git a/packages/gas-fee-controller/src/gas-util.test.ts b/packages/gas-fee-controller/src/gas-util.test.ts index baea4369289..46939ad4515 100644 --- a/packages/gas-fee-controller/src/gas-util.test.ts +++ b/packages/gas-fee-controller/src/gas-util.test.ts @@ -65,25 +65,42 @@ const mockEIP1559ApiResponses: GasFeeEstimates[] = [ }, ]; +const INFURA_AUTH_TOKEN_MOCK = 'test'; + describe('gas utils', () => { describe('fetchGasEstimates', () => { it('should fetch external gasFeeEstimates when data is valid', async () => { - const scope = nock('https://not-a-real-url/') + const scope = nock('https://not-a-real-url/', { + reqheaders: { + Authorization: INFURA_AUTH_TOKEN_MOCK, + }, + }) .get(/.+/u) .reply(200, mockEIP1559ApiResponses[0]) .persist(); - const result = await fetchGasEstimates('https://not-a-real-url/'); + const result = await fetchGasEstimates( + 'https://not-a-real-url/', + INFURA_AUTH_TOKEN_MOCK, + ); expect(result).toMatchObject(mockEIP1559ApiResponses[0]); scope.done(); }); it('should fetch external gasFeeEstimates with client id header when clientId arg is added', async () => { - const scope = nock('https://not-a-real-url/') + const scope = nock('https://not-a-real-url/', { + reqheaders: { + Authorization: INFURA_AUTH_TOKEN_MOCK, + }, + }) .matchHeader('x-client-id', 'test') .get(/.+/u) .reply(200, mockEIP1559ApiResponses[0]) .persist(); - const result = await fetchGasEstimates('https://not-a-real-url/', 'test'); + const result = await fetchGasEstimates( + 'https://not-a-real-url/', + INFURA_AUTH_TOKEN_MOCK, + 'test', + ); expect(result).toMatchObject(mockEIP1559ApiResponses[0]); scope.done(); }); @@ -111,11 +128,18 @@ describe('gas utils', () => { estimatedBaseFee: '32.000000017', }; - const scope = nock('https://not-a-real-url/') + const scope = nock('https://not-a-real-url/', { + reqheaders: { + Authorization: INFURA_AUTH_TOKEN_MOCK, + }, + }) .get(/.+/u) .reply(200, mockEIP1559ApiResponses[1]) .persist(); - const result = await fetchGasEstimates('https://not-a-real-url/'); + const result = await fetchGasEstimates( + 'https://not-a-real-url/', + INFURA_AUTH_TOKEN_MOCK, + ); expect(result).toMatchObject(expectedResult); scope.done(); }); @@ -123,7 +147,11 @@ describe('gas utils', () => { describe('fetchLegacyGasPriceEstimates', () => { it('should fetch external gasPrices and return high/medium/low', async () => { - const scope = nock('https://not-a-real-url/') + const scope = nock('https://not-a-real-url/', { + reqheaders: { + Authorization: INFURA_AUTH_TOKEN_MOCK, + }, + }) .get(/.+/u) .reply(200, { SafeGasPrice: '22', @@ -133,6 +161,7 @@ describe('gas utils', () => { .persist(); const result = await fetchLegacyGasPriceEstimates( 'https://not-a-real-url/', + INFURA_AUTH_TOKEN_MOCK, ); expect(result).toMatchObject({ high: '30', @@ -143,7 +172,11 @@ describe('gas utils', () => { }); it('should fetch external gasPrices with client id header when clientId arg is passed', async () => { - const scope = nock('https://not-a-real-url/') + const scope = nock('https://not-a-real-url/', { + reqheaders: { + Authorization: INFURA_AUTH_TOKEN_MOCK, + }, + }) .matchHeader('x-client-id', 'test') .get(/.+/u) .reply(200, { @@ -154,6 +187,7 @@ describe('gas utils', () => { .persist(); const result = await fetchLegacyGasPriceEstimates( 'https://not-a-real-url/', + INFURA_AUTH_TOKEN_MOCK, 'test', ); expect(result).toMatchObject({ diff --git a/packages/gas-fee-controller/src/gas-util.ts b/packages/gas-fee-controller/src/gas-util.ts index 17a242ac8be..4336553781d 100644 --- a/packages/gas-fee-controller/src/gas-util.ts +++ b/packages/gas-fee-controller/src/gas-util.ts @@ -33,17 +33,21 @@ export function normalizeGWEIDecimalNumbers(n: string | number) { * Fetch gas estimates from the given URL. * * @param url - The gas estimate URL. + * @param infuraAuthToken - The infura auth token to use for the request. * @param clientId - The client ID used to identify to the API who is asking for estimates. * @returns The gas estimates. */ export async function fetchGasEstimates( url: string, + infuraAuthToken: string, clientId?: string, ): Promise { - const estimates = await handleFetch( - url, - clientId ? { headers: makeClientIdHeader(clientId) } : undefined, - ); + const estimates = await handleFetch(url, { + headers: { + Authorization: `Basic ${infuraAuthToken}`, + ...(clientId && makeClientIdHeader(clientId)), + }, + }); return { low: { ...estimates.low, @@ -87,11 +91,13 @@ export async function fetchGasEstimates( * high values from that API. * * @param url - The URL to fetch gas price estimates from. + * @param infuraAuthToken - The infura auth token to use for the request. * @param clientId - The client ID used to identify to the API who is asking for estimates. * @returns The gas price estimates. */ export async function fetchLegacyGasPriceEstimates( url: string, + infuraAuthToken: string, clientId?: string, ): Promise { const result = await handleFetch(url, { @@ -101,6 +107,7 @@ export async function fetchLegacyGasPriceEstimates( mode: 'cors', headers: { 'Content-Type': 'application/json', + Authorization: `Basic ${infuraAuthToken}`, ...(clientId && makeClientIdHeader(clientId)), }, }); From 1afeb7a30c3b63b6b5a158d5813aa24b0e01fdc0 Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Mon, 18 Mar 2024 12:42:09 +0100 Subject: [PATCH 2/9] Fix tests remove nock --- packages/gas-fee-controller/package.json | 1 - .../gas-fee-controller/src/gas-util.test.ts | 139 ++++++++++-------- yarn.lock | 1 - 3 files changed, 76 insertions(+), 65 deletions(-) diff --git a/packages/gas-fee-controller/package.json b/packages/gas-fee-controller/package.json index a4342d6ae7a..6492fe5dc79 100644 --- a/packages/gas-fee-controller/package.json +++ b/packages/gas-fee-controller/package.json @@ -60,7 +60,6 @@ "deepmerge": "^4.2.2", "jest": "^27.5.1", "jest-when": "^3.4.2", - "nock": "^13.3.1", "sinon": "^9.2.4", "ts-jest": "^27.1.4", "typedoc": "^0.24.8", diff --git a/packages/gas-fee-controller/src/gas-util.test.ts b/packages/gas-fee-controller/src/gas-util.test.ts index 46939ad4515..3138cc76dc2 100644 --- a/packages/gas-fee-controller/src/gas-util.test.ts +++ b/packages/gas-fee-controller/src/gas-util.test.ts @@ -1,4 +1,4 @@ -import nock from 'nock'; +import { handleFetch } from '@metamask/controller-utils'; import { fetchLegacyGasPriceEstimates, @@ -8,6 +8,13 @@ import { } from './gas-util'; import type { GasFeeEstimates } from './GasFeeController'; +jest.mock('@metamask/controller-utils', () => { + return { + ...jest.requireActual('@metamask/controller-utils'), + handleFetch: jest.fn(), + }; +}); + const mockEIP1559ApiResponses: GasFeeEstimates[] = [ { low: { @@ -66,43 +73,50 @@ const mockEIP1559ApiResponses: GasFeeEstimates[] = [ ]; const INFURA_AUTH_TOKEN_MOCK = 'test'; +const INFURA_GAS_API_URL_MOCK = 'https://gas.api.infura.io'; describe('gas utils', () => { + let handleFetchMock: jest.Mock; + + beforeEach(() => { + handleFetchMock = handleFetch as jest.Mock; + handleFetchMock.mockReset(); + }); + describe('fetchGasEstimates', () => { it('should fetch external gasFeeEstimates when data is valid', async () => { - const scope = nock('https://not-a-real-url/', { - reqheaders: { - Authorization: INFURA_AUTH_TOKEN_MOCK, - }, - }) - .get(/.+/u) - .reply(200, mockEIP1559ApiResponses[0]) - .persist(); + handleFetchMock.mockResolvedValue(mockEIP1559ApiResponses[0]); const result = await fetchGasEstimates( - 'https://not-a-real-url/', + INFURA_GAS_API_URL_MOCK, INFURA_AUTH_TOKEN_MOCK, ); + + expect(handleFetchMock).toHaveBeenCalledTimes(1); + expect(handleFetchMock).toHaveBeenCalledWith(INFURA_GAS_API_URL_MOCK, { + headers: { + Authorization: `Basic ${INFURA_AUTH_TOKEN_MOCK}`, + }, + }); expect(result).toMatchObject(mockEIP1559ApiResponses[0]); - scope.done(); }); it('should fetch external gasFeeEstimates with client id header when clientId arg is added', async () => { - const scope = nock('https://not-a-real-url/', { - reqheaders: { - Authorization: INFURA_AUTH_TOKEN_MOCK, - }, - }) - .matchHeader('x-client-id', 'test') - .get(/.+/u) - .reply(200, mockEIP1559ApiResponses[0]) - .persist(); + const clientIdMock = 'test'; + handleFetchMock.mockResolvedValue(mockEIP1559ApiResponses[0]); const result = await fetchGasEstimates( - 'https://not-a-real-url/', + INFURA_GAS_API_URL_MOCK, INFURA_AUTH_TOKEN_MOCK, - 'test', + clientIdMock, ); + + expect(handleFetchMock).toHaveBeenCalledTimes(1); + expect(handleFetchMock).toHaveBeenCalledWith(INFURA_GAS_API_URL_MOCK, { + headers: { + Authorization: `Basic ${INFURA_AUTH_TOKEN_MOCK}`, + 'X-Client-Id': clientIdMock, + }, + }); expect(result).toMatchObject(mockEIP1559ApiResponses[0]); - scope.done(); }); it('should fetch and normalize external gasFeeEstimates when data is has an invalid number of decimals', async () => { @@ -128,74 +142,73 @@ describe('gas utils', () => { estimatedBaseFee: '32.000000017', }; - const scope = nock('https://not-a-real-url/', { - reqheaders: { - Authorization: INFURA_AUTH_TOKEN_MOCK, - }, - }) - .get(/.+/u) - .reply(200, mockEIP1559ApiResponses[1]) - .persist(); + handleFetchMock.mockResolvedValue(mockEIP1559ApiResponses[1]); const result = await fetchGasEstimates( - 'https://not-a-real-url/', + INFURA_GAS_API_URL_MOCK, INFURA_AUTH_TOKEN_MOCK, ); expect(result).toMatchObject(expectedResult); - scope.done(); }); }); describe('fetchLegacyGasPriceEstimates', () => { it('should fetch external gasPrices and return high/medium/low', async () => { - const scope = nock('https://not-a-real-url/', { - reqheaders: { - Authorization: INFURA_AUTH_TOKEN_MOCK, - }, - }) - .get(/.+/u) - .reply(200, { - SafeGasPrice: '22', - ProposeGasPrice: '25', - FastGasPrice: '30', - }) - .persist(); + handleFetchMock.mockResolvedValue({ + SafeGasPrice: '22', + ProposeGasPrice: '25', + FastGasPrice: '30', + }); const result = await fetchLegacyGasPriceEstimates( - 'https://not-a-real-url/', + INFURA_GAS_API_URL_MOCK, INFURA_AUTH_TOKEN_MOCK, ); + + expect(handleFetchMock).toHaveBeenCalledTimes(1); + expect(handleFetchMock).toHaveBeenCalledWith( + INFURA_GAS_API_URL_MOCK, + + expect.objectContaining({ + headers: expect.objectContaining({ + Authorization: `Basic ${INFURA_AUTH_TOKEN_MOCK}`, + }), + }), + ); expect(result).toMatchObject({ high: '30', medium: '25', low: '22', }); - scope.done(); }); it('should fetch external gasPrices with client id header when clientId arg is passed', async () => { - const scope = nock('https://not-a-real-url/', { - reqheaders: { - Authorization: INFURA_AUTH_TOKEN_MOCK, - }, - }) - .matchHeader('x-client-id', 'test') - .get(/.+/u) - .reply(200, { - SafeGasPrice: '22', - ProposeGasPrice: '25', - FastGasPrice: '30', - }) - .persist(); + const clientIdMock = 'test'; + handleFetchMock.mockResolvedValue({ + SafeGasPrice: '22', + ProposeGasPrice: '25', + FastGasPrice: '30', + }); const result = await fetchLegacyGasPriceEstimates( - 'https://not-a-real-url/', + INFURA_GAS_API_URL_MOCK, INFURA_AUTH_TOKEN_MOCK, - 'test', + clientIdMock, + ); + + expect(handleFetchMock).toHaveBeenCalledTimes(1); + expect(handleFetchMock).toHaveBeenCalledWith( + INFURA_GAS_API_URL_MOCK, + + expect.objectContaining({ + headers: expect.objectContaining({ + Authorization: `Basic ${INFURA_AUTH_TOKEN_MOCK}`, + 'X-Client-Id': clientIdMock, + }), + }), ); expect(result).toMatchObject({ high: '30', medium: '25', low: '22', }); - scope.done(); }); }); diff --git a/yarn.lock b/yarn.lock index b94ce729691..6f60e0355c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2342,7 +2342,6 @@ __metadata: deepmerge: ^4.2.2 jest: ^27.5.1 jest-when: ^3.4.2 - nock: ^13.3.1 sinon: ^9.2.4 ts-jest: ^27.1.4 typedoc: ^0.24.8 From 9ae7d900481398b31d67276602f065e374c683b7 Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Tue, 19 Mar 2024 09:27:11 +0100 Subject: [PATCH 3/9] Move endpoint logic into constructor --- .../gas-fee-controller/src/GasFeeController.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index 7f8d38435e0..7e362f80e01 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -349,9 +349,8 @@ export class GasFeeController extends StaticIntervalPollingController< this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility; this.#getProvider = getProvider; - const { EIP1559APIEndpoint, legacyAPIEndpoint } = this.#getAPIEndpoints(); - this.EIP1559APIEndpoint = EIP1559APIEndpoint; - this.legacyAPIEndpoint = legacyAPIEndpoint; + this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks//suggestedGasFees`; + this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks//gasPrices`; this.clientId = clientId; this.infuraAuthToken = Buffer.from( `${infuraAPIKey}:${infuraAPIKeySecret}`, @@ -595,16 +594,6 @@ export class GasFeeController extends StaticIntervalPollingController< this.currentChainId = newChainId; } } - - #getAPIEndpoints() { - const EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks//suggestedGasFees`; - const legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks//gasPrices`; - - return { - EIP1559APIEndpoint, - legacyAPIEndpoint, - }; - } } export default GasFeeController; From 291da3482627377a929999721d83ef11a03f7bb5 Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Tue, 19 Mar 2024 09:30:52 +0100 Subject: [PATCH 4/9] Fix gas-util mock function --- packages/gas-fee-controller/src/gas-util.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/gas-fee-controller/src/gas-util.test.ts b/packages/gas-fee-controller/src/gas-util.test.ts index 3138cc76dc2..e4d4e41c1bc 100644 --- a/packages/gas-fee-controller/src/gas-util.test.ts +++ b/packages/gas-fee-controller/src/gas-util.test.ts @@ -14,6 +14,7 @@ jest.mock('@metamask/controller-utils', () => { handleFetch: jest.fn(), }; }); +const handleFetchMock = jest.mocked(handleFetch); const mockEIP1559ApiResponses: GasFeeEstimates[] = [ { @@ -76,11 +77,8 @@ const INFURA_AUTH_TOKEN_MOCK = 'test'; const INFURA_GAS_API_URL_MOCK = 'https://gas.api.infura.io'; describe('gas utils', () => { - let handleFetchMock: jest.Mock; - beforeEach(() => { - handleFetchMock = handleFetch as jest.Mock; - handleFetchMock.mockReset(); + jest.resetAllMocks(); }); describe('fetchGasEstimates', () => { From 80db365c564668224041db96c637a9b84eae66e0 Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Tue, 19 Mar 2024 09:40:57 +0100 Subject: [PATCH 5/9] Eliminate empty string in x-client-id --- packages/gas-fee-controller/src/gas-util.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/gas-fee-controller/src/gas-util.ts b/packages/gas-fee-controller/src/gas-util.ts index 4336553781d..20710431da2 100644 --- a/packages/gas-fee-controller/src/gas-util.ts +++ b/packages/gas-fee-controller/src/gas-util.ts @@ -45,7 +45,8 @@ export async function fetchGasEstimates( const estimates = await handleFetch(url, { headers: { Authorization: `Basic ${infuraAuthToken}`, - ...(clientId && makeClientIdHeader(clientId)), + // Only add the clientId header if clientId is a non-empty string + ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}), }, }); return { @@ -108,7 +109,8 @@ export async function fetchLegacyGasPriceEstimates( headers: { 'Content-Type': 'application/json', Authorization: `Basic ${infuraAuthToken}`, - ...(clientId && makeClientIdHeader(clientId)), + // Only add the clientId header if clientId is a non-empty string + ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}), }, }); return { From 831fa3ad5b0a63c2d2fde637d9f7bec80d853ec6 Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Mon, 25 Mar 2024 14:06:58 +0100 Subject: [PATCH 6/9] fix minor comments --- .../src/GasFeeController.ts | 10 +++-- .../gas-fee-controller/src/gas-util.test.ts | 8 ++-- packages/gas-fee-controller/src/gas-util.ts | 45 ++++++++++++++----- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index 7e362f80e01..95e4bf8d3b8 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -25,10 +25,11 @@ import { v1 as random } from 'uuid'; import determineGasFeeCalculations from './determineGasFeeCalculations'; import fetchGasEstimatesViaEthFeeHistory from './fetchGasEstimatesViaEthFeeHistory'; import { + buildInfuraAuthToken, + calculateTimeEstimate, fetchGasEstimates, fetchLegacyGasPriceEstimates, fetchEthGasPriceEstimate, - calculateTimeEstimate, } from './gas-util'; export const GAS_API_BASE_URL = 'https://gas.api.infura.io'; @@ -352,9 +353,10 @@ export class GasFeeController extends StaticIntervalPollingController< this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks//suggestedGasFees`; this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks//gasPrices`; this.clientId = clientId; - this.infuraAuthToken = Buffer.from( - `${infuraAPIKey}:${infuraAPIKeySecret}`, - ).toString('base64'); + this.infuraAuthToken = buildInfuraAuthToken( + infuraAPIKey, + infuraAPIKeySecret, + ); this.ethQuery = new EthQuery(this.#getProvider()); diff --git a/packages/gas-fee-controller/src/gas-util.test.ts b/packages/gas-fee-controller/src/gas-util.test.ts index e4d4e41c1bc..df51dc6c8b9 100644 --- a/packages/gas-fee-controller/src/gas-util.test.ts +++ b/packages/gas-fee-controller/src/gas-util.test.ts @@ -91,9 +91,9 @@ describe('gas utils', () => { expect(handleFetchMock).toHaveBeenCalledTimes(1); expect(handleFetchMock).toHaveBeenCalledWith(INFURA_GAS_API_URL_MOCK, { - headers: { + headers: expect.objectContaining({ Authorization: `Basic ${INFURA_AUTH_TOKEN_MOCK}`, - }, + }), }); expect(result).toMatchObject(mockEIP1559ApiResponses[0]); }); @@ -109,10 +109,10 @@ describe('gas utils', () => { expect(handleFetchMock).toHaveBeenCalledTimes(1); expect(handleFetchMock).toHaveBeenCalledWith(INFURA_GAS_API_URL_MOCK, { - headers: { + headers: expect.objectContaining({ Authorization: `Basic ${INFURA_AUTH_TOKEN_MOCK}`, 'X-Client-Id': clientIdMock, - }, + }), }); expect(result).toMatchObject(mockEIP1559ApiResponses[0]); }); diff --git a/packages/gas-fee-controller/src/gas-util.ts b/packages/gas-fee-controller/src/gas-util.ts index 20710431da2..68ad56e0710 100644 --- a/packages/gas-fee-controller/src/gas-util.ts +++ b/packages/gas-fee-controller/src/gas-util.ts @@ -43,11 +43,7 @@ export async function fetchGasEstimates( clientId?: string, ): Promise { const estimates = await handleFetch(url, { - headers: { - Authorization: `Basic ${infuraAuthToken}`, - // Only add the clientId header if clientId is a non-empty string - ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}), - }, + headers: getHeaders(infuraAuthToken, clientId), }); return { low: { @@ -106,12 +102,7 @@ export async function fetchLegacyGasPriceEstimates( referrerPolicy: 'no-referrer-when-downgrade', method: 'GET', mode: 'cors', - headers: { - 'Content-Type': 'application/json', - Authorization: `Basic ${infuraAuthToken}`, - // Only add the clientId header if clientId is a non-empty string - ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}), - }, + headers: getHeaders(infuraAuthToken, clientId), }); return { low: result.SafeGasPrice, @@ -200,3 +191,35 @@ export function calculateTimeEstimate( upperTimeBound, }; } + +/** + * Build an infura auth token from the given API key and secret. + * + * @param infuraAPIKey - The Infura API key. + * @param infuraAPIKeySecret - The Infura API key secret. + * @returns The base64 encoded auth token. + */ +export function buildInfuraAuthToken( + infuraAPIKey: string, + infuraAPIKeySecret: string, +) { + return Buffer.from(`${infuraAPIKey}:${infuraAPIKeySecret}`).toString( + 'base64', + ); +} + +/** + * Get the headers for a request to the gas fee API. + * + * @param infuraAuthToken - The Infura auth token to use for the request. + * @param clientId - The client ID used to identify to the API who is asking for estimates. + * @returns The headers for the request. + */ +function getHeaders(infuraAuthToken: string, clientId?: string) { + return { + 'Content-Type': 'application/json', + Authorization: `Basic ${infuraAuthToken}`, + // Only add the clientId header if clientId is a non-empty string + ...(clientId?.trim() ? makeClientIdHeader(clientId) : {}), + }; +} From 14be4d0de36510e7be12ca4deb56489b08162795 Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Tue, 26 Mar 2024 08:16:10 +0100 Subject: [PATCH 7/9] Remove infuraKeySecret from constructor --- .../gas-fee-controller/src/GasFeeController.test.ts | 4 ---- packages/gas-fee-controller/src/GasFeeController.ts | 8 +------- packages/gas-fee-controller/src/gas-util.ts | 11 +++-------- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.test.ts b/packages/gas-fee-controller/src/GasFeeController.test.ts index 604d82196da..90a2853008b 100644 --- a/packages/gas-fee-controller/src/GasFeeController.test.ts +++ b/packages/gas-fee-controller/src/GasFeeController.test.ts @@ -228,7 +228,6 @@ describe('GasFeeController', () => { * @param options.interval - The polling interval. * @param options.state - The initial GasFeeController state * @param options.infuraAPIKey - The Infura API key. - * @param options.infuraAPIKeySecret - The Infura API key secret. */ async function setupGasFeeController({ getIsEIP1559Compatible = jest.fn().mockResolvedValue(true), @@ -236,7 +235,6 @@ describe('GasFeeController', () => { .fn() .mockReturnValue(false), infuraAPIKey = 'INFURA_API_KEY', - infuraAPIKeySecret = 'INFURA_API_KEY_SECRET', clientId, getChainId, networkControllerState = {}, @@ -251,7 +249,6 @@ describe('GasFeeController', () => { state?: GasFeeState; interval?: number; infuraAPIKey?: string; - infuraAPIKeySecret?: string; } = {}) { const controllerMessenger = getControllerMessenger(); networkController = await setupNetworkController({ @@ -270,7 +267,6 @@ describe('GasFeeController', () => { clientId, interval, infuraAPIKey, - infuraAPIKeySecret, }); } diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index 95e4bf8d3b8..dbd908b356d 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -305,7 +305,6 @@ export class GasFeeController extends StaticIntervalPollingController< * @param options.clientId - The client ID used to identify to the gas estimation API who is * asking for estimates. * @param options.infuraAPIKey - The Infura API key used for infura API requests. - * @param options.infuraAPIKeySecret - The Infura API key secret used for infura API requests. */ constructor({ interval = 15000, @@ -319,7 +318,6 @@ export class GasFeeController extends StaticIntervalPollingController< onNetworkDidChange, clientId, infuraAPIKey, - infuraAPIKeySecret, }: { interval?: number; messenger: GasFeeMessenger; @@ -332,7 +330,6 @@ export class GasFeeController extends StaticIntervalPollingController< onNetworkDidChange?: (listener: (state: NetworkState) => void) => void; clientId?: string; infuraAPIKey: string; - infuraAPIKeySecret: string; }) { super({ name, @@ -353,10 +350,7 @@ export class GasFeeController extends StaticIntervalPollingController< this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks//suggestedGasFees`; this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks//gasPrices`; this.clientId = clientId; - this.infuraAuthToken = buildInfuraAuthToken( - infuraAPIKey, - infuraAPIKeySecret, - ); + this.infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); this.ethQuery = new EthQuery(this.#getProvider()); diff --git a/packages/gas-fee-controller/src/gas-util.ts b/packages/gas-fee-controller/src/gas-util.ts index 68ad56e0710..ca6032930db 100644 --- a/packages/gas-fee-controller/src/gas-util.ts +++ b/packages/gas-fee-controller/src/gas-util.ts @@ -196,16 +196,11 @@ export function calculateTimeEstimate( * Build an infura auth token from the given API key and secret. * * @param infuraAPIKey - The Infura API key. - * @param infuraAPIKeySecret - The Infura API key secret. * @returns The base64 encoded auth token. */ -export function buildInfuraAuthToken( - infuraAPIKey: string, - infuraAPIKeySecret: string, -) { - return Buffer.from(`${infuraAPIKey}:${infuraAPIKeySecret}`).toString( - 'base64', - ); +export function buildInfuraAuthToken(infuraAPIKey: string) { + // We intentionally leave the password empty, as Infura does not require one + return Buffer.from(`${infuraAPIKey}:`).toString('base64'); } /** From cd6bb24d1fb5e5215ff46f85b3e820c1064a910e Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Tue, 26 Mar 2024 10:20:49 +0100 Subject: [PATCH 8/9] Pass APIKey instead of authToken in gas-utils --- .../src/GasFeeController.test.ts | 10 +++++----- .../gas-fee-controller/src/GasFeeController.ts | 7 +++---- .../src/determineGasFeeCalculations.ts | 14 +++++++------- packages/gas-fee-controller/src/gas-util.test.ts | 13 +++++++------ packages/gas-fee-controller/src/gas-util.ts | 12 +++++++----- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.test.ts b/packages/gas-fee-controller/src/GasFeeController.test.ts index 90a2853008b..b7dd918b120 100644 --- a/packages/gas-fee-controller/src/GasFeeController.test.ts +++ b/packages/gas-fee-controller/src/GasFeeController.test.ts @@ -344,7 +344,7 @@ describe('GasFeeController', () => { calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), - infuraAuthToken: expect.any(String), + infuraAPIKey: expect.any(String), }); }); @@ -400,7 +400,7 @@ describe('GasFeeController', () => { calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), - infuraAuthToken: expect.any(String), + infuraAPIKey: expect.any(String), }); }); @@ -707,7 +707,7 @@ describe('GasFeeController', () => { calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), - infuraAuthToken: expect.any(String), + infuraAPIKey: expect.any(String), }); }); @@ -815,7 +815,7 @@ describe('GasFeeController', () => { calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), - infuraAuthToken: expect.any(String), + infuraAPIKey: expect.any(String), }); }); @@ -912,7 +912,7 @@ describe('GasFeeController', () => { calculateTimeEstimate, clientId: '99999', ethQuery: expect.any(EthQuery), - infuraAuthToken: expect.any(String), + infuraAPIKey: expect.any(String), }); }); diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index dbd908b356d..411449827ad 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -25,7 +25,6 @@ import { v1 as random } from 'uuid'; import determineGasFeeCalculations from './determineGasFeeCalculations'; import fetchGasEstimatesViaEthFeeHistory from './fetchGasEstimatesViaEthFeeHistory'; import { - buildInfuraAuthToken, calculateTimeEstimate, fetchGasEstimates, fetchLegacyGasPriceEstimates, @@ -275,7 +274,7 @@ export class GasFeeController extends StaticIntervalPollingController< private readonly getCurrentAccountEIP1559Compatibility; - private readonly infuraAuthToken: string; + private readonly infuraAPIKey: string; private currentChainId; @@ -350,7 +349,7 @@ export class GasFeeController extends StaticIntervalPollingController< this.EIP1559APIEndpoint = `${GAS_API_BASE_URL}/networks//suggestedGasFees`; this.legacyAPIEndpoint = `${GAS_API_BASE_URL}/networks//gasPrices`; this.clientId = clientId; - this.infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); + this.infuraAPIKey = infuraAPIKey; this.ethQuery = new EthQuery(this.#getProvider()); @@ -473,7 +472,7 @@ export class GasFeeController extends StaticIntervalPollingController< calculateTimeEstimate, clientId: this.clientId, ethQuery, - infuraAuthToken: this.infuraAuthToken, + infuraAPIKey: this.infuraAPIKey, }); if (shouldUpdateState) { diff --git a/packages/gas-fee-controller/src/determineGasFeeCalculations.ts b/packages/gas-fee-controller/src/determineGasFeeCalculations.ts index 5d324ce6651..96496dc678c 100644 --- a/packages/gas-fee-controller/src/determineGasFeeCalculations.ts +++ b/packages/gas-fee-controller/src/determineGasFeeCalculations.ts @@ -31,7 +31,7 @@ import { GAS_ESTIMATE_TYPES } from './GasFeeController'; * @param args.calculateTimeEstimate - A function that determine time estimate bounds. * @param args.clientId - An identifier that an API can use to know who is asking for estimates. * @param args.ethQuery - An EthQuery instance we can use to talk to Ethereum directly. - * @param args.infuraAuthToken - Infura auth token to use for the requests. + * @param args.infuraAPIKey - Infura API key to use for requests to Infura. * @returns The gas fee calculations. */ export default async function determineGasFeeCalculations({ @@ -46,13 +46,13 @@ export default async function determineGasFeeCalculations({ calculateTimeEstimate, clientId, ethQuery, - infuraAuthToken, + infuraAPIKey, }: { isEIP1559Compatible: boolean; isLegacyGasAPICompatible: boolean; fetchGasEstimates: ( url: string, - infuraAuthToken: string, + infuraAPIKey: string, clientId?: string, ) => Promise; fetchGasEstimatesUrl: string; @@ -63,7 +63,7 @@ export default async function determineGasFeeCalculations({ ) => Promise; fetchLegacyGasPriceEstimates: ( url: string, - infuraAuthToken: string, + infuraAPIKey: string, clientId?: string, ) => Promise; fetchLegacyGasPriceEstimatesUrl: string; @@ -79,7 +79,7 @@ export default async function determineGasFeeCalculations({ // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any ethQuery: any; - infuraAuthToken: string; + infuraAPIKey: string; }): Promise { try { if (isEIP1559Compatible) { @@ -87,7 +87,7 @@ export default async function determineGasFeeCalculations({ try { estimates = await fetchGasEstimates( fetchGasEstimatesUrl, - infuraAuthToken, + infuraAPIKey, clientId, ); } catch { @@ -108,7 +108,7 @@ export default async function determineGasFeeCalculations({ } else if (isLegacyGasAPICompatible) { const estimates = await fetchLegacyGasPriceEstimates( fetchLegacyGasPriceEstimatesUrl, - infuraAuthToken, + infuraAPIKey, clientId, ); return { diff --git a/packages/gas-fee-controller/src/gas-util.test.ts b/packages/gas-fee-controller/src/gas-util.test.ts index df51dc6c8b9..b1e5647be84 100644 --- a/packages/gas-fee-controller/src/gas-util.test.ts +++ b/packages/gas-fee-controller/src/gas-util.test.ts @@ -73,7 +73,8 @@ const mockEIP1559ApiResponses: GasFeeEstimates[] = [ }, ]; -const INFURA_AUTH_TOKEN_MOCK = 'test'; +const INFURA_API_KEY_MOCK = 'test'; +const INFURA_AUTH_TOKEN_MOCK = 'dGVzdDo='; const INFURA_GAS_API_URL_MOCK = 'https://gas.api.infura.io'; describe('gas utils', () => { @@ -86,7 +87,7 @@ describe('gas utils', () => { handleFetchMock.mockResolvedValue(mockEIP1559ApiResponses[0]); const result = await fetchGasEstimates( INFURA_GAS_API_URL_MOCK, - INFURA_AUTH_TOKEN_MOCK, + INFURA_API_KEY_MOCK, ); expect(handleFetchMock).toHaveBeenCalledTimes(1); @@ -103,7 +104,7 @@ describe('gas utils', () => { handleFetchMock.mockResolvedValue(mockEIP1559ApiResponses[0]); const result = await fetchGasEstimates( INFURA_GAS_API_URL_MOCK, - INFURA_AUTH_TOKEN_MOCK, + INFURA_API_KEY_MOCK, clientIdMock, ); @@ -143,7 +144,7 @@ describe('gas utils', () => { handleFetchMock.mockResolvedValue(mockEIP1559ApiResponses[1]); const result = await fetchGasEstimates( INFURA_GAS_API_URL_MOCK, - INFURA_AUTH_TOKEN_MOCK, + INFURA_API_KEY_MOCK, ); expect(result).toMatchObject(expectedResult); }); @@ -158,7 +159,7 @@ describe('gas utils', () => { }); const result = await fetchLegacyGasPriceEstimates( INFURA_GAS_API_URL_MOCK, - INFURA_AUTH_TOKEN_MOCK, + INFURA_API_KEY_MOCK, ); expect(handleFetchMock).toHaveBeenCalledTimes(1); @@ -187,7 +188,7 @@ describe('gas utils', () => { }); const result = await fetchLegacyGasPriceEstimates( INFURA_GAS_API_URL_MOCK, - INFURA_AUTH_TOKEN_MOCK, + INFURA_API_KEY_MOCK, clientIdMock, ); diff --git a/packages/gas-fee-controller/src/gas-util.ts b/packages/gas-fee-controller/src/gas-util.ts index ca6032930db..8a7c863f2f1 100644 --- a/packages/gas-fee-controller/src/gas-util.ts +++ b/packages/gas-fee-controller/src/gas-util.ts @@ -33,15 +33,16 @@ export function normalizeGWEIDecimalNumbers(n: string | number) { * Fetch gas estimates from the given URL. * * @param url - The gas estimate URL. - * @param infuraAuthToken - The infura auth token to use for the request. + * @param infuraAPIKey - The Infura API key used for infura API requests. * @param clientId - The client ID used to identify to the API who is asking for estimates. * @returns The gas estimates. */ export async function fetchGasEstimates( url: string, - infuraAuthToken: string, + infuraAPIKey: string, clientId?: string, ): Promise { + const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); const estimates = await handleFetch(url, { headers: getHeaders(infuraAuthToken, clientId), }); @@ -88,15 +89,16 @@ export async function fetchGasEstimates( * high values from that API. * * @param url - The URL to fetch gas price estimates from. - * @param infuraAuthToken - The infura auth token to use for the request. + * @param infuraAPIKey - The Infura API key used for infura API requests. * @param clientId - The client ID used to identify to the API who is asking for estimates. * @returns The gas price estimates. */ export async function fetchLegacyGasPriceEstimates( url: string, - infuraAuthToken: string, + infuraAPIKey: string, clientId?: string, ): Promise { + const infuraAuthToken = buildInfuraAuthToken(infuraAPIKey); const result = await handleFetch(url, { referrer: url, referrerPolicy: 'no-referrer-when-downgrade', @@ -198,7 +200,7 @@ export function calculateTimeEstimate( * @param infuraAPIKey - The Infura API key. * @returns The base64 encoded auth token. */ -export function buildInfuraAuthToken(infuraAPIKey: string) { +function buildInfuraAuthToken(infuraAPIKey: string) { // We intentionally leave the password empty, as Infura does not require one return Buffer.from(`${infuraAPIKey}:`).toString('base64'); } From a8ffe8e02e9f8ea74072e290c136b269657b802f Mon Sep 17 00:00:00 2001 From: OGPoyraz Date: Tue, 26 Mar 2024 10:28:08 +0100 Subject: [PATCH 9/9] fix test --- .../src/determineGasFeeCalculations.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts b/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts index 04ac3c7700b..4d21cccbaca 100644 --- a/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts +++ b/packages/gas-fee-controller/src/determineGasFeeCalculations.test.ts @@ -40,7 +40,7 @@ const mockedFetchGasEstimatesViaEthFeeHistory = Parameters >; -const INFURA_AUTH_TOKEN_MOCK = 'test'; +const INFURA_API_KEY_MOCK = 'test'; /** * Builds mock data for the `fetchGasEstimates` function. All of the data here is filled in to make @@ -134,7 +134,7 @@ describe('determineGasFeeCalculations', () => { calculateTimeEstimate: mockedCalculateTimeEstimate, clientId: 'some-client-id', ethQuery: {}, - infuraAuthToken: INFURA_AUTH_TOKEN_MOCK, + infuraAPIKey: INFURA_API_KEY_MOCK, }; describe('when isEIP1559Compatible is true', () => {