mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-29 23:58:06 +01:00
7b963cabd7
When a lot of transactions are occurring on the network, such as during an NFT drop, it drives gas fees up. When this happens, we want to not only inform the user about this, but also dissuade them from using a higher gas fee (as we have proved in testing that high gas fees can cause bidding wars and exacerbate the situation). The method for determining whether the network is "busy" is already handled by GasFeeController, which exposes a `networkCongestion` property within the gas fee estimate data. If this number exceeds 0.66 — meaning that the current base fee is above the 66th percentile among the base fees over the last several days — then we determine that the network is "busy".
445 lines
12 KiB
JavaScript
445 lines
12 KiB
JavaScript
import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction';
|
|
import * as actionConstants from '../../store/actionConstants';
|
|
import reduceMetamask, {
|
|
getBlockGasLimit,
|
|
getConversionRate,
|
|
getIsNetworkBusy,
|
|
getNativeCurrency,
|
|
getSendHexDataFeatureFlagState,
|
|
getSendToAccounts,
|
|
getUnapprovedTxs,
|
|
isNotEIP1559Network,
|
|
} from './metamask';
|
|
|
|
describe('MetaMask Reducers', () => {
|
|
const mockState = {
|
|
metamask: reduceMetamask(
|
|
{
|
|
isInitialized: true,
|
|
isUnlocked: true,
|
|
featureFlags: { sendHexData: true },
|
|
identities: {
|
|
'0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': {
|
|
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
|
|
name: 'Send Account 1',
|
|
},
|
|
'0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': {
|
|
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
|
|
name: 'Send Account 2',
|
|
},
|
|
'0x2f8d4a878cfa04a6e60d46362f5644deab66572d': {
|
|
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
|
|
name: 'Send Account 3',
|
|
},
|
|
'0xd85a4b6a394794842887b8284293d69163007bbb': {
|
|
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
|
|
name: 'Send Account 4',
|
|
},
|
|
},
|
|
cachedBalances: {},
|
|
currentBlockGasLimit: '0x4c1878',
|
|
conversionRate: 1200.88200327,
|
|
nativeCurrency: 'ETH',
|
|
network: '3',
|
|
provider: {
|
|
type: 'testnet',
|
|
chainId: '0x3',
|
|
},
|
|
accounts: {
|
|
'0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': {
|
|
code: '0x',
|
|
balance: '0x47c9d71831c76efe',
|
|
nonce: '0x1b',
|
|
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
|
|
},
|
|
'0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': {
|
|
code: '0x',
|
|
balance: '0x37452b1315889f80',
|
|
nonce: '0xa',
|
|
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
|
|
},
|
|
'0x2f8d4a878cfa04a6e60d46362f5644deab66572d': {
|
|
code: '0x',
|
|
balance: '0x30c9d71831c76efe',
|
|
nonce: '0x1c',
|
|
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
|
|
},
|
|
'0xd85a4b6a394794842887b8284293d69163007bbb': {
|
|
code: '0x',
|
|
balance: '0x0',
|
|
nonce: '0x0',
|
|
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
|
|
},
|
|
},
|
|
addressBook: {
|
|
'0x3': {
|
|
'0x06195827297c7a80a443b6894d3bdb8824b43896': {
|
|
address: '0x06195827297c7a80a443b6894d3bdb8824b43896',
|
|
name: 'Address Book Account 1',
|
|
chainId: '0x3',
|
|
},
|
|
},
|
|
},
|
|
unapprovedTxs: {
|
|
4768706228115573: {
|
|
id: 4768706228115573,
|
|
time: 1487363153561,
|
|
status: TRANSACTION_STATUSES.UNAPPROVED,
|
|
gasMultiplier: 1,
|
|
metamaskNetworkId: '3',
|
|
txParams: {
|
|
from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
|
|
to: '0x18a3462427bcc9133bb46e88bcbe39cd7ef0e761',
|
|
value: '0xde0b6b3a7640000',
|
|
metamaskId: 4768706228115573,
|
|
metamaskNetworkId: '3',
|
|
gas: '0x5209',
|
|
},
|
|
txFee: '17e0186e60800',
|
|
txValue: 'de0b6b3a7640000',
|
|
maxCost: 'de234b52e4a0800',
|
|
gasPrice: '4a817c800',
|
|
},
|
|
},
|
|
networkDetails: {
|
|
EIPS: { 1559: true },
|
|
},
|
|
},
|
|
{},
|
|
),
|
|
};
|
|
it('init state', () => {
|
|
const initState = reduceMetamask(undefined, {});
|
|
|
|
expect.anything(initState);
|
|
});
|
|
|
|
it('locks MetaMask', () => {
|
|
const unlockMetaMaskState = {
|
|
isUnlocked: true,
|
|
selectedAddress: 'test address',
|
|
};
|
|
const lockMetaMask = reduceMetamask(unlockMetaMaskState, {
|
|
type: actionConstants.LOCK_METAMASK,
|
|
});
|
|
|
|
expect(lockMetaMask.isUnlocked).toStrictEqual(false);
|
|
});
|
|
|
|
it('sets rpc target', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SET_RPC_TARGET,
|
|
value: 'https://custom.rpc',
|
|
},
|
|
);
|
|
|
|
expect(state.provider.rpcUrl).toStrictEqual('https://custom.rpc');
|
|
});
|
|
|
|
it('sets provider type', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SET_PROVIDER_TYPE,
|
|
value: 'provider type',
|
|
},
|
|
);
|
|
|
|
expect(state.provider.type).toStrictEqual('provider type');
|
|
});
|
|
|
|
it('shows account detail', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SHOW_ACCOUNT_DETAIL,
|
|
},
|
|
);
|
|
|
|
expect(state.isUnlocked).toStrictEqual(true);
|
|
expect(state.isInitialized).toStrictEqual(true);
|
|
});
|
|
|
|
it('sets account label', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SET_ACCOUNT_LABEL,
|
|
value: {
|
|
account: 'test account',
|
|
label: 'test label',
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(state.identities).toStrictEqual({
|
|
'test account': { name: 'test label' },
|
|
});
|
|
});
|
|
|
|
it('toggles account menu', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.TOGGLE_ACCOUNT_MENU,
|
|
},
|
|
);
|
|
|
|
expect(state.isAccountMenuOpen).toStrictEqual(true);
|
|
});
|
|
|
|
it('updates value of tx by id', () => {
|
|
const oldState = {
|
|
currentNetworkTxList: [
|
|
{
|
|
id: 1,
|
|
txParams: 'foo',
|
|
},
|
|
],
|
|
};
|
|
|
|
const state = reduceMetamask(oldState, {
|
|
type: actionConstants.UPDATE_TRANSACTION_PARAMS,
|
|
id: 1,
|
|
value: 'bar',
|
|
});
|
|
|
|
expect(state.currentNetworkTxList[0].txParams).toStrictEqual('bar');
|
|
});
|
|
|
|
it('sets blockies', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SET_USE_BLOCKIE,
|
|
value: true,
|
|
},
|
|
);
|
|
|
|
expect(state.useBlockie).toStrictEqual(true);
|
|
});
|
|
|
|
it('updates an arbitrary feature flag', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.UPDATE_FEATURE_FLAGS,
|
|
value: {
|
|
foo: true,
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(state.featureFlags.foo).toStrictEqual(true);
|
|
});
|
|
|
|
it('close welcome screen', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.CLOSE_WELCOME_SCREEN,
|
|
},
|
|
);
|
|
|
|
expect(state.welcomeScreenSeen).toStrictEqual(true);
|
|
});
|
|
|
|
it('sets current locale', () => {
|
|
const state = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SET_CURRENT_LOCALE,
|
|
value: { locale: 'ge' },
|
|
},
|
|
);
|
|
|
|
expect(state.currentLocale).toStrictEqual('ge');
|
|
});
|
|
|
|
it('sets pending tokens', () => {
|
|
const payload = {
|
|
address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4',
|
|
decimals: 18,
|
|
symbol: 'META',
|
|
};
|
|
|
|
const pendingTokensState = reduceMetamask(
|
|
{},
|
|
{
|
|
type: actionConstants.SET_PENDING_TOKENS,
|
|
payload,
|
|
},
|
|
);
|
|
|
|
expect(pendingTokensState.pendingTokens).toStrictEqual(payload);
|
|
});
|
|
|
|
it('clears pending tokens', () => {
|
|
const payload = {
|
|
address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4',
|
|
decimals: 18,
|
|
symbol: 'META',
|
|
};
|
|
|
|
const pendingTokensState = {
|
|
pendingTokens: payload,
|
|
};
|
|
|
|
const state = reduceMetamask(pendingTokensState, {
|
|
type: actionConstants.CLEAR_PENDING_TOKENS,
|
|
});
|
|
|
|
expect(state.pendingTokens).toStrictEqual({});
|
|
});
|
|
|
|
describe('metamask state selectors', () => {
|
|
describe('getBlockGasLimit', () => {
|
|
it('should return the current block gas limit', () => {
|
|
expect(getBlockGasLimit(mockState)).toStrictEqual('0x4c1878');
|
|
});
|
|
});
|
|
|
|
describe('getConversionRate()', () => {
|
|
it('should return the eth conversion rate', () => {
|
|
expect(getConversionRate(mockState)).toStrictEqual(1200.88200327);
|
|
});
|
|
});
|
|
|
|
describe('getNativeCurrency()', () => {
|
|
it('should return the ticker symbol of the selected network', () => {
|
|
expect(getNativeCurrency(mockState)).toStrictEqual('ETH');
|
|
});
|
|
});
|
|
|
|
describe('getSendHexDataFeatureFlagState()', () => {
|
|
it('should return the sendHexData feature flag state', () => {
|
|
expect(getSendHexDataFeatureFlagState(mockState)).toStrictEqual(true);
|
|
});
|
|
});
|
|
|
|
describe('getSendToAccounts()', () => {
|
|
it('should return an array including all the users accounts and the address book', () => {
|
|
expect(getSendToAccounts(mockState)).toStrictEqual([
|
|
{
|
|
code: '0x',
|
|
balance: '0x47c9d71831c76efe',
|
|
nonce: '0x1b',
|
|
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
|
|
name: 'Send Account 1',
|
|
},
|
|
{
|
|
code: '0x',
|
|
balance: '0x37452b1315889f80',
|
|
nonce: '0xa',
|
|
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
|
|
name: 'Send Account 2',
|
|
},
|
|
{
|
|
code: '0x',
|
|
balance: '0x30c9d71831c76efe',
|
|
nonce: '0x1c',
|
|
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
|
|
name: 'Send Account 3',
|
|
},
|
|
{
|
|
code: '0x',
|
|
balance: '0x0',
|
|
nonce: '0x0',
|
|
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
|
|
name: 'Send Account 4',
|
|
},
|
|
{
|
|
address: '0x06195827297c7a80a443b6894d3bdb8824b43896',
|
|
name: 'Address Book Account 1',
|
|
chainId: '0x3',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
it('should return the unapproved txs', () => {
|
|
expect(getUnapprovedTxs(mockState)).toStrictEqual({
|
|
4768706228115573: {
|
|
id: 4768706228115573,
|
|
time: 1487363153561,
|
|
status: TRANSACTION_STATUSES.UNAPPROVED,
|
|
gasMultiplier: 1,
|
|
metamaskNetworkId: '3',
|
|
txParams: {
|
|
from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
|
|
to: '0x18a3462427bcc9133bb46e88bcbe39cd7ef0e761',
|
|
value: '0xde0b6b3a7640000',
|
|
metamaskId: 4768706228115573,
|
|
metamaskNetworkId: '3',
|
|
gas: '0x5209',
|
|
},
|
|
txFee: '17e0186e60800',
|
|
txValue: 'de0b6b3a7640000',
|
|
maxCost: 'de234b52e4a0800',
|
|
gasPrice: '4a817c800',
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('isNotEIP1559Network()', () => {
|
|
it('should return true if network does not supports EIP-1559', () => {
|
|
expect(
|
|
isNotEIP1559Network({
|
|
...mockState,
|
|
metamask: {
|
|
...mockState.metamask,
|
|
networkDetails: {
|
|
EIPS: { 1559: false },
|
|
},
|
|
},
|
|
}),
|
|
).toStrictEqual(true);
|
|
});
|
|
|
|
it('should return false if networkDetails.EIPS.1559 is not false', () => {
|
|
expect(isNotEIP1559Network(mockState)).toStrictEqual(false);
|
|
|
|
expect(
|
|
isNotEIP1559Network({
|
|
...mockState,
|
|
metamask: {
|
|
...mockState.metamask,
|
|
networkDetails: {
|
|
EIPS: { 1559: undefined },
|
|
},
|
|
},
|
|
}),
|
|
).toStrictEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('getIsNetworkBusy', () => {
|
|
it('should return true if state.metamask.gasFeeEstimates.networkCongestion is over the "busy" threshold', () => {
|
|
expect(
|
|
getIsNetworkBusy({
|
|
metamask: { gasFeeEstimates: { networkCongestion: 0.67 } },
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('should return true if state.metamask.gasFeeEstimates.networkCongestion is right at the "busy" threshold', () => {
|
|
expect(
|
|
getIsNetworkBusy({
|
|
metamask: { gasFeeEstimates: { networkCongestion: 0.66 } },
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('should return false if state.metamask.gasFeeEstimates.networkCongestion is not over the "busy" threshold', () => {
|
|
expect(
|
|
getIsNetworkBusy({
|
|
metamask: { gasFeeEstimates: { networkCongestion: 0.65 } },
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
});
|