mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
conflict fixes
This commit is contained in:
parent
f1403f4849
commit
1739ed9710
@ -27,9 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- [#11115](https://github.com/MetaMask/metamask-extension/pull/11115): Hide basic tab in advanced gas modal for speedup and cancel when on testnets
|
- [#11115](https://github.com/MetaMask/metamask-extension/pull/11115): Hide basic tab in advanced gas modal for speedup and cancel when on testnets
|
||||||
- [#11030](https://github.com/MetaMask/metamask-extension/pull/11030): Return a specific error (code 4902) for switchEthereumChain requests for chains that aren't already in the user's wallet.
|
- [#11030](https://github.com/MetaMask/metamask-extension/pull/11030): Return a specific error (code 4902) for switchEthereumChain requests for chains that aren't already in the user's wallet.
|
||||||
- [#11093](https://github.com/MetaMask/metamask-extension/pull/11093): Update all uses of "Seed Phrase" to "Secret Recovery Phrase"
|
- [#11093](https://github.com/MetaMask/metamask-extension/pull/11093): Update all uses of "Seed Phrase" to "Secret Recovery Phrase"
|
||||||
## [9.5.9]
|
|
||||||
### Added
|
|
||||||
- Re-added "Add Ledger Live Support" ([#10293](https://github.com/MetaMask/metamask-extension/pull/10293)), which was reverted in the previous version
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- [#11025](https://github.com/MetaMask/metamask-extension/pull/11025): Fixed redirection to the build quotes page from the swaps page when failure has occured
|
- [#11025](https://github.com/MetaMask/metamask-extension/pull/11025): Fixed redirection to the build quotes page from the swaps page when failure has occured
|
||||||
@ -45,6 +42,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- [#11031](https://github.com/MetaMask/metamask-extension/pull/11031): Fixes error behavior of addEthereumChain
|
- [#11031](https://github.com/MetaMask/metamask-extension/pull/11031): Fixes error behavior of addEthereumChain
|
||||||
|
|
||||||
## [9.5.9]
|
## [9.5.9]
|
||||||
|
### Added
|
||||||
|
- Re-added "Add Ledger Live Support" ([#10293](https://github.com/MetaMask/metamask-extension/pull/10293)), which was reverted in the previous version
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- [#11225](https://github.com/MetaMask/metamask-extension/pull/11225) - Fix persistent display of chrome ledger What's New popup message
|
- [#11225](https://github.com/MetaMask/metamask-extension/pull/11225) - Fix persistent display of chrome ledger What's New popup message
|
||||||
|
|
||||||
|
@ -191,9 +191,4 @@ describe('ComposableObservableStore', function () {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return empty flattened state when not configured', function () {
|
|
||||||
const store = new ComposableObservableStore();
|
|
||||||
assert.deepEqual(store.getFlatState(), {});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,6 @@ import { getTranslatedUINoficiations } from '../../../../shared/notifications';
|
|||||||
import { getSortedNotificationsToShow } from '../../../selectors';
|
import { getSortedNotificationsToShow } from '../../../selectors';
|
||||||
import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes';
|
import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes';
|
||||||
import { TYPOGRAPHY } from '../../../helpers/constants/design-system';
|
import { TYPOGRAPHY } from '../../../helpers/constants/design-system';
|
||||||
import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes';
|
|
||||||
|
|
||||||
function getActionFunctionById(id, history) {
|
function getActionFunctionById(id, history) {
|
||||||
const actionFunctions = {
|
const actionFunctions = {
|
||||||
|
399
ui/ducks/metamask/metamask.test.js
Normal file
399
ui/ducks/metamask/metamask.test.js
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction';
|
||||||
|
import * as actionConstants from '../../store/actionConstants';
|
||||||
|
import reduceMetamask, {
|
||||||
|
getBlockGasLimit,
|
||||||
|
getConversionRate,
|
||||||
|
getNativeCurrency,
|
||||||
|
getSendHexDataFeatureFlagState,
|
||||||
|
getSendToAccounts,
|
||||||
|
getUnapprovedTxs,
|
||||||
|
} 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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
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('updates tokens', () => {
|
||||||
|
const newTokens = {
|
||||||
|
address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4',
|
||||||
|
decimals: 18,
|
||||||
|
symbol: 'META',
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = reduceMetamask(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
type: actionConstants.UPDATE_TOKENS,
|
||||||
|
newTokens,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(state.tokens).toStrictEqual(newTokens);
|
||||||
|
});
|
||||||
|
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
382
ui/ducks/send/send.duck.js
Normal file
382
ui/ducks/send/send.duck.js
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
import log from 'loglevel';
|
||||||
|
import { estimateGas } from '../../store/actions';
|
||||||
|
import { setCustomGasLimit } from '../gas/gas.duck';
|
||||||
|
import {
|
||||||
|
estimateGasForSend,
|
||||||
|
calcTokenBalance,
|
||||||
|
} from '../../pages/send/send.utils';
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN';
|
||||||
|
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN';
|
||||||
|
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS';
|
||||||
|
const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE';
|
||||||
|
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP';
|
||||||
|
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP';
|
||||||
|
const UPDATE_GAS_LIMIT = 'UPDATE_GAS_LIMIT';
|
||||||
|
const UPDATE_GAS_PRICE = 'UPDATE_GAS_PRICE';
|
||||||
|
const UPDATE_GAS_TOTAL = 'UPDATE_GAS_TOTAL';
|
||||||
|
const UPDATE_SEND_HEX_DATA = 'UPDATE_SEND_HEX_DATA';
|
||||||
|
const UPDATE_SEND_TOKEN_BALANCE = 'UPDATE_SEND_TOKEN_BALANCE';
|
||||||
|
const UPDATE_SEND_TO = 'UPDATE_SEND_TO';
|
||||||
|
const UPDATE_SEND_AMOUNT = 'UPDATE_SEND_AMOUNT';
|
||||||
|
const UPDATE_MAX_MODE = 'UPDATE_MAX_MODE';
|
||||||
|
const UPDATE_SEND = 'UPDATE_SEND';
|
||||||
|
const UPDATE_SEND_TOKEN = 'UPDATE_SEND_TOKEN';
|
||||||
|
const CLEAR_SEND = 'CLEAR_SEND';
|
||||||
|
const GAS_LOADING_STARTED = 'GAS_LOADING_STARTED';
|
||||||
|
const GAS_LOADING_FINISHED = 'GAS_LOADING_FINISHED';
|
||||||
|
const UPDATE_SEND_ENS_RESOLUTION = 'UPDATE_SEND_ENS_RESOLUTION';
|
||||||
|
const UPDATE_SEND_ENS_RESOLUTION_ERROR = 'UPDATE_SEND_ENS_RESOLUTION_ERROR';
|
||||||
|
|
||||||
|
const initState = {
|
||||||
|
toDropdownOpen: false,
|
||||||
|
gasButtonGroupShown: true,
|
||||||
|
errors: {},
|
||||||
|
gasLimit: null,
|
||||||
|
gasPrice: null,
|
||||||
|
gasTotal: null,
|
||||||
|
tokenBalance: '0x0',
|
||||||
|
from: '',
|
||||||
|
to: '',
|
||||||
|
amount: '0',
|
||||||
|
memo: '',
|
||||||
|
maxModeOn: false,
|
||||||
|
editingTransactionId: null,
|
||||||
|
toNickname: '',
|
||||||
|
ensResolution: null,
|
||||||
|
ensResolutionError: '',
|
||||||
|
gasIsLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reducer
|
||||||
|
export default function reducer(state = initState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case OPEN_TO_DROPDOWN:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toDropdownOpen: true,
|
||||||
|
};
|
||||||
|
case CLOSE_TO_DROPDOWN:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toDropdownOpen: false,
|
||||||
|
};
|
||||||
|
case UPDATE_SEND_ERRORS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
errors: {
|
||||||
|
...state.errors,
|
||||||
|
...action.value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
case SHOW_GAS_BUTTON_GROUP:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasButtonGroupShown: true,
|
||||||
|
};
|
||||||
|
case HIDE_GAS_BUTTON_GROUP:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasButtonGroupShown: false,
|
||||||
|
};
|
||||||
|
case UPDATE_GAS_LIMIT:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasLimit: action.value,
|
||||||
|
};
|
||||||
|
case UPDATE_GAS_PRICE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasPrice: action.value,
|
||||||
|
};
|
||||||
|
case RESET_SEND_STATE:
|
||||||
|
return { ...initState };
|
||||||
|
case UPDATE_GAS_TOTAL:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasTotal: action.value,
|
||||||
|
};
|
||||||
|
case UPDATE_SEND_TOKEN_BALANCE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tokenBalance: action.value,
|
||||||
|
};
|
||||||
|
case UPDATE_SEND_HEX_DATA:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
data: action.value,
|
||||||
|
};
|
||||||
|
case UPDATE_SEND_TO:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
to: action.value.to,
|
||||||
|
toNickname: action.value.nickname,
|
||||||
|
};
|
||||||
|
case UPDATE_SEND_AMOUNT:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
amount: action.value,
|
||||||
|
};
|
||||||
|
case UPDATE_MAX_MODE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
maxModeOn: action.value,
|
||||||
|
};
|
||||||
|
case UPDATE_SEND:
|
||||||
|
return Object.assign(state, action.value);
|
||||||
|
case UPDATE_SEND_TOKEN: {
|
||||||
|
const newSend = {
|
||||||
|
...state,
|
||||||
|
token: action.value,
|
||||||
|
};
|
||||||
|
// erase token-related state when switching back to native currency
|
||||||
|
if (newSend.editingTransactionId && !newSend.token) {
|
||||||
|
const unapprovedTx =
|
||||||
|
newSend?.unapprovedTxs?.[newSend.editingTransactionId] || {};
|
||||||
|
const txParams = unapprovedTx.txParams || {};
|
||||||
|
Object.assign(newSend, {
|
||||||
|
tokenBalance: null,
|
||||||
|
balance: '0',
|
||||||
|
from: unapprovedTx.from || '',
|
||||||
|
unapprovedTxs: {
|
||||||
|
...newSend.unapprovedTxs,
|
||||||
|
[newSend.editingTransactionId]: {
|
||||||
|
...unapprovedTx,
|
||||||
|
txParams: {
|
||||||
|
...txParams,
|
||||||
|
data: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Object.assign(state, newSend);
|
||||||
|
}
|
||||||
|
case UPDATE_SEND_ENS_RESOLUTION:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
ensResolution: action.payload,
|
||||||
|
ensResolutionError: '',
|
||||||
|
};
|
||||||
|
case UPDATE_SEND_ENS_RESOLUTION_ERROR:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
ensResolution: null,
|
||||||
|
ensResolutionError: action.payload,
|
||||||
|
};
|
||||||
|
case CLEAR_SEND:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasLimit: null,
|
||||||
|
gasPrice: null,
|
||||||
|
gasTotal: null,
|
||||||
|
tokenBalance: null,
|
||||||
|
from: '',
|
||||||
|
to: '',
|
||||||
|
amount: '0x0',
|
||||||
|
memo: '',
|
||||||
|
errors: {},
|
||||||
|
maxModeOn: false,
|
||||||
|
editingTransactionId: null,
|
||||||
|
toNickname: '',
|
||||||
|
};
|
||||||
|
case GAS_LOADING_STARTED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasIsLoading: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
case GAS_LOADING_FINISHED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gasIsLoading: false,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action Creators
|
||||||
|
export function openToDropdown() {
|
||||||
|
return { type: OPEN_TO_DROPDOWN };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeToDropdown() {
|
||||||
|
return { type: CLOSE_TO_DROPDOWN };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showGasButtonGroup() {
|
||||||
|
return { type: SHOW_GAS_BUTTON_GROUP };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hideGasButtonGroup() {
|
||||||
|
return { type: HIDE_GAS_BUTTON_GROUP };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendErrors(errorObject) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_ERRORS,
|
||||||
|
value: errorObject,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetSendState() {
|
||||||
|
return { type: RESET_SEND_STATE };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setGasLimit(gasLimit) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_GAS_LIMIT,
|
||||||
|
value: gasLimit,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setGasPrice(gasPrice) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_GAS_PRICE,
|
||||||
|
value: gasPrice,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setGasTotal(gasTotal) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_GAS_TOTAL,
|
||||||
|
value: gasTotal,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateGasData({
|
||||||
|
gasPrice,
|
||||||
|
blockGasLimit,
|
||||||
|
selectedAddress,
|
||||||
|
sendToken,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(gasLoadingStarted());
|
||||||
|
return estimateGasForSend({
|
||||||
|
estimateGasMethod: estimateGas,
|
||||||
|
blockGasLimit,
|
||||||
|
selectedAddress,
|
||||||
|
sendToken,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
|
estimateGasPrice: gasPrice,
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
.then((gas) => {
|
||||||
|
dispatch(setGasLimit(gas));
|
||||||
|
dispatch(setCustomGasLimit(gas));
|
||||||
|
dispatch(updateSendErrors({ gasLoadingError: null }));
|
||||||
|
dispatch(gasLoadingFinished());
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
log.error(err);
|
||||||
|
dispatch(updateSendErrors({ gasLoadingError: 'gasLoadingError' }));
|
||||||
|
dispatch(gasLoadingFinished());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function gasLoadingStarted() {
|
||||||
|
return {
|
||||||
|
type: GAS_LOADING_STARTED,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function gasLoadingFinished() {
|
||||||
|
return {
|
||||||
|
type: GAS_LOADING_FINISHED,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendTokenBalance({ sendToken, tokenContract, address }) {
|
||||||
|
return (dispatch) => {
|
||||||
|
const tokenBalancePromise = tokenContract
|
||||||
|
? tokenContract.balanceOf(address)
|
||||||
|
: Promise.resolve();
|
||||||
|
return tokenBalancePromise
|
||||||
|
.then((usersToken) => {
|
||||||
|
if (usersToken) {
|
||||||
|
const newTokenBalance = calcTokenBalance({ sendToken, usersToken });
|
||||||
|
dispatch(setSendTokenBalance(newTokenBalance));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
log.error(err);
|
||||||
|
updateSendErrors({ tokenBalance: 'tokenBalanceError' });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setSendTokenBalance(tokenBalance) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_TOKEN_BALANCE,
|
||||||
|
value: tokenBalance,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendHexData(value) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_HEX_DATA,
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendTo(to, nickname = '') {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_TO,
|
||||||
|
value: { to, nickname },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendAmount(amount) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_AMOUNT,
|
||||||
|
value: amount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setMaxModeTo(bool) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_MAX_MODE,
|
||||||
|
value: bool,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSend(newSend) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND,
|
||||||
|
value: newSend,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendToken(token) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_TOKEN,
|
||||||
|
value: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearSend() {
|
||||||
|
return {
|
||||||
|
type: CLEAR_SEND,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendEnsResolution(ensResolution) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_ENS_RESOLUTION,
|
||||||
|
payload: ensResolution,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSendEnsResolutionError(errorMessage) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_ENS_RESOLUTION_ERROR,
|
||||||
|
payload: errorMessage,
|
||||||
|
};
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`IntroPopup renders the component with initial props 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="intro-popup"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
`;
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './intro-popup';
|
|
@ -1,71 +0,0 @@
|
|||||||
.intro-popup {
|
|
||||||
&__liquidity-sources-label {
|
|
||||||
@include H7;
|
|
||||||
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
color: $Black-100;
|
|
||||||
|
|
||||||
@media screen and (min-width: 576px) {
|
|
||||||
@include H6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__learn-more-header {
|
|
||||||
@include H4;
|
|
||||||
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__learn-more-link {
|
|
||||||
@include H6;
|
|
||||||
|
|
||||||
color: $Blue-500;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
margin-left: 24px;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
width: 96%;
|
|
||||||
margin-left: -9px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__footer {
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__button {
|
|
||||||
border-radius: 100px;
|
|
||||||
height: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__source-logo-container {
|
|
||||||
width: 276px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20px 16px;
|
|
||||||
background: $Grey-000;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
@media screen and (min-width: 576px) {
|
|
||||||
width: 412px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 364px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__popover {
|
|
||||||
@media screen and (min-width: 576px) {
|
|
||||||
width: 460px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
import React, { useContext } from 'react';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { setSwapsFromToken } from '../../../ducks/swaps/swaps';
|
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
|
||||||
import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes';
|
|
||||||
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
|
|
||||||
import { getSwapsDefaultToken } from '../../../selectors';
|
|
||||||
import Button from '../../../components/ui/button';
|
|
||||||
import Popover from '../../../components/ui/popover';
|
|
||||||
|
|
||||||
export default function IntroPopup({ onClose }) {
|
|
||||||
const dispatch = useDispatch(useDispatch);
|
|
||||||
const history = useHistory();
|
|
||||||
const t = useContext(I18nContext);
|
|
||||||
|
|
||||||
const swapsDefaultToken = useSelector(getSwapsDefaultToken);
|
|
||||||
const enteredSwapsEvent = useNewMetricEvent({
|
|
||||||
event: 'Swaps Opened',
|
|
||||||
properties: {
|
|
||||||
source: 'Intro popup',
|
|
||||||
active_currency: swapsDefaultToken.symbol,
|
|
||||||
},
|
|
||||||
category: 'swaps',
|
|
||||||
});
|
|
||||||
const blogPostVisitedEvent = useNewMetricEvent({
|
|
||||||
event: 'Blog Post Visited ',
|
|
||||||
category: 'swaps',
|
|
||||||
});
|
|
||||||
const contractAuditVisitedEvent = useNewMetricEvent({
|
|
||||||
event: 'Contract Audit Visited',
|
|
||||||
category: 'swaps',
|
|
||||||
});
|
|
||||||
const productOverviewDismissedEvent = useNewMetricEvent({
|
|
||||||
event: 'Product Overview Dismissed',
|
|
||||||
category: 'swaps',
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="intro-popup">
|
|
||||||
<Popover
|
|
||||||
className="intro-popup__popover"
|
|
||||||
title={t('swapIntroPopupTitle')}
|
|
||||||
subtitle={t('swapIntroPopupSubTitle')}
|
|
||||||
onClose={() => {
|
|
||||||
productOverviewDismissedEvent();
|
|
||||||
onClose();
|
|
||||||
}}
|
|
||||||
footerClassName="intro-popup__footer"
|
|
||||||
footer={
|
|
||||||
<Button
|
|
||||||
type="confirm"
|
|
||||||
className="intro-popup__button"
|
|
||||||
onClick={() => {
|
|
||||||
onClose();
|
|
||||||
enteredSwapsEvent();
|
|
||||||
dispatch(setSwapsFromToken(swapsDefaultToken));
|
|
||||||
history.push(BUILD_QUOTE_ROUTE);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('swapStartSwapping')}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className="intro-popup__content">
|
|
||||||
<div className="intro-popup__liquidity-sources-label">
|
|
||||||
{t('swapIntroLiquiditySourcesLabel')}
|
|
||||||
</div>
|
|
||||||
<div className="intro-popup__source-logo-container">
|
|
||||||
<img src="images/source-logos-all.svg" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="intro-popup__learn-more-header">
|
|
||||||
{t('swapIntroLearnMoreHeader')}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="intro-popup__learn-more-link"
|
|
||||||
onClick={() => {
|
|
||||||
global.platform.openTab({
|
|
||||||
url:
|
|
||||||
'https://medium.com/metamask/introducing-metamask-swaps-84318c643785',
|
|
||||||
});
|
|
||||||
blogPostVisitedEvent();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('swapIntroLearnMoreLink')}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="intro-popup__learn-more-link"
|
|
||||||
onClick={() => {
|
|
||||||
global.platform.openTab({
|
|
||||||
url:
|
|
||||||
'https://diligence.consensys.net/audits/private/lsjipyllnw2/',
|
|
||||||
});
|
|
||||||
contractAuditVisitedEvent();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('swapLearnMoreContractsAuditReview')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
IntroPopup.propTypes = {
|
|
||||||
onClose: PropTypes.func.isRequired,
|
|
||||||
};
|
|
@ -1,24 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import configureMockStore from 'redux-mock-store';
|
|
||||||
|
|
||||||
import {
|
|
||||||
renderWithProvider,
|
|
||||||
createSwapsMockStore,
|
|
||||||
} from '../../../../test/jest';
|
|
||||||
import IntroPopup from '.';
|
|
||||||
|
|
||||||
const createProps = (customProps = {}) => {
|
|
||||||
return {
|
|
||||||
onClose: jest.fn(),
|
|
||||||
...customProps,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('IntroPopup', () => {
|
|
||||||
it('renders the component with initial props', () => {
|
|
||||||
const store = configureMockStore()(createSwapsMockStore());
|
|
||||||
const props = createProps();
|
|
||||||
const { container } = renderWithProvider(<IntroPopup {...props} />, store);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue
Block a user