Skip to content

Commit

Permalink
chore: migrate swaps controller to typescript (#25063)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR refactors the SwapsController class to be rewritten in
typescript. For the sake of making sure all functionality stays the
same, the tests have not been affected
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25063?quickstart=1)

## **Related issues**

Fixes:

## **Manual testing steps**

Go to swaps. Swap on the following scenarios:

ETH -> WETH
WETH -> ETH
ETH -> ERC20
ERC20 -> ETH
ERC20 -> ERC20

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
N/A
### **Before**

<!-- [screenshots/recordings] -->
N/A
### **After**

<!-- [screenshots/recordings] -->
N/A
## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
nikoferro authored Jun 21, 2024
1 parent 5ce1822 commit 533a483
Show file tree
Hide file tree
Showing 5 changed files with 932 additions and 610 deletions.
50 changes: 50 additions & 0 deletions app/scripts/controllers/swaps.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
FALLBACK_SMART_TRANSACTIONS_MAX_FEE_MULTIPLIER,
FALLBACK_SMART_TRANSACTIONS_REFRESH_TIME,
} from '../../../shared/constants/smartTransactions';
import { MINUTE } from '../../../shared/constants/time';

import type { SwapsControllerState } from './swaps.types';

// The MAX_GAS_LIMIT is a number that is higher than the maximum gas costs we have observed on any aggregator
export const MAX_GAS_LIMIT = 2500000;

// To ensure that our serves are not spammed if MetaMask is left idle, we limit the number of fetches for quotes that are made on timed intervals.
// 3 seems to be an appropriate balance of giving users the time they need when MetaMask is not left idle, and turning polling off when it is.
export const POLL_COUNT_LIMIT = 3;

// If for any reason the MetaSwap API fails to provide a refresh time,
// provide a reasonable fallback to avoid further errors
export const FALLBACK_QUOTE_REFRESH_TIME = MINUTE;

export const swapsControllerInitialState: { swapsState: SwapsControllerState } =
{
swapsState: {
quotes: {},
quotesPollingLimitEnabled: false,
fetchParams: null,
tokens: null,
tradeTxId: null,
approveTxId: null,
quotesLastFetched: null,
customMaxGas: '',
customGasPrice: null,
customMaxFeePerGas: null,
customMaxPriorityFeePerGas: null,
swapsUserFeeLevel: '',
selectedAggId: null,
customApproveTxData: '',
errorKey: '',
topAggId: null,
routeState: '',
swapsFeatureIsLive: true,
saveFetchedQuotes: false,
swapsQuoteRefreshTime: FALLBACK_QUOTE_REFRESH_TIME,
swapsQuotePrefetchingRefreshTime: FALLBACK_QUOTE_REFRESH_TIME,
swapsStxBatchStatusRefreshTime: FALLBACK_SMART_TRANSACTIONS_REFRESH_TIME,
swapsStxGetTransactionsRefreshTime:
FALLBACK_SMART_TRANSACTIONS_REFRESH_TIME,
swapsStxMaxFeeMultiplier: FALLBACK_SMART_TRANSACTIONS_MAX_FEE_MULTIPLIER,
swapsFeatureFlags: {},
},
};
29 changes: 14 additions & 15 deletions app/scripts/controllers/swaps.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
FALLBACK_SMART_TRANSACTIONS_REFRESH_TIME,
FALLBACK_SMART_TRANSACTIONS_MAX_FEE_MULTIPLIER,
} from '../../../shared/constants/smartTransactions';
import SwapsController, { utils } from './swaps';
import SwapsController from './swaps';
import { getMedianEthValueQuote } from './swaps.utils';

