conflict fixes

feature/default_network_editable
ryanml 4 years ago
parent f1403f4849
commit 1739ed9710
  1. 6
      CHANGELOG.md
  2. 5
      app/scripts/lib/ComposableObservableStore.test.js
  3. 1
      ui/components/app/whats-new-popup/whats-new-popup.js
  4. 399
      ui/ducks/metamask/metamask.test.js
  5. 382
      ui/ducks/send/send.duck.js
  6. 9
      ui/pages/swaps/intro-popup/__snapshots__/intro-popup.test.js.snap
  7. 1
      ui/pages/swaps/intro-popup/index.js
  8. 71
      ui/pages/swaps/intro-popup/index.scss
  9. 108
      ui/pages/swaps/intro-popup/intro-popup.js
  10. 24
      ui/pages/swaps/intro-popup/intro-popup.test.js

@ -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 = {

@ -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',
},
});
});
});
});

@ -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…
Cancel
Save