{
const t = useI18nContext();
const primaryTokenImage = useSelector(getNativeCurrencyImage);
const trackEvent = useContext(MetaMetricsContext);
+ const metaMetricsId = useSelector(getMetaMetricsId);
const chainId = useSelector(getCurrentChainId);
// Scam warning
@@ -82,7 +88,45 @@ export const TokenListItem = ({
title === CURRENCY_SYMBOLS.ETH && isOriginalTokenSymbol
? t('networkNameEthereum')
: title;
-
+ const stakeableTitle = (
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ const url = getPortfolioUrl('stake', 'ext_stake_button', metaMetricsId);
+ global.platform.openTab({ url });
+ trackEvent({
+ event: MetaMetricsEventName.StakingEntryPointClicked,
+ category: MetaMetricsEventCategory.Tokens,
+ properties: {
+ location: 'Token List Item',
+ text: 'Stake',
+ chain_id: chainId,
+ token_symbol: tokenSymbol,
+ },
+ });
+ }}
+ >
+ •
+
+ {t('stake')}
+
+
+
+ );
// Used for badge icon
const currentNetwork = useSelector(getCurrentNetwork);
const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor);
@@ -160,7 +204,10 @@ export const TokenListItem = ({
justifyContent={JustifyContent.spaceBetween}
gap={1}
>
-
+
{title?.length > 12 ? (
- {tokenSymbol}
+ {isStakeable ? (
+ <>
+ {tokenSymbol} {stakeableTitle}
+ >
+ ) : (
+ tokenSymbol
+ )}
) : (
@@ -184,7 +237,13 @@ export const TokenListItem = ({
variant={TextVariant.bodyMd}
ellipsis
>
- {tokenSymbol}
+ {isStakeable ? (
+
+ {tokenSymbol} {stakeableTitle}
+
+ ) : (
+ tokenSymbol
+ )}
)}
@@ -205,9 +264,10 @@ export const TokenListItem = ({
{secondary}
@@ -317,4 +377,8 @@ TokenListItem.propTypes = {
* isNativeCurrency represents if this item is the native currency
*/
isNativeCurrency: PropTypes.bool,
+ /**
+ * isStakeable represents if this item is stakeable
+ */
+ isStakeable: PropTypes.bool,
};
diff --git a/ui/components/multichain/token-list-item/token-list-item.stories.js b/ui/components/multichain/token-list-item/token-list-item.stories.js
index 0cf57ae7defc..473fd6e2affb 100644
--- a/ui/components/multichain/token-list-item/token-list-item.stories.js
+++ b/ui/components/multichain/token-list-item/token-list-item.stories.js
@@ -64,6 +64,9 @@ DefaultStory.decorators = [
),
];
+DefaultStory.args = {
+ isStakeable: true,
+};
export const ChaosStory = (args) => (
{
+ beforeAll(() => {
+ global.platform = { openTab: jest.fn() };
+ openTabSpy = jest.spyOn(global.platform, 'openTab');
+ });
const props = {
onClick: jest.fn(),
};
@@ -59,4 +65,28 @@ describe('TokenListItem', () => {
expect(props.onClick).toHaveBeenCalled();
});
+
+ it('handles clicking staking opens tab', async () => {
+ const store = configureMockStore()(state);
+ const { queryByTestId } = renderWithProvider(
+ ,
+ store,
+ );
+
+ const stakeButton = queryByTestId(
+ `staking-entrypoint-${CHAIN_IDS.MAINNET}`,
+ );
+
+ expect(stakeButton).toBeInTheDocument();
+ expect(stakeButton).not.toBeDisabled();
+
+ fireEvent.click(stakeButton);
+ expect(openTabSpy).toHaveBeenCalledTimes(1);
+
+ await waitFor(() =>
+ expect(openTabSpy).toHaveBeenCalledWith({
+ url: expect.stringContaining('/stake?metamaskEntry=ext_stake_button'),
+ }),
+ );
+ });
});
diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js
index d7c244f3544d..1cea69491d61 100644
--- a/ui/selectors/selectors.js
+++ b/ui/selectors/selectors.js
@@ -95,6 +95,7 @@ import {
NOTIFICATION_OPEN_BETA_SNAPS,
NOTIFICATION_PETNAMES,
NOTIFICATION_U2F_LEDGER_LIVE,
+ NOTIFICATION_STAKING_PORTFOLIO,
} from '../../shared/notifications';
import {
SURVEY_DATE,
@@ -1277,6 +1278,7 @@ function getAllowedAnnouncementIds(state) {
[NOTIFICATION_OPEN_BETA_SNAPS]: true,
[NOTIFICATION_BUY_SELL_BUTTON]: true,
[NOTIFICATION_U2F_LEDGER_LIVE]: currentKeyringIsLedger && !isFirefox,
+ [NOTIFICATION_STAKING_PORTFOLIO]: true,
///: BEGIN:ONLY_INCLUDE_IF(blockaid)
[NOTIFICATION_BLOCKAID_DEFAULT]: true,
///: END:ONLY_INCLUDE_IF