Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Message system - Add context banner to solana staking #17267

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Context } from '@suite-common/message-system';
import { isSupportedEthStakingNetworkSymbol } from '@suite-common/wallet-utils';
import {
isSupportedEthStakingNetworkSymbol,
isSupportedSolStakingNetworkSymbol,
} from '@suite-common/wallet-utils';
import { Column } from '@trezor/components';
import { spacings } from '@trezor/theme';

Expand Down Expand Up @@ -31,6 +34,9 @@ export const AccountBanners = ({ account }: AccountBannersProps) => {
{account?.symbol &&
isSupportedEthStakingNetworkSymbol(account.symbol) &&
route?.name === 'wallet-staking' && <ContextMessage context={Context.ethStaking} />}
{account?.symbol &&
isSupportedSolStakingNetworkSymbol(account.symbol) &&
route?.name === 'wallet-staking' && <ContextMessage context={Context.solStaking} />}
<AuthConfirmFailed />
<BackendDisconnected />
<DeviceUnavailable />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Context, selectContextMessageContent } from '@suite-common/message-system';
import { Banner } from '@trezor/components';
import { Banner, Row } from '@trezor/components';

import { useSelector } from 'src/hooks/suite';
import { selectLanguage } from 'src/reducers/suite/suiteReducer';
import { goto } from 'src/actions/suite/routerActions';
import { useDispatch, useSelector } from 'src/hooks/suite';
import { selectLanguage, selectTorState } from 'src/reducers/suite/suiteReducer';
import { getTorUrlIfAvailable } from 'src/utils/suite/tor';

type ContextMessageProps = {
context: (typeof Context)[keyof typeof Context];
Expand All @@ -11,17 +13,43 @@ type ContextMessageProps = {
export const ContextMessage = ({ context }: ContextMessageProps) => {
const language = useSelector(selectLanguage);
const message = useSelector(state => selectContextMessageContent(state, context, language));
const { isTorEnabled } = useSelector(selectTorState);
const torOnionLinks = useSelector(state => state.suite.settings.torOnionLinks);
const dispatch = useDispatch();

return message ? (
if (!message) return null;

const onCallToAction = ({ action, link, anchor }: NonNullable<(typeof message)['cta']>) => {
switch (action) {
case 'internal-link':
// @ts-expect-error: impossible to add all href options to the message system config json schema
return () => dispatch(goto(link, { anchor, preserveParams: true }));
case 'external-link':
return () =>
window.open(
isTorEnabled && torOnionLinks ? getTorUrlIfAvailable(link) : link,
'_blank',
);
}
};

return (
<Banner
variant={message.variant === 'critical' ? 'destructive' : message.variant}
rightContent={
message.cta ? (
<Banner.Button href={message.cta.link}>{message.cta.label}</Banner.Button>
) : undefined
<Row gap={8}>
{message.cta && (
<Banner.Button
onClick={onCallToAction(message.cta)}
data-testid={`@context-message/${context}/cta`}
>
{message.cta.label}
</Banner.Button>
)}
</Row>
}
>
{message.content}
</Banner>
) : null;
);
};
96 changes: 94 additions & 2 deletions suite-common/message-system/config/config.v1.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"version": 1,
"timestamp": "2025-02-24T00:00:00+00:00",
"sequence": 81,
"sequence": 82,
"actions": [
{
"conditions": [
Expand Down Expand Up @@ -294,6 +294,98 @@
}
}
},
{
"conditions": [
{
"settings": [
{
"sol": true
}
],
"environment": {
"desktop": ">25.2.1",
"mobile": "!",
"web": ">25.2.1"
},
"devices": [
{
"model": "T2B1",
"firmware": "<2.8.9",
"bootloader": "*",
"variant": "*",
"firmwareRevision": "*",
"vendor": "*"
},
{
"model": "T3B1",
"firmware": "<2.8.9",
"bootloader": "*",
"variant": "*",
"firmwareRevision": "*",
"vendor": "*"
},
{
"model": "T2T1",
"firmware": "<2.8.9",
"bootloader": "*",
"variant": "*",
"firmwareRevision": "*",
"vendor": "*"
},
{
"model": "T3T1",
"firmware": "<2.8.9",
"bootloader": "*",
"variant": "*",
"firmwareRevision": "*",
"vendor": "*"
}
]
}
],
"message": {
"id": "ccd7b443-1e0e-449e-b58f-affa0459a29d",
"priority": 93,
"dismissible": true,
"variant": "info",
"category": ["context"],
"content": {
"en-GB": "For the best Solana staking experience, update your Trezor firmware to the latest version.",
"en": "For the best Solana staking experience, update your Trezor firmware to the latest version.",
"es": "Para la mejor experiencia de staking en Solana, actualiza el firmware de tu Trezor a la última versión.",
"cs": "Aby byl váš staking na Solaně co nejefektivnější, aktualizujte firmware vašeho Trezoru na nejnovější verzi.",
"ru": "Для наилучшего опыта стейкинга Solana обновите прошивку вашего Trezor до последней версии.",
"ja": "最高のSolanaステーキング体験を得るために、Trezorのファームウェアを最新バージョンに更新してください。",
"hu": "A legjobb Solana staking élményért frissítsd a Trezor firmware-ét a legújabb verzióra.",
"it": "Per la migliore esperienza di staking su Solana, aggiorna il firmware del tuo Trezor all'ultima versione.",
"fr": "Pour la meilleure expérience de staking sur Solana, mettez à jour le firmware de votre Trezor vers la dernière version.",
"de": "Für das beste Solana-Staking-Erlebnis, aktualisiere die Firmware deines Trezor auf die neueste Version.",
"tr": "En iyi Solana staking deneyimi için Trezor cihazınızın yazılımını en son sürüme güncelleyin.",
"pt": "Para a melhor experiência de staking em Solana, atualize o firmware do seu Trezor para a versão mais recente.",
"uk": "Для найкращого досвіду стейкінгу Solana оновіть прошивку свого Trezor до останньої версії."
},
"cta": {
"action": "internal-link",
"link": "firmware-index",
"label": {
"en-GB": "Update now",
"en": "Update now",
"es": "Actualizar ahora",
"cs": "Aktualizujte nyní",
"ru": "Обновить сейчас",
"ja": "今すぐアップデート",
"hu": "Frissítés most",
"it": "Aggiorna ora",
"fr": "Mettre à jour maintenant",
"de": "Jetzt aktualisieren",
"tr": "Şimdi güncelle",
"pt": "Atualizar agora",
"uk": "Оновити зараз"
}
},
"context": { "domain": "accounts.sol.staking" }
}
},
{
"conditions": [
{
Expand Down Expand Up @@ -1239,7 +1331,7 @@
"priority": 96,
"dismissible": true,
"variant": "critical",
"category": "banner",
"category": ["banner"],
"content": {
"en-GB": "Updating the firmware may wipe your Trezor. Verify your backup now to ensure you can recover your assets.",
"en": "Updating the firmware may wipe your Trezor. Verify your backup now to ensure you can recover your assets.",
Expand Down
1 change: 1 addition & 0 deletions suite-common/message-system/src/messageSystemTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type FeatureDomain = (typeof Feature)[keyof typeof Feature];
export const Context = {
coinjoin: 'accounts.coinjoin',
ethStaking: 'accounts.eth.staking',
solStaking: 'accounts.sol.staking',
} as const;

export type ContextDomain = (typeof Context)[keyof typeof Context];
Expand Down