diff --git a/eslint-suppressions.json b/eslint-suppressions.json index af8709babe..de890403c3 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -2073,7 +2073,7 @@ "count": 4 }, "no-restricted-syntax": { - "count": 4 + "count": 3 } }, "packages/smart-transactions-controller/src/featureFlags/feature-flags.ts": { diff --git a/packages/smart-transactions-controller/CHANGELOG.md b/packages/smart-transactions-controller/CHANGELOG.md index 1503d45a3d..866d951c3a 100644 --- a/packages/smart-transactions-controller/CHANGELOG.md +++ b/packages/smart-transactions-controller/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump `@metamask/remote-feature-flag-controller` from `^6.0.0` to `^6.1.0` ([#9980](https://github.com/MetaMask/core/pull/9980)) +### Removed + +- Remove `API_BASE_URL` export and STX migration feature flags (`stxMigrationGetFees`, `stxMigrationSubmitTransactions`, `stxMigrationCancel`, `stxMigrationBatchStatus`) — all API calls now always route to the sentinel API ([#9996](https://github.com/MetaMask/core/pull/9996)) + ## [25.1.1] ### Changed diff --git a/packages/smart-transactions-controller/jest.config.js b/packages/smart-transactions-controller/jest.config.js index 04f7610988..492a07efd4 100644 --- a/packages/smart-transactions-controller/jest.config.js +++ b/packages/smart-transactions-controller/jest.config.js @@ -18,9 +18,9 @@ module.exports = merge(baseConfig, { coverageThreshold: { global: { branches: 87.88, - functions: 97.32, - lines: 95.35, - statements: 95.33, + functions: 97.27, + lines: 95.23, + statements: 95.22, }, }, }); diff --git a/packages/smart-transactions-controller/src/SmartTransactionsController.test.ts b/packages/smart-transactions-controller/src/SmartTransactionsController.test.ts index 5d9c0ad2f4..7ba602f597 100644 --- a/packages/smart-transactions-controller/src/SmartTransactionsController.test.ts +++ b/packages/smart-transactions-controller/src/SmartTransactionsController.test.ts @@ -32,7 +32,6 @@ import { getFakeProvider, } from '../tests/helpers.js'; import { - API_BASE_URL, SENTINEL_API_BASE_URL_MAP, SmartTransactionsTraceName, } from './constants.js'; @@ -1096,8 +1095,8 @@ describe('SmartTransactionsController', () => { const tradeTx = createUnsignedTransaction(ethereumChainIdDec); const approvalTx = createUnsignedTransaction(ethereumChainIdDec); const getFeesApiResponse = createGetFeesApiResponse(); - nock(API_BASE_URL) - .post(`/networks/${ethereumChainIdDec}/getFees`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/getFees`) .reply(200, getFeesApiResponse); const fees = await controller.getFees(tradeTx, approvalTx); @@ -1123,8 +1122,8 @@ describe('SmartTransactionsController', () => { const tradeTx = createUnsignedTransaction(ethereumChainIdDec); const approvalTx = createUnsignedTransaction(ethereumChainIdDec); const getFeesApiResponse = createGetFeesApiResponse(); - nock(API_BASE_URL) - .post(`/networks/${ethereumChainIdDec}/getFees`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/getFees`) .reply(200, getFeesApiResponse); const fees = await controller.getFees(tradeTx, approvalTx); @@ -1142,8 +1141,8 @@ describe('SmartTransactionsController', () => { createUnsignedTransaction(ethereumChainIdDec); tradeTx.nonce = undefined; const getFeesApiResponse = createGetFeesApiResponse(); - nock(API_BASE_URL) - .post(`/networks/${ethereumChainIdDec}/getFees`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/getFees`) .reply(200, getFeesApiResponse); const fees = await controller.getFees(tradeTx); @@ -1159,8 +1158,8 @@ describe('SmartTransactionsController', () => { const tradeTx = createUnsignedTransaction(sepoliaChainIdDec); const approvalTx = createUnsignedTransaction(sepoliaChainIdDec); const getFeesApiResponse = createGetFeesApiResponse(); - nock(API_BASE_URL) - .post(`/networks/${sepoliaChainIdDec}/getFees`) + nock(SENTINEL_API_BASE_URL_MAP[sepoliaChainIdDec]) + .post(`/v1/networks/${sepoliaChainIdDec}/getFees`) .reply(200, getFeesApiResponse); expect( @@ -1203,9 +1202,9 @@ describe('SmartTransactionsController', () => { const signedCanceledTransaction = createSignedCanceledTransaction(); const submitTransactionsApiResponse = createSubmitTransactionsApiResponse(); // It has uuid. - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); @@ -1248,16 +1247,16 @@ describe('SmartTransactionsController', () => { createSubmitTransactionsApiResponse(); // First API mock for the case without nonce - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); // Second API mock for the case with nonce - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); @@ -1313,9 +1312,9 @@ describe('SmartTransactionsController', () => { const signedTransaction = createSignedTransaction(); const submitTransactionsApiResponse = createSubmitTransactionsApiResponse(); - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); @@ -1368,9 +1367,9 @@ describe('SmartTransactionsController', () => { const signedTransaction = createSignedTransaction(); const submitTransactionsApiResponse = createSubmitTransactionsApiResponse(); - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); @@ -1407,9 +1406,9 @@ describe('SmartTransactionsController', () => { const signedTransaction2 = createSignedTransaction(); const submitTransactionsApiResponse = createSubmitTransactionsApiResponse(); // It has uuid. - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); @@ -1447,9 +1446,9 @@ describe('SmartTransactionsController', () => { // Verify that the request body has empty rawCancelTxs array when signedCanceledTransactions is omitted let requestBody: any; - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, (body) => { requestBody = body; return true; @@ -1485,9 +1484,9 @@ describe('SmartTransactionsController', () => { ]; let requestBody: any; - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, (body) => { requestBody = body; return true; @@ -1516,9 +1515,9 @@ describe('SmartTransactionsController', () => { createSubmitTransactionsApiResponse(); let requestBody: any; - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, (body) => { requestBody = body; return true; @@ -1544,9 +1543,9 @@ describe('SmartTransactionsController', () => { const submitTransactionsApiResponse = createSubmitTransactionsApiResponse(); - nock(API_BASE_URL) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, submitTransactionsApiResponse); @@ -1582,8 +1581,8 @@ describe('SmartTransactionsController', () => { const uuids = ['uuid1']; const pendingBatchStatusApiResponse = createPendingBatchStatusApiResponse(); - nock(API_BASE_URL) - .get(`/networks/${ethereumChainIdDec}/batchStatus?uuids=uuid1`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .get(`/v1/networks/${ethereumChainIdDec}/batchStatus?uuids=uuid1`) .reply(200, pendingBatchStatusApiResponse); const params = uuids.map((uuid) => ({ @@ -1646,8 +1645,8 @@ describe('SmartTransactionsController', () => { const uuids = ['uuid2']; const successBatchStatusApiResponse = createSuccessBatchStatusApiResponse(); - nock(API_BASE_URL) - .get(`/networks/${ethereumChainIdDec}/batchStatus?uuids=uuid2`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .get(`/v1/networks/${ethereumChainIdDec}/batchStatus?uuids=uuid2`) .reply(200, successBatchStatusApiResponse); const params = uuids.map((uuid) => ({ @@ -2150,8 +2149,8 @@ describe('SmartTransactionsController', () => { describe('cancelSmartTransaction', () => { it('sends POST call to Transactions API', async () => { await withController(async ({ controller }) => { - const apiCall = nock(API_BASE_URL) - .post(`/networks/${ethereumChainIdDec}/cancel`) + const apiCall = nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/cancel`) .reply(200, { message: 'successful' }); await controller.cancelSmartTransaction('uuid1'); @@ -2167,8 +2166,8 @@ describe('SmartTransactionsController', () => { bearerToken, }, async ({ controller }) => { - const apiCall = nock(API_BASE_URL) - .post(`/networks/${ethereumChainIdDec}/cancel`) + const apiCall = nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/cancel`) .matchHeader('Authorization', `Bearer ${bearerToken}`) .reply(200, { message: 'successful' }); @@ -2414,7 +2413,7 @@ describe('SmartTransactionsController', () => { expect(handleFetchSpy).toHaveBeenNthCalledWith( 1, - `${API_BASE_URL}/networks/${convertHexToDecimal( + `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${convertHexToDecimal( ChainId.mainnet, )}/batchStatus?uuids=uuid1`, fetchHeaders, @@ -2424,7 +2423,7 @@ describe('SmartTransactionsController', () => { expect(handleFetchSpy).toHaveBeenNthCalledWith( 2, - `${API_BASE_URL}/networks/${convertHexToDecimal( + `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${convertHexToDecimal( ChainId.mainnet, )}/batchStatus?uuids=uuid1`, fetchHeaders, @@ -2435,7 +2434,7 @@ describe('SmartTransactionsController', () => { expect(handleFetchSpy).toHaveBeenNthCalledWith( 3, - `${API_BASE_URL}/networks/${convertHexToDecimal( + `${SENTINEL_API_BASE_URL_MAP[sepoliaChainIdDec]}/v1/networks/${convertHexToDecimal( ChainId.sepolia, )}/batchStatus?uuids=uuid2`, fetchHeaders, @@ -2445,7 +2444,7 @@ describe('SmartTransactionsController', () => { expect(handleFetchSpy).toHaveBeenNthCalledWith( 5, - `${API_BASE_URL}/networks/${convertHexToDecimal( + `${SENTINEL_API_BASE_URL_MAP[sepoliaChainIdDec]}/v1/networks/${convertHexToDecimal( ChainId.sepolia, )}/batchStatus?uuids=uuid2`, fetchHeaders, @@ -2462,7 +2461,7 @@ describe('SmartTransactionsController', () => { // check that the mainnet polling has stopped while the sepolia polling continues expect(handleFetchSpy).toHaveBeenNthCalledWith( 6, - `${API_BASE_URL}/networks/${convertHexToDecimal( + `${SENTINEL_API_BASE_URL_MAP[sepoliaChainIdDec]}/v1/networks/${convertHexToDecimal( ChainId.sepolia, )}/batchStatus?uuids=uuid2`, fetchHeaders, @@ -2470,7 +2469,7 @@ describe('SmartTransactionsController', () => { expect(handleFetchSpy).toHaveBeenNthCalledWith( 7, - `${API_BASE_URL}/networks/${convertHexToDecimal( + `${SENTINEL_API_BASE_URL_MAP[sepoliaChainIdDec]}/v1/networks/${convertHexToDecimal( ChainId.sepolia, )}/batchStatus?uuids=uuid2`, fetchHeaders, @@ -2897,9 +2896,8 @@ describe('SmartTransactionsController', () => { }, }, async ({ controller }) => { - const apiUrl = API_BASE_URL; - nock(apiUrl) - .post(`/networks/${ethereumChainIdDec}/getFees`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/getFees`) .reply(200, createGetFeesApiResponse()); const tradeTx = createUnsignedTransaction(ethereumChainIdDec); @@ -2923,10 +2921,9 @@ describe('SmartTransactionsController', () => { }, }, async ({ controller }) => { - const apiUrl = API_BASE_URL; - nock(apiUrl) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) .post( - `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ) .reply(200, createSubmitTransactionsApiResponse()); @@ -2958,9 +2955,8 @@ describe('SmartTransactionsController', () => { }, }, async ({ controller }) => { - const apiUrl = API_BASE_URL; - nock(apiUrl) - .post(`/networks/${ethereumChainIdDec}/cancel`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/cancel`) .reply(200, {}); await controller.cancelSmartTransaction('uuid1'); @@ -3007,10 +3003,9 @@ describe('SmartTransactionsController', () => { }, }, async ({ controller }) => { - const apiUrl = API_BASE_URL; const expectedResponse = createGetFeesApiResponse(); - nock(apiUrl) - .post(`/networks/${ethereumChainIdDec}/getFees`) + nock(SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]) + .post(`/v1/networks/${ethereumChainIdDec}/getFees`) .reply(200, expectedResponse); const tradeTx = createUnsignedTransaction(ethereumChainIdDec); diff --git a/packages/smart-transactions-controller/src/SmartTransactionsController.ts b/packages/smart-transactions-controller/src/SmartTransactionsController.ts index c5e107f826..d726e1bc85 100644 --- a/packages/smart-transactions-controller/src/SmartTransactionsController.ts +++ b/packages/smart-transactions-controller/src/SmartTransactionsController.ts @@ -37,7 +37,6 @@ import { BigNumber } from 'bignumber.js'; import cloneDeep from 'lodash/cloneDeep'; import { - API_BASE_URL, DEFAULT_DISABLED_SMART_TRANSACTIONS_FEATURE_FLAGS, MetaMetricsEventCategory, MetaMetricsEventName, @@ -288,14 +287,6 @@ export class SmartTransactionsController extends StaticIntervalPollingController readonly #trace: TraceCallback; - #isStxMigrationFlagEnabled(flagName: string): boolean { - const flag = this.messenger.call('RemoteFeatureFlagController:getState') - ?.remoteFeatureFlags?.[flagName]; - return Boolean( - flag && typeof flag === 'object' && 'value' in flag && flag.value, - ); - } - /** * Validates the smart transactions feature flags from the remote feature flag controller * and reports any validation errors to Sentry via ErrorReportingService. @@ -332,11 +323,9 @@ export class SmartTransactionsController extends StaticIntervalPollingController ...(this.#clientId && { 'X-Client-Id': this.#clientId }), }; - const urlMatches = - request.startsWith(API_BASE_URL) || - Object.values(SENTINEL_API_BASE_URL_MAP).some((baseUrl) => - request.startsWith(baseUrl), - ); + const urlMatches = Object.values(SENTINEL_API_BASE_URL_MAP).some( + (baseUrl) => request.startsWith(baseUrl), + ); if (urlMatches) { const token = await this.messenger.call( @@ -826,14 +815,7 @@ export class SmartTransactionsController extends StaticIntervalPollingController }); // Construct the URL and fetch the data - const useSentinelForBatchStatus = this.#isStxMigrationFlagEnabled( - 'stxMigrationBatchStatus', - ); - const url = `${getAPIRequestURL( - APIType.BATCH_STATUS, - chainId, - useSentinelForBatchStatus, - )}?${params.toString()}`; + const url = `${getAPIRequestURL(APIType.BATCH_STATUS, chainId)}?${params.toString()}`; const data = (await this.#fetch(url)) as Record< string, SmartTransactionsStatus @@ -924,21 +906,15 @@ export class SmartTransactionsController extends StaticIntervalPollingController ); } transactions.push(unsignedTradeTransactionWithNonce); - const useSentinelForGetFees = this.#isStxMigrationFlagEnabled( - 'stxMigrationGetFees', - ); const data = await this.#trace( { name: SmartTransactionsTraceName.GetFees }, async () => - await this.#fetch( - getAPIRequestURL(APIType.GET_FEES, chainId, useSentinelForGetFees), - { - method: 'POST', - body: JSON.stringify({ - txs: transactions, - }), - }, - ), + await this.#fetch(getAPIRequestURL(APIType.GET_FEES, chainId), { + method: 'POST', + body: JSON.stringify({ + txs: transactions, + }), + }), ); let approvalTxFees: IndividualTxFees | null; let tradeTxFees: IndividualTxFees | null; @@ -995,18 +971,11 @@ export class SmartTransactionsController extends StaticIntervalPollingController const ethQuery = this.#getEthQuery({ networkClientId: selectedNetworkClientId, }); - const useSentinelForSubmitTransactions = this.#isStxMigrationFlagEnabled( - 'stxMigrationSubmitTransactions', - ); const data = await this.#trace( { name: SmartTransactionsTraceName.SubmitTransactions }, async () => await this.#fetch( - getAPIRequestURL( - APIType.SUBMIT_TRANSACTIONS, - chainId, - useSentinelForSubmitTransactions, - ), + getAPIRequestURL(APIType.SUBMIT_TRANSACTIONS, chainId), { method: 'POST', body: JSON.stringify({ @@ -1154,18 +1123,13 @@ export class SmartTransactionsController extends StaticIntervalPollingController } = {}, ): Promise { const chainId = this.#getChainId({ networkClientId }); - const useSentinelForCancel = - this.#isStxMigrationFlagEnabled('stxMigrationCancel'); await this.#trace( { name: SmartTransactionsTraceName.CancelTransaction }, async () => - await this.#fetch( - getAPIRequestURL(APIType.CANCEL, chainId, useSentinelForCancel), - { - method: 'POST', - body: JSON.stringify({ uuid }), - }, - ), + await this.#fetch(getAPIRequestURL(APIType.CANCEL, chainId), { + method: 'POST', + body: JSON.stringify({ uuid }), + }), ); } diff --git a/packages/smart-transactions-controller/src/constants.ts b/packages/smart-transactions-controller/src/constants.ts index 43360aecd8..0d11d7bf01 100644 --- a/packages/smart-transactions-controller/src/constants.ts +++ b/packages/smart-transactions-controller/src/constants.ts @@ -1,5 +1,3 @@ -export const API_BASE_URL = 'https://transaction.api.cx.metamask.io'; - type SentinelApiBaseUrlMap = { [key: number]: string; }; diff --git a/packages/smart-transactions-controller/src/utils.test.ts b/packages/smart-transactions-controller/src/utils.test.ts index 31edd698ca..7d2b39c32f 100644 --- a/packages/smart-transactions-controller/src/utils.test.ts +++ b/packages/smart-transactions-controller/src/utils.test.ts @@ -5,7 +5,7 @@ import { TransactionStatus } from '@metamask/transaction-controller'; import type { TransactionMeta } from '@metamask/transaction-controller'; import packageJson from '../package.json'; -import { API_BASE_URL, SENTINEL_API_BASE_URL_MAP } from './constants.js'; +import { SENTINEL_API_BASE_URL_MAP } from './constants.js'; import { SmartTransactionMinedTx, APIType, @@ -49,44 +49,46 @@ describe('src/utils.js', () => { const ethereumChainIdDec = parseInt(ChainId.mainnet, 16); const ethSepoliaChainIdDec = parseInt(ChainId.sepolia, 16); - it('returns a URL for getting transactions', () => { + it('returns a sentinel URL for getting fees', () => { expect(utils.getAPIRequestURL(APIType.GET_FEES, ChainId.mainnet)).toBe( - `${API_BASE_URL}/networks/${ethereumChainIdDec}/getFees`, + `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/getFees`, ); }); - it('returns correct URL for ESTIMATE_GAS', () => { + it('returns correct sentinel URL for ESTIMATE_GAS', () => { const chainId = '0x1'; // Mainnet in hex - const expectedUrl = `${API_BASE_URL}/networks/1/estimateGas`; + const expectedUrl = `${SENTINEL_API_BASE_URL_MAP[1]}/v1/networks/1/estimateGas`; const result = utils.getAPIRequestURL(APIType.ESTIMATE_GAS, chainId); expect(result).toBe(expectedUrl); }); it('converts hex chainId to decimal for ESTIMATE_GAS', () => { const chainId = '0x89'; // Polygon in hex (137 in decimal) - const expectedUrl = `${API_BASE_URL}/networks/137/estimateGas`; + const expectedUrl = `${SENTINEL_API_BASE_URL_MAP[137]}/v1/networks/137/estimateGas`; const result = utils.getAPIRequestURL(APIType.ESTIMATE_GAS, chainId); expect(result).toBe(expectedUrl); }); - it('returns a URL for submitting transactions', () => { + it('returns a sentinel URL for submitting transactions', () => { expect( utils.getAPIRequestURL(APIType.SUBMIT_TRANSACTIONS, ChainId.mainnet), ).toBe( - `${API_BASE_URL}/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, ); }); - it('returns a URL for transaction cancelation', () => { + it('returns a sentinel URL for transaction cancellation', () => { expect(utils.getAPIRequestURL(APIType.CANCEL, ChainId.mainnet)).toBe( - `${API_BASE_URL}/networks/${ethereumChainIdDec}/cancel`, + `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/cancel`, ); }); - it('returns a URL for checking a smart transactions status', () => { + it('returns a sentinel URL for checking smart transaction status', () => { expect( utils.getAPIRequestURL(APIType.BATCH_STATUS, ChainId.mainnet), - ).toBe(`${API_BASE_URL}/networks/${ethereumChainIdDec}/batchStatus`); + ).toBe( + `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/batchStatus`, + ); }); it('returns a URL for smart transactions API liveness on ETH Mainnet', () => { @@ -117,121 +119,12 @@ describe('src/utils.js', () => { ); }); - // Sentinel routing via useSentinel flag - describe('GET_FEES sentinel routing', () => { - it('returns a sentinel URL when useSentinel is true and chain is in SENTINEL_API_BASE_URL_MAP', () => { - expect( - utils.getAPIRequestURL(APIType.GET_FEES, ChainId.mainnet, true), - ).toBe( - `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/getFees`, - ); - }); - - it('returns the API_BASE_URL when useSentinel is false', () => { - expect( - utils.getAPIRequestURL(APIType.GET_FEES, ChainId.mainnet, false), - ).toBe(`${API_BASE_URL}/networks/${ethereumChainIdDec}/getFees`); - }); - - it('returns the API_BASE_URL when useSentinel is true but chain is not in SENTINEL_API_BASE_URL_MAP', () => { - const unsupportedChainId = '0x539'; // 1337 — local dev chain, not in map - const chainIdDec = parseInt(unsupportedChainId, 16); - expect( - utils.getAPIRequestURL(APIType.GET_FEES, unsupportedChainId, true), - ).toBe(`${API_BASE_URL}/networks/${chainIdDec}/getFees`); - }); - }); - - describe('SUBMIT_TRANSACTIONS sentinel routing', () => { - it('returns a sentinel URL when useSentinel is true and chain is in SENTINEL_API_BASE_URL_MAP', () => { - expect( - utils.getAPIRequestURL( - APIType.SUBMIT_TRANSACTIONS, - ChainId.mainnet, - true, - ), - ).toBe( - `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, - ); - }); - - it('returns the API_BASE_URL when useSentinel is false', () => { - expect( - utils.getAPIRequestURL( - APIType.SUBMIT_TRANSACTIONS, - ChainId.mainnet, - false, - ), - ).toBe( - `${API_BASE_URL}/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, - ); - }); - - it('returns the API_BASE_URL when useSentinel is true but chain is not in SENTINEL_API_BASE_URL_MAP', () => { - const unsupportedChainId = '0x539'; - const chainIdDec = parseInt(unsupportedChainId, 16); - expect( - utils.getAPIRequestURL( - APIType.SUBMIT_TRANSACTIONS, - unsupportedChainId, - true, - ), - ).toBe( - `${API_BASE_URL}/networks/${chainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, - ); - }); - }); - - describe('CANCEL sentinel routing', () => { - it('returns a sentinel URL when useSentinel is true and chain is in SENTINEL_API_BASE_URL_MAP', () => { - expect( - utils.getAPIRequestURL(APIType.CANCEL, ChainId.mainnet, true), - ).toBe( - `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/cancel`, - ); - }); - - it('returns the API_BASE_URL when useSentinel is false', () => { - expect( - utils.getAPIRequestURL(APIType.CANCEL, ChainId.mainnet, false), - ).toBe(`${API_BASE_URL}/networks/${ethereumChainIdDec}/cancel`); - }); - - it('returns the API_BASE_URL when useSentinel is true but chain is not in SENTINEL_API_BASE_URL_MAP', () => { - const unsupportedChainId = '0x539'; - const chainIdDec = parseInt(unsupportedChainId, 16); - expect( - utils.getAPIRequestURL(APIType.CANCEL, unsupportedChainId, true), - ).toBe(`${API_BASE_URL}/networks/${chainIdDec}/cancel`); - }); - }); - - describe('BATCH_STATUS sentinel routing', () => { - it('returns a sentinel URL when useSentinel is true and chain is in SENTINEL_API_BASE_URL_MAP', () => { - expect( - utils.getAPIRequestURL(APIType.BATCH_STATUS, ChainId.mainnet, true), - ).toBe( - `${SENTINEL_API_BASE_URL_MAP[ethereumChainIdDec]}/v1/networks/${ethereumChainIdDec}/batchStatus`, - ); - }); - - it('returns the API_BASE_URL when useSentinel is false', () => { - expect( - utils.getAPIRequestURL(APIType.BATCH_STATUS, ChainId.mainnet, false), - ).toBe(`${API_BASE_URL}/networks/${ethereumChainIdDec}/batchStatus`); - }); - - it('returns the API_BASE_URL when useSentinel is true but chain is not in SENTINEL_API_BASE_URL_MAP', () => { - const unsupportedChainId = '0x539'; - const chainIdDec = parseInt(unsupportedChainId, 16); - expect( - utils.getAPIRequestURL( - APIType.BATCH_STATUS, - unsupportedChainId, - true, - ), - ).toBe(`${API_BASE_URL}/networks/${chainIdDec}/batchStatus`); - }); + it('throws when chain is not in SENTINEL_API_BASE_URL_MAP', () => { + const unsupportedChainId = '0x539'; // 1337 — local dev chain + const chainIdDec = parseInt(unsupportedChainId, 16); + expect(() => + utils.getAPIRequestURL(APIType.GET_FEES, unsupportedChainId), + ).toThrow(`Chain ${chainIdDec} is not supported`); }); }); diff --git a/packages/smart-transactions-controller/src/utils.ts b/packages/smart-transactions-controller/src/utils.ts index def15a7489..a3d9a266ef 100644 --- a/packages/smart-transactions-controller/src/utils.ts +++ b/packages/smart-transactions-controller/src/utils.ts @@ -14,7 +14,7 @@ import _ from 'lodash'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import packageJson from '../package.json'; -import { API_BASE_URL, SENTINEL_API_BASE_URL_MAP } from './constants.js'; +import { SENTINEL_API_BASE_URL_MAP } from './constants.js'; import type { SmartTransaction, SmartTransactionsStatus, @@ -37,44 +37,32 @@ export const isSmartTransactionStatusResolved = ( stxStatus: SmartTransactionsStatus | string, ) => stxStatus === 'uuid_not_found'; -// TODO use actual url once API is defined -export function getAPIRequestURL( - apiType: APIType, - chainId: string, - useSentinel = false, -): string { +export function getAPIRequestURL(apiType: APIType, chainId: string): string { const chainIdDec = parseInt(chainId, 16); + + if (!SENTINEL_API_BASE_URL_MAP[chainIdDec]) { + throw new Error(`Chain ${chainIdDec} is not supported`); + } + switch (apiType) { case APIType.GET_FEES: { - if (useSentinel && SENTINEL_API_BASE_URL_MAP[chainIdDec]) { - return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/getFees`; - } - return `${API_BASE_URL}/networks/${chainIdDec}/getFees`; + return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/getFees`; } case APIType.ESTIMATE_GAS: { - return `${API_BASE_URL}/networks/${chainIdDec}/estimateGas`; + return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/estimateGas`; } case APIType.SUBMIT_TRANSACTIONS: { - if (useSentinel && SENTINEL_API_BASE_URL_MAP[chainIdDec]) { - return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`; - } - return `${API_BASE_URL}/networks/${chainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`; + return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`; } case APIType.CANCEL: { - if (useSentinel && SENTINEL_API_BASE_URL_MAP[chainIdDec]) { - return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/cancel`; - } - return `${API_BASE_URL}/networks/${chainIdDec}/cancel`; + return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/cancel`; } case APIType.BATCH_STATUS: { - if (useSentinel && SENTINEL_API_BASE_URL_MAP[chainIdDec]) { - return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/batchStatus`; - } - return `${API_BASE_URL}/networks/${chainIdDec}/batchStatus`; + return `${SENTINEL_API_BASE_URL_MAP[chainIdDec]}/v1/networks/${chainIdDec}/batchStatus`; } case APIType.LIVENESS: {