mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Show a tx link and the "create a new swap" link for STX (#14995)
This commit is contained in:
parent
6553b9a29b
commit
8cbfa2ea9e
@ -17,7 +17,6 @@ import {
|
|||||||
getUSDConversionRate,
|
getUSDConversionRate,
|
||||||
isHardwareWallet,
|
isHardwareWallet,
|
||||||
getHardwareWalletType,
|
getHardwareWalletType,
|
||||||
getSwapsDefaultToken,
|
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -34,10 +33,8 @@ import {
|
|||||||
getCurrentSmartTransactionsEnabled,
|
getCurrentSmartTransactionsEnabled,
|
||||||
getFromTokenInputValue,
|
getFromTokenInputValue,
|
||||||
getMaxSlippage,
|
getMaxSlippage,
|
||||||
setSwapsFromToken,
|
|
||||||
} from '../../../ducks/swaps/swaps';
|
} from '../../../ducks/swaps/swaps';
|
||||||
import Mascot from '../../../components/ui/mascot';
|
import Mascot from '../../../components/ui/mascot';
|
||||||
import Box from '../../../components/ui/box';
|
|
||||||
import {
|
import {
|
||||||
QUOTES_EXPIRED_ERROR,
|
QUOTES_EXPIRED_ERROR,
|
||||||
SWAP_FAILED_ERROR,
|
SWAP_FAILED_ERROR,
|
||||||
@ -56,10 +53,11 @@ import { stopPollingForQuotes } from '../../../store/actions';
|
|||||||
import { getRenderableNetworkFeesForQuote } from '../swaps.util';
|
import { getRenderableNetworkFeesForQuote } from '../swaps.util';
|
||||||
import SwapsFooter from '../swaps-footer';
|
import SwapsFooter from '../swaps-footer';
|
||||||
|
|
||||||
|
import CreateNewSwap from '../create-new-swap';
|
||||||
|
import ViewOnBlockExplorer from '../view-on-block-explorer';
|
||||||
import SwapFailureIcon from './swap-failure-icon';
|
import SwapFailureIcon from './swap-failure-icon';
|
||||||
import SwapSuccessIcon from './swap-success-icon';
|
import SwapSuccessIcon from './swap-success-icon';
|
||||||
import QuotesTimeoutIcon from './quotes-timeout-icon';
|
import QuotesTimeoutIcon from './quotes-timeout-icon';
|
||||||
import ViewOnEtherScanLink from './view-on-ether-scan-link';
|
|
||||||
|
|
||||||
export default function AwaitingSwap({
|
export default function AwaitingSwap({
|
||||||
swapComplete,
|
swapComplete,
|
||||||
@ -85,8 +83,6 @@ export default function AwaitingSwap({
|
|||||||
const usdConversionRate = useSelector(getUSDConversionRate);
|
const usdConversionRate = useSelector(getUSDConversionRate);
|
||||||
const chainId = useSelector(getCurrentChainId);
|
const chainId = useSelector(getCurrentChainId);
|
||||||
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
||||||
const defaultSwapsToken = useSelector(getSwapsDefaultToken, isEqual);
|
|
||||||
|
|
||||||
const [trackedQuotesExpiredEvent, setTrackedQuotesExpiredEvent] = useState(
|
const [trackedQuotesExpiredEvent, setTrackedQuotesExpiredEvent] = useState(
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
@ -141,11 +137,6 @@ export default function AwaitingSwap({
|
|||||||
{ blockExplorerUrl: baseNetworkUrl },
|
{ blockExplorerUrl: baseNetworkUrl },
|
||||||
);
|
);
|
||||||
|
|
||||||
const isCustomBlockExplorerUrl = Boolean(
|
|
||||||
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ||
|
|
||||||
rpcPrefs.blockExplorerUrl,
|
|
||||||
);
|
|
||||||
|
|
||||||
let headerText;
|
let headerText;
|
||||||
let statusImage;
|
let statusImage;
|
||||||
let descriptionText;
|
let descriptionText;
|
||||||
@ -173,10 +164,9 @@ export default function AwaitingSwap({
|
|||||||
submitText = t('tryAgain');
|
submitText = t('tryAgain');
|
||||||
statusImage = <SwapFailureIcon />;
|
statusImage = <SwapFailureIcon />;
|
||||||
content = blockExplorerUrl && (
|
content = blockExplorerUrl && (
|
||||||
<ViewOnEtherScanLink
|
<ViewOnBlockExplorer
|
||||||
txHash={txHash}
|
|
||||||
blockExplorerUrl={blockExplorerUrl}
|
blockExplorerUrl={blockExplorerUrl}
|
||||||
isCustomBlockExplorerUrl={isCustomBlockExplorerUrl}
|
sensitiveTrackingProperties={sensitiveProperties}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (errorKey === QUOTES_EXPIRED_ERROR) {
|
} else if (errorKey === QUOTES_EXPIRED_ERROR) {
|
||||||
@ -221,10 +211,9 @@ export default function AwaitingSwap({
|
|||||||
</span>,
|
</span>,
|
||||||
]);
|
]);
|
||||||
content = blockExplorerUrl && (
|
content = blockExplorerUrl && (
|
||||||
<ViewOnEtherScanLink
|
<ViewOnBlockExplorer
|
||||||
txHash={txHash}
|
|
||||||
blockExplorerUrl={blockExplorerUrl}
|
blockExplorerUrl={blockExplorerUrl}
|
||||||
isCustomBlockExplorerUrl={isCustomBlockExplorerUrl}
|
sensitiveTrackingProperties={sensitiveProperties}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (!errorKey && swapComplete) {
|
} else if (!errorKey && swapComplete) {
|
||||||
@ -240,35 +229,13 @@ export default function AwaitingSwap({
|
|||||||
</span>,
|
</span>,
|
||||||
]);
|
]);
|
||||||
content = blockExplorerUrl && (
|
content = blockExplorerUrl && (
|
||||||
<ViewOnEtherScanLink
|
<ViewOnBlockExplorer
|
||||||
txHash={txHash}
|
|
||||||
blockExplorerUrl={blockExplorerUrl}
|
blockExplorerUrl={blockExplorerUrl}
|
||||||
isCustomBlockExplorerUrl={isCustomBlockExplorerUrl}
|
sensitiveTrackingProperties={sensitiveProperties}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MakeAnotherSwap = () => {
|
|
||||||
return (
|
|
||||||
<Box marginBottom={3}>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
onClick={async () => {
|
|
||||||
trackEvent({
|
|
||||||
event: 'Make Another Swap',
|
|
||||||
category: EVENT.CATEGORIES.SWAPS,
|
|
||||||
sensitiveProperties,
|
|
||||||
});
|
|
||||||
await dispatch(navigateBackToBuildQuote(history));
|
|
||||||
dispatch(setSwapsFromToken(defaultSwapsToken));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('makeAnotherSwap')}
|
|
||||||
</a>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (errorKey) {
|
if (errorKey) {
|
||||||
// If there was an error, stop polling for quotes.
|
// If there was an error, stop polling for quotes.
|
||||||
@ -291,7 +258,9 @@ export default function AwaitingSwap({
|
|||||||
<div className="awaiting-swap__main-description">{descriptionText}</div>
|
<div className="awaiting-swap__main-description">{descriptionText}</div>
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
{!errorKey && swapComplete ? <MakeAnotherSwap /> : null}
|
{!errorKey && swapComplete ? (
|
||||||
|
<CreateNewSwap sensitiveTrackingProperties={sensitiveProperties} />
|
||||||
|
) : null}
|
||||||
<SwapsFooter
|
<SwapsFooter
|
||||||
onSubmit={async () => {
|
onSubmit={async () => {
|
||||||
if (errorKey === OFFLINE_FOR_MAINTENANCE) {
|
if (errorKey === OFFLINE_FOR_MAINTENANCE) {
|
||||||
|
@ -20,10 +20,6 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--color-primary-default);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__status-image {
|
&__status-image {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
@ -64,7 +60,6 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__view-on-etherscan,
|
|
||||||
&__support-link {
|
&__support-link {
|
||||||
color: var(--color-primary-default);
|
color: var(--color-primary-default);
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
@ -75,20 +70,6 @@
|
|||||||
@include H6;
|
@include H6;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__view-on-etherscan {
|
|
||||||
@include H7;
|
|
||||||
|
|
||||||
transition: opacity 1s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__view-on-etherscan--invisible {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__view-on-etherscan--visible {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__amount-and-symbol {
|
&__amount-and-symbol {
|
||||||
color: var(--color-text-default);
|
color: var(--color-text-default);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`ViewOnEtherScanLink renders the component with a custom block explorer link 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="awaiting-swap__view-on-etherscan awaiting-swap__view-on-etherscan--visible"
|
|
||||||
>
|
|
||||||
View Swap at custom-blockchain.explorer
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ViewOnEtherScanLink renders the component with initial props 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="awaiting-swap__view-on-etherscan awaiting-swap__view-on-etherscan--visible"
|
|
||||||
>
|
|
||||||
View Swap on Etherscan
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './view-on-ether-scan-link';
|
|
@ -1,50 +0,0 @@
|
|||||||
import React, { useContext } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { I18nContext } from '../../../../contexts/i18n';
|
|
||||||
import { getURLHostName } from '../../../../helpers/utils/util';
|
|
||||||
import { MetaMetricsContext } from '../../../../contexts/metametrics';
|
|
||||||
import { EVENT } from '../../../../../shared/constants/metametrics';
|
|
||||||
|
|
||||||
export default function ViewOnEtherScanLink({
|
|
||||||
txHash,
|
|
||||||
blockExplorerUrl,
|
|
||||||
isCustomBlockExplorerUrl,
|
|
||||||
}) {
|
|
||||||
const t = useContext(I18nContext);
|
|
||||||
const trackEvent = useContext(MetaMetricsContext);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classnames('awaiting-swap__view-on-etherscan', {
|
|
||||||
'awaiting-swap__view-on-etherscan--visible': txHash,
|
|
||||||
'awaiting-swap__view-on-etherscan--invisible': !txHash,
|
|
||||||
})}
|
|
||||||
onClick={() => {
|
|
||||||
trackEvent({
|
|
||||||
event: 'Clicked Block Explorer Link',
|
|
||||||
category: EVENT.CATEGORIES.SWAPS,
|
|
||||||
properties: {
|
|
||||||
link_type: 'Transaction Block Explorer',
|
|
||||||
action: 'Swap Transaction',
|
|
||||||
block_explorer_domain: getURLHostName(blockExplorerUrl),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
global.platform.openTab({ url: blockExplorerUrl });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isCustomBlockExplorerUrl
|
|
||||||
? t('viewOnCustomBlockExplorer', [
|
|
||||||
t('blockExplorerSwapAction'),
|
|
||||||
getURLHostName(blockExplorerUrl),
|
|
||||||
])
|
|
||||||
: t('viewOnEtherscan', [t('blockExplorerSwapAction')])}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewOnEtherScanLink.propTypes = {
|
|
||||||
txHash: PropTypes.string,
|
|
||||||
blockExplorerUrl: PropTypes.string,
|
|
||||||
isCustomBlockExplorerUrl: PropTypes.bool,
|
|
||||||
};
|
|
@ -1,39 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { renderWithProvider } from '../../../../../test/jest';
|
|
||||||
import ViewOnEtherScanLink from '.';
|
|
||||||
|
|
||||||
const createProps = (customProps = {}) => {
|
|
||||||
return {
|
|
||||||
txHash:
|
|
||||||
'0x58e5a0fc7fbc849eddc100d44e86276168a8c7baaa5604e44ba6f5eb8ba1b7eb',
|
|
||||||
blockExplorerUrl: 'https://block.explorer',
|
|
||||||
isCustomBlockExplorerUrl: false,
|
|
||||||
...customProps,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('ViewOnEtherScanLink', () => {
|
|
||||||
it('renders the component with initial props', () => {
|
|
||||||
const { container, getByText } = renderWithProvider(
|
|
||||||
<ViewOnEtherScanLink {...createProps()} />,
|
|
||||||
);
|
|
||||||
expect(getByText('View Swap on Etherscan')).toBeInTheDocument();
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders the component with a custom block explorer link', () => {
|
|
||||||
const { container, getByText } = renderWithProvider(
|
|
||||||
<ViewOnEtherScanLink
|
|
||||||
{...createProps({
|
|
||||||
blockExplorerUrl: 'https://custom-blockchain.explorer',
|
|
||||||
isCustomBlockExplorerUrl: true,
|
|
||||||
})}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
getByText('View Swap at custom-blockchain.explorer'),
|
|
||||||
).toBeInTheDocument();
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
47
ui/pages/swaps/create-new-swap/create-new-swap.js
Normal file
47
ui/pages/swaps/create-new-swap/create-new-swap.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import isEqual from 'lodash/isEqual';
|
||||||
|
|
||||||
|
import Box from '../../../components/ui/box';
|
||||||
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
|
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||||
|
import { EVENT } from '../../../../shared/constants/metametrics';
|
||||||
|
import {
|
||||||
|
navigateBackToBuildQuote,
|
||||||
|
setSwapsFromToken,
|
||||||
|
} from '../../../ducks/swaps/swaps';
|
||||||
|
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
|
||||||
|
import { getSwapsDefaultToken } from '../../../selectors';
|
||||||
|
|
||||||
|
export default function CreateNewSwap({ sensitiveTrackingProperties }) {
|
||||||
|
const t = useContext(I18nContext);
|
||||||
|
const trackEvent = useContext(MetaMetricsContext);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const history = useHistory();
|
||||||
|
const defaultSwapsToken = useSelector(getSwapsDefaultToken, isEqual);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box marginBottom={3} className="create-new-swap">
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
trackEvent({
|
||||||
|
event: 'Make Another Swap',
|
||||||
|
category: EVENT.CATEGORIES.SWAPS,
|
||||||
|
sensitiveProperties: sensitiveTrackingProperties,
|
||||||
|
});
|
||||||
|
history.push(DEFAULT_ROUTE); // It cleans up Swaps state.
|
||||||
|
await dispatch(navigateBackToBuildQuote(history));
|
||||||
|
dispatch(setSwapsFromToken(defaultSwapsToken));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('makeAnotherSwap')}
|
||||||
|
</button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateNewSwap.propTypes = {
|
||||||
|
sensitiveTrackingProperties: PropTypes.object.isRequired,
|
||||||
|
};
|
27
ui/pages/swaps/create-new-swap/create-new-swap.test.js
Normal file
27
ui/pages/swaps/create-new-swap/create-new-swap.test.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import configureMockStore from 'redux-mock-store';
|
||||||
|
|
||||||
|
import {
|
||||||
|
renderWithProvider,
|
||||||
|
createSwapsMockStore,
|
||||||
|
} from '../../../../test/jest';
|
||||||
|
import CreateNewSwap from '.';
|
||||||
|
|
||||||
|
const createProps = (customProps = {}) => {
|
||||||
|
return {
|
||||||
|
sensitiveProperties: {},
|
||||||
|
...customProps,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('CreateNewSwap', () => {
|
||||||
|
it('renders the component with initial props', () => {
|
||||||
|
const store = configureMockStore()(createSwapsMockStore());
|
||||||
|
const props = createProps();
|
||||||
|
const { getByText } = renderWithProvider(
|
||||||
|
<CreateNewSwap {...props} />,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(getByText('Create a new swap')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
1
ui/pages/swaps/create-new-swap/index.js
Normal file
1
ui/pages/swaps/create-new-swap/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './create-new-swap';
|
8
ui/pages/swaps/create-new-swap/index.scss
Normal file
8
ui/pages/swaps/create-new-swap/index.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.create-new-swap {
|
||||||
|
button {
|
||||||
|
@include H5;
|
||||||
|
|
||||||
|
color: var(--color-primary-default);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,8 @@
|
|||||||
@import 'swaps-footer/index';
|
@import 'swaps-footer/index';
|
||||||
@import 'view-quote/index';
|
@import 'view-quote/index';
|
||||||
@import 'import-token/index';
|
@import 'import-token/index';
|
||||||
|
@import 'create-new-swap/index';
|
||||||
|
@import 'view-on-block-explorer/index';
|
||||||
|
|
||||||
.swaps {
|
.swaps {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { getBlockExplorerLink } from '@metamask/etherscan-link';
|
||||||
|
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
import {
|
import {
|
||||||
@ -22,7 +23,9 @@ import {
|
|||||||
getUSDConversionRate,
|
getUSDConversionRate,
|
||||||
conversionRateSelector,
|
conversionRateSelector,
|
||||||
getCurrentCurrency,
|
getCurrentCurrency,
|
||||||
|
getRpcPrefsForCurrentProvider,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
|
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps';
|
||||||
import { getNativeCurrency } from '../../../ducks/metamask/metamask';
|
import { getNativeCurrency } from '../../../ducks/metamask/metamask';
|
||||||
import {
|
import {
|
||||||
DEFAULT_ROUTE,
|
DEFAULT_ROUTE,
|
||||||
@ -54,6 +57,8 @@ import {
|
|||||||
getFeeForSmartTransaction,
|
getFeeForSmartTransaction,
|
||||||
} from '../swaps.util';
|
} from '../swaps.util';
|
||||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||||
|
import CreateNewSwap from '../create-new-swap';
|
||||||
|
import ViewOnBlockExplorer from '../view-on-block-explorer';
|
||||||
import SuccessIcon from './success-icon';
|
import SuccessIcon from './success-icon';
|
||||||
import RevertedIcon from './reverted-icon';
|
import RevertedIcon from './reverted-icon';
|
||||||
import CanceledIcon from './canceled-icon';
|
import CanceledIcon from './canceled-icon';
|
||||||
@ -79,12 +84,17 @@ export default function SmartTransactionStatus() {
|
|||||||
const smartTransactionsOptInStatus = useSelector(
|
const smartTransactionsOptInStatus = useSelector(
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
|
const chainId = useSelector(getCurrentChainId);
|
||||||
|
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
||||||
const swapsNetworkConfig = useSelector(getSwapsNetworkConfig);
|
const swapsNetworkConfig = useSelector(getSwapsNetworkConfig);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
const currentSmartTransactionsEnabled = useSelector(
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
getCurrentSmartTransactionsEnabled,
|
getCurrentSmartTransactionsEnabled,
|
||||||
);
|
);
|
||||||
const chainId = useSelector(getCurrentChainId);
|
const baseNetworkUrl =
|
||||||
|
rpcPrefs.blockExplorerUrl ??
|
||||||
|
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ??
|
||||||
|
null;
|
||||||
const nativeCurrencySymbol = useSelector(getNativeCurrency);
|
const nativeCurrencySymbol = useSelector(getNativeCurrency);
|
||||||
const conversionRate = useSelector(conversionRateSelector);
|
const conversionRate = useSelector(conversionRateSelector);
|
||||||
const USDConversionRate = useSelector(getUSDConversionRate);
|
const USDConversionRate = useSelector(getUSDConversionRate);
|
||||||
@ -139,6 +149,7 @@ export default function SmartTransactionStatus() {
|
|||||||
const showCloseButtonOnly =
|
const showCloseButtonOnly =
|
||||||
isSmartTransactionPending ||
|
isSmartTransactionPending ||
|
||||||
smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS;
|
smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS;
|
||||||
|
const txHash = latestSmartTransaction?.statusMetadata?.minedHash;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
trackEvent({
|
trackEvent({
|
||||||
@ -190,6 +201,7 @@ export default function SmartTransactionStatus() {
|
|||||||
let description;
|
let description;
|
||||||
let subDescription;
|
let subDescription;
|
||||||
let icon;
|
let icon;
|
||||||
|
let blockExplorerUrl;
|
||||||
if (isSmartTransactionPending) {
|
if (isSmartTransactionPending) {
|
||||||
if (cancelSwapLinkClicked) {
|
if (cancelSwapLinkClicked) {
|
||||||
headerText = t('stxTryingToCancel');
|
headerText = t('stxTryingToCancel');
|
||||||
@ -238,6 +250,12 @@ export default function SmartTransactionStatus() {
|
|||||||
]);
|
]);
|
||||||
icon = <RevertedIcon />;
|
icon = <RevertedIcon />;
|
||||||
}
|
}
|
||||||
|
if (txHash && latestSmartTransactionUuid) {
|
||||||
|
blockExplorerUrl = getBlockExplorerLink(
|
||||||
|
{ hash: txHash, chainId },
|
||||||
|
{ blockExplorerUrl: baseNetworkUrl },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const showCancelSwapLink =
|
const showCancelSwapLink =
|
||||||
latestSmartTransaction.cancellable && !cancelSwapLinkClicked;
|
latestSmartTransaction.cancellable && !cancelSwapLinkClicked;
|
||||||
@ -397,12 +415,18 @@ export default function SmartTransactionStatus() {
|
|||||||
{description && (
|
{description && (
|
||||||
<Typography
|
<Typography
|
||||||
variant={TYPOGRAPHY.H6}
|
variant={TYPOGRAPHY.H6}
|
||||||
boxProps={{ marginTop: 0 }}
|
boxProps={{ ...(blockExplorerUrl && { margin: [1, 0, 0] }) }}
|
||||||
color={COLORS.TEXT_ALTERNATIVE}
|
color={COLORS.TEXT_ALTERNATIVE}
|
||||||
>
|
>
|
||||||
{description}
|
{description}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
{blockExplorerUrl && (
|
||||||
|
<ViewOnBlockExplorer
|
||||||
|
blockExplorerUrl={blockExplorerUrl}
|
||||||
|
sensitiveTrackingProperties={sensitiveProperties}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Box
|
<Box
|
||||||
marginTop={3}
|
marginTop={3}
|
||||||
className="smart-transaction-status__background-animation smart-transaction-status__background-animation--bottom"
|
className="smart-transaction-status__background-animation smart-transaction-status__background-animation--bottom"
|
||||||
@ -420,6 +444,9 @@ export default function SmartTransactionStatus() {
|
|||||||
{showCancelSwapLink &&
|
{showCancelSwapLink &&
|
||||||
latestSmartTransactionUuid &&
|
latestSmartTransactionUuid &&
|
||||||
isSmartTransactionPending && <CancelSwap />}
|
isSmartTransactionPending && <CancelSwap />}
|
||||||
|
{smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS ? (
|
||||||
|
<CreateNewSwap sensitiveTrackingProperties={sensitiveProperties} />
|
||||||
|
) : null}
|
||||||
<SwapsFooter
|
<SwapsFooter
|
||||||
onSubmit={async () => {
|
onSubmit={async () => {
|
||||||
if (showCloseButtonOnly) {
|
if (showCloseButtonOnly) {
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`ViewOnBlockExplorer renders the component with initial props 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="box view-on-block-explorer box--margin-top-6 box--flex-direction-row"
|
||||||
|
>
|
||||||
|
<button>
|
||||||
|
View Swap at etherscan.io
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
1
ui/pages/swaps/view-on-block-explorer/index.js
Normal file
1
ui/pages/swaps/view-on-block-explorer/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './view-on-block-explorer';
|
8
ui/pages/swaps/view-on-block-explorer/index.scss
Normal file
8
ui/pages/swaps/view-on-block-explorer/index.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.view-on-block-explorer {
|
||||||
|
button {
|
||||||
|
@include H7;
|
||||||
|
|
||||||
|
color: var(--color-primary-default);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Box from '../../../components/ui/box';
|
||||||
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
|
import { getURLHostName } from '../../../helpers/utils/util';
|
||||||
|
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||||
|
import { EVENT } from '../../../../shared/constants/metametrics';
|
||||||
|
|
||||||
|
export default function ViewOnBlockExplorer({
|
||||||
|
blockExplorerUrl,
|
||||||
|
sensitiveTrackingProperties,
|
||||||
|
}) {
|
||||||
|
const t = useContext(I18nContext);
|
||||||
|
const trackEvent = useContext(MetaMetricsContext);
|
||||||
|
const blockExplorerHostName = getURLHostName(blockExplorerUrl);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box marginTop={6} className="view-on-block-explorer">
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
trackEvent({
|
||||||
|
event: 'Clicked Block Explorer Link',
|
||||||
|
category: EVENT.CATEGORIES.SWAPS,
|
||||||
|
sensitiveProperties: sensitiveTrackingProperties,
|
||||||
|
properties: {
|
||||||
|
link_type: 'Transaction Block Explorer',
|
||||||
|
action: 'Swap Transaction',
|
||||||
|
block_explorer_domain: blockExplorerHostName,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
global.platform.openTab({ url: blockExplorerUrl });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('viewOnCustomBlockExplorer', [
|
||||||
|
t('blockExplorerSwapAction'),
|
||||||
|
blockExplorerHostName,
|
||||||
|
])}
|
||||||
|
</button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewOnBlockExplorer.propTypes = {
|
||||||
|
blockExplorerUrl: PropTypes.string.isRequired,
|
||||||
|
sensitiveTrackingProperties: PropTypes.object.isRequired,
|
||||||
|
};
|
@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { renderWithProvider } from '../../../../test/jest';
|
||||||
|
import ViewOnBlockExplorer from '.';
|
||||||
|
|
||||||
|
const createProps = (customProps = {}) => {
|
||||||
|
return {
|
||||||
|
txHash:
|
||||||
|
'0x58e5a0fc7fbc849eddc100d44e86276168a8c7baaa5604e44ba6f5eb8ba1b7eb',
|
||||||
|
blockExplorerUrl: 'https://etherscan.io',
|
||||||
|
...customProps,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('ViewOnBlockExplorer', () => {
|
||||||
|
it('renders the component with initial props', () => {
|
||||||
|
const { container, getByText } = renderWithProvider(
|
||||||
|
<ViewOnBlockExplorer {...createProps()} />,
|
||||||
|
);
|
||||||
|
expect(getByText('View Swap at etherscan.io')).toBeInTheDocument();
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user