Skip to content
21 changes: 14 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,26 @@
"build": "tsc --project ."
},
"peerDependencies": {
"@metamask/composable-controller": "^1.0.2",
"@metamask/composable-controller": "^4.0.0",
"@metamask/network-controller": "^3.0.0"
},
"devDependencies": {
"@babel/runtime": "^7.0.0",
"@lavamoat/allow-scripts": "^3.0.0",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/composable-controller": "^1.0.2",
"@metamask/composable-controller": "^4.0.0",
"@metamask/eslint-config": "^12.2.0",
"@metamask/eslint-config-jest": "^12.1.0",
"@metamask/eslint-config-nodejs": "^12.1.0",
"@metamask/eslint-config-typescript": "^12.1.0",
"@metamask/transaction-controller": "^3.0.0",
"@metamask/approval-controller": "^5.1.1",
"@metamask/network-controller": "^17.1.0",
"@metamask/transaction-controller": "^19.0.1",
"@types/jest": "^26.0.22",
"@types/node": "^20.10.4",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"babel-runtime": "^6.26.0",
"eslint": "^8.55.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "~2.26.0",
Expand All @@ -66,10 +70,10 @@
"typescript": "^5.1.0"
},
"dependencies": {
"@metamask/base-controller": "^1.1.2",
"@metamask/base-controller": "^4.1.1",
"@metamask/controller-utils": "^8.0.2",
"@metamask/eth-query": "^4.0.0",
"@metamask/gas-fee-controller": "^3.0.0",
"@metamask/gas-fee-controller": "^12.0.0",
"@metamask/utils": "^8.3.0",
"abort-controller": "^3.0.0",
"async-mutex": "^0.4.1",
Expand All @@ -81,9 +85,12 @@
"lavamoat": {
"allowScripts": {
"@lavamoat/preinstall-always-fail": false,
"@metamask/gas-fee-controller>babel-runtime>core-js": false,
"@metamask/gas-fee-controller>ethereumjs-util>ethereum-cryptography>keccak": false,
"@metamask/gas-fee-controller>ethereumjs-util>ethereum-cryptography>secp256k1": false
"@metamask/gas-fee-controller>ethereumjs-util>ethereum-cryptography>secp256k1": false,
"@metamask/transaction-controller>babel-runtime>core-js": false,
"babel-runtime>core-js": false,
"@metamask/controller-utils>ethereumjs-util>ethereum-cryptography>keccak": false,
"@metamask/controller-utils>ethereumjs-util>ethereum-cryptography>secp256k1": false
}
}
}
104 changes: 69 additions & 35 deletions src/SwapsController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,37 +404,47 @@ describe('SwapsController', () => {

describe('tokens cache', () => {
it('should fetch tokens when no tokens in state', async () => {
swapsController.state.tokens = null;
swapsController.update({
tokens: [],
});
await swapsController.fetchTokenWithCache();
expect(swapsUtilFetchTokens).toHaveBeenCalled();
});

it('should fetch tokens when last fetched is 0', async () => {
swapsController.state.tokens = [];
swapsController.state.tokensLastFetched = 0;
swapsController.update({
tokens: [],
tokensLastFetched: 0,
});
await swapsController.fetchTokenWithCache();
expect(swapsUtilFetchTokens).toHaveBeenCalled();
});

it('should fetch tokens when last fetched is over threshold', async () => {
const threshold = 5000;
swapsController.configure({ fetchTokensThreshold: threshold });
swapsController.state.tokens = [];
swapsController.state.tokensLastFetched = Date.now() - threshold - 1;
swapsController.update({
tokens: [],
tokensLastFetched: Date.now() - threshold - 1,
});
await swapsController.fetchTokenWithCache();
expect(swapsUtilFetchTokens).toHaveBeenCalled();
});

it('should not fetch tokens when no threshold reached', async () => {
swapsController.state.tokens = [];
swapsController.state.tokensLastFetched = Date.now();
swapsController.update({
tokens: [],
tokensLastFetched: Date.now(),
});
await swapsController.fetchTokenWithCache();
expect(swapsUtilFetchTokens).not.toHaveBeenCalled();
});

it('should not fetch tokens when no threshold reached or tokens are available', async () => {
swapsController.state.tokens = [];
swapsController.state.tokensLastFetched = Date.now();
swapsController.update({
tokens: [],
tokensLastFetched: Date.now(),
});
await swapsController.fetchTokenWithCache();
expect(swapsUtilFetchTokens).not.toHaveBeenCalled();
});
Expand All @@ -445,8 +455,10 @@ describe('SwapsController', () => {
});
const threshold = 5000;
swapsController.configure({ fetchTokensThreshold: threshold });
swapsController.state.tokens = [];
swapsController.state.tokensLastFetched = Date.now() - threshold - 1;
swapsController.update({
tokens: [],
tokensLastFetched: Date.now() - threshold - 1,
});
await swapsController.fetchTokenWithCache();
expect(swapsUtilFetchTokens).toHaveBeenCalled();
expect(swapsController.state.tokensLastFetched).toBe(0);
Expand All @@ -466,37 +478,47 @@ describe('SwapsController', () => {

describe('top assets cache', () => {
it('should fetch top assets when no top assets in state', async () => {
swapsController.state.topAssets = null;
swapsController.update({
topAssets: null,
});
await swapsController.fetchTopAssetsWithCache();
expect(swapsUtilFetchTopAssets).toHaveBeenCalled();
});

it('should fetch top assets when last fetched is 0', async () => {
swapsController.state.topAssets = [];
swapsController.state.topAssetsLastFetched = 0;
swapsController.update({
topAssets: [],
topAssetsLastFetched: 0,
});
await swapsController.fetchTopAssetsWithCache();
expect(swapsUtilFetchTopAssets).toHaveBeenCalled();
});

it('should fetch top assets when last fetched is over threshold', async () => {
const threshold = 5000;
swapsController.configure({ fetchTopAssetsThreshold: threshold });
swapsController.state.topAssets = [];
swapsController.state.topAssetsLastFetched = Date.now() - threshold - 1;
swapsController.update({
topAssets: [],
topAssetsLastFetched: Date.now() - threshold - 1,
});
await swapsController.fetchTopAssetsWithCache();
expect(swapsUtilFetchTopAssets).toHaveBeenCalled();
});

it('should not fetch top assets when no threshold reached', async () => {
swapsController.state.topAssets = [];
swapsController.state.topAssetsLastFetched = Date.now();
swapsController.update({
topAssets: [],
topAssetsLastFetched: Date.now(),
});
await swapsController.fetchTopAssetsWithCache();
expect(swapsUtilFetchTopAssets).not.toHaveBeenCalled();
});

it('should not fetch top assets when no threshold reached or tokens are available', async () => {
swapsController.state.topAssets = [];
swapsController.state.topAssetsLastFetched = Date.now();
swapsController.update({
topAssets: [],
topAssetsLastFetched: Date.now(),
});
await swapsController.fetchTopAssetsWithCache();
expect(swapsUtilFetchTopAssets).not.toHaveBeenCalled();
});
Expand All @@ -507,8 +529,10 @@ describe('SwapsController', () => {
});
const threshold = 5000;
swapsController.configure({ fetchTopAssetsThreshold: threshold });
swapsController.state.topAssets = [];
swapsController.state.topAssetsLastFetched = Date.now() - threshold - 1;
swapsController.update({
topAssets: [],
topAssetsLastFetched: Date.now() - threshold - 1,
});
await swapsController.fetchTopAssetsWithCache();
expect(swapsUtilFetchTopAssets).toHaveBeenCalled();
expect(swapsController.state.topAssetsLastFetched).toBe(0);
Expand All @@ -517,14 +541,18 @@ describe('SwapsController', () => {

describe('aggregator metadata cache', () => {
it('should fetch aggregator metadata when no aggregator metadata in state', async () => {
swapsController.state.aggregatorMetadata = null;
swapsController.update({
aggregatorMetadata: null,
});
await swapsController.fetchAggregatorMetadataWithCache();
expect(swapsUtilFetchAggregatorMetadata).toHaveBeenCalled();
});

it('should fetch aggregator metadata when last fetched is 0', async () => {
swapsController.state.aggregatorMetadata = {};
swapsController.state.aggregatorMetadataLastFetched = 0;
swapsController.update({
aggregatorMetadata: {},
aggregatorMetadataLastFetched: 0,
});
await swapsController.fetchAggregatorMetadataWithCache();
expect(swapsUtilFetchAggregatorMetadata).toHaveBeenCalled();
});
Expand All @@ -534,23 +562,28 @@ describe('SwapsController', () => {
swapsController.configure({
fetchAggregatorMetadataThreshold: threshold,
});
swapsController.state.aggregatorMetadata = {};
swapsController.state.aggregatorMetadataLastFetched =
Date.now() - threshold - 1;
swapsController.update({
aggregatorMetadata: {},
aggregatorMetadataLastFetched: Date.now() - threshold - 1,
});
await swapsController.fetchAggregatorMetadataWithCache();
expect(swapsUtilFetchAggregatorMetadata).toHaveBeenCalled();
});

it('should not fetch aggregator metadata when no threshold reached', async () => {
swapsController.state.aggregatorMetadata = {};
swapsController.state.aggregatorMetadataLastFetched = Date.now();
swapsController.update({
aggregatorMetadata: {},
aggregatorMetadataLastFetched: Date.now(),
});
await swapsController.fetchAggregatorMetadataWithCache();
expect(swapsUtilFetchAggregatorMetadata).not.toHaveBeenCalled();
});

it('should not fetch aggregator metadata when no threshold reached or tokens are available', async () => {
swapsController.state.aggregatorMetadata = {};
swapsController.state.aggregatorMetadataLastFetched = Date.now();
swapsController.update({
aggregatorMetadata: {},
aggregatorMetadataLastFetched: Date.now(),
});
await swapsController.fetchAggregatorMetadataWithCache();
expect(swapsUtilFetchAggregatorMetadata).not.toHaveBeenCalled();
});
Expand All @@ -563,9 +596,10 @@ describe('SwapsController', () => {
swapsController.configure({
fetchAggregatorMetadataThreshold: threshold,
});
swapsController.state.aggregatorMetadata = {};
swapsController.state.aggregatorMetadataLastFetched =
Date.now() - threshold - 1;
swapsController.update({
aggregatorMetadata: {},
aggregatorMetadataLastFetched: Date.now() - threshold - 1,
});
await swapsController.fetchAggregatorMetadataWithCache();
expect(swapsUtilFetchAggregatorMetadata).toHaveBeenCalled();
expect(swapsController.state.aggregatorMetadataLastFetched).toBe(0);
Expand Down
16 changes: 8 additions & 8 deletions src/SwapsController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BaseConfig, BaseState } from '@metamask/base-controller';
import { BaseController } from '@metamask/base-controller';
import { BaseControllerV1 } from '@metamask/base-controller';
import {
gweiDecToWEIBN,
query,
Expand All @@ -16,7 +16,7 @@ import type {
GasFeeStateLegacy,
} from '@metamask/gas-fee-controller';
import { GAS_ESTIMATE_TYPES } from '@metamask/gas-fee-controller';
import type { Transaction } from '@metamask/transaction-controller';
import type { TransactionParams } from '@metamask/transaction-controller';
import type { Hex } from '@metamask/utils';
import { Mutex } from 'async-mutex';
import { BigNumber } from 'bignumber.js';
Expand Down Expand Up @@ -160,7 +160,7 @@ export type SwapsState = {
topAggId: null | string;
isInPolling: boolean;
pollingCyclesLeft: number;
approvalTransaction: Transaction | null;
approvalTransaction: TransactionParams | null;
quoteValues: { [key: string]: QuoteValues } | null;
quoteRefreshSeconds: number | null;
usedGasEstimate: EthGasPriceEstimate | GasFeeEstimates | null;
Expand All @@ -177,7 +177,7 @@ export type SwapsState = {
type SwapsNextState = {
quotes: { [key: string]: Quote };
quotesLastFetched: null | number;
approvalTransaction: Transaction | null;
approvalTransaction: TransactionParams | null;
topAggId: null | string;
topAggSavings?: QuoteSavings | null;
quoteValues: { [key: string]: QuoteValues } | null;
Expand Down Expand Up @@ -214,7 +214,7 @@ function getNewChainCache(
};
}

export default class SwapsController extends BaseController<
export default class SwapsController extends BaseControllerV1<
SwapsConfig,
SwapsState
> {
Expand All @@ -237,7 +237,7 @@ export default class SwapsController extends BaseController<
private readonly fetchEstimatedMultiLayerL1Fee?: (
eth: any,
options: {
txParams: Transaction;
txParams: TransactionParams;
chainId: Hex;
},
) => Promise<string | undefined>;
Expand Down Expand Up @@ -563,7 +563,7 @@ export default class SwapsController extends BaseController<

/* istanbul ignore next */
private async timedoutGasReturn(
tradeTxParams: Transaction | null,
tradeTxParams: TransactionParams | null,
): Promise<{ gas: string | null }> {
if (!tradeTxParams) {
return { gas: null };
Expand Down Expand Up @@ -825,7 +825,7 @@ export default class SwapsController extends BaseController<
fetchEstimatedMultiLayerL1Fee?: (
eth: EthQuery,
options: {
txParams: Transaction;
txParams: TransactionParams;
chainId: Hex;
},
) => Promise<string | undefined>;
Expand Down
4 changes: 2 additions & 2 deletions src/swapsInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Transaction } from '@metamask/transaction-controller';
import type { TransactionParams } from '@metamask/transaction-controller';
import type { BigNumber } from 'bignumber.js';

export enum APIType {
Expand Down Expand Up @@ -116,7 +116,7 @@ export type APIAggregatorMetadata = {

type QuoteTransaction = {
value: string;
} & Transaction;
} & TransactionParams;

/**
* Savings of a quote
Expand Down
Loading