const MOCK_FETCH_PARAMS = {
slippage: 3,
Expand Down Expand Up @@ -179,7 +180,7 @@ describe('SwapsController', function () {
expect(swapsController.getBufferedGasLimit).toStrictEqual(
MOCK_GET_BUFFERED_GAS_LIMIT,
);
expect(swapsController.pollCount).toStrictEqual(0);
expect(swapsController._pollCount).toStrictEqual(0);
expect(swapsController.getProviderConfig).toStrictEqual(
MOCK_GET_PROVIDER_CONFIG,
);
Expand Down Expand Up @@ -716,7 +717,7 @@ describe('SwapsController', function () {

const timedoutGasReturnResult = { gasLimit: 1000000 };
const timedoutGasReturnSpy = jest
.spyOn(swapsController, 'timedoutGasReturn')
.spyOn(swapsController, '_timedoutGasReturn')
.mockReturnValue(timedoutGasReturnResult);

await swapsController.fetchAndSetQuotes(
Expand Down Expand Up @@ -820,7 +821,7 @@ describe('SwapsController', function () {

const _swapsController = getSwapsController();

const currentEthersInstance = _swapsController.ethersProvider;
const currentEthersInstance = _swapsController._ethersProvider;

// Make the network fetch error message disappear
jest
Expand All @@ -832,7 +833,7 @@ describe('SwapsController', function () {
chainId: CHAIN_IDS.GOERLI,
});

const newEthersInstance = _swapsController.ethersProvider;
const newEthersInstance = _swapsController._ethersProvider;
expect(currentEthersInstance).not.toStrictEqual(newEthersInstance);
});

Expand All @@ -845,7 +846,7 @@ describe('SwapsController', function () {
fetchTradesInfo: fetchTradesInfoStub,
getCurrentChainId: getCurrentChainIdStub,
});
const currentEthersInstance = _swapsController.ethersProvider;
const currentEthersInstance = _swapsController._ethersProvider;

// Make the network fetch error message disappear
jest.spyOn(swapsController, '_setSwapsNetworkConfig').mockReturnValue();
Expand All @@ -855,7 +856,7 @@ describe('SwapsController', function () {
chainId: CHAIN_IDS.MAINNET,
});

const newEthersInstance = _swapsController.ethersProvider;
const newEthersInstance = _swapsController._ethersProvider;
expect(currentEthersInstance).toStrictEqual(newEthersInstance);
});

Expand All @@ -870,7 +871,7 @@ describe('SwapsController', function () {
getLayer1GasFee: getLayer1GasFeeStub,
getNetworkClientId: getNetworkClientIdStub,
});
const firstEthersInstance = _swapsController.ethersProvider;
const firstEthersInstance = _swapsController._ethersProvider;
const firstEthersProviderChainId =
_swapsController._ethersProviderChainId;

Expand All @@ -884,7 +885,7 @@ describe('SwapsController', function () {
chainId: CHAIN_IDS.GOERLI,
});

const secondEthersInstance = _swapsController.ethersProvider;
const secondEthersInstance = _swapsController._ethersProvider;
const secondEthersProviderChainId =
_swapsController._ethersProviderChainId;

Expand All @@ -898,7 +899,7 @@ describe('SwapsController', function () {
chainId: CHAIN_IDS.LOCALHOST,
});

const thirdEthersInstance = _swapsController.ethersProvider;
const thirdEthersInstance = _swapsController._ethersProvider;
const thirdEthersProviderChainId =
_swapsController._ethersProviderChainId;

Expand Down Expand Up @@ -946,7 +947,7 @@ describe('SwapsController', function () {
});

it('clears polling timeout', function () {
swapsController.pollingTimeout = setTimeout(() => {
swapsController._pollingTimeout = setTimeout(() => {
throw new Error('Polling timeout not cleared');
}, POLLING_TIMEOUT);

Expand All @@ -960,7 +961,7 @@ describe('SwapsController', function () {

describe('stopPollingForQuotes', function () {
it('clears polling timeout', function () {
swapsController.pollingTimeout = setTimeout(() => {
swapsController._pollingTimeout = setTimeout(() => {
throw new Error('Polling timeout not cleared');
}, POLLING_TIMEOUT);

Expand All @@ -981,7 +982,7 @@ describe('SwapsController', function () {

describe('resetPostFetchState', function () {
it('clears polling timeout', function () {
swapsController.pollingTimeout = setTimeout(() => {
swapsController._pollingTimeout = setTimeout(() => {
throw new Error('Polling timeout not cleared');
}, POLLING_TIMEOUT);

Expand Down Expand Up @@ -1031,8 +1032,6 @@ describe('SwapsController', function () {

describe('utils', function () {
describe('getMedianEthValueQuote', function () {
const { getMedianEthValueQuote } = utils;

it('calculates median correctly with uneven sample', function () {
const expectedResult = {
ethFee: '10',
Expand Down
Loading

0 comments on commit 533a483

Please sign in to comment.