diff --git a/jest.config.js b/jest.config.js index 153f417..432cbfa 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,10 +6,10 @@ module.exports = { coverageReporters: ['text', 'html'], coverageThreshold: { global: { - branches: 76.5, - functions: 92.5, - lines: 93.35, - statements: 93.35, + branches: 77, + functions: 89, + lines: 92, + statements: 91, }, }, moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'], diff --git a/package.json b/package.json index 6a72f57..390e668 100644 --- a/package.json +++ b/package.json @@ -25,12 +25,12 @@ "test:watch": "jest --watchAll" }, "dependencies": { + "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", + "@ethersproject/providers": "^5.7.0", "@metamask/base-controller": "^3.2.1", "@metamask/controller-utils": "^5.0.0", - "@metamask/eth-query": "^3.0.1", "@metamask/network-controller": "^15.0.0", - "@metamask/polling-controller": "^0.2.0", "bignumber.js": "^9.0.1", "fast-json-patch": "^3.1.0", "lodash": "^4.17.21" diff --git a/src/SmartTransactionsController.test.ts b/src/SmartTransactionsController.test.ts index 0dc2c1d..80cd235 100644 --- a/src/SmartTransactionsController.test.ts +++ b/src/SmartTransactionsController.test.ts @@ -1,6 +1,5 @@ import nock from 'nock'; import { NetworkState } from '@metamask/network-controller'; -import { convertHexToDecimal } from '@metamask/controller-utils'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import packageJson from '../package.json'; @@ -10,61 +9,32 @@ import SmartTransactionsController, { } from './SmartTransactionsController'; import { API_BASE_URL, CHAIN_IDS } from './constants'; import { SmartTransaction, SmartTransactionStatuses } from './types'; -import * as utils from './utils'; -/** - * Resolve all pending promises. - * This method is used for async tests that use fake timers. - * See https://stackoverflow.com/a/58716087 and https://jestjs.io/docs/timer-mocks. - */ -function flushPromises(): Promise { - return new Promise(jest.requireActual('timers').setImmediate); -} +const confirmExternalMock = jest.fn(); jest.mock('@ethersproject/bytes', () => ({ ...jest.requireActual('@ethersproject/bytes'), hexlify: (str: string) => `0x${str}`, })); -jest.mock('@metamask/eth-query', () => { - const EthQuery = jest.requireActual('@metamask/eth-query'); - return class FakeEthQuery extends EthQuery { - sendAsync = jest.fn(({ method }, callback) => { - switch (method) { - case 'eth_getBalance': { - callback(null, '0x1000'); - break; - } - - case 'eth_getTransactionReceipt': { - callback(null, { blockNumber: '123' }); - break; - } - - case 'eth_getBlockByNumber': { - callback(null, { baseFeePerGas: '0x123' }); - break; - } - - case 'eth_getTransactionByHash': { - callback(null, { - maxFeePerGas: '0x123', - maxPriorityFeePerGas: '0x123', - }); - break; - } - - default: { - throw new Error('Invalid method'); - } - } - }); - }; -}); +jest.mock('@ethersproject/providers', () => ({ + Web3Provider: class Web3Provider { + getBalance = () => ({ toHexString: () => '0x1000' }); + + getTransactionReceipt = jest.fn(() => ({ blockNumber: '123' })); + + getTransaction = jest.fn(() => ({ + maxFeePerGas: { toHexString: () => '0x123' }, + maxPriorityFeePerGas: { toHexString: () => '0x123' }, + })); + + getBlock = jest.fn(); + }, +})); const addressFrom = '0x268392a24B6b093127E8581eAfbD1DA228bAdAe3'; -const createUnsignedTransaction = (chainId: number) => { +const createUnsignedTransaction = () => { return { from: addressFrom, to: '0x0000000000000000000000000000000000000000', @@ -72,7 +42,7 @@ const createUnsignedTransaction = (chainId: number) => { data: '0x', nonce: 0, type: 2, - chainId, + chainId: 4, }; }; @@ -282,41 +252,13 @@ const testHistory = [ ]; const ethereumChainIdDec = parseInt(CHAIN_IDS.ETHEREUM, 16); -const goerliChainIdDec = parseInt(CHAIN_IDS.GOERLI, 16); const trackMetaMetricsEventSpy = jest.fn(); -const defaultState = { - smartTransactionsState: { - smartTransactions: { - [CHAIN_IDS.ETHEREUM]: [], - }, - userOptIn: undefined, - userOptInV2: undefined, - fees: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - feesByChainId: { - [CHAIN_IDS.ETHEREUM]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - [CHAIN_IDS.GOERLI]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - }, - liveness: true, - livenessByChainId: { - [CHAIN_IDS.ETHEREUM]: true, - [CHAIN_IDS.GOERLI]: true, - }, - }, -}; describe('SmartTransactionsController', () => { let smartTransactionsController: SmartTransactionsController; let networkListener: (networkState: NetworkState) => void; + beforeEach(() => { smartTransactionsController = new SmartTransactionsController({ onNetworkStateChange: (listener) => { @@ -329,26 +271,8 @@ describe('SmartTransactionsController', () => { }; }), provider: jest.fn(), - confirmExternalTransaction: jest.fn(), + confirmExternalTransaction: confirmExternalMock, trackMetaMetricsEvent: trackMetaMetricsEventSpy, - getNetworkClientById: jest.fn().mockImplementation((networkClientId) => { - switch (networkClientId) { - case 'mainnet': - return { - configuration: { - chainId: CHAIN_IDS.ETHEREUM, - }, - }; - case 'goerli': - return { - configuration: { - chainId: CHAIN_IDS.GOERLI, - }, - }; - default: - throw new Error('Invalid network client id'); - } - }), }); // eslint-disable-next-line jest/prefer-spy-on smartTransactionsController.subscribe = jest.fn(); @@ -363,35 +287,38 @@ describe('SmartTransactionsController', () => { it('initializes with default config', () => { expect(smartTransactionsController.config).toStrictEqual({ interval: DEFAULT_INTERVAL, - supportedChainIds: [CHAIN_IDS.ETHEREUM, CHAIN_IDS.GOERLI], + supportedChainIds: [CHAIN_IDS.ETHEREUM, CHAIN_IDS.RINKEBY], chainId: CHAIN_IDS.ETHEREUM, clientId: 'default', }); }); it('initializes with default state', () => { - expect(smartTransactionsController.state).toStrictEqual(defaultState); + expect(smartTransactionsController.state).toStrictEqual({ + smartTransactionsState: { + smartTransactions: { + [CHAIN_IDS.ETHEREUM]: [], + }, + userOptIn: undefined, + userOptInV2: undefined, + fees: { + approvalTxFees: undefined, + tradeTxFees: undefined, + }, + liveness: true, + }, + }); }); describe('onNetworkChange', () => { it('is triggered', () => { - networkListener({ - providerConfig: { chainId: '0x32', type: 'rpc', ticker: 'CET' }, - selectedNetworkClientId: 'networkClientId', - networkConfigurations: {}, - networksMetadata: {}, - } as NetworkState); - expect(smartTransactionsController.config.chainId).toBe('0x32'); + networkListener({ providerConfig: { chainId: '52' } } as NetworkState); + expect(smartTransactionsController.config.chainId).toBe('52'); }); it('calls poll', () => { const checkPollSpy = jest.spyOn(smartTransactionsController, 'checkPoll'); - networkListener({ - providerConfig: { chainId: '0x32', type: 'rpc', ticker: 'CET' }, - selectedNetworkClientId: 'networkClientId', - networkConfigurations: {}, - networksMetadata: {}, - } as NetworkState); + networkListener({ providerConfig: { chainId: '2' } } as NetworkState); expect(checkPollSpy).toHaveBeenCalled(); }); }); @@ -418,7 +345,7 @@ describe('SmartTransactionsController', () => { it('calls stop if there is a timeoutHandle and no pending transactions', () => { const stopSpy = jest.spyOn(smartTransactionsController, 'stop'); - smartTransactionsController.timeoutHandle = setTimeout(() => ({})); + smartTransactionsController.timeoutHandle = setInterval(() => ({})); smartTransactionsController.checkPoll(smartTransactionsController.state); expect(stopSpy).toHaveBeenCalled(); clearInterval(smartTransactionsController.timeoutHandle); @@ -432,19 +359,12 @@ describe('SmartTransactionsController', () => { 'updateSmartTransactions', ); expect(updateSmartTransactionsSpy).not.toHaveBeenCalled(); - networkListener({ - providerConfig: { chainId: '0x32', type: 'rpc', ticker: 'CET' }, - selectedNetworkClientId: 'networkClientId', - networkConfigurations: {}, - networksMetadata: {}, - } as NetworkState); + networkListener({ providerConfig: { chainId: '56' } } as NetworkState); expect(updateSmartTransactionsSpy).not.toHaveBeenCalled(); }); }); describe('updateSmartTransactions', () => { - // TODO rewrite this test... updateSmartTransactions is getting called via the checkPoll method which is called whenever state is updated. - // this test should be more isolated to the updateSmartTransactions method. it('calls fetchSmartTransactionsStatus if there are pending transactions', () => { const fetchSmartTransactionsStatusSpy = jest .spyOn(smartTransactionsController, 'fetchSmartTransactionsStatus') @@ -516,8 +436,8 @@ describe('SmartTransactionsController', () => { describe('getFees', () => { it('gets unsigned transactions and estimates based on an unsigned transaction', async () => { - const tradeTx = createUnsignedTransaction(ethereumChainIdDec); - const approvalTx = createUnsignedTransaction(ethereumChainIdDec); + const tradeTx = createUnsignedTransaction(); + const approvalTx = createUnsignedTransaction(); const getFeesApiResponse = createGetFeesApiResponse(); nock(API_BASE_URL) .post(`/networks/${ethereumChainIdDec}/getFees`) @@ -531,36 +451,6 @@ describe('SmartTransactionsController', () => { tradeTxFees: getFeesApiResponse.txs[1], }); }); - - it('should add fee data to feesByChainId state using the networkClientId passed in to identify the appropriate chain', async () => { - const tradeTx = createUnsignedTransaction(goerliChainIdDec); - const approvalTx = createUnsignedTransaction(goerliChainIdDec); - const getFeesApiResponse = createGetFeesApiResponse(); - nock(API_BASE_URL) - .post(`/networks/${goerliChainIdDec}/getFees`) - .reply(200, getFeesApiResponse); - - expect( - smartTransactionsController.state.smartTransactionsState.feesByChainId, - ).toStrictEqual(defaultState.smartTransactionsState.feesByChainId); - - await smartTransactionsController.getFees(tradeTx, approvalTx, { - networkClientId: 'goerli', - }); - - expect( - smartTransactionsController.state.smartTransactionsState.feesByChainId, - ).toMatchObject({ - [CHAIN_IDS.ETHEREUM]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - [CHAIN_IDS.GOERLI]: { - approvalTxFees: getFeesApiResponse.txs[0], - tradeTxFees: getFeesApiResponse.txs[1], - }, - }); - }); }); describe('submitSignedTransactions', () => { @@ -606,10 +496,7 @@ describe('SmartTransactionsController', () => { nock(API_BASE_URL) .get(`/networks/${ethereumChainIdDec}/batchStatus?uuids=uuid1`) .reply(200, pendingBatchStatusApiResponse); - - await smartTransactionsController.fetchSmartTransactionsStatus(uuids, { - networkClientId: 'mainnet', - }); + await smartTransactionsController.fetchSmartTransactionsStatus(uuids); const pendingState = createStateAfterPending()[0]; const pendingTransaction = { ...pendingState, history: [pendingState] }; expect(smartTransactionsController.state).toStrictEqual({ @@ -623,21 +510,7 @@ describe('SmartTransactionsController', () => { approvalTxFees: undefined, tradeTxFees: undefined, }, - feesByChainId: { - [CHAIN_IDS.ETHEREUM]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - [CHAIN_IDS.GOERLI]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - }, liveness: true, - livenessByChainId: { - [CHAIN_IDS.ETHEREUM]: true, - [CHAIN_IDS.GOERLI]: true, - }, }, }); }); @@ -659,10 +532,7 @@ describe('SmartTransactionsController', () => { nock(API_BASE_URL) .get(`/networks/${ethereumChainIdDec}/batchStatus?uuids=uuid2`) .reply(200, successBatchStatusApiResponse); - - await smartTransactionsController.fetchSmartTransactionsStatus(uuids, { - networkClientId: 'mainnet', - }); + await smartTransactionsController.fetchSmartTransactionsStatus(uuids); const successState = createStateAfterSuccess()[0]; const successTransaction = { ...successState, history: [successState] }; expect(smartTransactionsController.state).toStrictEqual({ @@ -680,20 +550,6 @@ describe('SmartTransactionsController', () => { tradeTxFees: undefined, }, liveness: true, - feesByChainId: { - '0x1': { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - '0x5': { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - }, - livenessByChainId: { - '0x1': true, - '0x5': true, - }, }, }); }); @@ -708,32 +564,6 @@ describe('SmartTransactionsController', () => { const liveness = await smartTransactionsController.fetchLiveness(); expect(liveness).toBe(true); }); - - it('fetches liveness and sets in feesByChainId state for the Smart Transactions API for the chainId of the networkClientId passed in', async () => { - nock(API_BASE_URL) - .get(`/networks/${goerliChainIdDec}/health`) - .replyWithError('random error'); - - expect( - smartTransactionsController.state.smartTransactionsState - .livenessByChainId, - ).toStrictEqual({ - [CHAIN_IDS.ETHEREUM]: true, - [CHAIN_IDS.GOERLI]: true, - }); - - await smartTransactionsController.fetchLiveness({ - networkClientId: 'goerli', - }); - - expect( - smartTransactionsController.state.smartTransactionsState - .livenessByChainId, - ).toStrictEqual({ - [CHAIN_IDS.ETHEREUM]: true, - [CHAIN_IDS.GOERLI]: false, - }); - }); }); describe('updateSmartTransaction', () => { @@ -762,9 +592,6 @@ describe('SmartTransactionsController', () => { }; smartTransactionsController.updateSmartTransaction( updateTransaction as SmartTransaction, - { - networkClientId: 'mainnet', - }, ); expect( @@ -775,6 +602,10 @@ describe('SmartTransactionsController', () => { it('confirms a smart transaction that has status success', async () => { const { smartTransactionsState } = smartTransactionsController.state; + const confirmSpy = jest.spyOn( + smartTransactionsController, + 'confirmSmartTransaction', + ); const pendingStx = { ...createStateAfterPending()[0], history: testHistory, @@ -789,27 +620,44 @@ describe('SmartTransactionsController', () => { }); const updateTransaction = { ...pendingStx, - status: SmartTransactionStatuses.SUCCESS, + status: 'success', }; - smartTransactionsController.updateSmartTransaction( updateTransaction as SmartTransaction, - { - networkClientId: 'mainnet', - }, ); + expect(confirmSpy).toHaveBeenCalled(); + }); + }); - await flushPromises(); + describe('confirmSmartTransaction', () => { + beforeEach(() => { + // eslint-disable-next-line jest/prefer-spy-on + smartTransactionsController.checkPoll = jest.fn(() => ({})); + }); - expect( - smartTransactionsController.state.smartTransactionsState - .smartTransactions[CHAIN_IDS.ETHEREUM], - ).toStrictEqual([ - { - ...updateTransaction, - confirmed: true, - }, - ]); + it('calls confirm external transaction', async () => { + const successfulStx = { + ...createStateAfterSuccess()[0], + history: testHistory, + }; + await smartTransactionsController.confirmSmartTransaction( + successfulStx as SmartTransaction, + ); + expect(confirmExternalMock).toHaveBeenCalled(); + }); + + it('throws an error if ethersProvider fails', async () => { + smartTransactionsController.ethersProvider.getTransactionReceipt.mockRejectedValueOnce( + 'random error' as never, + ); + const successfulStx = { + ...createStateAfterSuccess()[0], + history: testHistory, + }; + await smartTransactionsController.confirmSmartTransaction( + successfulStx as SmartTransaction, + ); + expect(trackMetaMetricsEventSpy).toHaveBeenCalled(); }); }); @@ -896,114 +744,4 @@ describe('SmartTransactionsController', () => { expect(actual).toBe(false); }); }); - - describe('startPollingByNetworkClientId', () => { - it('starts and stops calling smart transactions batch status api endpoint with the correct chainId at the polling interval', async () => { - // mock this to a noop because it causes an extra fetch call to the API upon state changes - jest - .spyOn(smartTransactionsController, 'checkPoll') - .mockImplementation(() => undefined); - - // pending transactions in state are required to test polling - smartTransactionsController.update({ - smartTransactionsState: { - ...defaultState.smartTransactionsState, - smartTransactions: { - '0x1': [ - { - uuid: 'uuid1', - status: 'pending', - cancellable: true, - chainId: '0x1', - }, - ], - '0x5': [ - { - uuid: 'uuid2', - status: 'pending', - cancellable: true, - chainId: '0x5', - }, - ], - }, - }, - }); - - jest.useFakeTimers(); - const handleFetchSpy = jest.spyOn(utils, 'handleFetch'); - - const mainnetPollingToken = - smartTransactionsController.startPollingByNetworkClientId('mainnet'); - - await Promise.all([ - jest.advanceTimersByTime(DEFAULT_INTERVAL), - flushPromises(), - ]); - - expect(handleFetchSpy.mock.calls[0]).toStrictEqual( - expect.arrayContaining([ - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.ETHEREUM, - )}/batchStatus?uuids=uuid1`, - ]), - ); - - smartTransactionsController.startPollingByNetworkClientId('goerli'); - await jest.advanceTimersByTime(DEFAULT_INTERVAL); - - expect( - JSON.stringify(handleFetchSpy.mock.calls.map((arg) => arg[0])), - ).toStrictEqual( - JSON.stringify([ - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.ETHEREUM, - )}/batchStatus?uuids=uuid1`, - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.ETHEREUM, - )}/batchStatus?uuids=uuid1`, - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.GOERLI, - )}/batchStatus?uuids=uuid2`, - ]), - ); - - // stop the mainnet polling - smartTransactionsController.stopPollingByPollingToken( - mainnetPollingToken, - ); - - // cycle two polling intervals - await jest.advanceTimersByTime(DEFAULT_INTERVAL); - await jest.advanceTimersByTime(DEFAULT_INTERVAL); - - // check that the mainnet polling has stopped while the goerli polling continues - expect( - JSON.stringify(handleFetchSpy.mock.calls.map((arg) => arg[0])), - ).toStrictEqual( - JSON.stringify([ - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.ETHEREUM, - )}/batchStatus?uuids=uuid1`, - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.ETHEREUM, - )}/batchStatus?uuids=uuid1`, - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.GOERLI, - )}/batchStatus?uuids=uuid2`, - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.GOERLI, - )}/batchStatus?uuids=uuid2`, - `${API_BASE_URL}/networks/${convertHexToDecimal( - CHAIN_IDS.GOERLI, - )}/batchStatus?uuids=uuid2`, - ]), - ); - - // cleanup - smartTransactionsController.update(defaultState); - - smartTransactionsController.stopAllPolling(); - jest.clearAllTimers(); - }); - }); }); diff --git a/src/SmartTransactionsController.ts b/src/SmartTransactionsController.ts index f09da24..74bdd65 100644 --- a/src/SmartTransactionsController.ts +++ b/src/SmartTransactionsController.ts @@ -1,14 +1,15 @@ -import { BaseConfig, BaseState } from '@metamask/base-controller'; -import { ChainId, safelyExecute, query } from '@metamask/controller-utils'; import { - NetworkState, - NetworkController, - NetworkClientId, -} from '@metamask/network-controller'; -import { PollingControllerV1 } from '@metamask/polling-controller'; + BaseConfig, + BaseController, + BaseState, +} from '@metamask/base-controller'; +import { safelyExecute } from '@metamask/controller-utils'; +import { NetworkState } from '@metamask/network-controller'; import { BigNumber } from 'bignumber.js'; -import EthQuery from '@metamask/eth-query'; +import { BigNumber as ethersBigNumber } from '@ethersproject/bignumber'; +import { Web3Provider } from '@ethersproject/providers'; import { hexlify } from '@ethersproject/bytes'; +import mapValues from 'lodash/mapValues'; import cloneDeep from 'lodash/cloneDeep'; import { @@ -21,7 +22,6 @@ import { SmartTransactionStatuses, Fees, IndividualTxFees, - Hex, } from './types'; import { getAPIRequestURL, @@ -43,28 +43,24 @@ export const DEFAULT_INTERVAL = SECOND * 5; export type SmartTransactionsControllerConfig = BaseConfig & { interval: number; clientId: string; - chainId: Hex; + chainId: string; supportedChainIds: string[]; }; -type FeeEstimates = { - approvalTxFees: IndividualTxFees | undefined; - tradeTxFees: IndividualTxFees | undefined; -}; - export type SmartTransactionsControllerState = BaseState & { smartTransactionsState: { - smartTransactions: Record; + smartTransactions: Record; userOptIn: boolean | undefined; userOptInV2: boolean | undefined; liveness: boolean | undefined; - fees: FeeEstimates; - feesByChainId: Record; - livenessByChainId: Record; + fees: { + approvalTxFees: IndividualTxFees | undefined; + tradeTxFees: IndividualTxFees | undefined; + }; }; }; -export default class SmartTransactionsController extends PollingControllerV1< +export default class SmartTransactionsController extends BaseController< SmartTransactionsControllerConfig, SmartTransactionsControllerState > { @@ -72,14 +68,12 @@ export default class SmartTransactionsController extends PollingControllerV1< private getNonceLock: any; - public ethQuery: EthQuery; + public ethersProvider: any; public confirmExternalTransaction: any; private trackMetaMetricsEvent: any; - private getNetworkClientById: NetworkController['getNetworkClientById']; - /* istanbul ignore next */ private async fetch(request: string, options?: RequestInit) { const { clientId } = this.config; @@ -101,7 +95,6 @@ export default class SmartTransactionsController extends PollingControllerV1< provider, confirmExternalTransaction, trackMetaMetricsEvent, - getNetworkClientById, }: { onNetworkStateChange: ( listener: (networkState: NetworkState) => void, @@ -110,7 +103,6 @@ export default class SmartTransactionsController extends PollingControllerV1< provider: any; confirmExternalTransaction: any; trackMetaMetricsEvent: any; - getNetworkClientById: NetworkController['getNetworkClientById']; }, config?: Partial, state?: Partial, @@ -119,9 +111,9 @@ export default class SmartTransactionsController extends PollingControllerV1< this.defaultConfig = { interval: DEFAULT_INTERVAL, - chainId: ChainId.mainnet, + chainId: CHAIN_IDS.ETHEREUM, clientId: 'default', - supportedChainIds: [CHAIN_IDS.ETHEREUM, CHAIN_IDS.GOERLI], + supportedChainIds: [CHAIN_IDS.ETHEREUM, CHAIN_IDS.RINKEBY], }; this.defaultState = { @@ -134,28 +126,13 @@ export default class SmartTransactionsController extends PollingControllerV1< tradeTxFees: undefined, }, liveness: true, - livenessByChainId: { - [CHAIN_IDS.ETHEREUM]: true, - [CHAIN_IDS.GOERLI]: true, - }, - feesByChainId: { - [CHAIN_IDS.ETHEREUM]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - [CHAIN_IDS.GOERLI]: { - approvalTxFees: undefined, - tradeTxFees: undefined, - }, - }, }, }; - this.setIntervalLength(this.config.interval || DEFAULT_INTERVAL); + this.getNonceLock = getNonceLock; - this.ethQuery = new EthQuery(provider); + this.ethersProvider = new Web3Provider(provider); this.confirmExternalTransaction = confirmExternalTransaction; this.trackMetaMetricsEvent = trackMetaMetricsEvent; - this.getNetworkClientById = getNetworkClientById; this.initialize(); this.initializeSmartTransactionsForChainId(); @@ -165,24 +142,12 @@ export default class SmartTransactionsController extends PollingControllerV1< this.configure({ chainId }); this.initializeSmartTransactionsForChainId(); this.checkPoll(this.state); - this.ethQuery = new EthQuery(provider); + this.ethersProvider = new Web3Provider(provider); }); this.subscribe((currentState: any) => this.checkPoll(currentState)); } - _executePoll(networkClientId: string): Promise { - // if this is going to be truly UI driven polling we shouldn't really reach here - // with a networkClientId that is not supported, but for now I'll add a check in case - // wondering if we should add some kind of predicate to the polling controller to check whether - // we should poll or not - const chainId = this.getChainId({ networkClientId }); - if (!this.config.supportedChainIds.includes(chainId)) { - return Promise.resolve(); - } - return this.updateSmartTransactions({ networkClientId }); - } - checkPoll(state: any) { const { smartTransactions } = state.smartTransactionsState; const currentSmartTransactions = smartTransactions[this.config.chainId]; @@ -290,35 +255,8 @@ export default class SmartTransactionsController extends PollingControllerV1< return currentIndex === -1 || currentIndex === undefined; } - updateSmartTransaction( - smartTransaction: SmartTransaction, - { networkClientId }: { networkClientId?: NetworkClientId } = {}, - ) { - let { chainId } = this.config; - let { ethQuery } = this; - if (networkClientId) { - const networkClient = this.getNetworkClientById(networkClientId); - chainId = networkClient.configuration.chainId; - // @ts-expect-error TODO: Provider type alignment - ethQuery = new EthQuery(networkClient.provider); - } - - this.#updateSmartTransaction(smartTransaction, { - chainId, - ethQuery, - }); - } - - #updateSmartTransaction( - smartTransaction: SmartTransaction, - { - chainId = this.config.chainId, - ethQuery = this.ethQuery, - }: { - chainId: Hex; - ethQuery: EthQuery; - }, - ): void { + updateSmartTransaction(smartTransaction: SmartTransaction): void { + const { chainId } = this.config; const { smartTransactionsState } = this.state; const { smartTransactions } = smartTransactionsState; const currentSmartTransactions = smartTransactions[chainId]; @@ -328,7 +266,6 @@ export default class SmartTransactionsController extends PollingControllerV1< const isNewSmartTransaction = this.isNewSmartTransaction( smartTransaction.uuid, ); - this.trackStxStatusChange( smartTransaction, isNewSmartTransaction @@ -338,7 +275,7 @@ export default class SmartTransactionsController extends PollingControllerV1< if (isNewSmartTransaction) { // add smart transaction - const cancelledNonceIndex = currentSmartTransactions?.findIndex( + const cancelledNonceIndex = currentSmartTransactions.findIndex( (stx: SmartTransaction) => stx.txParams?.nonce === smartTransaction.txParams?.nonce && stx.status?.startsWith('cancelled'), @@ -352,7 +289,7 @@ export default class SmartTransactionsController extends PollingControllerV1< .slice(0, cancelledNonceIndex) .concat(currentSmartTransactions.slice(cancelledNonceIndex + 1)) .concat(historifiedSmartTransaction) - : currentSmartTransactions?.concat(historifiedSmartTransaction); + : currentSmartTransactions.concat(historifiedSmartTransaction); this.update({ smartTransactionsState: { ...smartTransactionsState, @@ -376,10 +313,7 @@ export default class SmartTransactionsController extends PollingControllerV1< ...currentSmartTransaction, ...smartTransaction, }; - this.#confirmSmartTransaction(nextSmartTransaction, { - chainId, - ethQuery, - }); + this.confirmSmartTransaction(nextSmartTransaction); } this.update({ @@ -399,59 +333,42 @@ export default class SmartTransactionsController extends PollingControllerV1< }); } - async updateSmartTransactions({ - networkClientId, - }: { - networkClientId?: NetworkClientId; - } = {}): Promise { + async updateSmartTransactions() { const { smartTransactions } = this.state.smartTransactionsState; - const chainId = this.getChainId({ networkClientId }); - const smartTransactionsForChainId = smartTransactions?.[chainId]; + const { chainId } = this.config; + + const currentSmartTransactions = smartTransactions?.[chainId]; - const transactionsToUpdate: string[] = smartTransactionsForChainId + const transactionsToUpdate: string[] = currentSmartTransactions .filter(isSmartTransactionPending) .map((smartTransaction) => smartTransaction.uuid); if (transactionsToUpdate.length > 0) { - this.fetchSmartTransactionsStatus(transactionsToUpdate, { - networkClientId, - }); + this.fetchSmartTransactionsStatus(transactionsToUpdate); } } - async #confirmSmartTransaction( - smartTransaction: SmartTransaction, - { - chainId, - ethQuery, - }: { - chainId: Hex; - ethQuery: EthQuery; - }, - ) { + async confirmSmartTransaction(smartTransaction: SmartTransaction) { const txHash = smartTransaction.statusMetadata?.minedHash; try { - const transactionReceipt: { - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - blockNumber: string; - } | null = await query(ethQuery, 'getTransactionReceipt', [txHash]); - - const transaction: { - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - } | null = await query(ethQuery, 'getTransactionByHash', [txHash]); - - const maxFeePerGas = transaction?.maxFeePerGas; - const maxPriorityFeePerGas = transaction?.maxPriorityFeePerGas; + const transactionReceipt = + await this.ethersProvider.getTransactionReceipt(txHash); + const transaction = await this.ethersProvider.getTransaction(txHash); + const maxFeePerGas = transaction.maxFeePerGas?.toHexString(); + const maxPriorityFeePerGas = + transaction.maxPriorityFeePerGas?.toHexString(); if (transactionReceipt?.blockNumber) { - const blockData: { baseFeePerGas?: string } | null = await query( - ethQuery, - 'getBlockByNumber', - [transactionReceipt?.blockNumber, false], + const blockData = await this.ethersProvider.getBlock( + transactionReceipt?.blockNumber, + false, ); - const baseFeePerGas = blockData?.baseFeePerGas; - const txReceipt = Object.values(transactionReceipt); + const baseFeePerGas = blockData?.baseFeePerGas.toHexString(); + const txReceipt = mapValues(transactionReceipt, (value) => { + if (value instanceof ethersBigNumber) { + return value.toHexString(); + } + return value; + }); const updatedTxParams = { ...smartTransaction.txParams, maxFeePerGas, @@ -482,7 +399,6 @@ export default class SmartTransactionsController extends PollingControllerV1< history: originalTxMeta.history.concat(entry), } : originalTxMeta; - this.confirmExternalTransaction(txMeta, txReceipt, baseFeePerGas); this.trackMetaMetricsEvent({ @@ -490,13 +406,10 @@ export default class SmartTransactionsController extends PollingControllerV1< category: 'swaps', }); - this.#updateSmartTransaction( - { - ...smartTransaction, - confirmed: true, - }, - { chainId, ethQuery }, - ); + this.updateSmartTransaction({ + ...smartTransaction, + confirmed: true, + }); } } catch (e) { this.trackMetaMetricsEvent({ @@ -510,31 +423,29 @@ export default class SmartTransactionsController extends PollingControllerV1< // ! Ask backend API to accept list of uuids as params async fetchSmartTransactionsStatus( uuids: string[], - { networkClientId }: { networkClientId?: NetworkClientId } = {}, ): Promise { + const { chainId } = this.config; + const params = new URLSearchParams({ uuids: uuids.join(','), }); - const chainId = this.getChainId({ networkClientId }); - const ethQuery = this.getEthQuery({ networkClientId }); + const url = `${getAPIRequestURL( APIType.BATCH_STATUS, chainId, )}?${params.toString()}`; const data = await this.fetch(url); + Object.entries(data).forEach(([uuid, stxStatus]) => { - this.#updateSmartTransaction( - { - statusMetadata: stxStatus as SmartTransactionsStatus, - status: calculateStatus(stxStatus as SmartTransactionsStatus), - cancellable: isSmartTransactionCancellable( - stxStatus as SmartTransactionsStatus, - ), - uuid, - }, - { chainId, ethQuery }, - ); + this.updateSmartTransaction({ + statusMetadata: stxStatus as SmartTransactionsStatus, + status: calculateStatus(stxStatus as SmartTransactionsStatus), + cancellable: isSmartTransactionCancellable( + stxStatus as SmartTransactionsStatus, + ), + uuid, + }); }); return data; @@ -569,9 +480,8 @@ export default class SmartTransactionsController extends PollingControllerV1< async getFees( tradeTx: UnsignedTransaction, approvalTx: UnsignedTransaction, - { networkClientId }: { networkClientId?: NetworkClientId } = {}, ): Promise { - const chainId = this.getChainId({ networkClientId }); + const { chainId } = this.config; const transactions = []; let unsignedTradeTransactionWithNonce; if (approvalTx) { @@ -611,16 +521,8 @@ export default class SmartTransactionsController extends PollingControllerV1< approvalTxFees, tradeTxFees, }, - feesByChainId: { - ...this.state.smartTransactionsState.feesByChainId, - [chainId]: { - approvalTxFees, - tradeTxFees, - }, - }, }, }); - return { approvalTxFees, tradeTxFees, @@ -633,15 +535,12 @@ export default class SmartTransactionsController extends PollingControllerV1< txParams, signedTransactions, signedCanceledTransactions, - networkClientId, }: { signedTransactions: SignedTransaction[]; signedCanceledTransactions: SignedCanceledTransaction[]; txParams?: any; - networkClientId?: NetworkClientId; }) { - const chainId = this.getChainId({ networkClientId }); - const ethQuery = this.getEthQuery({ networkClientId }); + const { chainId } = this.config; const data = await this.fetch( getAPIRequestURL(APIType.SUBMIT_TRANSACTIONS, chainId), { @@ -655,12 +554,12 @@ export default class SmartTransactionsController extends PollingControllerV1< const time = Date.now(); let preTxBalance; try { - const preTxBalanceBN = await query(ethQuery, 'getBalance', [ + const preTxBalanceBN = await this.ethersProvider.getBalance( txParams?.from, - ]); - preTxBalance = new BigNumber(preTxBalanceBN).toString(16); + ); + preTxBalance = new BigNumber(preTxBalanceBN.toHexString()).toString(16); } catch (e) { - console.error('provider error', e); + console.error('ethers error', e); } const nonceLock = await this.getNonceLock(txParams?.from); try { @@ -670,18 +569,16 @@ export default class SmartTransactionsController extends PollingControllerV1< } const { nonceDetails } = nonceLock; - this.#updateSmartTransaction( - { - nonceDetails, - preTxBalance, - status: SmartTransactionStatuses.PENDING, - time, - txParams, - uuid: data.uuid, - cancellable: true, - }, - { chainId, ethQuery }, - ); + this.updateSmartTransaction({ + chainId, + nonceDetails, + preTxBalance, + status: SmartTransactionStatuses.PENDING, + time, + txParams, + uuid: data.uuid, + cancellable: true, + }); } finally { nonceLock.releaseLock(); } @@ -689,49 +586,19 @@ export default class SmartTransactionsController extends PollingControllerV1< return data; } - getChainId({ - networkClientId, - }: { networkClientId?: NetworkClientId } = {}): Hex { - return networkClientId - ? this.getNetworkClientById(networkClientId).configuration.chainId - : this.config.chainId; - } - - getEthQuery({ - networkClientId, - }: { - networkClientId?: NetworkClientId; - }): EthQuery { - return networkClientId - ? // @ts-expect-error TODO: Provider type alignment - new EthQuery(this.getNetworkClientById(networkClientId).provider) - : this.ethQuery; - } - // TODO: This should return if the cancellation was on chain or not (for nonce management) // After this successful call client must update nonce representative // in transaction controller external transactions list - async cancelSmartTransaction( - uuid: string, - { - networkClientId, - }: { - networkClientId?: NetworkClientId; - } = {}, - ): Promise { - const chainId = this.getChainId({ networkClientId }); + async cancelSmartTransaction(uuid: string): Promise { + const { chainId } = this.config; await this.fetch(getAPIRequestURL(APIType.CANCEL, chainId), { method: 'POST', body: JSON.stringify({ uuid }), }); } - async fetchLiveness({ - networkClientId, - }: { - networkClientId?: NetworkClientId; - } = {}): Promise { - const chainId = this.getChainId({ networkClientId }); + async fetchLiveness(): Promise { + const { chainId } = this.config; let liveness = false; try { const response = await this.fetch( @@ -746,13 +613,8 @@ export default class SmartTransactionsController extends PollingControllerV1< smartTransactionsState: { ...this.state.smartTransactionsState, liveness, - livenessByChainId: { - ...this.state.smartTransactionsState.livenessByChainId, - [chainId]: liveness, - }, }, }); - return liveness; } diff --git a/src/constants.ts b/src/constants.ts index 693df74..070e289 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,7 +1,6 @@ export const API_BASE_URL = 'https://transaction.metaswap.codefi.network'; export const CHAIN_IDS = { ETHEREUM: '0x1', - GOERLI: '0x5', RINKEBY: '0x4', BSC: '0x38', -} as const; +}; diff --git a/src/index.test.ts b/src/index.test.ts index 678b078..411d2c1 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -10,7 +10,6 @@ describe('default export', () => { provider: jest.fn(), confirmExternalTransaction: jest.fn(), trackMetaMetricsEvent: jest.fn(), - getNetworkClientById: jest.fn(), }); expect(controller).toBeInstanceOf(SmartTransactionsController); jest.clearAllTimers(); diff --git a/src/types.ts b/src/types.ts index b1032c1..045463f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -117,5 +117,3 @@ export type SignedTransaction = any; // TODO export type SignedCanceledTransaction = any; - -export type Hex = `0x${string}`; diff --git a/yarn.lock b/yarn.lock index c7e435a..b8a98ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -589,6 +589,77 @@ __metadata: languageName: node linkType: hard +"@ethersproject/abstract-provider@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abstract-provider@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/networks": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + "@ethersproject/web": ^5.7.0 + checksum: 74cf4696245cf03bb7cc5b6cbf7b4b89dd9a79a1c4688126d214153a938126d4972d42c93182198653ce1de35f2a2cad68be40337d4774b3698a39b28f0228a8 + languageName: node + linkType: hard + +"@ethersproject/abstract-signer@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abstract-signer@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + checksum: a823dac9cfb761e009851050ebebd5b229d1b1cc4a75b125c2da130ff37e8218208f7f9d1386f77407705b889b23d4a230ad67185f8872f083143e0073cbfbe3 + languageName: node + linkType: hard + +"@ethersproject/address@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/address@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/rlp": ^5.7.0 + checksum: 64ea5ebea9cc0e845c413e6cb1e54e157dd9fc0dffb98e239d3a3efc8177f2ff798cd4e3206cf3660ee8faeb7bef1a47dc0ebef0d7b132c32e61e550c7d4c843 + languageName: node + linkType: hard + +"@ethersproject/base64@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/base64@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + checksum: 7dd5d734d623582f08f665434f53685041a3d3b334a0e96c0c8afa8bbcaab934d50e5b6b980e826a8fde8d353e0b18f11e61faf17468177274b8e7c69cd9742b + languageName: node + linkType: hard + +"@ethersproject/basex@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/basex@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + checksum: 326087b7e1f3787b5fe6cd1cf2b4b5abfafbc355a45e88e22e5e9d6c845b613ffc5301d629b28d5c4d5e2bfe9ec424e6782c804956dff79be05f0098cb5817de + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bignumber@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + bn.js: ^5.2.1 + checksum: 8c9a134b76f3feb4ec26a5a27379efb4e156b8fb2de0678a67788a91c7f4e30abe9d948638458e4b20f2e42380da0adacc7c9389d05fce070692edc6ae9b4904 + languageName: node + linkType: hard + "@ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" @@ -598,6 +669,42 @@ __metadata: languageName: node linkType: hard +"@ethersproject/constants@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/constants@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + checksum: 6d4b1355747cce837b3e76ec3bde70e4732736f23b04f196f706ebfa5d4d9c2be50904a390d4d40ce77803b98d03d16a9b6898418e04ba63491933ce08c4ba8a + languageName: node + linkType: hard + +"@ethersproject/hash@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/hash@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/base64": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: 6e9fa8d14eb08171cd32f17f98cc108ec2aeca74a427655f0d689c550fee0b22a83b3b400fad7fb3f41cf14d4111f87f170aa7905bcbcd1173a55f21b06262ef + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/keccak256@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + js-sha3: 0.8.0 + checksum: ff70950d82203aab29ccda2553422cbac2e7a0c15c986bd20a69b13606ed8bb6e4fdd7b67b8d3b27d4f841e8222cbaccd33ed34be29f866fec7308f96ed244c6 + languageName: node + linkType: hard + "@ethersproject/logger@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/logger@npm:5.7.0" @@ -605,6 +712,138 @@ __metadata: languageName: node linkType: hard +"@ethersproject/networks@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/networks@npm:5.7.0" + dependencies: + "@ethersproject/logger": ^5.7.0 + checksum: 4f4d77e7c59e79cfcba616315a5d0e634a7653acbd11bb06a0028f4bd009b19f9a31556148a1e38f7308f55d1a1d170eb9f065290de9f9cf104b34e91cc348b8 + languageName: node + linkType: hard + +"@ethersproject/properties@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/properties@npm:5.7.0" + dependencies: + "@ethersproject/logger": ^5.7.0 + checksum: 6ab0ccf0c3aadc9221e0cdc5306ce6cd0df7f89f77d77bccdd1277182c9ead0202cd7521329ba3acde130820bf8af299e17cf567d0d497c736ee918207bbf59f + languageName: node + linkType: hard + +"@ethersproject/providers@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/providers@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/base64": ^5.7.0 + "@ethersproject/basex": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/hash": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/networks": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/random": ^5.7.0 + "@ethersproject/rlp": ^5.7.0 + "@ethersproject/sha2": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + "@ethersproject/web": ^5.7.0 + bech32: 1.1.4 + ws: 7.4.6 + checksum: a6f80cea838424ceb367ff8e0f004f9fd6b43a87505da9d6aef33eb2bbc77cdb03ab51709ae83b7aa07d038fadf00634e08d8683fe6ae8b17b9351e3b30b26cb + languageName: node + linkType: hard + +"@ethersproject/random@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/random@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + checksum: 017829c91cff6c76470852855108115b0b52c611b6be817ed1948d56ba42d6677803ec2012aa5ae298a7660024156a64c11fcf544e235e239ab3f89f0fff7345 + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/rlp@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + checksum: bce165b0f7e68e4d091c9d3cf47b247cac33252df77a095ca4281d32d5eeaaa3695d9bc06b2b057c5015353a68df89f13a4a54a72e888e4beeabbe56b15dda6e + languageName: node + linkType: hard + +"@ethersproject/sha2@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/sha2@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + hash.js: 1.1.7 + checksum: 09321057c022effbff4cc2d9b9558228690b5dd916329d75c4b1ffe32ba3d24b480a367a7cc92d0f0c0b1c896814d03351ae4630e2f1f7160be2bcfbde435dbc + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/signing-key@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + bn.js: ^5.2.1 + elliptic: 6.5.4 + hash.js: 1.1.7 + checksum: 8f8de09b0aac709683bbb49339bc0a4cd2f95598f3546436c65d6f3c3a847ffa98e06d35e9ed2b17d8030bd2f02db9b7bd2e11c5cf8a71aad4537487ab4cf03a + languageName: node + linkType: hard + +"@ethersproject/strings@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/strings@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + checksum: 5ff78693ae3fdf3cf23e1f6dc047a61e44c8197d2408c42719fef8cb7b7b3613a4eec88ac0ed1f9f5558c74fe0de7ae3195a29ca91a239c74b9f444d8e8b50df + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/transactions@npm:5.7.0" + dependencies: + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/rlp": ^5.7.0 + "@ethersproject/signing-key": ^5.7.0 + checksum: a31b71996d2b283f68486241bff0d3ea3f1ba0e8f1322a8fffc239ccc4f4a7eb2ea9994b8fd2f093283fd75f87bae68171e01b6265261f821369aca319884a79 + languageName: node + linkType: hard + +"@ethersproject/web@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/web@npm:5.7.0" + dependencies: + "@ethersproject/base64": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: 9d4ca82f8b1295bbc1c59d58cb351641802d2f70f4b7d523fc726f51b0615296da6d6585dee5749b4d5e4a6a9af6d6650d46fe562d5b04f43a0af5c7f7f4a77e + languageName: node + linkType: hard + "@gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -1125,23 +1364,6 @@ __metadata: languageName: node linkType: hard -"@metamask/polling-controller@npm:^0.2.0": - version: 0.2.0 - resolution: "@metamask/polling-controller@npm:0.2.0" - dependencies: - "@metamask/base-controller": ^3.2.3 - "@metamask/controller-utils": ^5.0.2 - "@metamask/network-controller": ^15.0.0 - "@metamask/utils": ^8.1.0 - "@types/uuid": ^8.3.0 - fast-json-stable-stringify: ^2.1.0 - uuid: ^8.3.2 - peerDependencies: - "@metamask/network-controller": ^15.0.0 - checksum: 4dee3e49b23ba2b92055816dcc68b8e468405d9b00528d14b01c490058dea6e7aae943b19a007adbbbe06aa9a5b61d961211f9de82c8b55c7622599de78eb76e - languageName: node - linkType: hard - "@metamask/rpc-errors@npm:^6.0.0, @metamask/rpc-errors@npm:^6.1.0": version: 6.1.0 resolution: "@metamask/rpc-errors@npm:6.1.0" @@ -1163,7 +1385,9 @@ __metadata: version: 0.0.0-use.local resolution: "@metamask/smart-transactions-controller@workspace:." dependencies: + "@ethersproject/bignumber": ^5.7.0 "@ethersproject/bytes": ^5.7.0 + "@ethersproject/providers": ^5.7.0 "@lavamoat/allow-scripts": ^2.3.1 "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": ^3.2.1 @@ -1172,9 +1396,7 @@ __metadata: "@metamask/eslint-config-jest": ^10.0.0 "@metamask/eslint-config-nodejs": ^10.0.0 "@metamask/eslint-config-typescript": ^10.0.0 - "@metamask/eth-query": ^3.0.1 "@metamask/network-controller": ^15.0.0 - "@metamask/polling-controller": ^0.2.0 "@types/jest": ^26.0.24 "@types/lodash": ^4.14.194 "@types/node": ^16.18.31 @@ -1603,13 +1825,6 @@ __metadata: languageName: node linkType: hard -"@types/uuid@npm:^8.3.0": - version: 8.3.4 - resolution: "@types/uuid@npm:8.3.4" - checksum: 6f11f3ff70f30210edaa8071422d405e9c1d4e53abbe50fdce365150d3c698fe7bbff65c1e71ae080cbfb8fded860dbb5e174da96fdbbdfcaa3fb3daa474d20f - languageName: node - linkType: hard - "@types/yargs-parser@npm:*": version: 21.0.0 resolution: "@types/yargs-parser@npm:21.0.0" @@ -2210,6 +2425,13 @@ __metadata: languageName: node linkType: hard +"bech32@npm:1.1.4": + version: 1.1.4 + resolution: "bech32@npm:1.1.4" + checksum: 0e98db619191548390d6f09ff68b0253ba7ae6a55db93dfdbb070ba234c1fd3308c0606fbcc95fad50437227b10011e2698b89f0181f6e7f845c499bd14d0f4b + languageName: node + linkType: hard + "big-integer@npm:^1.6.44": version: 1.6.51 resolution: "big-integer@npm:1.6.51" @@ -2257,7 +2479,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^5.1.2": +"bn.js@npm:^5.1.2, bn.js@npm:^5.2.1": version: 5.2.1 resolution: "bn.js@npm:5.2.1" checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 @@ -3095,7 +3317,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.5.2": +"elliptic@npm:6.5.4, elliptic@npm:^6.5.2": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -3875,7 +4097,7 @@ __metadata: languageName: node linkType: hard -"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": +"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0": version: 2.1.0 resolution: "fast-json-stable-stringify@npm:2.1.0" checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb @@ -4455,7 +4677,7 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": +"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": version: 1.1.7 resolution: "hash.js@npm:1.1.7" dependencies: @@ -5637,6 +5859,13 @@ __metadata: languageName: node linkType: hard +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce + languageName: node + linkType: hard + "js-sha3@npm:^0.5.7": version: 0.5.7 resolution: "js-sha3@npm:0.5.7" @@ -8747,7 +8976,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.4.4": +"ws@npm:7.4.6, ws@npm:^7.4.4": version: 7.4.6 resolution: "ws@npm:7.4.6" peerDependencies: