From 07fff7930b73d02eb3e0bf68cda3439973e468c6 Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Wed, 2 Oct 2024 12:22:24 +0200 Subject: [PATCH 001/624] feat: NewModal can have color (to override the variant), also CSSColor is userd for Icon color instead of a string chore: sue color control select for storybook --- .../src/components/Badge/Badge.stories.tsx | 14 +++++ .../components/src/components/Badge/Badge.tsx | 4 +- .../components/Divider/Divider.stories.tsx | 2 +- .../src/components/Icon/Icon.stories.tsx | 4 ++ .../components/src/components/Icon/Icon.tsx | 8 +-- .../src/components/Icon/icons.stories.tsx | 3 + .../components/NewModal/NewModal.stories.tsx | 25 +++++++- .../src/components/NewModal/NewModal.tsx | 62 ++++++++----------- .../src/components/NewModal/NewModalIcon.tsx | 57 +++++++++++++++++ .../src/components/NewModal/utils.tsx | 17 +++-- .../src/components/buttons/Button/Button.tsx | 15 ++--- .../DeviceDisplay/DisplayPaginatedText.tsx | 4 +- .../suite/src/components/suite/QrCode.tsx | 5 +- .../src/components/suite/TooltipSymbol.tsx | 3 +- .../modals/ReduxModal/CopyAddressModal.tsx | 2 +- .../DeviceConfirmationModal/NoBackupModal.tsx | 2 +- .../modals/ReduxModal/UnhideTokenModal.tsx | 2 +- .../ConfirmUnverifiedModal.tsx | 2 +- .../DeviceAuthenticityOptOutModal.tsx | 2 +- .../FirmwareRevisionOptOutModal.tsx | 2 +- .../UserContextModal/WipeDeviceModal.tsx | 2 +- .../CoinControl/UtxoSelectionList.tsx | 3 +- .../BitcoinOptions/CoinControl/UtxoTag.tsx | 3 +- .../src/views/wallet/send/Outputs/Address.tsx | 2 +- packages/theme/src/types.ts | 10 +-- .../icons-deprecated/src/components/Icon.tsx | 3 +- 26 files changed, 173 insertions(+), 85 deletions(-) create mode 100644 packages/components/src/components/NewModal/NewModalIcon.tsx diff --git a/packages/components/src/components/Badge/Badge.stories.tsx b/packages/components/src/components/Badge/Badge.stories.tsx index 91256ca80fa..c97522f92b0 100644 --- a/packages/components/src/components/Badge/Badge.stories.tsx +++ b/packages/components/src/components/Badge/Badge.stories.tsx @@ -11,10 +11,24 @@ export default meta; export const Badge: StoryObj = { args: { children: 'Badge label', + isDisabled: false, + variant: 'primary', size: 'tiny', ...getFramePropsStory(allowedBadgeFrameProps).args, }, argTypes: { + isDisabled: { control: 'boolean' }, + variant: { + control: { + type: 'radio', + }, + options: [ + 'primary', + 'tertiary', + 'destructive', + undefined, + ] satisfies BadgeProps['variant'][], + }, size: { control: { type: 'radio', diff --git a/packages/components/src/components/Badge/Badge.tsx b/packages/components/src/components/Badge/Badge.tsx index 66199cbf0ce..491867c8fc4 100644 --- a/packages/components/src/components/Badge/Badge.tsx +++ b/packages/components/src/components/Badge/Badge.tsx @@ -18,7 +18,7 @@ export type BadgeSize = Extract; export const allowedBadgeFrameProps = ['margin'] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; -type BadgeVariant = Extract; +export type BadgeVariant = Extract; export type BadgeProps = AllowedFrameProps & { size?: BadgeSize; @@ -150,7 +150,7 @@ export const Badge = ({ name={icon} color={ isDisabled - ? 'iconDisabled' + ? theme.iconDisabled : mapVariantToIconColor({ $variant: variant, theme }) } /> diff --git a/packages/components/src/components/Divider/Divider.stories.tsx b/packages/components/src/components/Divider/Divider.stories.tsx index c93e77fd5e4..a7fd9b8bfbe 100644 --- a/packages/components/src/components/Divider/Divider.stories.tsx +++ b/packages/components/src/components/Divider/Divider.stories.tsx @@ -35,7 +35,7 @@ export const Divider: StoryObj = { type: 'number', }, color: { - type: 'string', + control: 'color', }, ...getFramePropsStory(allowedDividerFrameProps).argTypes, }, diff --git a/packages/components/src/components/Icon/Icon.stories.tsx b/packages/components/src/components/Icon/Icon.stories.tsx index 595e387aae2..a7c68227cd8 100644 --- a/packages/components/src/components/Icon/Icon.stories.tsx +++ b/packages/components/src/components/Icon/Icon.stories.tsx @@ -12,6 +12,7 @@ import { IconName as IconNameDeprecated, } from '@suite-common/icons-deprecated/src/webComponents'; import { getFramePropsStory } from '../../utils/frameProps'; + const meta: Meta = { title: 'Icons', component: IconComponent, @@ -55,6 +56,9 @@ export const Icon: StoryObj = { type: 'select', }, }, + color: { + control: 'color', + }, size: { options: iconSizes, control: { diff --git a/packages/components/src/components/Icon/Icon.tsx b/packages/components/src/components/Icon/Icon.tsx index 6ce0eb7c68c..44b02c5bd03 100644 --- a/packages/components/src/components/Icon/Icon.tsx +++ b/packages/components/src/components/Icon/Icon.tsx @@ -34,7 +34,7 @@ export type ExclusiveColorOrVariant = | { variant?: undefined; /** @deprecated Use only is case of absolute desperation. Prefer using `variant`. */ - color?: string; + color?: CSSColor; }; export const allowedIconFrameProps = [ @@ -70,10 +70,7 @@ export const getColorForIconVariant = ({ variant, theme, color, -}: Pick & { theme: DefaultTheme }): - | CSSColor - | 'inherit' - | string => { +}: Pick & { theme: DefaultTheme }): CSSColor => { if (color !== undefined) { return color; } @@ -92,7 +89,6 @@ const SvgWrapper = styled.div getColorForIconVariant({ variant: $variant, color: $color, theme })}; diff --git a/packages/components/src/components/Icon/icons.stories.tsx b/packages/components/src/components/Icon/icons.stories.tsx index 9f94ce79390..323ae2f8364 100644 --- a/packages/components/src/components/Icon/icons.stories.tsx +++ b/packages/components/src/components/Icon/icons.stories.tsx @@ -152,6 +152,9 @@ export const AllIcons: StoryObj = { type: 'select', }, }, + color: { + control: 'color', + }, size: { options: iconSizes, control: { diff --git a/packages/components/src/components/NewModal/NewModal.stories.tsx b/packages/components/src/components/NewModal/NewModal.stories.tsx index 0121aa1d309..1560b20a555 100644 --- a/packages/components/src/components/NewModal/NewModal.stories.tsx +++ b/packages/components/src/components/NewModal/NewModal.stories.tsx @@ -46,6 +46,8 @@ export default meta; export const NewModal: StoryObj = { args: { variant: 'primary', + iconName: undefined, + iconComponent: undefined, heading: 'Modal heading', description: 'Modal description', children: @@ -62,13 +64,30 @@ export const NewModal: StoryObj = { control: { type: 'radio', }, - options: ['primary', 'warning', 'destructive'], + options: [ + 'primary', + 'warning', + 'destructive', + undefined, + ] satisfies NewModalProps['variant'][], + }, + iconComponent: { + options: ['nothing', 'purple'], + mapping: { + nothing: undefined, + purple: ( + + ), + }, }, size: { control: { type: 'radio', }, - options: ['tiny', 'small', 'medium', 'large'], + options: ['tiny', 'small', 'medium', 'large'] satisfies NewModalProps['size'][], }, heading: { control: 'text', @@ -112,7 +131,7 @@ export const NewModal: StoryObj = { }, }, }, - icon: { + iconName: { options: ['none', ...variables.ICONS], mapping: { ...variables.ICONS, diff --git a/packages/components/src/components/NewModal/NewModal.tsx b/packages/components/src/components/NewModal/NewModal.tsx index c422161aea2..f2636cee1ed 100644 --- a/packages/components/src/components/NewModal/NewModal.tsx +++ b/packages/components/src/components/NewModal/NewModal.tsx @@ -18,13 +18,9 @@ import { NewModalButton } from './NewModalButton'; import { NewModalContext } from './NewModalContext'; import { NewModalBackdrop } from './NewModalBackdrop'; import { NewModalProvider } from './NewModalProvider'; -import type { NewModalVariant, NewModalSize, NewModalAlignment } from './types'; -import { - mapVariantToIconBackground, - mapVariantToIconBorderColor, - mapModalSizeToWidth, -} from './utils'; -import { Icon, IconName } from '../Icon/Icon'; +import { NewModalSize, NewModalAlignment, NewModalVariant } from './types'; +import { mapModalSizeToWidth } from './utils'; +import { IconName } from '../Icon/Icon'; import { FrameProps, FramePropsKeys, @@ -32,13 +28,13 @@ import { withFrameProps, } from '../../utils/frameProps'; import { TransientProps } from '../../utils/transientProps'; +import { NewModalIcon } from './NewModalIcon'; export const allowedNewModalFrameProps = ['height'] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; const NEW_MODAL_CONTENT_ID = 'modal-content'; const MODAL_ELEVATION = 0; -const ICON_SIZE = 40; const Container = styled.div< TransientProps & { $elevation: Elevation; $size: NewModalSize } @@ -105,41 +101,33 @@ const Footer = styled.footer` border-top: 1px solid ${({ theme }) => theme.borderElevation0}; `; -const IconWrapper = styled.div<{ $variant: NewModalVariant; $size: number; $isPushedTop: boolean }>` - width: ${({ $size }) => $size}px; - background: ${({ theme, $variant }) => mapVariantToIconBackground({ theme, $variant })}; - padding: ${spacingsPx.lg}; - border-radius: ${borders.radii.full}; - border: ${spacingsPx.sm} solid - ${({ theme, $variant }) => mapVariantToIconBorderColor({ theme, $variant })}; - box-sizing: content-box; - margin-bottom: ${spacingsPx.md}; - margin-top: ${({ $isPushedTop }) => ($isPushedTop ? `-${spacingsPx.md}` : 0)}; -`; +type ExclusiveIconNameOrComponent = + | { iconName?: IconName; iconComponent?: undefined } + | { iconName?: undefined; iconComponent?: ReactNode }; type NewModalProps = AllowedFrameProps & { - children?: ReactNode; variant?: NewModalVariant; + children?: ReactNode; heading?: ReactNode; description?: ReactNode; bottomContent?: ReactNode; onBackClick?: () => void; onCancel?: () => void; isBackdropCancelable?: boolean; - icon?: IconName; alignment?: NewModalAlignment; size?: NewModalSize; 'data-testid'?: string; -}; +} & ExclusiveIconNameOrComponent; const _NewModalBase = ({ children, - variant = 'primary', + variant, size = 'medium', heading, description, bottomContent, - icon, + iconName, + iconComponent, onBackClick, onCancel, 'data-testid': dataTest = '@modal', @@ -205,17 +193,19 @@ const _NewModalBase = ({ - {icon && ( - - - - )} + {iconComponent ?? + (iconName && ( + + ))} {children} @@ -229,7 +219,6 @@ const _NewModalBase = ({ ); }; - const NewModalBase = (props: NewModalProps) => ( @@ -255,6 +244,7 @@ NewModal.Button = NewModalButton; NewModal.Backdrop = NewModalBackdrop; NewModal.Provider = NewModalProvider; NewModal.ModalBase = NewModalBase; +NewModal.Icon = NewModalIcon; export { NewModal, NEW_MODAL_CONTENT_ID }; export type { NewModalProps, NewModalSize }; diff --git a/packages/components/src/components/NewModal/NewModalIcon.tsx b/packages/components/src/components/NewModal/NewModalIcon.tsx new file mode 100644 index 00000000000..6e76e23572b --- /dev/null +++ b/packages/components/src/components/NewModal/NewModalIcon.tsx @@ -0,0 +1,57 @@ +import styled from 'styled-components'; + +import { ExclusiveColorOrVariant, Icon, IconName } from '../Icon/Icon'; +import { TransientProps } from '../../utils/transientProps'; +import { NewModalVariant } from './types'; +import { mapVariantToIconBackground, mapVariantToIconBorderColor } from './utils'; +import { borders, CSSColor, spacingsPx } from '@trezor/theme'; + +const ICON_SIZE = 40; + +export type NewModalIconColors = { foreground: CSSColor; background: CSSColor }; + +export type NewModalIconExclusiveColorOrVariant = + | { variant?: NewModalVariant; iconColor?: undefined } + | { variant?: undefined; iconColor?: NewModalIconColors }; + +type IconWrapperProps = TransientProps & { + $size: number; + $isPushedTop: boolean; +}; + +const IconWrapper = styled.div` + width: ${({ $size }) => $size}px; + background: ${props => mapVariantToIconBackground(props)}; + padding: ${spacingsPx.lg}; + border-radius: ${borders.radii.full}; + border: ${spacingsPx.sm} solid ${props => mapVariantToIconBorderColor(props)}; + box-sizing: content-box; + margin-bottom: ${spacingsPx.md}; + margin-top: ${({ $isPushedTop }) => ($isPushedTop ? `-${spacingsPx.md}` : 0)}; +`; + +type NewModalIconProps = { + isPushedTop?: boolean; + iconName: IconName; +} & NewModalIconExclusiveColorOrVariant; + +export const NewModalIcon = ({ + isPushedTop = false, + iconName, + iconColor, + variant, +}: NewModalIconProps) => { + const wrapperColorOrVariant: TransientProps = + iconColor === undefined ? { $variant: variant ?? 'primary' } : { $iconColor: iconColor }; + + const iconColorOrVariant: ExclusiveColorOrVariant = + iconColor === undefined + ? { variant: variant ?? 'primary' } + : { color: iconColor.foreground }; + + return ( + + + + ); +}; diff --git a/packages/components/src/components/NewModal/utils.tsx b/packages/components/src/components/NewModal/utils.tsx index bc5057f62ac..f3196a23ddd 100644 --- a/packages/components/src/components/NewModal/utils.tsx +++ b/packages/components/src/components/NewModal/utils.tsx @@ -2,13 +2,18 @@ import { Color, CSSColor } from '@trezor/theme'; import { NewModalVariant, NewModalSize, NewModalAlignment } from './types'; import { DefaultTheme } from 'styled-components'; import { UIVerticalAlignment, UIHorizontalAlignment } from '../../config/types'; +import { TransientProps } from '../../utils/transientProps'; +import { NewModalIconExclusiveColorOrVariant } from './NewModalIcon'; type MapArgs = { - $variant: NewModalVariant; theme: DefaultTheme; -}; +} & TransientProps; + +export const mapVariantToIconBackground = ({ $variant, theme, $iconColor }: MapArgs): CSSColor => { + if ($variant === undefined) { + return $iconColor?.background ?? 'transparent'; + } -export const mapVariantToIconBackground = ({ $variant, theme }: MapArgs): CSSColor => { const colorMap: Record = { primary: 'backgroundPrimarySubtleOnElevation2', warning: 'backgroundAlertYellowSubtleOnElevation2', @@ -18,7 +23,11 @@ export const mapVariantToIconBackground = ({ $variant, theme }: MapArgs): CSSCol return theme[colorMap[$variant]]; }; -export const mapVariantToIconBorderColor = ({ $variant, theme }: MapArgs): CSSColor => { +export const mapVariantToIconBorderColor = ({ $variant, theme, $iconColor }: MapArgs): CSSColor => { + if ($variant === undefined) { + return $iconColor?.foreground ?? 'transparent'; + } + const colorMap: Record = { primary: 'backgroundPrimarySubtleOnElevation0', warning: 'backgroundAlertYellowSubtleOnElevation0', diff --git a/packages/components/src/components/buttons/Button/Button.tsx b/packages/components/src/components/buttons/Button/Button.tsx index 934bbfb7d85..187b5c817ac 100644 --- a/packages/components/src/components/buttons/Button/Button.tsx +++ b/packages/components/src/components/buttons/Button/Button.tsx @@ -1,6 +1,6 @@ import { ButtonHTMLAttributes } from 'react'; import styled, { useTheme } from 'styled-components'; -import { borders, Elevation, spacingsPx, typography } from '@trezor/theme'; +import { borders, CSSColor, Elevation, spacingsPx, typography } from '@trezor/theme'; import { Spinner } from '../../loaders/Spinner/Spinner'; import { ButtonSize, @@ -61,7 +61,6 @@ export const ButtonContainer = styled.button` ${getFocusShadowStyle()} ${({ $variant, $isSubtle, $elevation }) => useVariantStyle($variant, $isSubtle, $elevation)} - &:disabled { background: ${({ theme }) => theme.backgroundNeutralDisabled}; color: ${({ theme }) => theme.textDisabled}; @@ -127,15 +126,13 @@ export type ButtonProps = SelectedHTMLButtonProps & textWrap?: boolean; }; -export const getIcon = ({ - icon, - size, - color, -}: { +type GetIconProps = { icon?: IconName | React.ReactElement; size?: number; - color?: string; -}) => { + color?: CSSColor; +}; + +export const getIcon = ({ icon, size, color }: GetIconProps) => { if (!icon) return null; if (typeof icon === 'string') { return ; diff --git a/packages/suite/src/components/suite/DeviceDisplay/DisplayPaginatedText.tsx b/packages/suite/src/components/suite/DeviceDisplay/DisplayPaginatedText.tsx index 85272ca54ee..1bffda3c618 100644 --- a/packages/suite/src/components/suite/DeviceDisplay/DisplayPaginatedText.tsx +++ b/packages/suite/src/components/suite/DeviceDisplay/DisplayPaginatedText.tsx @@ -6,7 +6,7 @@ import { ResultRow, parseTextToPagesAndLines } from './parseTextToPagesAndLines' import { DeviceDisplayText } from './DeviceDisplayText'; import { DisplayPageSeparator } from './DisplayPageSeparator'; import { handleOnCopy } from 'src/utils/suite/deviceDisplay'; -import { Icon, IconName } from '@trezor/components'; +import { Icon, IconName, IconProps } from '@trezor/components'; // eslint-disable-next-line local-rules/no-override-ds-component const StyledNextIcon = styled(Icon)<{ $isPixelType: boolean }>` @@ -55,7 +55,7 @@ const Row = ({ const iconNextName: IconName = isPixelType ? 'addressPixelNext' : 'addressNext'; const iconContinuesName: IconName = isPixelType ? 'addressPixelContinues' : 'addressContinues'; - const iconConfig = { + const iconConfig: Pick = { size: isPixelType ? 10 : 20, color: isPixelType ? '#ffffff' : '#959596', }; diff --git a/packages/suite/src/components/suite/QrCode.tsx b/packages/suite/src/components/suite/QrCode.tsx index 35c1e83ffdc..3683b63980d 100644 --- a/packages/suite/src/components/suite/QrCode.tsx +++ b/packages/suite/src/components/suite/QrCode.tsx @@ -3,6 +3,7 @@ import styled from 'styled-components'; import { Icon, Tooltip, variables, intermediaryTheme } from '@trezor/components'; import { Translation } from './Translation'; +import { CSSColor } from '@trezor/theme/libDev/src'; export const QRCODE_SIZE = 384; export const QRCODE_PADDING = 12; @@ -49,8 +50,8 @@ interface QrCodeProps { value: string; className?: string; showMessage?: boolean; - bgColor?: string; - fgColor?: string; + bgColor?: CSSColor; + fgColor?: CSSColor; } export const QrCode = ({ value, className, bgColor, fgColor, showMessage }: QrCodeProps) => ( diff --git a/packages/suite/src/components/suite/TooltipSymbol.tsx b/packages/suite/src/components/suite/TooltipSymbol.tsx index 331a48141c4..12371c14bf1 100644 --- a/packages/suite/src/components/suite/TooltipSymbol.tsx +++ b/packages/suite/src/components/suite/TooltipSymbol.tsx @@ -1,6 +1,7 @@ import { ReactNode } from 'react'; import styled from 'styled-components'; import { Icon, IconName, Tooltip } from '@trezor/components'; +import { CSSColor } from '@trezor/theme'; // eslint-disable-next-line local-rules/no-override-ds-component const InlineTooltip = styled(Tooltip)` @@ -11,7 +12,7 @@ const InlineTooltip = styled(Tooltip)` type TooltipSymbolProps = { content: ReactNode; icon?: IconName; - iconColor?: string; + iconColor?: CSSColor; className?: string; }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/CopyAddressModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/CopyAddressModal.tsx index 0f0680549c3..2238d9896f0 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/CopyAddressModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/CopyAddressModal.tsx @@ -46,7 +46,7 @@ export const CopyAddressModal = ({ address, onCancel, addressType }: CopyAddress return ( diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceConfirmationModal/NoBackupModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceConfirmationModal/NoBackupModal.tsx index d53f2b3a4a8..59cc0a88f1e 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceConfirmationModal/NoBackupModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceConfirmationModal/NoBackupModal.tsx @@ -19,7 +19,7 @@ export const NoBackupModal = () => { return ( diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ConfirmUnverifiedModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ConfirmUnverifiedModal.tsx index 68329556a60..e880097f858 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ConfirmUnverifiedModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ConfirmUnverifiedModal.tsx @@ -64,7 +64,7 @@ export const ConfirmUnverifiedModal = ({ diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/DeviceAuthenticityOptOutModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/DeviceAuthenticityOptOutModal.tsx index 416690d4e96..9eec4af1cc0 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/DeviceAuthenticityOptOutModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/DeviceAuthenticityOptOutModal.tsx @@ -22,7 +22,7 @@ export const DeviceAuthenticityOptOutModal = ({ onCancel }: DeviceAuthenticityOp return ( diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx index 12a7d52d806..1f39a613369 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx @@ -22,7 +22,7 @@ export const FirmwareRevisionOptOutModal = ({ onCancel }: DeviceAuthenticityOptO return ( diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/WipeDeviceModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/WipeDeviceModal.tsx index f80559b7073..f43fe1bc452 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/WipeDeviceModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/WipeDeviceModal.tsx @@ -23,7 +23,7 @@ export const WipeDeviceModal = ({ onCancel }: WipeDeviceModalProps) => { diff --git a/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList.tsx b/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList.tsx index 3e8322b5fc1..3ea932513c8 100644 --- a/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList.tsx +++ b/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList.tsx @@ -8,6 +8,7 @@ import { useSelector } from 'src/hooks/suite'; import type { AccountUtxo } from '@trezor/connect'; import { useSendFormContext } from 'src/hooks/wallet'; import { UtxoSelection } from './UtxoSelection'; +import { CSSColor } from '@trezor/theme'; const Wrapper = styled.section` border-bottom: 1px solid ${({ theme }) => theme.legacy.STROKE_GREY}; @@ -46,7 +47,7 @@ interface UtxoSelectionListProps { description: ReactNode; heading: ReactNode; icon: IconName; - iconColor?: string; + iconColor?: CSSColor; utxos: AccountUtxo[]; withHeader: boolean; } diff --git a/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoTag.tsx b/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoTag.tsx index d4348154ced..68dadaa72c5 100644 --- a/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoTag.tsx +++ b/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoTag.tsx @@ -1,9 +1,10 @@ import { ReactNode } from 'react'; import { Icon, Tooltip, IconName } from '@trezor/components'; +import { CSSColor } from '@trezor/theme'; interface UtxoTagProps { icon: IconName; - iconColor: string; + iconColor: CSSColor; tooltipMessage: ReactNode; } diff --git a/packages/suite/src/views/wallet/send/Outputs/Address.tsx b/packages/suite/src/views/wallet/send/Outputs/Address.tsx index e1077d3dcb5..35f5d3012bd 100644 --- a/packages/suite/src/views/wallet/send/Outputs/Address.tsx +++ b/packages/suite/src/views/wallet/send/Outputs/Address.tsx @@ -306,7 +306,7 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => { const getBottomTextIconComponent = () => { if (hasAddressChecksummed) { - return ; + return ; } if (isAddressWithLabel) { diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts index b378d4df9df..7e168f9c7ea 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -2,11 +2,5 @@ export type CSSColor = | `#${string}` | `rgb(${number}, ${number}, ${number})` | `rgba(${number}, ${number}, ${number}, ${number})` - | 'transparent'; - -export const isCSSColor = (color: string): color is CSSColor => { - const cssColorRegex = - /^#([0-9a-fA-F]{3,8})$|^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),?\s*(\d{1,3})\)$/; - - return cssColorRegex.test(color); -}; + | 'transparent' + | 'currentColor'; diff --git a/suite-common/icons-deprecated/src/components/Icon.tsx b/suite-common/icons-deprecated/src/components/Icon.tsx index 2343c1f86e5..0b1ca6fc190 100644 --- a/suite-common/icons-deprecated/src/components/Icon.tsx +++ b/suite-common/icons-deprecated/src/components/Icon.tsx @@ -26,7 +26,8 @@ function isCSSColor(value: any): value is CSSColor { (value.startsWith('#') || value.startsWith('rgb(') || value.startsWith('rgba(') || - value === 'transparent') + value === 'transparent' || + value === 'currentColor') ); } From cf6ed625a389ef6d520fe8afbf055813979cdae6 Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Fri, 27 Sep 2024 12:27:46 +0200 Subject: [PATCH 002/624] refactor(coinmarket): replace useActions --- .../coinmarket/form/useCoinmarketBuyForm.tsx | 111 ++++++++--------- .../form/useCoinmarketExchangeForm.ts | 113 +++++++++--------- .../src/types/coinmarket/coinmarketForm.ts | 12 +- .../ExchangeTransaction.tsx | 4 +- .../CoinmarketVerify/CoinmarketVerify.tsx | 10 +- 5 files changed, 126 insertions(+), 124 deletions(-) diff --git a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx index 7a01fd64c8f..a87af7e1c0b 100644 --- a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx +++ b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx @@ -4,7 +4,7 @@ import useDebounce from 'react-use/lib/useDebounce'; import type { BuyTrade, BuyTradeQuoteRequest, CryptoId } from 'invity-api'; import { isChanged } from '@suite-common/suite-utils'; import { formatAmount } from '@suite-common/wallet-utils'; -import { useActions, useDispatch, useSelector } from 'src/hooks/suite'; +import { useDispatch, useSelector } from 'src/hooks/suite'; import invityAPI from 'src/services/suite/invityAPI'; import { createQuoteLink, @@ -64,35 +64,6 @@ const useCoinmarketBuyForm = ({ useCoinmarketCommonOffers({ selectedAccount, type }); const { paymentMethods, getPaymentMethods, getQuotesByPaymentMethod } = useCoinmarketPaymentMethod(); - const { - saveTrade, - saveQuotes, - saveSelectedQuote, - setIsFromRedirect, - openCoinmarketBuyConfirmModal, - addNotification, - saveTransactionDetailId, - verifyAddress, - submitRequestForm, - goto, - savePaymentMethods, - saveQuoteRequest, - saveCachedAccountInfo, - } = useActions({ - saveTrade: coinmarketBuyActions.saveTrade, - saveQuotes: coinmarketBuyActions.saveQuotes, - saveSelectedQuote: coinmarketBuyActions.saveSelectedQuote, - setIsFromRedirect: coinmarketBuyActions.setIsFromRedirect, - openCoinmarketBuyConfirmModal: coinmarketBuyActions.openCoinmarketBuyConfirmModal, - addNotification: notificationsActions.addToast, - saveTransactionDetailId: coinmarketBuyActions.saveTransactionDetailId, - submitRequestForm: coinmarketCommonActions.submitRequestForm, - verifyAddress: coinmarketBuyActions.verifyAddress, - goto: routerActions.goto, - savePaymentMethods: coinmarketInfoActions.savePaymentMethods, - saveQuoteRequest: coinmarketBuyActions.saveQuoteRequest, - saveCachedAccountInfo: coinmarketBuyActions.saveCachedAccountInfo, - }); const { navigateToBuyForm, navigateToBuyOffers, navigateToBuyConfirm } = useCoinmarketNavigation(account); @@ -266,9 +237,9 @@ const useCoinmarketBuyForm = ({ } setInnerQuotes(quotesSuccess); - dispatch(saveQuotes(quotesSuccess)); - dispatch(saveQuoteRequest(quoteRequest)); - dispatch(savePaymentMethods(paymentMethodsFromQuotes)); + dispatch(coinmarketBuyActions.saveQuotes(quotesSuccess)); + dispatch(coinmarketBuyActions.saveQuoteRequest(quoteRequest)); + dispatch(coinmarketInfoActions.savePaymentMethods(paymentMethodsFromQuotes)); setAmountLimits(limits); if (!paymentMethodSelected || !isSelectedPaymentMethodAvailable) { @@ -293,9 +264,6 @@ const useCoinmarketBuyForm = ({ getQuotesRequest, getPaymentMethods, dispatch, - saveQuotes, - saveQuoteRequest, - savePaymentMethods, setValue, ], ); @@ -303,17 +271,26 @@ const useCoinmarketBuyForm = ({ const goToOffers = async () => { await handleChange(); - dispatch(saveCachedAccountInfo(account.symbol, account.index, account.accountType)); + dispatch( + coinmarketBuyActions.saveCachedAccountInfo( + account.symbol, + account.index, + account.accountType, + ), + ); navigateToBuyOffers(); }; const selectQuote = async (quote: BuyTrade) => { const provider = buyInfo && quote.exchange ? buyInfo.providerInfos[quote.exchange] : null; if (quotesRequest) { - const result = await openCoinmarketBuyConfirmModal( - provider?.companyName, - cryptoIdToCoinSymbol(quote.receiveCurrency!), + const result = await dispatch( + coinmarketBuyActions.openCoinmarketBuyConfirmModal( + provider?.companyName, + cryptoIdToCoinSymbol(quote.receiveCurrency!), + ), ); + if (result) { // empty quoteId means the partner requests login first, requestTrade to get login screen if (!quote.quoteId) { @@ -321,7 +298,9 @@ const useCoinmarketBuyForm = ({ const response = await invityAPI.doBuyTrade({ trade: quote, returnUrl }); if (response) { if (response.trade.status === 'LOGIN_REQUEST' && response.tradeForm) { - submitRequestForm(response.tradeForm.form); + dispatch( + coinmarketCommonActions.submitRequestForm(response.tradeForm.form), + ); } else { const errorMessage = `[doBuyTrade] ${response.trade.status} ${response.trade.error}`; console.log(errorMessage); @@ -329,13 +308,15 @@ const useCoinmarketBuyForm = ({ } else { const errorMessage = 'No response from the server'; console.log(`[doBuyTrade] ${errorMessage}`); - addNotification({ - type: 'error', - error: errorMessage, - }); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: errorMessage, + }), + ); } } else { - saveSelectedQuote(quote); + dispatch(coinmarketBuyActions.saveSelectedQuote(quote)); timer.stop(); @@ -364,23 +345,33 @@ const useCoinmarketBuyForm = ({ }); if (!response || !response.trade || !response.trade.paymentId) { - addNotification({ - type: 'error', - error: 'No response from the server', - }); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: 'No response from the server', + }), + ); } else if (response.trade.error) { - addNotification({ - type: 'error', - error: response.trade.error, - }); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: response.trade.error, + }), + ); } else { - saveTrade(response.trade, account, new Date().toISOString()); + dispatch( + coinmarketBuyActions.saveTrade(response.trade, account, new Date().toISOString()), + ); if (response.tradeForm) { - submitRequestForm(response.tradeForm.form); + dispatch(coinmarketCommonActions.submitRequestForm(response.tradeForm.form)); } if (isDesktop()) { - saveTransactionDetailId(response.trade.paymentId); - goto('wallet-coinmarket-buy-detail', { params: selectedAccount.params }); + dispatch(coinmarketBuyActions.saveTransactionDetailId(response.trade.paymentId)); + dispatch( + routerActions.goto('wallet-coinmarket-buy-detail', { + params: selectedAccount.params, + }), + ); } } setCallInProgress(false); @@ -451,7 +442,7 @@ const useCoinmarketBuyForm = ({ } if (isFromRedirect && quotesRequest) { - setIsFromRedirect(false); + dispatch(coinmarketBuyActions.setIsFromRedirect(false)); } checkQuotesTimer(handleChange); @@ -525,7 +516,7 @@ const useCoinmarketBuyForm = ({ selectQuote, confirmTrade, goToOffers, - verifyAddress, + verifyAddress: coinmarketBuyActions.verifyAddress, removeDraft, setAmountLimits, }; diff --git a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts index e28566e5be9..1113d9b80a6 100644 --- a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts +++ b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts @@ -9,7 +9,7 @@ import type { import useDebounce from 'react-use/lib/useDebounce'; import { amountToSatoshi, formatAmount, toFiatCurrency } from '@suite-common/wallet-utils'; import { isChanged } from '@suite-common/suite-utils'; -import { useActions, useDispatch, useSelector } from 'src/hooks/suite'; +import { useDispatch, useSelector } from 'src/hooks/suite'; import invityAPI from 'src/services/suite/invityAPI'; import { saveQuoteRequest, saveQuotes } from 'src/actions/wallet/coinmarketExchangeActions'; import { @@ -62,7 +62,6 @@ import { networks } from '@suite-common/wallet-config'; import { useCoinmarketAccount } from 'src/hooks/wallet/coinmarket/form/common/useCoinmarketAccount'; import { useCoinmarketInfo } from 'src/hooks/wallet/coinmarket/useCoinmarketInfo'; import { analytics, EventType } from '@trezor/suite-analytics'; -import { setCoinmarketModalAccount } from 'src/actions/wallet/coinmarket/coinmarketCommonActions'; export const useCoinmarketExchangeForm = ({ selectedAccount, @@ -112,26 +111,6 @@ export const useCoinmarketExchangeForm = ({ navigateToExchangeConfirm, } = useCoinmarketNavigation(account); - const { - saveTrade, - openCoinmarketExchangeConfirmModal, - saveTransactionId, - addNotification, - verifyAddress, - saveSelectedQuote, - setCoinmarketExchangeAccount, - } = useActions({ - saveTrade: coinmarketExchangeActions.saveTrade, - openCoinmarketExchangeConfirmModal: - coinmarketExchangeActions.openCoinmarketExchangeConfirmModal, - saveTransactionId: coinmarketExchangeActions.saveTransactionId, - addNotification: notificationsActions.addToast, - verifyAddress: coinmarketExchangeActions.verifyAddress, - saveSelectedQuote: coinmarketExchangeActions.saveSelectedQuote, - setCoinmarketExchangeAccount: coinmarketExchangeActions.setCoinmarketExchangeAccount, - setCoinmarketModalAccount: coinmarketCommonActions.setCoinmarketModalAccount, - }); - const { symbol } = account; const { shouldSendInSats } = useBitcoinAmountUnit(symbol); const network = networks[account.symbol]; @@ -326,7 +305,7 @@ export const useCoinmarketExchangeForm = ({ changeFeeLevel, composeRequest, setAccountOnChange: newAccount => { - dispatch(setCoinmarketExchangeAccount(newAccount)); + dispatch(coinmarketExchangeActions.setCoinmarketExchangeAccount(newAccount)); setAccount(newAccount); }, }); @@ -337,14 +316,16 @@ export const useCoinmarketExchangeForm = ({ ? exchangeInfo?.providerInfos[quote.exchange] : null; if (quotesRequest) { - const result = await openCoinmarketExchangeConfirmModal( - provider?.companyName, - quote.isDex, - quote.send, - quote.receive, + const result = await dispatch( + coinmarketExchangeActions.openCoinmarketExchangeConfirmModal( + provider?.companyName, + quote.isDex, + quote.send, + quote.receive, + ), ); if (result) { - saveSelectedQuote(quote); + dispatch(coinmarketExchangeActions.saveSelectedQuote(quote)); navigateToExchangeConfirm(); timer.stop(); @@ -380,27 +361,31 @@ export const useCoinmarketExchangeForm = ({ }); if (!response) { - addNotification({ - type: 'error', - error: 'No response from the server', - }); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: 'No response from the server', + }), + ); } else if ( response.error || !response.status || !response.orderId || response.status === 'ERROR' ) { - addNotification({ - type: 'error', - error: response.error || 'Error response from the server', - }); - saveSelectedQuote(response); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: response.error || 'Error response from the server', + }), + ); + dispatch(coinmarketExchangeActions.saveSelectedQuote(response)); } else if (response.status === 'APPROVAL_REQ' || response.status === 'APPROVAL_PENDING') { - saveSelectedQuote(response); + dispatch(coinmarketExchangeActions.saveSelectedQuote(response)); setExchangeStep('SEND_APPROVAL_TRANSACTION'); ok = true; } else if (response.status === 'CONFIRM') { - saveSelectedQuote(response); + dispatch(coinmarketExchangeActions.saveSelectedQuote(response)); if (response.isDex) { if (exchangeStep === 'RECEIVING_ADDRESS' || trade.approvalType === 'ZERO') { setExchangeStep('SEND_APPROVAL_TRANSACTION'); @@ -413,8 +398,10 @@ export const useCoinmarketExchangeForm = ({ ok = true; } else { // CONFIRMING, SUCCESS - saveTrade(response, account, new Date().toISOString()); - saveTransactionId(response.orderId); + dispatch( + coinmarketExchangeActions.saveTrade(response, account, new Date().toISOString()), + ); + dispatch(coinmarketExchangeActions.saveTransactionId(response.orderId)); ok = true; navigateToExchangeDetail(); } @@ -449,7 +436,13 @@ export const useCoinmarketExchangeForm = ({ if (selectedQuote.status === 'CONFIRM' && selectedQuote.approvalType !== 'ZERO') { quote.receiveTxHash = txid; quote.status = 'CONFIRMING'; - saveTrade(quote, account, new Date().toISOString()); + dispatch( + coinmarketExchangeActions.saveTrade( + quote, + account, + new Date().toISOString(), + ), + ); confirmTrade(quote.receiveAddress || '', undefined, quote); } else { quote.approvalSendTxHash = txid; @@ -458,15 +451,17 @@ export const useCoinmarketExchangeForm = ({ } } } else { - addNotification({ - type: 'error', - error: 'Cannot send transaction, missing data', - }); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: 'Cannot send transaction, missing data', + }), + ); } }; const sendTransaction = async () => { - dispatch(setCoinmarketModalAccount(account)); + dispatch(coinmarketCommonActions.setCoinmarketModalAccount(account)); if (selectedQuote?.isDex) { sendDexTransaction(); @@ -494,15 +489,23 @@ export const useCoinmarketExchangeForm = ({ ); // in case of not success, recomposeAndSign shows notification if (result?.success) { - saveTrade(selectedQuote, account, new Date().toISOString()); - saveTransactionId(selectedQuote.orderId); + dispatch( + coinmarketExchangeActions.saveTrade( + selectedQuote, + account, + new Date().toISOString(), + ), + ); + dispatch(coinmarketExchangeActions.saveTransactionId(selectedQuote.orderId)); navigateToExchangeDetail(); } } else { - addNotification({ - type: 'error', - error: 'Cannot send transaction, missing data', - }); + dispatch( + notificationsActions.addToast({ + type: 'error', + error: 'Cannot send transaction, missing data', + }), + ); } }; @@ -649,7 +652,7 @@ export const useCoinmarketExchangeForm = ({ goToOffers, setExchangeStep, sendTransaction, - verifyAddress, + verifyAddress: coinmarketExchangeActions.verifyAddress, selectQuote, confirmTrade, }; diff --git a/packages/suite/src/types/coinmarket/coinmarketForm.ts b/packages/suite/src/types/coinmarket/coinmarketForm.ts index 9707b596f33..888a0609eee 100644 --- a/packages/suite/src/types/coinmarket/coinmarketForm.ts +++ b/packages/suite/src/types/coinmarket/coinmarketForm.ts @@ -30,7 +30,7 @@ import type { } from 'invity-api'; import { Timer } from '@trezor/react-utils'; import { AppState } from 'src/reducers/store'; -import { ExtendedMessageDescriptor } from 'src/types/suite'; +import { Dispatch, ExtendedMessageDescriptor, GetState } from 'src/types/suite'; import { PropsWithChildren } from 'react'; import { AmountLimits, @@ -162,6 +162,12 @@ export interface CoinmarketCommonFormBuySellProps { amountLimits?: AmountLimits; } +type CoinmarketVerifyAccountProps = ( + account: Account, + address?: string, + path?: string, +) => (dispatch: Dispatch, getState: GetState) => Promise; + export interface CoinmarketBuyFormContextProps extends UseFormReturn, CoinmarketCommonFormProps, @@ -180,7 +186,7 @@ export interface CoinmarketBuyFormContextProps selectQuote: (quote: BuyTrade) => Promise; confirmTrade: (address: string) => void; - verifyAddress: (account: Account, address?: string, path?: string) => Promise; + verifyAddress: CoinmarketVerifyAccountProps; removeDraft: (key: string) => void; setAmountLimits: (limits?: AmountLimits) => void; } @@ -256,7 +262,7 @@ export interface CoinmarketExchangeFormContextProps confirmTrade: (address: string, extraField?: string, trade?: ExchangeTrade) => Promise; sendTransaction: () => void; selectQuote: (quote: ExchangeTrade) => void; - verifyAddress: (account: Account, address?: string, path?: string) => Promise; + verifyAddress: CoinmarketVerifyAccountProps; } export type CoinmarketFormMapProps = { diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx index e63c5b4e0d9..4a799c2cf0e 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx @@ -116,8 +116,8 @@ export const ExchangeTransaction = ({ trade, providers, account }: ExchangeTrans const { date, data } = trade; const { send, sendStringAmount, receive, receiveStringAmount, exchange } = data; - const viewDetail = async () => { - await dispatch(saveTransactionId(trade.key || '')); + const viewDetail = () => { + dispatch(saveTransactionId(trade.key || '')); dispatch( goto('wallet-coinmarket-exchange-detail', { params: { diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketVerify/CoinmarketVerify.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketVerify/CoinmarketVerify.tsx index 346ec3d2076..ea0f3840616 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketVerify/CoinmarketVerify.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketVerify/CoinmarketVerify.tsx @@ -244,10 +244,12 @@ export const CoinmarketVerify = ({ coinmarketVerifyAccount, currency }: Coinmark isDisabled={callInProgress} onClick={() => { if (selectedAccountOption.account && accountAddress) { - verifyAddress( - selectedAccountOption.account, - accountAddress.address, - accountAddress.path, + dispatch( + verifyAddress( + selectedAccountOption.account, + accountAddress.address, + accountAddress.path, + ), ); } }} From 171c7d6a207c00fba82c2f51438971b92245bd0b Mon Sep 17 00:00:00 2001 From: PeterBenc Date: Wed, 2 Oct 2024 14:16:15 +0200 Subject: [PATCH 003/624] fix(blockchain-link): do not fetch solana token account signatures for recipient address --- .../src/workers/solana/index.ts | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/blockchain-link/src/workers/solana/index.ts b/packages/blockchain-link/src/workers/solana/index.ts index 1753f1af26c..7c54701b45e 100644 --- a/packages/blockchain-link/src/workers/solana/index.ts +++ b/packages/blockchain-link/src/workers/solana/index.ts @@ -154,14 +154,21 @@ const getAccountInfo = async (request: Request) => const allAccounts = [payload.descriptor, ...tokenAccounts.value.map(a => a.pubkey.toString())]; - const allTxIds = Array.from( - new Set( - (await Promise.all(allAccounts.map(account => getAllSignatures(api, account)))) - .flat() - .sort((a, b) => b.slot - a.slot) - .map(it => it.signature), - ), - ); + const allTxIds = + details === 'basic' || details === 'txs' || details === 'txids' + ? Array.from( + new Set( + ( + await Promise.all( + allAccounts.map(account => getAllSignatures(api, account)), + ) + ) + .flat() + .sort((a, b) => b.slot - a.slot) + .map(it => it.signature), + ), + ) + : []; const pageNumber = payload.page ? payload.page - 1 : 0; // for the first page of txs, payload.page is undefined, for the second page is 2 From 532d22ee2395250cf2631f7427eb64c0e4eacb3e Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Thu, 3 Oct 2024 14:03:25 +0200 Subject: [PATCH 004/624] fix: refactor EAP modals to NewModal with purple icon --- .../src/components/NewModal/NewModal.tsx | 4 +- .../DesktopUpdater/EarlyAccessDisable.tsx | 92 +++++++-------- .../DesktopUpdater/EarlyAccessEnable.tsx | 109 +++++++++--------- 3 files changed, 101 insertions(+), 104 deletions(-) diff --git a/packages/components/src/components/NewModal/NewModal.tsx b/packages/components/src/components/NewModal/NewModal.tsx index f2636cee1ed..75886bba64f 100644 --- a/packages/components/src/components/NewModal/NewModal.tsx +++ b/packages/components/src/components/NewModal/NewModal.tsx @@ -28,7 +28,7 @@ import { withFrameProps, } from '../../utils/frameProps'; import { TransientProps } from '../../utils/transientProps'; -import { NewModalIcon } from './NewModalIcon'; +import { NewModalIcon, type NewModalIconColors } from './NewModalIcon'; export const allowedNewModalFrameProps = ['height'] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; @@ -247,4 +247,4 @@ NewModal.ModalBase = NewModalBase; NewModal.Icon = NewModalIcon; export { NewModal, NEW_MODAL_CONTENT_ID }; -export type { NewModalProps, NewModalSize }; +export type { NewModalProps, NewModalSize, NewModalIconColors }; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessDisable.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessDisable.tsx index 3b28a1dafa8..9e790d72b43 100644 --- a/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessDisable.tsx +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessDisable.tsx @@ -1,33 +1,15 @@ import { useCallback, useState } from 'react'; -import styled from 'styled-components'; +import { useTheme } from 'styled-components'; import { SUITE_URL } from '@trezor/urls'; import { analytics, EventType } from '@trezor/suite-analytics'; import { desktopApi } from '@trezor/suite-desktop-api'; -import { Button, Image } from '@trezor/components'; +import { Button, Column, NewModal, Paragraph } from '@trezor/components'; +import { spacings } from '@trezor/theme'; +import { NewModalIconColors } from '@trezor/components'; -import { Translation, Modal, TrezorLink } from 'src/components/suite'; -import { DialogModal } from 'src/components/suite/modals/Modal/DialogRenderer'; - -import { ImageWrapper, Description, Title } from './styles'; - -export const Link = styled(TrezorLink)` - width: 100%; -`; - -const StyledModal = styled(Modal)` - ${Modal.BottomBar} { - > * { - flex: 1; - } - } -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const LinkButton = styled(Button)` - width: 100%; -`; +import { Translation, TrezorLink } from 'src/components/suite'; interface EarlyAccessDisableProps { hideWindow: () => void; @@ -36,6 +18,8 @@ interface EarlyAccessDisableProps { export const EarlyAccessDisable = ({ hideWindow }: EarlyAccessDisableProps) => { const [enabled, setEnabled] = useState(true); + const theme = useTheme(); + const allowPrerelease = useCallback(() => { analytics.report({ type: EventType.SettingsGeneralEarlyAccess, @@ -47,9 +31,19 @@ export const EarlyAccessDisable = ({ hideWindow }: EarlyAccessDisableProps) => { setEnabled(false); }, []); + const purpleModalColorBranding: NewModalIconColors = { + foreground: theme.iconAlertPurple, + background: theme.backgroundAlertPurpleSubtleOnElevationNegative, + }; + + const eapIconComponent = ; + return enabled ? ( - } + bottomContent={ <> + } - /> + > + + + + + + + + + ); }; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessEnable.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessEnable.tsx index 84afcef66ee..6fb08b3fe90 100644 --- a/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessEnable.tsx +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/EarlyAccessEnable.tsx @@ -1,33 +1,21 @@ import { useCallback, useState } from 'react'; -import styled from 'styled-components'; +import { useTheme } from 'styled-components'; import { analytics, EventType } from '@trezor/suite-analytics'; import { desktopApi } from '@trezor/suite-desktop-api'; -import { Button, Paragraph, Tooltip, Image } from '@trezor/components'; +import { + Button, + Paragraph, + Tooltip, + NewModal, + Card, + Column, + NewModalIconColors, +} from '@trezor/components'; +import { spacings } from '@trezor/theme'; -import { CheckItem, Translation, Modal } from 'src/components/suite'; -import { DialogModal } from 'src/components/suite/modals/Modal/DialogRenderer'; - -import { Description, Divider } from './styles'; - -const DescriptionWrapper = styled.div` - display: flex; -`; - -const DescriptionTextWrapper = styled.div` - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: space-around; - margin-left: 20px; - text-align: left; -`; - -// Checkbox has 80% max-width by default but it's nicer full width here. -const Checkbox = styled(CheckItem)` - max-width: 100%; -`; +import { CheckItem, Translation } from 'src/components/suite'; interface EarlyAccessEnableProps { hideWindow: () => void; @@ -37,6 +25,8 @@ export const EarlyAccessEnable = ({ hideWindow }: EarlyAccessEnableProps) => { const [understood, setUnderstood] = useState(false); const [enabled, setEnabled] = useState(false); + const theme = useTheme(); + const allowPrerelease = useCallback(() => { analytics.report({ type: EventType.SettingsGeneralEarlyAccess, @@ -50,12 +40,19 @@ export const EarlyAccessEnable = ({ hideWindow }: EarlyAccessEnableProps) => { const checkForUpdates = useCallback(() => desktopApi.checkForUpdates(true), []); + const purpleModalColorBranding: NewModalIconColors = { + foreground: theme.iconAlertPurple, + background: theme.backgroundAlertPurpleSubtleOnElevationNegative, + }; + + const eapIconComponent = ; + return enabled ? ( - } - body={} - bottomBarComponents={ + } + onCancel={hideWindow} + bottomContent={ <> } - /> + > + + ) : ( - } - isCancelable onCancel={hideWindow} - bottomBarComponents={ + bottomContent={ { } > + } - onCancel={hideWindow} > - - {progress?.verifying ? ( - - - {ellipsisArray.filter((_, k) => k < step)} - - ) : ( - <> + + + {progress?.verifying ? ( - + + {ellipsisArray.filter((_, k) => k < step)} - - - {bytesToHumanReadable(progress?.transferred || 0)} - - /{bytesToHumanReadable(progress?.total || 0)} - - - )} - - - - + ) : ( + <> + + + + + + {bytesToHumanReadable(progress?.transferred || 0)} + + /{bytesToHumanReadable(progress?.total || 0)} + + + )} + + + + + ); }; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/Ready.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater/Ready.tsx index 071a4fea8f4..fc90908c5df 100644 --- a/packages/suite-desktop-ui/src/support/DesktopUpdater/Ready.tsx +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/Ready.tsx @@ -1,31 +1,15 @@ -import styled from 'styled-components'; +import { Button, NewModal, Paragraph, Row } from '@trezor/components'; +import { spacings } from '@trezor/theme'; -import { Button, H2, variables } from '@trezor/components'; - -import { Translation, Modal } from 'src/components/suite'; +import { Translation } from 'src/components/suite'; import { useDispatch } from 'src/hooks/suite'; import { installUpdate } from 'src/actions/suite/desktopUpdateActions'; -const Description = styled.span` - font-size: ${variables.FONT_SIZE.SMALL}; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; -`; - -const StyledModal = styled(Modal)` - ${Modal.BottomBar} { - > * { - flex: 1; - } - } -`; - interface ReadyProps { hideWindow: () => void; - isCancelable: boolean; } -export const Ready = ({ hideWindow, isCancelable }: ReadyProps) => { +export const Ready = ({ hideWindow }: ReadyProps) => { const dispatch = useDispatch(); const install = () => dispatch(installUpdate({ shouldInstallOnQuit: false })); @@ -35,27 +19,26 @@ export const Ready = ({ hideWindow, isCancelable }: ReadyProps) => { }; return ( - } - isCancelable={isCancelable} onCancel={installOnQuit} - bottomBarComponents={ - <> + bottomContent={ + - + } > -

+ -

- + + - -
+ +
); }; From fedf275bae6e61b11542e3279e61359057671e62 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Thu, 3 Oct 2024 10:22:07 +0200 Subject: [PATCH 006/624] fix(suite): HiddenPlaceholder onHover when not discreet mode --- .../suite/src/components/suite/HiddenPlaceholder.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/suite/src/components/suite/HiddenPlaceholder.tsx b/packages/suite/src/components/suite/HiddenPlaceholder.tsx index 19e5733eb25..de3158f2af7 100644 --- a/packages/suite/src/components/suite/HiddenPlaceholder.tsx +++ b/packages/suite/src/components/suite/HiddenPlaceholder.tsx @@ -8,7 +8,6 @@ type WrapperProps = { $intensity: number; $discreetMode: boolean; $minWidth?: number; - $disableKeepingWidth?: boolean; }; const Wrapper = styled.span` @@ -26,9 +25,8 @@ const Wrapper = styled.span` } `} - ${({ $minWidth, $disableKeepingWidth }: WrapperProps) => + ${({ $minWidth }: WrapperProps) => !!$minWidth && - !$disableKeepingWidth && css` display: inline-block; min-width: ${$minWidth}px; @@ -95,14 +93,15 @@ export const HiddenPlaceholder = ({ setWrapperMinWidth(undefined); }; + const shouldEnforceMinWidth = discreetMode && !disableKeepingWidth; + return ( Date: Thu, 3 Oct 2024 14:30:23 +0200 Subject: [PATCH 007/624] feat(components): Table colWidths enforces width --- .../src/components/Table/Table.stories.tsx | 12 ++++++++++++ packages/components/src/components/Table/Table.tsx | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/Table/Table.stories.tsx b/packages/components/src/components/Table/Table.stories.tsx index 0b7ab6d55f9..143b7aa01cd 100644 --- a/packages/components/src/components/Table/Table.stories.tsx +++ b/packages/components/src/components/Table/Table.stories.tsx @@ -37,8 +37,20 @@ export const Table: StoryObj = { ), args: { ...getFramePropsStory(allowedTableFrameProps).args, + colWidths: 'none', }, argTypes: { ...getFramePropsStory(allowedTableFrameProps).argTypes, + colWidths: { + options: ['none', 'fixed'], + mapping: { none: undefined, fixed: ['150px', '400px'] }, + control: { + type: 'select', + labels: { + none: 'undefined', + fixed: "fixed = ['150px', '400px']", + }, + }, + }, }, }; diff --git a/packages/components/src/components/Table/Table.tsx b/packages/components/src/components/Table/Table.tsx index 1bf4303411a..897908f35fb 100644 --- a/packages/components/src/components/Table/Table.tsx +++ b/packages/components/src/components/Table/Table.tsx @@ -43,7 +43,7 @@ export const Table = ({ children, margin, colWidths }: TableProps) => { {colWidths && ( {colWidths.map((width, index) => ( - + ))} )} From a864485b9c769a55c47102d20a7ecca52b3507cc Mon Sep 17 00:00:00 2001 From: MiroslavProchazka Date: Wed, 2 Oct 2024 15:34:07 +0200 Subject: [PATCH 008/624] fix(suite): fix colors and icons in Tx detail --- .../suite/FormattedDateWithBullet.tsx | 3 - .../TransactionReviewSummary.tsx | 4 +- .../TxDetailModal/BasicTxDetails.tsx | 76 +++++++++++------- .../TxDetailModal/IOAddress.tsx | 79 ++++++++++--------- 4 files changed, 91 insertions(+), 71 deletions(-) diff --git a/packages/suite/src/components/suite/FormattedDateWithBullet.tsx b/packages/suite/src/components/suite/FormattedDateWithBullet.tsx index aee1eeefdcf..5e60e967aad 100644 --- a/packages/suite/src/components/suite/FormattedDateWithBullet.tsx +++ b/packages/suite/src/components/suite/FormattedDateWithBullet.tsx @@ -5,13 +5,10 @@ import { FormattedDate, FormattedDateProps } from './FormattedDate'; const Bullet = styled.span` margin-left: 0.5ch; margin-right: 0.5ch; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; `; const HourWrapper = styled.div<{ $timeLightColor?: boolean }>` display: inline-flex; - color: ${({ theme, $timeLightColor }) => - $timeLightColor ? theme.legacy.TYPE_LIGHT_GREY : 'inherit'}; `; const Timestamp = styled.span` diff --git a/packages/suite/src/components/suite/modals/ReduxModal/TransactionReviewModal/TransactionReviewSummary.tsx b/packages/suite/src/components/suite/modals/ReduxModal/TransactionReviewModal/TransactionReviewSummary.tsx index a33e50089f6..42a5838164a 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/TransactionReviewModal/TransactionReviewSummary.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/TransactionReviewModal/TransactionReviewSummary.tsx @@ -293,7 +293,7 @@ export const TransactionReviewSummary = ({ {!!tx.feeLimit && network.networkType !== 'solana' && ( - + @@ -304,7 +304,7 @@ export const TransactionReviewSummary = ({ )} - + diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/BasicTxDetails.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/BasicTxDetails.tsx index 54c4c1bf034..c3a677eab46 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/BasicTxDetails.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/BasicTxDetails.tsx @@ -26,7 +26,7 @@ const Wrapper = styled.div<{ $elevation: Elevation }>` const Confirmations = styled.div` display: flex; - color: ${({ theme }) => theme.textSubdued}; + color: ${({ theme }) => theme.textDefault}; ${typography.hint} `; @@ -82,12 +82,6 @@ const Value = styled.div` text-overflow: ellipsis; font-variant-numeric: tabular-nums; `; - -const TxidValue = styled.div` - color: ${({ theme }) => theme.textDefault}; - ${typography.label} -`; - const IconWrapper = styled.div<{ $elevation: Elevation }>` background-color: ${mapElevationToBorder}; border-radius: ${borders.radii.full}; @@ -145,18 +139,13 @@ const ConfirmationStatus = styled.div<{ $confirmed: boolean; $tiny?: boolean }>` const Circle = styled.div` margin-left: ${spacingsPx.xxs}; margin-right: ${spacingsPx.xxs}; - color: ${({ theme }) => theme.textSubdued}; + color: ${({ theme }) => theme.textDefault}; `; const Timestamp = styled.span` white-space: nowrap; `; -const IconPlaceholder = styled.span` - min-width: 10px; - margin-right: ${spacingsPx.xs}; -`; - interface BasicTxDetailsProps { tx: WalletAccountTransaction; network: Network; @@ -229,7 +218,12 @@ export const BasicTxDetails = ({ {/* MINED TIME */} - <Icon name="calendar" size={10} margin={{ right: spacings.xs }} /> + <Icon + name="calendar" + size={15} + margin={{ right: spacings.xs }} + variant="tertiary" + /> {isConfirmed ? ( <Translation id="TR_MINED_TIME" /> ) : ( @@ -252,23 +246,31 @@ export const BasicTxDetails = ({ {/* TX ID */} <Title> - <Icon name="biometric" size={10} margin={{ right: spacings.xs }} /> + <Icon + name="biometric" + size={15} + margin={{ right: spacings.xs }} + variant="tertiary" + /> <Translation id="TR_TXID" /> - - - + {network.networkType === 'bitcoin' && ( <> {/* Fee level */} - <Icon margin={{ right: spacings.xs }} name="gas" size={10} /> + <Icon + margin={{ right: spacings.xs }} + name="gas" + size={15} + variant="tertiary" + /> <Translation id="TR_FEE_RATE" /> @@ -287,13 +289,23 @@ export const BasicTxDetails = ({ {tx.ethereumSpecific && ( <> - <Icon name="gas" size={10} margin={{ right: spacings.xs }} /> + <Icon + name="gasPump" + size={15} + margin={{ right: spacings.xs }} + variant="tertiary" + /> <Translation id="TR_GAS_LIMIT" /> {tx.ethereumSpecific.gasLimit} - <Icon name="gas" size={10} margin={{ right: spacings.xs }} /> + <Icon + name="gasPump" + size={15} + margin={{ right: spacings.xs }} + variant="tertiary" + /> <Translation id="TR_GAS_USED" /> @@ -305,7 +317,12 @@ export const BasicTxDetails = ({ - <Icon name="gas" size={10} margin={{ right: spacings.xs }} /> + <Icon + name="gasPump" + size={15} + margin={{ right: spacings.xs }} + variant="tertiary" + /> <Translation id="TR_GAS_PRICE" /> {`${fromWei(tx.ethereumSpecific?.gasPrice ?? '0', 'gwei')} ${getFeeUnits( @@ -313,7 +330,12 @@ export const BasicTxDetails = ({ )}`} - <IconPlaceholder>#</IconPlaceholder> + <Icon + name="hash" + size={15} + margin={{ right: spacings.xs }} + variant="tertiary" + /> <Translation id="TR_NONCE" /> {tx.ethereumSpecific?.nonce} diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/IOAddress.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/IOAddress.tsx index 12551fbcad5..b47b2b51bea 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/IOAddress.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/IOAddress.tsx @@ -1,5 +1,5 @@ import { HiddenPlaceholder } from 'src/components/suite/HiddenPlaceholder'; -import { Icon, Link } from '@trezor/components'; +import { Icon, Link, Paragraph } from '@trezor/components'; import { useState } from 'react'; import { copyToClipboard } from '@trezor/dom-utils'; import styled, { css, useTheme } from 'styled-components'; @@ -34,7 +34,6 @@ const TextOverflowContainer = styled.div<{ $shouldAllowCopy?: boolean }>` align-items: center; max-width: 100%; overflow: hidden; - color: ${({ theme }) => theme.textSubdued}; cursor: ${({ $shouldAllowCopy }) => ($shouldAllowCopy ? 'pointer' : 'cursor')}; user-select: none; @@ -95,42 +94,44 @@ export const IOAddress = ({ // HiddenPlaceholder disableKeepingWidth: it isn't needed (no numbers to redact), but inline-block disrupts overflow behavior return ( - - setIsClicked(false)} - data-testid="@tx-detail/txid-value" - id={txAddress} - $shouldAllowCopy={shouldAllowCopy} - > - {txAddress.length <= 5 ? ( - {txAddress} - ) : ( - <> - {txAddress.slice(0, -4)} - {txAddress.slice(-4)} - - )} - {shouldAllowCopy ? ( - - - - ) : null} - {explorerUrl ? ( - - - - - - ) : null} - - + + + setIsClicked(false)} + data-testid="@tx-detail/txid-value" + id={txAddress} + $shouldAllowCopy={shouldAllowCopy} + > + {txAddress.length <= 5 ? ( + {txAddress} + ) : ( + <> + {txAddress.slice(0, -4)} + {txAddress.slice(-4)} + + )} + {shouldAllowCopy ? ( + + + + ) : null} + {explorerUrl ? ( + + + + + + ) : null} + + + ); }; From befbe2d95b107b3ae9c5e367364580eb2f26eddc Mon Sep 17 00:00:00 2001 From: yanas Date: Thu, 3 Oct 2024 15:48:56 +0200 Subject: [PATCH 009/624] refactor(suite-native): use spacings constants for gap attributes --- .../src/components/DeviceItem/DeviceItemContent.tsx | 4 ++-- .../device-manager/src/components/DeviceManagerContent.tsx | 4 ++-- suite-native/device-manager/src/components/WalletItem.tsx | 2 +- .../src/screens/SelectAccountTypeScreen.tsx | 2 +- .../src/screens/passphrase/PassphraseEmptyWalletScreen.tsx | 2 +- .../src/components/ViewOnly/DevicesManagement.tsx | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx b/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx index 2f16bd8f3c0..5f1ab2fce13 100644 --- a/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx +++ b/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx @@ -38,12 +38,12 @@ const contentWrapperStyle = prepareNativeStyle<{ height: number }>((utils, { hei spacing: utils.spacings.sp16, })); -const itemStyle = prepareNativeStyle<{ isCompact: boolean }>((_, { isCompact }) => ({ +const itemStyle = prepareNativeStyle<{ isCompact: boolean }>((utils, { isCompact }) => ({ flexShrink: 1, extend: { condition: !isCompact, style: { - gap: 2, + gap: utils.spacings.sp2, }, }, })); diff --git a/suite-native/device-manager/src/components/DeviceManagerContent.tsx b/suite-native/device-manager/src/components/DeviceManagerContent.tsx index 374b576c18f..f233cb2e5db 100644 --- a/suite-native/device-manager/src/components/DeviceManagerContent.tsx +++ b/suite-native/device-manager/src/components/DeviceManagerContent.tsx @@ -26,8 +26,8 @@ import { useDeviceManager } from '../hooks/useDeviceManager'; const CONTENT_MAX_HEIGHT = Dimensions.get('window').height * 0.8; const HEADER_HEIGHT = 86; -const scrollViewStyle = prepareNativeStyle<{ maxHeight: number }>((_, { maxHeight }) => ({ - gap: 12, +const scrollViewStyle = prepareNativeStyle<{ maxHeight: number }>((utils, { maxHeight }) => ({ + gap: utils.spacings.sp12, flexGrow: 0, maxHeight, borderBottomLeftRadius: MANAGER_MODAL_BOTTOM_RADIUS, diff --git a/suite-native/device-manager/src/components/WalletItem.tsx b/suite-native/device-manager/src/components/WalletItem.tsx index 3ebe73ea6c6..4da09aea93d 100644 --- a/suite-native/device-manager/src/components/WalletItem.tsx +++ b/suite-native/device-manager/src/components/WalletItem.tsx @@ -23,7 +23,7 @@ const walletItemStyle = prepareNativeStyle( justifyContent: 'space-between', alignItems: 'center', height: 60, - gap: 12, + gap: utils.spacings.sp12, borderRadius: 12, borderColor: utils.colors.borderElevation1, flex: 1, diff --git a/suite-native/module-add-accounts/src/screens/SelectAccountTypeScreen.tsx b/suite-native/module-add-accounts/src/screens/SelectAccountTypeScreen.tsx index 538d967c78b..417ac2a33e5 100644 --- a/suite-native/module-add-accounts/src/screens/SelectAccountTypeScreen.tsx +++ b/suite-native/module-add-accounts/src/screens/SelectAccountTypeScreen.tsx @@ -79,7 +79,7 @@ const aboutStyle = prepareNativeStyle((utils, { bottomInset }: { bottomInset: nu paddingBottom: EXTRA_BOTTOM_PADDING + GRADIENT_HEIGHT + bottomInset, width: '100%', paddingHorizontal: utils.spacings.sp8, - gap: 12, + gap: utils.spacings.sp12, })); export const SelectAccountTypeScreen = ({ diff --git a/suite-native/module-authorize-device/src/screens/passphrase/PassphraseEmptyWalletScreen.tsx b/suite-native/module-authorize-device/src/screens/passphrase/PassphraseEmptyWalletScreen.tsx index b37eee59ce9..9e4460a7edf 100644 --- a/suite-native/module-authorize-device/src/screens/passphrase/PassphraseEmptyWalletScreen.tsx +++ b/suite-native/module-authorize-device/src/screens/passphrase/PassphraseEmptyWalletScreen.tsx @@ -24,7 +24,7 @@ import { QuestionMarks } from '../../assets/passphrase/QuestionMarks'; const cardStyle = prepareNativeStyle(utils => ({ borderColor: utils.colors.borderElevation0, borderWidth: utils.borders.widths.small, - gap: 12, + gap: utils.spacings.sp12, })); const cardContentStyle = prepareNativeStyle(() => ({ diff --git a/suite-native/module-settings/src/components/ViewOnly/DevicesManagement.tsx b/suite-native/module-settings/src/components/ViewOnly/DevicesManagement.tsx index a61d96cda4f..86fcaa31f64 100644 --- a/suite-native/module-settings/src/components/ViewOnly/DevicesManagement.tsx +++ b/suite-native/module-settings/src/components/ViewOnly/DevicesManagement.tsx @@ -18,7 +18,7 @@ const cardStyle = prepareNativeStyle(utils => ({ const deviceStyle = prepareNativeStyle(utils => ({ padding: utils.spacings.sp16, alignItems: 'center', - gap: 12, + gap: utils.spacings.sp12, })); export const DevicesManagement = ({ onPressAbout }: AboutProps) => { From 019e734086cfdca45f9ec030cd00a4cf6967b94f Mon Sep 17 00:00:00 2001 From: yanas Date: Thu, 3 Oct 2024 15:09:03 +0200 Subject: [PATCH 010/624] refactor(suite-native): rename and add missing border radii constants --- packages/theme/src/borders.ts | 14 +++++++++----- .../AccountsList/AccountsListItemBase.tsx | 8 ++++---- suite-native/alerts/src/components/AlertSheet.tsx | 2 +- suite-native/atoms/src/AlertBox.tsx | 2 +- suite-native/atoms/src/Card/Card.tsx | 6 +++--- suite-native/atoms/src/CheckBox.tsx | 2 +- suite-native/atoms/src/ErrorMessage.tsx | 2 +- suite-native/atoms/src/Input/Input.tsx | 2 +- suite-native/atoms/src/Input/SearchInput.tsx | 2 +- suite-native/atoms/src/OrderedListIcon.tsx | 2 +- suite-native/atoms/src/Select/SelectTrigger.tsx | 2 +- suite-native/atoms/src/SelectableItem.tsx | 2 +- suite-native/atoms/src/Sheet/BottomSheet.tsx | 4 ++-- suite-native/atoms/src/Skeleton/BoxSkeleton.tsx | 2 +- .../atoms/src/Skeleton/ListItemSkeleton.tsx | 4 ++-- suite-native/atoms/src/StepsProgressBar.tsx | 4 ++-- .../device-manager/src/components/DeviceAction.tsx | 2 +- .../src/components/DeviceManagerModal.tsx | 3 ++- .../device-manager/src/components/WalletItem.tsx | 2 +- suite-native/graph/src/components/GraphError.tsx | 4 ++-- .../src/components/AccountImportOverviewCard.tsx | 2 +- .../src/components/CoinPriceCard.tsx | 2 +- .../src/components/passphrase/PassphraseForm.tsx | 2 +- .../screens/passphrase/PassphraseFormScreen.tsx | 2 +- .../module-dev-utils/src/screens/DemoScreen.tsx | 2 +- .../components/BiometricsBottomSheet.tsx | 2 +- .../module-send/src/components/FeeOption.tsx | 2 +- .../src/components/ReviewOutputCard.tsx | 2 +- .../src/components/ColorSchemePickerItem.tsx | 2 +- .../qr-code/src/components/QRCodeScanner.tsx | 2 +- .../src/components/DevicePaginationButton.tsx | 6 +++--- .../src/components/UnverifiedAddressDevice.tsx | 4 ++-- .../src/components/TransactionsEmptyState.tsx | 2 +- .../TransactionListItemContainer.tsx | 8 ++++---- suite-native/video-assets/src/components/Video.tsx | 2 +- 35 files changed, 59 insertions(+), 54 deletions(-) diff --git a/packages/theme/src/borders.ts b/packages/theme/src/borders.ts index 9e46fcd34f3..ba141ab6b3d 100644 --- a/packages/theme/src/borders.ts +++ b/packages/theme/src/borders.ts @@ -17,6 +17,8 @@ export const borders = { export type Borders = typeof borders; +type NativeRadiusValue = 4 | 8 | 12 | 16 | 20 | 24; + export const nativeBorders = { widths: { small: 1, @@ -24,12 +26,14 @@ export const nativeBorders = { large: 2, }, radii: { - extraSmall: 4, - small: 8, - medium: 16, - large: 24, + r4: 4, + r8: 8, + r12: 12, + r16: 16, + r20: 20, + r24: 24, round: 100, // Equivalent to 50% on the web - }, + } satisfies { [V in NativeRadiusValue as `r${V}`]: V } & { round: 100 }, } as const; export type NativeBorders = typeof nativeBorders; diff --git a/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx b/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx index 2aa951e614e..9fecf9fb354 100644 --- a/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx +++ b/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx @@ -44,16 +44,16 @@ const accountListItemStyle = prepareNativeStyle<{ { condition: isFirst, style: { - borderTopLeftRadius: utils.borders.radii.medium, - borderTopRightRadius: utils.borders.radii.medium, + borderTopLeftRadius: utils.borders.radii.r16, + borderTopRightRadius: utils.borders.radii.r16, ...utils.boxShadows.small, }, }, { condition: isLast, style: { - borderBottomLeftRadius: utils.borders.radii.medium, - borderBottomRightRadius: utils.borders.radii.medium, + borderBottomLeftRadius: utils.borders.radii.r16, + borderBottomRightRadius: utils.borders.radii.r16, marginBottom: utils.spacings.sp32, ...utils.boxShadows.small, }, diff --git a/suite-native/alerts/src/components/AlertSheet.tsx b/suite-native/alerts/src/components/AlertSheet.tsx index 493e4ae8646..3a987a8363a 100644 --- a/suite-native/alerts/src/components/AlertSheet.tsx +++ b/suite-native/alerts/src/components/AlertSheet.tsx @@ -29,7 +29,7 @@ const alertSheetContainerStyle = prepareNativeStyle(utils => ({ paddingVertical: utils.spacings.sp32, marginBottom: utils.spacings.sp32, marginHorizontal: utils.spacings.sp8, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, ...utils.boxShadows.small, })); diff --git a/suite-native/atoms/src/AlertBox.tsx b/suite-native/atoms/src/AlertBox.tsx index 43b3c4cf180..18d77c13409 100644 --- a/suite-native/atoms/src/AlertBox.tsx +++ b/suite-native/atoms/src/AlertBox.tsx @@ -94,7 +94,7 @@ const AlertSpinner = ({ color }: { color: Color }) => { export const AlertBox = ({ title, variant = 'info', - borderRadius = nativeBorders.radii.medium, + borderRadius = nativeBorders.radii.r16, }: AlertBoxProps) => { const { applyStyle } = useNativeStyles(); const { contentColor, backgroundColor, borderColor } = variantToColorMap[variant]; diff --git a/suite-native/atoms/src/Card/Card.tsx b/suite-native/atoms/src/Card/Card.tsx index e900973fe8e..6395fd0c17a 100644 --- a/suite-native/atoms/src/Card/Card.tsx +++ b/suite-native/atoms/src/Card/Card.tsx @@ -25,7 +25,7 @@ const cardContainerStyle = prepareNativeStyle<{ borderColor?: Color; }>((utils, { isAlertDisplayed, noPadding, borderColor }) => ({ backgroundColor: utils.colors.backgroundSurfaceElevation1, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, padding: noPadding ? 0 : utils.spacings.sp16, ...utils.boxShadows.small, @@ -49,8 +49,8 @@ const cardContainerStyle = prepareNativeStyle<{ const alertBoxWrapperStyle = prepareNativeStyle(utils => ({ backgroundColor: utils.colors.backgroundSurfaceElevation1, - borderTopLeftRadius: utils.borders.radii.medium, - borderTopRightRadius: utils.borders.radii.medium, + borderTopLeftRadius: utils.borders.radii.r16, + borderTopRightRadius: utils.borders.radii.r16, paddingHorizontal: utils.spacings.sp4, paddingTop: utils.spacings.sp4, })); diff --git a/suite-native/atoms/src/CheckBox.tsx b/suite-native/atoms/src/CheckBox.tsx index 11c1b6adc55..90b0343dc15 100644 --- a/suite-native/atoms/src/CheckBox.tsx +++ b/suite-native/atoms/src/CheckBox.tsx @@ -26,7 +26,7 @@ const checkBoxStyle = prepareNativeStyle( width: CHECKBOX_SIZE, alignItems: 'center', justifyContent: 'center', - borderRadius: 4, + borderRadius: utils.borders.radii.r4, borderWidth: utils.borders.widths.medium, borderColor: utils.colors.borderElevation2, backgroundColor: isDisabled diff --git a/suite-native/atoms/src/ErrorMessage.tsx b/suite-native/atoms/src/ErrorMessage.tsx index 8776104d9be..a5c48810587 100644 --- a/suite-native/atoms/src/ErrorMessage.tsx +++ b/suite-native/atoms/src/ErrorMessage.tsx @@ -18,7 +18,7 @@ const errorMessageStyle = prepareNativeStyle(utils => ({ margin: utils.spacings.sp8, borderColor: utils.colors.borderAlertRed, borderWidth: 1, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, padding: utils.spacings.sp24, })); diff --git a/suite-native/atoms/src/Input/Input.tsx b/suite-native/atoms/src/Input/Input.tsx index d7fee699b87..6d48d40231a 100644 --- a/suite-native/atoms/src/Input/Input.tsx +++ b/suite-native/atoms/src/Input/Input.tsx @@ -87,7 +87,7 @@ const inputWrapperStyle = prepareNativeStyle( ? utils.colors.backgroundNeutralSubtleOnElevation1 : utils.colors.borderInputDefault, borderWidth: utils.borders.widths.small, - borderRadius: 1.5 * utils.borders.radii.small, + borderRadius: utils.borders.radii.r12, margin: utils.borders.widths.small, paddingHorizontal: INPUT_WRAPPER_PADDING_HORIZONTAL, justifyContent: 'flex-end', diff --git a/suite-native/atoms/src/Input/SearchInput.tsx b/suite-native/atoms/src/Input/SearchInput.tsx index 4c3219d76fb..78aeada338c 100644 --- a/suite-native/atoms/src/Input/SearchInput.tsx +++ b/suite-native/atoms/src/Input/SearchInput.tsx @@ -34,7 +34,7 @@ const inputWrapperStyle = prepareNativeStyle( alignItems: 'center', height: 48, borderWidth: utils.borders.widths.small, - borderRadius: utils.borders.radii.small, + borderRadius: utils.borders.radii.r8, borderColor: utils.colors.backgroundNeutralSubtleOnElevation0, backgroundColor: utils.colors.backgroundNeutralSubtleOnElevation0, paddingLeft: 14, diff --git a/suite-native/atoms/src/OrderedListIcon.tsx b/suite-native/atoms/src/OrderedListIcon.tsx index 73fec6d13ec..fcfa61c4050 100644 --- a/suite-native/atoms/src/OrderedListIcon.tsx +++ b/suite-native/atoms/src/OrderedListIcon.tsx @@ -14,7 +14,7 @@ const iconBackgroundStyle = prepareNativeStyle<{ color: Color; borderColor: Colo justifyContent: 'center', width: utils.spacings.sp32, height: utils.spacings.sp32, - borderRadius: 12, + borderRadius: utils.borders.radii.r12, extend: [ { condition: G.isNotNullable(color), diff --git a/suite-native/atoms/src/Select/SelectTrigger.tsx b/suite-native/atoms/src/Select/SelectTrigger.tsx index 20a87210051..b3d1b84119f 100644 --- a/suite-native/atoms/src/Select/SelectTrigger.tsx +++ b/suite-native/atoms/src/Select/SelectTrigger.tsx @@ -22,7 +22,7 @@ const selectStyle = prepareNativeStyle(utils => ({ alignItems: 'center', backgroundColor: utils.colors.backgroundNeutralSubtleOnElevation1, borderWidth: utils.borders.widths.small, - borderRadius: utils.borders.radii.small, + borderRadius: utils.borders.radii.r8, borderColor: utils.colors.backgroundNeutralSubtleOnElevation1, color: utils.colors.textSubdued, paddingLeft: utils.spacings.sp12, diff --git a/suite-native/atoms/src/SelectableItem.tsx b/suite-native/atoms/src/SelectableItem.tsx index 930f1391bcf..d89f6e24d87 100644 --- a/suite-native/atoms/src/SelectableItem.tsx +++ b/suite-native/atoms/src/SelectableItem.tsx @@ -12,7 +12,7 @@ import { Radio } from './Radio'; const cardStyle = prepareNativeStyle((utils, { isSelected }: { isSelected: boolean }) => ({ backgroundColor: utils.colors.backgroundSurfaceElevation1, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, padding: utils.spacings.sp16, ...utils.boxShadows.small, extend: [ diff --git a/suite-native/atoms/src/Sheet/BottomSheet.tsx b/suite-native/atoms/src/Sheet/BottomSheet.tsx index 02f450cbb1c..94e42f1a5a9 100644 --- a/suite-native/atoms/src/Sheet/BottomSheet.tsx +++ b/suite-native/atoms/src/Sheet/BottomSheet.tsx @@ -29,8 +29,8 @@ const DEFAULT_INSET_BOTTOM = 50; const sheetWrapperStyle = prepareNativeStyle((utils, { insetBottom }) => ({ backgroundColor: utils.colors.backgroundSurfaceElevation0, - borderTopLeftRadius: utils.borders.radii.large, - borderTopRightRadius: utils.borders.radii.large, + borderTopLeftRadius: utils.borders.radii.r24, + borderTopRightRadius: utils.borders.radii.r24, paddingBottom: Math.max(insetBottom, utils.spacings.sp16), maxHeight: '90%', })); diff --git a/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx b/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx index 3c395577401..105cb0a194d 100644 --- a/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx +++ b/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx @@ -48,7 +48,7 @@ export const BoxSkeleton = ({ height, width, elevation = '1', - borderRadius = nativeBorders.radii.small, + borderRadius = nativeBorders.radii.r8, }: BoxSkeletonProps) => { const { utils: { colors }, diff --git a/suite-native/atoms/src/Skeleton/ListItemSkeleton.tsx b/suite-native/atoms/src/Skeleton/ListItemSkeleton.tsx index 03d0479273b..89e661d8a8d 100644 --- a/suite-native/atoms/src/Skeleton/ListItemSkeleton.tsx +++ b/suite-native/atoms/src/Skeleton/ListItemSkeleton.tsx @@ -36,12 +36,12 @@ export const ListItemSkeleton = () => { diff --git a/suite-native/atoms/src/StepsProgressBar.tsx b/suite-native/atoms/src/StepsProgressBar.tsx index b046ad53499..6925ec9aa6f 100644 --- a/suite-native/atoms/src/StepsProgressBar.tsx +++ b/suite-native/atoms/src/StepsProgressBar.tsx @@ -15,7 +15,7 @@ const progressBarWrapperStyle = prepareNativeStyle(utils => ({ paddingVertical: utils.spacings.sp8, paddingHorizontal: utils.spacings.sp8, gap: utils.spacings.sp4, - borderRadius: 10, + borderRadius: utils.borders.radii.round, borderWidth: utils.borders.widths.small, alignItems: 'center', height: 20, @@ -26,7 +26,7 @@ const progressBarWrapperStyle = prepareNativeStyle(utils => ({ const progressBarItemStyle = prepareNativeStyle<{ isActive: boolean }>((utils, { isActive }) => ({ width: isActive ? 8 : 4, height: 4, - borderRadius: utils.borders.radii.small / 4, + borderRadius: utils.borders.radii.round, backgroundColor: isActive ? utils.colors.backgroundSecondaryDefault : utils.colors.backgroundNeutralSubdued, diff --git a/suite-native/device-manager/src/components/DeviceAction.tsx b/suite-native/device-manager/src/components/DeviceAction.tsx index ee837ee4a4a..df2e172ec3d 100644 --- a/suite-native/device-manager/src/components/DeviceAction.tsx +++ b/suite-native/device-manager/src/components/DeviceAction.tsx @@ -20,7 +20,7 @@ const contentStyle = prepareNativeStyle(utils => ({ gap: utils.spacings.sp8, backgroundColor: utils.colors.backgroundSurfaceElevation1, borderWidth: utils.borders.widths.small, - borderRadius: 12, + borderRadius: utils.borders.radii.r12, borderColor: utils.colors.borderElevation1, })); diff --git a/suite-native/device-manager/src/components/DeviceManagerModal.tsx b/suite-native/device-manager/src/components/DeviceManagerModal.tsx index 140d9d2237f..8ac671be336 100644 --- a/suite-native/device-manager/src/components/DeviceManagerModal.tsx +++ b/suite-native/device-manager/src/components/DeviceManagerModal.tsx @@ -7,6 +7,7 @@ import { useSelector } from 'react-redux'; import { ScreenHeaderWrapper, Box, HStack } from '@suite-native/atoms'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; import { selectDeviceState } from '@suite-common/wallet-core'; +import { nativeBorders } from '@trezor/theme'; import { useDeviceManager } from '../hooks/useDeviceManager'; import { DeviceItemContent } from './DeviceItem/DeviceItemContent'; @@ -17,7 +18,7 @@ type DeviceManagerModalProps = { onClose?: () => void; }; -export const MANAGER_MODAL_BOTTOM_RADIUS = 12; +export const MANAGER_MODAL_BOTTOM_RADIUS = nativeBorders.radii.r12; const modalBackgroundOverlayStyle = prepareNativeStyle(utils => ({ flex: 1, diff --git a/suite-native/device-manager/src/components/WalletItem.tsx b/suite-native/device-manager/src/components/WalletItem.tsx index 4da09aea93d..de86856fdd4 100644 --- a/suite-native/device-manager/src/components/WalletItem.tsx +++ b/suite-native/device-manager/src/components/WalletItem.tsx @@ -24,7 +24,7 @@ const walletItemStyle = prepareNativeStyle( alignItems: 'center', height: 60, gap: utils.spacings.sp12, - borderRadius: 12, + borderRadius: utils.borders.radii.r12, borderColor: utils.colors.borderElevation1, flex: 1, extend: [ diff --git a/suite-native/graph/src/components/GraphError.tsx b/suite-native/graph/src/components/GraphError.tsx index 2b84c7fec06..570c4a1863a 100644 --- a/suite-native/graph/src/components/GraphError.tsx +++ b/suite-native/graph/src/components/GraphError.tsx @@ -11,10 +11,10 @@ type GraphErrorProps = { onTryAgain: () => void; }; -const errorIconStyle = prepareNativeStyle(({ colors }) => ({ +const errorIconStyle = prepareNativeStyle(({ borders, colors }) => ({ width: 48, height: 48, - borderRadius: 24, + borderRadius: borders.radii.r24, backgroundColor: colors.backgroundAlertYellowSubtleOnElevation1, borderColor: colors.backgroundAlertYellowSubtleOnElevation0, borderWidth: 3, diff --git a/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx b/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx index 1745e12864d..13d193076db 100644 --- a/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx +++ b/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx @@ -15,7 +15,7 @@ import { NetworkSymbol } from '@suite-common/wallet-config'; const assetCardStyle = prepareNativeStyle(utils => ({ padding: utils.spacings.sp24, - borderRadius: utils.borders.radii.large, + borderRadius: utils.borders.radii.r24, width: '100%', })); diff --git a/suite-native/module-accounts-management/src/components/CoinPriceCard.tsx b/suite-native/module-accounts-management/src/components/CoinPriceCard.tsx index ffcf015c298..db64e8102aa 100644 --- a/suite-native/module-accounts-management/src/components/CoinPriceCard.tsx +++ b/suite-native/module-accounts-management/src/components/CoinPriceCard.tsx @@ -23,7 +23,7 @@ const cardStyle = prepareNativeStyle(utils => ({ alignItem: 'center', padding: utils.spacings.sp16, backgroundColor: utils.colors.backgroundSurfaceElevation1, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, })); const cardContentStyle = prepareNativeStyle(_ => ({ diff --git a/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx b/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx index 9b9eb9e5669..cb81d0162c1 100644 --- a/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx +++ b/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx @@ -44,7 +44,7 @@ type PassphraseFormProps = { const formStyle = prepareNativeStyle(utils => ({ backgroundColor: utils.colors.backgroundSurfaceElevation1, - borderRadius: utils.borders.radii.large, + borderRadius: utils.borders.radii.r24, gap: utils.spacings.sp16, })); diff --git a/suite-native/module-authorize-device/src/screens/passphrase/PassphraseFormScreen.tsx b/suite-native/module-authorize-device/src/screens/passphrase/PassphraseFormScreen.tsx index 59545110e54..2170fa95768 100644 --- a/suite-native/module-authorize-device/src/screens/passphrase/PassphraseFormScreen.tsx +++ b/suite-native/module-authorize-device/src/screens/passphrase/PassphraseFormScreen.tsx @@ -15,7 +15,7 @@ const ANIMATION_DURATION = 300; const cardStyle = prepareNativeStyle(utils => ({ backgroundColor: utils.colors.backgroundAlertBlueSubtleOnElevation1, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, borderColor: utils.colors.backgroundAlertBlueSubtleOnElevationNegative, borderWidth: utils.borders.widths.small, padding: utils.spacings.sp16, diff --git a/suite-native/module-dev-utils/src/screens/DemoScreen.tsx b/suite-native/module-dev-utils/src/screens/DemoScreen.tsx index 3a76688d646..4acc7a91285 100644 --- a/suite-native/module-dev-utils/src/screens/DemoScreen.tsx +++ b/suite-native/module-dev-utils/src/screens/DemoScreen.tsx @@ -35,7 +35,7 @@ import { isDevelopOrDebugEnv } from '@suite-native/config'; import { TypographyStyle } from '@trezor/theme'; const inputStackStyle = prepareNativeStyle(utils => ({ - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, padding: utils.spacings.sp8, })); diff --git a/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx b/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx index 05d1dcbeddc..774e7d1cda5 100644 --- a/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx +++ b/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx @@ -23,7 +23,7 @@ const SHOW_TIMEOUT = 1500; const cardStyle = prepareNativeStyle(utils => ({ alignItems: 'center', textAlign: 'center', - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, backgroundColor: utils.colors.backgroundSurfaceElevation1, padding: utils.spacings.sp24, marginBottom: utils.spacings.sp24, diff --git a/suite-native/module-send/src/components/FeeOption.tsx b/suite-native/module-send/src/components/FeeOption.tsx index c48c0a3b231..8c065fd2fc9 100644 --- a/suite-native/module-send/src/components/FeeOption.tsx +++ b/suite-native/module-send/src/components/FeeOption.tsx @@ -37,7 +37,7 @@ const feeLabelsMap = { const wrapperStyle = prepareNativeStyle(utils => ({ overflow: 'hidden', - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, borderWidth: utils.borders.widths.large, backgroundColor: utils.colors.backgroundSurfaceElevation1, borderColor: utils.colors.backgroundSurfaceElevation0, diff --git a/suite-native/module-send/src/components/ReviewOutputCard.tsx b/suite-native/module-send/src/components/ReviewOutputCard.tsx index fdcbfe81671..9ae06866ef7 100644 --- a/suite-native/module-send/src/components/ReviewOutputCard.tsx +++ b/suite-native/module-send/src/components/ReviewOutputCard.tsx @@ -18,7 +18,7 @@ const cardStyle = prepareNativeStyle<{ isConfirmed: boolean }>((utils, { isConfi marginHorizontal: utils.spacings.sp8, paddingHorizontal: utils.spacings.sp16, paddingVertical: utils.spacings.sp12, - borderRadius: 12, + borderRadius: utils.borders.radii.r12, extend: { condition: isConfirmed, style: { diff --git a/suite-native/module-settings/src/components/ColorSchemePickerItem.tsx b/suite-native/module-settings/src/components/ColorSchemePickerItem.tsx index e92ac227c3d..e863e924b69 100644 --- a/suite-native/module-settings/src/components/ColorSchemePickerItem.tsx +++ b/suite-native/module-settings/src/components/ColorSchemePickerItem.tsx @@ -12,7 +12,7 @@ type ColorSchemePickerItemProps = { const pickerItemWrapperStyle = prepareNativeStyle<{ isColorSchemeActive: boolean }>( (utils, { isColorSchemeActive }) => ({ backgroundColor: utils.colors.backgroundSurfaceElevationNegative, - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, minHeight: 114, flex: 1, paddingTop: 33, diff --git a/suite-native/qr-code/src/components/QRCodeScanner.tsx b/suite-native/qr-code/src/components/QRCodeScanner.tsx index 105fd2f0490..46d80c70895 100644 --- a/suite-native/qr-code/src/components/QRCodeScanner.tsx +++ b/suite-native/qr-code/src/components/QRCodeScanner.tsx @@ -19,7 +19,7 @@ type QRCodeScannerProps = { const SCANNER_SIZE = Dimensions.get('screen').width - 2 * nativeSpacings.sp16; const cameraContainerStyle = prepareNativeStyle(utils => ({ - borderRadius: utils.borders.radii.medium, + borderRadius: utils.borders.radii.r16, overflow: 'hidden', })); diff --git a/suite-native/receive/src/components/DevicePaginationButton.tsx b/suite-native/receive/src/components/DevicePaginationButton.tsx index aeaf03e8100..e25d3c6dac3 100644 --- a/suite-native/receive/src/components/DevicePaginationButton.tsx +++ b/suite-native/receive/src/components/DevicePaginationButton.tsx @@ -29,18 +29,18 @@ type DeviceButtonStyleProps = { const safe3Styles = { backgroundColor: DEVICE_SCREEN_BACKGROUND_COLOR, borderColor: DEVICE_TEXT_COLOR, - borderRadius: nativeBorders.radii.large / 2, + borderRadius: nativeBorders.radii.r12, borderWidth: nativeBorders.widths.large, } as const; const modelToStyles = { [DeviceModelInternal.T2T1]: { backgroundColor: T2B1_BUTTON_COLOR, - borderRadius: nativeBorders.radii.small, + borderRadius: nativeBorders.radii.r8, }, [DeviceModelInternal.T3T1]: { backgroundColor: T2B1_BUTTON_COLOR, - borderRadius: nativeBorders.radii.small, + borderRadius: nativeBorders.radii.r8, }, [DeviceModelInternal.T2B1]: safe3Styles, [DeviceModelInternal.T3B1]: safe3Styles, diff --git a/suite-native/receive/src/components/UnverifiedAddressDevice.tsx b/suite-native/receive/src/components/UnverifiedAddressDevice.tsx index 75a7aa49af8..e4566757c8b 100644 --- a/suite-native/receive/src/components/UnverifiedAddressDevice.tsx +++ b/suite-native/receive/src/components/UnverifiedAddressDevice.tsx @@ -34,7 +34,7 @@ const deviceFrameStyle = prepareNativeStyle(utils => ({ width: DEVICE_SCREEN_WIDTH, padding: utils.spacings.sp4, borderWidth: utils.borders.widths.small, - borderRadius: utils.borders.radii.large / 2, + borderRadius: utils.borders.radii.r12, borderColor: utils.colors.borderElevation2, })); @@ -46,7 +46,7 @@ const deviceScreenStyle = prepareNativeStyle<{ isPaginationEnabled: boolean }>( paddingVertical: isPaginationEnabled ? utils.spacings.sp24 : 40, maxWidth: DEVICE_SCREEN_WIDTH, backgroundColor: DEVICE_SCREEN_BACKGROUND_COLOR, - borderRadius: utils.borders.radii.large / 2, + borderRadius: utils.borders.radii.r12, }), ); diff --git a/suite-native/transactions/src/components/TransactionsEmptyState.tsx b/suite-native/transactions/src/components/TransactionsEmptyState.tsx index f0b727a9f10..15939369522 100644 --- a/suite-native/transactions/src/components/TransactionsEmptyState.tsx +++ b/suite-native/transactions/src/components/TransactionsEmptyState.tsx @@ -19,7 +19,7 @@ const cardStyle = prepareNativeStyle(utils => ({ width: '100%', paddingHorizontal: utils.spacings.sp24, paddingVertical: utils.spacings.sp32, - borderRadius: utils.borders.radii.large, + borderRadius: utils.borders.radii.r24, })); const receiveButtonStyle = prepareNativeStyle(() => ({ diff --git a/suite-native/transactions/src/components/TransactionsList/TransactionListItemContainer.tsx b/suite-native/transactions/src/components/TransactionsList/TransactionListItemContainer.tsx index 5da81dc2fdb..b55c4fa94b3 100644 --- a/suite-native/transactions/src/components/TransactionsList/TransactionListItemContainer.tsx +++ b/suite-native/transactions/src/components/TransactionsList/TransactionListItemContainer.tsx @@ -73,8 +73,8 @@ export const transactionListItemContainerStyle = prepareNativeStyle ({ flex: 1, aspectRatio, - borderRadius: utils.borders.radii.large, + borderRadius: utils.borders.radii.r24, })); const activityIndicatorStyle = prepareNativeStyle(_ => ({ From 8eca23acb8313bde925f34c85058ffe7b6702e02 Mon Sep 17 00:00:00 2001 From: tomasklim Date: Thu, 3 Oct 2024 16:12:19 +0200 Subject: [PATCH 011/624] fix(suite): tokens table columns --- .../src/components/Table/Table.stories.tsx | 9 ++++++--- packages/components/src/components/Table/Table.tsx | 9 ++++++--- .../wallet/tokens/common/TokensTable/TokensTable.tsx | 12 +++++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/components/src/components/Table/Table.stories.tsx b/packages/components/src/components/Table/Table.stories.tsx index 143b7aa01cd..c55002ea096 100644 --- a/packages/components/src/components/Table/Table.stories.tsx +++ b/packages/components/src/components/Table/Table.stories.tsx @@ -42,13 +42,16 @@ export const Table: StoryObj = { argTypes: { ...getFramePropsStory(allowedTableFrameProps).argTypes, colWidths: { - options: ['none', 'fixed'], - mapping: { none: undefined, fixed: ['150px', '400px'] }, + options: ['none', 'secondCol300px'], + mapping: { + none: undefined, + secondCol300px: [{}, { minWidth: '300px', maxWidth: '300px' }], + }, control: { type: 'select', labels: { none: 'undefined', - fixed: "fixed = ['150px', '400px']", + secondCol300px: 'second column 300px', }, }, }, diff --git a/packages/components/src/components/Table/Table.tsx b/packages/components/src/components/Table/Table.tsx index 897908f35fb..acaba61153f 100644 --- a/packages/components/src/components/Table/Table.tsx +++ b/packages/components/src/components/Table/Table.tsx @@ -29,7 +29,10 @@ const ScrollContainer = styled.div` export type TableProps = AllowedFrameProps & { children: ReactNode; - colWidths?: string[]; + colWidths?: { + minWidth?: string; + maxWidth?: string; + }[]; }; export const Table = ({ children, margin, colWidths }: TableProps) => { @@ -42,8 +45,8 @@ export const Table = ({ children, margin, colWidths }: TableProps) => { {colWidths && ( - {colWidths.map((width, index) => ( - + {colWidths.map((widths, index) => ( + ))} )} diff --git a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx index 9af92bd2538..5893bf96cf3 100644 --- a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx +++ b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx @@ -42,10 +42,6 @@ export const TokensTable = ({ }: TokensTableProps) => { const [isZeroBalanceOpen, setIsZeroBalanceOpen] = useState(false); - // first two columns have fixed width, the rest have variable width - // in case of 2nd column, it's due to HiddenPlaceholder - it changes content width when hovered - const colWidths = ['250px', '250px']; - return ( {tokensWithBalance.length === 0 && tokensWithoutBalance.length === 0 && searchQuery ? ( @@ -57,7 +53,13 @@ export const TokensTable = ({ ) : ( - +
From b79b4e24da2b86a4d6e47df394264737fae18eb4 Mon Sep 17 00:00:00 2001 From: tomasklim Date: Thu, 3 Oct 2024 16:12:37 +0200 Subject: [PATCH 012/624] fix(suite): tokens balance without ellipsis --- .../src/views/wallet/tokens/common/TokensTable/TokenRow.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx index 317259bd4e2..90c570e5eb3 100644 --- a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx +++ b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx @@ -179,7 +179,6 @@ export const TokenRow = ({ From 6bb513a1c157961b2d4cd22892bee094e9893004 Mon Sep 17 00:00:00 2001 From: tomasklim Date: Thu, 3 Oct 2024 16:14:24 +0200 Subject: [PATCH 013/624] fix(suite): prevent overflowing in tokens and tx history --- .../src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx index 1af352ac6d8..7937741f67e 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx @@ -94,10 +94,7 @@ export const MainBar = styled.div` flex: 1; flex-direction: column; align-items: center; - - ${variables.SCREEN_QUERY.BELOW_LAPTOP} { - overflow-x: hidden; - } + overflow-x: hidden; `; interface SuiteLayoutProps { From 128b96325763e22cb1cf2f2f016ac2ed34bc0c33 Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Thu, 3 Oct 2024 09:36:11 +0200 Subject: [PATCH 014/624] feat(coinmarket): disable 'you buy' select in trezor btc only firmware --- .../AddAccountModal/AddAccountModal.tsx | 3 +-- packages/suite/src/types/coinmarket/coinmarketForm.ts | 1 + .../CoinmarketFormInputCryptoSelect.tsx | 2 ++ .../common/CoinmarketForm/CoinmarketFormInputs.tsx | 4 +++- .../CoinmarketLayout/CoinmarketLayoutNavigation.tsx | 6 ++---- .../CoinmarketLayoutNavigation.tsx | 5 ++--- .../wallet/transactions/TradeBox/TradeBoxMenu.tsx | 10 ++-------- 7 files changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AddAccountModal/AddAccountModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AddAccountModal/AddAccountModal.tsx index b538f4550e7..b25f163f0dc 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AddAccountModal/AddAccountModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AddAccountModal/AddAccountModal.tsx @@ -10,7 +10,6 @@ import { arrayPartition } from '@trezor/utils'; import { hasBitcoinOnlyFirmware } from '@trezor/device-utils'; import { networks, Network, NetworkSymbol, NetworkAccount } from '@suite-common/wallet-config'; import { CollapsibleBox, NewModal, Tooltip } from '@trezor/components'; -import { FirmwareType } from '@trezor/connect'; import { spacings, spacingsPx } from '@trezor/theme'; import { Translation, CoinList } from 'src/components/suite'; import { Account } from 'src/types/wallet'; @@ -78,7 +77,7 @@ export const AddAccountModal = ({ const preselectedNetwork = symbol && supportedNetworks.find(n => n.symbol === symbol); // or in case of only btc is enabled on bitcoin-only firmware const bitcoinOnlyDefaultNetworkSelection = - device.firmwareType === FirmwareType.BitcoinOnly && + hasBitcoinOnlyFirmware(device) && supportedMainnets.length === 1 && allTestnetNetworksDisabled ? networks.btc diff --git a/packages/suite/src/types/coinmarket/coinmarketForm.ts b/packages/suite/src/types/coinmarket/coinmarketForm.ts index 888a0609eee..ba2538c2eae 100644 --- a/packages/suite/src/types/coinmarket/coinmarketForm.ts +++ b/packages/suite/src/types/coinmarket/coinmarketForm.ts @@ -305,6 +305,7 @@ export interface CoinmarketFormInputCryptoSelectProps; supportedCryptoCurrencies: Set | undefined; methods: UseFormReturn; + isDisabled?: boolean; } export interface CoinmarketFormInputFiatCryptoProps { diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCryptoSelect.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCryptoSelect.tsx index ca495a4d3e0..85ee90d60c3 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCryptoSelect.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCryptoSelect.tsx @@ -37,6 +37,7 @@ export const CoinmarketFormInputCryptoSelect = < cryptoSelectName, supportedCryptoCurrencies, methods, + isDisabled, }: CoinmarketFormInputCryptoSelectProps) => { const context = useCoinmarketFormContext(); const { buildCryptoOptions, cryptoIdToPlatformName } = useCoinmarketInfo(); @@ -130,6 +131,7 @@ export const CoinmarketFormInputCryptoSelect = < data-testid="@coinmarket/form/select-crypto" isClearable={false} isMenuOpen={false} + isDisabled={isDisabled} /> )} /> diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInputs.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInputs.tsx index 66328f35370..ff50e482ab1 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInputs.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInputs.tsx @@ -33,6 +33,7 @@ import { CoinmarketBalance } from 'src/views/wallet/coinmarket/common/Coinmarket import { TokenAddress } from '@suite-common/wallet-types'; import { formatAmount } from '@suite-common/wallet-utils'; import { getNetworkDecimals } from 'src/utils/wallet/coinmarket/coinmarketUtils'; +import { hasBitcoinOnlyFirmware } from '@trezor/device-utils'; const CoinmarketFeesWrapper = styled.div` margin-bottom: ${spacingsPx.md}; @@ -224,7 +225,7 @@ export const CoinmarketFormInputs = () => { ); } - const { buyInfo } = context; + const { buyInfo, device } = context; const { currencySelect, cryptoSelect } = context.getValues(); const supportedCryptoCurrencies = buyInfo?.supportedCryptoCurrencies; @@ -236,6 +237,7 @@ export const CoinmarketFormInputs = () => { cryptoSelectName={FORM_CRYPTO_CURRENCY_SELECT} supportedCryptoCurrencies={supportedCryptoCurrencies} methods={{ ...context }} + isDisabled={hasBitcoinOnlyFirmware(device)} /> diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayoutNavigation.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayoutNavigation.tsx index adad31c85e7..e0ba52fb7da 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayoutNavigation.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayoutNavigation.tsx @@ -1,11 +1,11 @@ import styled, { css } from 'styled-components'; import { useDevice, useSelector } from 'src/hooks/suite'; -import { FirmwareType } from '@trezor/connect'; import { TranslationKey } from '@suite-common/intl-types'; import { Route } from '@suite-common/suite-types'; import { borders, spacingsPx, typography } from '@trezor/theme'; import { NavigationItem } from '../../../../../components/suite/layouts/SuiteLayout/Sidebar/NavigationItem'; import { variables, IconName } from '@trezor/components'; +import { hasBitcoinOnlyFirmware } from '@trezor/device-utils'; const List = styled.div` display: flex; @@ -37,8 +37,6 @@ export const CoinmarketLayoutNavigation = () => { const { device } = useDevice(); - const isBitcoinOnly = device?.firmwareType === FirmwareType.BitcoinOnly; - const Item = ({ route, title, @@ -63,7 +61,7 @@ export const CoinmarketLayoutNavigation = () => { - {!isBitcoinOnly ? ( + {!hasBitcoinOnlyFirmware(device) ? ( { const { device } = useDevice(); - const isBitcoinOnly = device?.firmwareType === FirmwareType.BitcoinOnly; const isBtcAccount = selectedAccount.account.symbol === 'btc'; const torStatus = useSelector(state => state.suite.torStatus); @@ -49,7 +48,7 @@ const CoinmarketLayoutNavigation = ({ selectedAccount }: CoinmarketLayoutNavigat icon="minus" /> - {!isBitcoinOnly ? ( + {!hasBitcoinOnlyFirmware(device) ? ( { return ( {menuItems - .filter( - item => - !( - item.type === 'exchange' && - device?.firmwareType === FirmwareType.BitcoinOnly - ), - ) + .filter(item => !(item.type === 'exchange' && hasBitcoinOnlyFirmware(device))) .map(item => ( Date: Thu, 12 Sep 2024 10:33:28 +0200 Subject: [PATCH 015/624] test(suite-native): increase e2e discovery timeout --- suite-native/app/e2e/tests/onboardAndConnect.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/suite-native/app/e2e/tests/onboardAndConnect.test.ts b/suite-native/app/e2e/tests/onboardAndConnect.test.ts index a121a370c2d..ed53ff49b40 100644 --- a/suite-native/app/e2e/tests/onboardAndConnect.test.ts +++ b/suite-native/app/e2e/tests/onboardAndConnect.test.ts @@ -56,11 +56,11 @@ describe('Go through onboarding and connect Trezor.', () => { await waitFor(element(by.id('skip-view-only-mode'))) .toBeVisible() - .withTimeout(60000); // communication between connected Trezor and app takes some time. + .withTimeout(90000); // Wait for discovery to finish await element(by.id('skip-view-only-mode')).tap(); - await detoxExpect(element(by.id('@home/portfolio/graph'))); // discovery finished and graph is visible + await detoxExpect(element(by.id('@home/portfolio/graph'))); } else { await detoxExpect(element(by.text('Hi there!'))).toBeVisible(); await detoxExpect(element(by.text('Get started'))).toBeVisible(); From 67dd2cf79c5668844f000e1aa31ae9517859e2a3 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Thu, 12 Sep 2024 10:50:34 +0200 Subject: [PATCH 016/624] test(suite-native): fix endless skeleton animation for e2e --- suite-native/app/package.json | 2 +- suite-native/atoms/package.json | 1 + suite-native/atoms/src/Skeleton/BoxSkeleton.tsx | 6 +++++- suite-native/{helpers => atoms}/src/constants.ts | 1 + suite-native/atoms/src/index.ts | 1 + suite-native/atoms/tsconfig.json | 1 + suite-native/helpers/package.json | 1 - suite-native/helpers/src/index.ts | 1 - suite-native/helpers/tsconfig.json | 5 +---- suite-native/module-accounts-import/package.json | 1 - .../module-accounts-import/src/components/QRWithLaser.tsx | 2 +- .../module-send/src/components/ReviewOutputStatusBadge.tsx | 2 +- .../components/TransactionsList/TransactionIconSpinner.tsx | 2 +- yarn.lock | 2 +- 14 files changed, 15 insertions(+), 13 deletions(-) rename suite-native/{helpers => atoms}/src/constants.ts (53%) diff --git a/suite-native/app/package.json b/suite-native/app/package.json index dd06171a07f..4417a15dbc7 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -130,4 +130,4 @@ "typescript": "^5.3.3" }, "private": true -} +} \ No newline at end of file diff --git a/suite-native/atoms/package.json b/suite-native/atoms/package.json index dd7ae02c237..9df528f06bb 100644 --- a/suite-native/atoms/package.json +++ b/suite-native/atoms/package.json @@ -14,6 +14,7 @@ "@mobily/ts-belt": "^3.13.1", "@shopify/react-native-skia": "1.3.11", "@suite-common/icons-deprecated": "workspace:*", + "@suite-native/config": "workspace:*", "@suite-native/intl": "workspace:^", "@suite-native/storage": "workspace:*", "@trezor/env-utils": "workspace:*", diff --git a/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx b/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx index 105cb0a194d..5d1a45a9ee8 100644 --- a/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx +++ b/suite-native/atoms/src/Skeleton/BoxSkeleton.tsx @@ -20,6 +20,7 @@ import { import { useNativeStyles } from '@trezor/styles'; import { Color, nativeBorders } from '@trezor/theme'; +import { ENDLESS_ANIMATION_VALUE } from '../constants'; import { SurfaceElevation } from '../types'; type BoxSkeletonProps = { @@ -56,7 +57,10 @@ export const BoxSkeleton = ({ const progress = useSharedValue(0); useEffect(() => { - progress.value = withRepeat(withTiming(width, { duration: ANIMATION_DURATION }), -1); + progress.value = withRepeat( + withTiming(width, { duration: ANIMATION_DURATION }), + ENDLESS_ANIMATION_VALUE, + ); }, [width, progress]); const position = useDerivedValue(() => [ diff --git a/suite-native/helpers/src/constants.ts b/suite-native/atoms/src/constants.ts similarity index 53% rename from suite-native/helpers/src/constants.ts rename to suite-native/atoms/src/constants.ts index f06eb45ae0d..309d1de0964 100644 --- a/suite-native/helpers/src/constants.ts +++ b/suite-native/atoms/src/constants.ts @@ -1,3 +1,4 @@ import { isDetoxTestBuild } from '@suite-native/config'; +// Ensures that the animation is not infinitely looped in the Detox tests to avoid synchronization problems. export const ENDLESS_ANIMATION_VALUE = isDetoxTestBuild() ? 1 : -1; diff --git a/suite-native/atoms/src/index.ts b/suite-native/atoms/src/index.ts index f4c462e8b60..db4f099d8c0 100644 --- a/suite-native/atoms/src/index.ts +++ b/suite-native/atoms/src/index.ts @@ -49,5 +49,6 @@ export * from './Skeleton/BoxSkeleton'; export * from './Skeleton/ListItemSkeleton'; export * from './BulletListItem'; export * from './SelectableItem'; +export * from './constants'; export { useDebugView } from './DebugView'; diff --git a/suite-native/atoms/tsconfig.json b/suite-native/atoms/tsconfig.json index 875613bfd77..43f67ddbe83 100644 --- a/suite-native/atoms/tsconfig.json +++ b/suite-native/atoms/tsconfig.json @@ -5,6 +5,7 @@ { "path": "../../suite-common/icons-deprecated" }, + { "path": "../config" }, { "path": "../intl" }, { "path": "../storage" }, { "path": "../../packages/env-utils" }, diff --git a/suite-native/helpers/package.json b/suite-native/helpers/package.json index a4ba9fb9d6e..1ae13da134c 100644 --- a/suite-native/helpers/package.json +++ b/suite-native/helpers/package.json @@ -13,7 +13,6 @@ }, "dependencies": { "@mobily/ts-belt": "^3.13.1", - "@suite-native/config": "workspace:*", "@suite-native/toasts": "workspace:*", "expo-clipboard": "6.0.3", "react": "18.2.0" diff --git a/suite-native/helpers/src/index.ts b/suite-native/helpers/src/index.ts index 7d4bf2bace8..9c64082013e 100644 --- a/suite-native/helpers/src/index.ts +++ b/suite-native/helpers/src/index.ts @@ -1,3 +1,2 @@ export * from './hooks/useCopyToClipboard'; export * from './splitAddressToChunks'; -export * from './constants'; diff --git a/suite-native/helpers/tsconfig.json b/suite-native/helpers/tsconfig.json index 79134d20504..e9ed4902f02 100644 --- a/suite-native/helpers/tsconfig.json +++ b/suite-native/helpers/tsconfig.json @@ -1,8 +1,5 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "libDev" }, - "references": [ - { "path": "../config" }, - { "path": "../toasts" } - ] + "references": [{ "path": "../toasts" }] } diff --git a/suite-native/module-accounts-import/package.json b/suite-native/module-accounts-import/package.json index 681fdec70af..dd7b9298bc2 100644 --- a/suite-native/module-accounts-import/package.json +++ b/suite-native/module-accounts-import/package.json @@ -36,7 +36,6 @@ "@suite-native/feature-flags": "workspace:*", "@suite-native/formatters": "workspace:*", "@suite-native/forms": "workspace:*", - "@suite-native/helpers": "workspace:*", "@suite-native/intl": "workspace:*", "@suite-native/navigation": "workspace:*", "@suite-native/qr-code": "workspace:*", diff --git a/suite-native/module-accounts-import/src/components/QRWithLaser.tsx b/suite-native/module-accounts-import/src/components/QRWithLaser.tsx index 280a38fe8a5..e0432b41348 100644 --- a/suite-native/module-accounts-import/src/components/QRWithLaser.tsx +++ b/suite-native/module-accounts-import/src/components/QRWithLaser.tsx @@ -25,7 +25,7 @@ import { import { icons } from '@suite-common/icons-deprecated'; import { useNativeStyles } from '@trezor/styles'; -import { ENDLESS_ANIMATION_VALUE } from '@suite-native/helpers'; +import { ENDLESS_ANIMATION_VALUE } from '@suite-native/atoms'; const ROUNDED_CORNER_SIZE = 15; diff --git a/suite-native/module-send/src/components/ReviewOutputStatusBadge.tsx b/suite-native/module-send/src/components/ReviewOutputStatusBadge.tsx index 2362c46fb9d..56849d3e677 100644 --- a/suite-native/module-send/src/components/ReviewOutputStatusBadge.tsx +++ b/suite-native/module-send/src/components/ReviewOutputStatusBadge.tsx @@ -9,7 +9,7 @@ import Animated, { import { Icon } from '@suite-common/icons-deprecated'; import { ReviewOutputState } from '@suite-common/wallet-types'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; -import { ENDLESS_ANIMATION_VALUE } from '@suite-native/helpers'; +import { ENDLESS_ANIMATION_VALUE } from '@suite-native/atoms'; const BADGE_SIZE = 14; const ANIMATION_DURATION = 550; diff --git a/suite-native/transactions/src/components/TransactionsList/TransactionIconSpinner.tsx b/suite-native/transactions/src/components/TransactionsList/TransactionIconSpinner.tsx index eda42ee654f..c356cb5391a 100644 --- a/suite-native/transactions/src/components/TransactionsList/TransactionIconSpinner.tsx +++ b/suite-native/transactions/src/components/TransactionsList/TransactionIconSpinner.tsx @@ -12,7 +12,7 @@ import { Canvas, Circle, vec, SweepGradient } from '@shopify/react-native-skia'; import { useNativeStyles, prepareNativeStyle } from '@trezor/styles'; import { Color } from '@trezor/theme'; -import { ENDLESS_ANIMATION_VALUE } from '@suite-native/helpers'; +import { ENDLESS_ANIMATION_VALUE } from '@suite-native/atoms'; type TransactionIconSpinnerProps = { size: number; diff --git a/yarn.lock b/yarn.lock index cec1ceb0070..3aab18507c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9685,6 +9685,7 @@ __metadata: "@mobily/ts-belt": "npm:^3.13.1" "@shopify/react-native-skia": "npm:1.3.11" "@suite-common/icons-deprecated": "workspace:*" + "@suite-native/config": "workspace:*" "@suite-native/intl": "workspace:^" "@suite-native/storage": "workspace:*" "@trezor/env-utils": "workspace:*" @@ -10001,7 +10002,6 @@ __metadata: resolution: "@suite-native/helpers@workspace:suite-native/helpers" dependencies: "@mobily/ts-belt": "npm:^3.13.1" - "@suite-native/config": "workspace:*" "@suite-native/toasts": "workspace:*" expo-clipboard: "npm:6.0.3" react: "npm:18.2.0" From 0b8aab4a0b73533aeec54594307595b874ebae85 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Thu, 12 Sep 2024 10:52:06 +0200 Subject: [PATCH 017/624] test(suite-native): mock of connect for e2e proof of concept --- suite-native/app/e2e/README.md | 4 + .../e2e/fixtures/connect/getAccountInfo.ts | 399 ++++++++++++++++++ suite-native/app/e2e/mocks/trezor-connect.js | 19 + suite-native/app/metro.config.js | 8 + suite-native/app/package.json | 2 +- .../module-accounts-import/tsconfig.json | 1 - yarn.lock | 1 - 7 files changed, 431 insertions(+), 3 deletions(-) create mode 100644 suite-native/app/e2e/fixtures/connect/getAccountInfo.ts create mode 100644 suite-native/app/e2e/mocks/trezor-connect.js diff --git a/suite-native/app/e2e/README.md b/suite-native/app/e2e/README.md index 1a73a5a68a6..2bee5dc942f 100644 --- a/suite-native/app/e2e/README.md +++ b/suite-native/app/e2e/README.md @@ -46,6 +46,10 @@ To test the app in the release mode, you need to build the app with the release Some tests use Trezor-user-env to simulate the Trezor device. To make these tests work locally, make sure that the trezor-user-env is up and running. To do so, follow the [trezor-user-env documentation](https://github.com/trezor/trezor-user-env/blob/master/README.md). +## Mocking + +To make the tests as much standalone and independent on third party services as possible, we are mocking some parts of the app. The mocks are located in the `/mocks` folder. + ## GitHub CI Android E2E test run on GitHub CI on every PR that is labeled with a `mobile-app` tag. The workflow is described in the [.github/workflows/native-test-e2e-android.yml](../../../.github/workflows/native-test-e2e-android.yml) file. diff --git a/suite-native/app/e2e/fixtures/connect/getAccountInfo.ts b/suite-native/app/e2e/fixtures/connect/getAccountInfo.ts new file mode 100644 index 00000000000..d9ebccf4e38 --- /dev/null +++ b/suite-native/app/e2e/fixtures/connect/getAccountInfo.ts @@ -0,0 +1,399 @@ +export const getAccountInfoMockedResponses = { + xrp: { + r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3: { + id: 26, + success: true, + payload: { + descriptor: 'r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3', + balance: '18746106', + availableBalance: '343434348746106', + empty: false, + history: { + total: -1, + unconfirmed: 0, + transactions: [ + { + type: 'recv', + txid: '16703220D42FB5ACFB2CD1553D473A6FD170836EB596795550182C85F9ED67B4', + amount: '999989', + fee: '12', + blockTime: 1702980372, + blockHeight: 84694628, + blockHash: + '16703220D42FB5ACFB2CD1553D473A6FD170836EB596795550182C85F9ED67B4', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '999989', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: '32A8B205B6B3D4C88B75C1585FFE32EA62E38F67CAE9BE7778B6F543ACEB3E78', + amount: '1000000', + fee: '12', + blockTime: 1702980302, + blockHeight: 84694610, + blockHash: + '32A8B205B6B3D4C88B75C1585FFE32EA62E38F67CAE9BE7778B6F543ACEB3E78', + targets: [ + { + addresses: ['rw62XQr4hLZjiuiq46CWiA6FretVuyZaoG'], + isAddress: true, + amount: '1000000', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'recv', + txid: '272F7A5993908EF025A01AB4FEC934EB9AE04911C968D5E5BB6B842ACF0DAACA', + amount: '5248', + fee: '12', + blockTime: 1690884741, + blockHeight: 81541871, + blockHash: + '272F7A5993908EF025A01AB4FEC934EB9AE04911C968D5E5BB6B842ACF0DAACA', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '5248', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: 'BDD71EE034AB7B900BAF0D18115E0C4DB6C753CB5DA70587148AE3A008513909', + amount: '5260', + fee: '12', + blockTime: 1690884611, + blockHeight: 81541837, + blockHash: + 'BDD71EE034AB7B900BAF0D18115E0C4DB6C753CB5DA70587148AE3A008513909', + targets: [ + { + addresses: ['rnp3Ysasm5DRFbg2nekLkGfCFL9UfkGKDf'], + isAddress: true, + amount: '5260', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: 'A8D9F385CB3DDCF39545A7DC610E18A510F6B19716CCE69BC8105C9C58C71192', + amount: '8100000', + fee: '12', + blockTime: 1688971822, + blockHeight: 81042493, + blockHash: + 'A8D9F385CB3DDCF39545A7DC610E18A510F6B19716CCE69BC8105C9C58C71192', + targets: [ + { + addresses: ['rKKbNYZRqwPgZYkFWvqNUFBuscEyiFyCE'], + isAddress: true, + amount: '8100000', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'recv', + txid: '5E930BC11C345A720675CEBD06EB142D434DC96F9E975751AF5CFC2434205051', + amount: '10037222', + fee: '300000', + blockTime: 1683270151, + blockHeight: 79563186, + blockHash: + '5E930BC11C345A720675CEBD06EB142D434DC96F9E975751AF5CFC2434205051', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '10037222', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: 'C5AA574FEFCCBFE1346591FF7105C7E0CE2842CB8B1B29F14FED1CBDF6692507', + amount: '7400000', + fee: '12', + blockTime: 1681478740, + blockHeight: 79098686, + blockHash: + 'C5AA574FEFCCBFE1346591FF7105C7E0CE2842CB8B1B29F14FED1CBDF6692507', + targets: [ + { + addresses: ['rKKbNYZRqwPgZYkFWvqNUFBuscEyiFyCE'], + isAddress: true, + amount: '7400000', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'recv', + txid: '9E50E46FF87C6C724C0EC3FFE9A1210173E68CD041AC2A0189076CB07D1D3B08', + amount: '6682802', + fee: '300000', + blockTime: 1680675650, + blockHeight: 78891212, + blockHash: + '9E50E46FF87C6C724C0EC3FFE9A1210173E68CD041AC2A0189076CB07D1D3B08', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '6682802', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: 'A0040ED514AEFC01C43C1D1DC38E09F6ADFD188DA3A3ECAEED844184AEB21909', + amount: '8400000', + fee: '12', + blockTime: 1678792680, + blockHeight: 78409260, + blockHash: + 'A0040ED514AEFC01C43C1D1DC38E09F6ADFD188DA3A3ECAEED844184AEB21909', + targets: [ + { + addresses: ['rKKbNYZRqwPgZYkFWvqNUFBuscEyiFyCE'], + isAddress: true, + amount: '8400000', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'recv', + txid: '2ED9CFC0457842DD8F23C3554A7B0A6FE0270DF08BE5C67ED901C8D6BF9144D7', + amount: '7285344', + fee: '300000', + blockTime: 1677679962, + blockHeight: 78125378, + blockHash: + '2ED9CFC0457842DD8F23C3554A7B0A6FE0270DF08BE5C67ED901C8D6BF9144D7', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '7285344', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: '3F4CC4990D2240BB5A59CB2EDA03B0937C4E65A82F5B8AEDA21F092E0D54219F', + amount: '8000000', + fee: '12', + blockTime: 1675264280, + blockHeight: 77510183, + blockHash: + '3F4CC4990D2240BB5A59CB2EDA03B0937C4E65A82F5B8AEDA21F092E0D54219F', + targets: [ + { + addresses: ['rKKbNYZRqwPgZYkFWvqNUFBuscEyiFyCE'], + isAddress: true, + amount: '8000000', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'sent', + txid: 'B829BEBB6A9E705FC130E546F2994BFEC945046B2EAEFA6470D335EC37A37481', + amount: '6190000', + fee: '12', + blockTime: 1672924140, + blockHeight: 76912409, + blockHash: + 'B829BEBB6A9E705FC130E546F2994BFEC945046B2EAEFA6470D335EC37A37481', + targets: [ + { + addresses: ['rKKbNYZRqwPgZYkFWvqNUFBuscEyiFyCE'], + isAddress: true, + amount: '6190000', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'recv', + txid: '6F56CC52F278859927D50525603F2F7AA9A3CD63BA359255F02E6DBE00A01E71', + amount: '5612406', + fee: '300000', + blockTime: 1672923931, + blockHeight: 76912357, + blockHash: + '6F56CC52F278859927D50525603F2F7AA9A3CD63BA359255F02E6DBE00A01E71', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '5612406', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + { + type: 'recv', + txid: '9301B0F27C6DAC6DFA2BDCF9DB959FB4534466F71F5F92510903CA9E6853E10B', + amount: '27218439', + fee: '12', + blockTime: 1656677000, + blockHeight: 72710665, + blockHash: + '9301B0F27C6DAC6DFA2BDCF9DB959FB4534466F71F5F92510903CA9E6853E10B', + targets: [ + { + addresses: ['r9TCDt3HmszcsnPrUrnvpynvLgaGQom9x3'], + isAddress: true, + amount: '27218439', + n: 0, + }, + ], + tokens: [], + internalTransfers: [], + details: { + vin: [], + vout: [], + size: 0, + totalInput: '0', + totalOutput: '0', + }, + }, + ], + }, + misc: { sequence: 72710672, reserve: '10000000' }, + }, + }, + }, +}; diff --git a/suite-native/app/e2e/mocks/trezor-connect.js b/suite-native/app/e2e/mocks/trezor-connect.js new file mode 100644 index 00000000000..9d08919139c --- /dev/null +++ b/suite-native/app/e2e/mocks/trezor-connect.js @@ -0,0 +1,19 @@ +import TrezorConnect from '../../../../packages/connect/src/index'; +import { getAccountInfoMockedResponses } from '../fixtures/connect/getAccountInfo'; + +const originalGetAccountInfo = TrezorConnect.getAccountInfo; + +TrezorConnect.getAccountInfo = params => { + const { coin, descriptor } = params; + + // If there is mocked response for this specific coin and descriptor skip the execution. + const mockedResponse = getAccountInfoMockedResponses[coin]?.[descriptor]; + if (mockedResponse) return mockedResponse; + + return originalGetAccountInfo(params); +}; + +// need to disable this rule to mimic export pattern of original index file. +// eslint-disable-next-line import/no-default-export +export default TrezorConnect; +export * from '../../../../packages/connect/src/exports'; diff --git a/suite-native/app/metro.config.js b/suite-native/app/metro.config.js index edaf97cad40..0737fcd4f89 100644 --- a/suite-native/app/metro.config.js +++ b/suite-native/app/metro.config.js @@ -54,6 +54,14 @@ const config = { }; } + if (process.env.IS_DETOX_BUILD && moduleName === '@trezor/connect') { + // Mock some Trezor Connect methods to avoid network flakiness during e2e tests. + return { + filePath: require.resolve('./e2e/mocks/trezor-connect.js'), + type: 'sourceFile', + }; + } + // Optionally, chain to the standard Metro resolver. return context.resolveRequest(context, moduleName, platform); }, diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 4417a15dbc7..dd06171a07f 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -130,4 +130,4 @@ "typescript": "^5.3.3" }, "private": true -} \ No newline at end of file +} diff --git a/suite-native/module-accounts-import/tsconfig.json b/suite-native/module-accounts-import/tsconfig.json index 9b132797eab..760423fdcb2 100644 --- a/suite-native/module-accounts-import/tsconfig.json +++ b/suite-native/module-accounts-import/tsconfig.json @@ -37,7 +37,6 @@ { "path": "../feature-flags" }, { "path": "../formatters" }, { "path": "../forms" }, - { "path": "../helpers" }, { "path": "../intl" }, { "path": "../navigation" }, { "path": "../qr-code" }, diff --git a/yarn.lock b/yarn.lock index 3aab18507c9..f79d81c2caf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10085,7 +10085,6 @@ __metadata: "@suite-native/feature-flags": "workspace:*" "@suite-native/formatters": "workspace:*" "@suite-native/forms": "workspace:*" - "@suite-native/helpers": "workspace:*" "@suite-native/intl": "workspace:*" "@suite-native/navigation": "workspace:*" "@suite-native/qr-code": "workspace:*" From 112b9d9e1046317976d85062af8a03ea683747a1 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Thu, 3 Oct 2024 14:08:27 +0200 Subject: [PATCH 018/624] test(suite-native): e2e: use jest retry mechanism over detox --- .github/workflows/test-suite-native-e2e-android.yml | 4 ++-- suite-native/app/e2e/jest.config.js | 1 + suite-native/app/e2e/jest.setup.ts | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 suite-native/app/e2e/jest.setup.ts diff --git a/.github/workflows/test-suite-native-e2e-android.yml b/.github/workflows/test-suite-native-e2e-android.yml index 3f55ace16ac..debaa53d2c5 100644 --- a/.github/workflows/test-suite-native-e2e-android.yml +++ b/.github/workflows/test-suite-native-e2e-android.yml @@ -158,11 +158,11 @@ jobs: force-avd-creation: true avd-name: ${{ steps.device.outputs.AVD_NAME }} emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -grpc 8554 - script: yarn test:e2e android.emu.release --headless --take-screenshots failing --record-videos failing --retries 2 + script: yarn test:e2e android.emu.release --headless --take-screenshots failing --record-videos failing - name: "Store failed test screenshot artifacts" if: ${{failure()}} uses: actions/upload-artifact@v4 with: - name: failed-android-tests-screenshots + name: failed-android-tests path: suite-native/app/artifacts diff --git a/suite-native/app/e2e/jest.config.js b/suite-native/app/e2e/jest.config.js index df22edf3a49..e06b28d5f44 100644 --- a/suite-native/app/e2e/jest.config.js +++ b/suite-native/app/e2e/jest.config.js @@ -11,4 +11,5 @@ module.exports = { testEnvironment: 'detox/runners/jest/testEnvironment', verbose: true, maxWorkers: 1, + setupFilesAfterEnv: ['/e2e/jest.setup.ts'], }; diff --git a/suite-native/app/e2e/jest.setup.ts b/suite-native/app/e2e/jest.setup.ts new file mode 100644 index 00000000000..35a9a0413d6 --- /dev/null +++ b/suite-native/app/e2e/jest.setup.ts @@ -0,0 +1 @@ +jest.retryTimes(2); From 51cd1ca9197c44ad5f2cbbbd11aace044074629a Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Thu, 3 Oct 2024 15:09:04 +0200 Subject: [PATCH 019/624] refactor(suite-native): e2e import tests --- suite-native/app/e2e/jest.setup.ts | 2 +- .../app/e2e/tests/accountsImport.test.ts | 118 ------------------ .../e2e/tests/bitcoinAccountsImport.test.ts | 50 ++++++++ .../e2e/tests/othersAccountsImport.test.ts | 65 ++++++++++ suite-native/app/e2e/utils.ts | 2 +- 5 files changed, 117 insertions(+), 120 deletions(-) delete mode 100644 suite-native/app/e2e/tests/accountsImport.test.ts create mode 100644 suite-native/app/e2e/tests/bitcoinAccountsImport.test.ts create mode 100644 suite-native/app/e2e/tests/othersAccountsImport.test.ts diff --git a/suite-native/app/e2e/jest.setup.ts b/suite-native/app/e2e/jest.setup.ts index 35a9a0413d6..527a3aaa8df 100644 --- a/suite-native/app/e2e/jest.setup.ts +++ b/suite-native/app/e2e/jest.setup.ts @@ -1 +1 @@ -jest.retryTimes(2); +jest.retryTimes(2, { logErrorsBeforeRetry: true }); diff --git a/suite-native/app/e2e/tests/accountsImport.test.ts b/suite-native/app/e2e/tests/accountsImport.test.ts deleted file mode 100644 index b3701a49837..00000000000 --- a/suite-native/app/e2e/tests/accountsImport.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { appIsFullyLoaded, openApp, restartApp } from '../utils'; -import { xpubs } from '../fixtures/xpubs'; -import { onAccountImport } from '../pageObjects/accountImportActions'; -import { onMyAssets } from '../pageObjects/myAssetsActions'; -import { onOnboarding } from '../pageObjects/onboardingActions'; -import { onHome } from '../pageObjects/homeActions'; -import { onTabBar } from '../pageObjects/tabBarActions'; - -describe('Import all possible accounts in watch only mode.', () => { - beforeAll(async () => { - await openApp({ newInstance: true }); - await onOnboarding.finishOnboarding(); - }); - - beforeEach(async () => { - await restartApp(); - await appIsFullyLoaded(); - }); - - it('Import BTC SegWit account', async () => { - await onHome.tapSyncCoinsButton(); - await onAccountImport.importAccount({ - networkSymbol: 'btc', - xpub: xpubs.btc.segwit, - accountName: 'BTC SegWit', - }); - }); - - it('Import BTC Legacy SegWit account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'btc', - xpub: xpubs.btc.legacySegwit, - accountName: 'BTC Legacy SegWit', - }); - }); - - it('Import BTC Taproot account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'btc', - xpub: xpubs.btc.taproot, - accountName: 'BTC Taproot', - }); - }); - - it('Import BTC Legacy account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'btc', - xpub: xpubs.btc.legacy, - accountName: 'BTC Legacy', - }); - }); - - it('Import LTC account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'ltc', - xpub: xpubs.ltc, - accountName: 'Litecoin SegWit', - }); - }); - - it('Import Cardano account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'ada', - xpub: xpubs.ada, - accountName: 'Cardano #1', - }); - }); - - it('Import DOGE account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'doge', - xpub: xpubs.doge, - accountName: 'Dogecoin #1', - }); - }); - - it('Import ZCash account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'zec', - xpub: xpubs.zec, - accountName: 'Zcash #1', - }); - }); - - it('Import XRP account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'xrp', - xpub: xpubs.xrp, - accountName: 'Ripple #1', - }); - }); - - it('Import ETH account', async () => { - await onTabBar.navigateToMyAssets(); - await onMyAssets.addAccount(); - await onAccountImport.importAccount({ - networkSymbol: 'eth', - xpub: xpubs.eth, - accountName: 'Ethereum #1', - }); - }); -}); diff --git a/suite-native/app/e2e/tests/bitcoinAccountsImport.test.ts b/suite-native/app/e2e/tests/bitcoinAccountsImport.test.ts new file mode 100644 index 00000000000..95b813af3b0 --- /dev/null +++ b/suite-native/app/e2e/tests/bitcoinAccountsImport.test.ts @@ -0,0 +1,50 @@ +import { openApp } from '../utils'; +import { xpubs } from '../fixtures/xpubs'; +import { onAccountImport } from '../pageObjects/accountImportActions'; +import { onMyAssets } from '../pageObjects/myAssetsActions'; +import { onOnboarding } from '../pageObjects/onboardingActions'; +import { onTabBar } from '../pageObjects/tabBarActions'; + +describe('Import Bitcoin network accounts.', () => { + beforeAll(async () => { + await openApp({ newInstance: true }); + await onOnboarding.finishOnboarding(); + await onTabBar.navigateToMyAssets(); + }); + + beforeEach(async () => { + await onMyAssets.addAccount(); + }); + + it('Import BTC SegWit account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'btc', + xpub: xpubs.btc.segwit, + accountName: 'BTC SegWit', + }); + }); + + it('Import BTC Legacy SegWit account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'btc', + xpub: xpubs.btc.legacySegwit, + accountName: 'BTC Legacy SegWit', + }); + }); + + it('Import BTC Taproot account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'btc', + xpub: xpubs.btc.taproot, + accountName: 'BTC Taproot', + }); + }); + + it('Import BTC Legacy account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'btc', + xpub: xpubs.btc.legacy, + accountName: 'BTC Legacy', + }); + }); +}); diff --git a/suite-native/app/e2e/tests/othersAccountsImport.test.ts b/suite-native/app/e2e/tests/othersAccountsImport.test.ts new file mode 100644 index 00000000000..407f48e562e --- /dev/null +++ b/suite-native/app/e2e/tests/othersAccountsImport.test.ts @@ -0,0 +1,65 @@ +import { openApp } from '../utils'; +import { xpubs } from '../fixtures/xpubs'; +import { onAccountImport } from '../pageObjects/accountImportActions'; +import { onMyAssets } from '../pageObjects/myAssetsActions'; +import { onOnboarding } from '../pageObjects/onboardingActions'; +import { onTabBar } from '../pageObjects/tabBarActions'; + +describe('Import accounts of other networks.', () => { + beforeAll(async () => { + await openApp({ newInstance: true }); + await onOnboarding.finishOnboarding(); + await onTabBar.navigateToMyAssets(); + }); + + beforeEach(async () => { + await onMyAssets.addAccount(); + }); + + it('Import LTC account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'ltc', + xpub: xpubs.ltc, + accountName: 'Litecoin SegWit', + }); + }); + + it('Import ZCash account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'zec', + xpub: xpubs.zec, + accountName: 'Zcash #1', + }); + }); + + it('Import DOGE account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'doge', + xpub: xpubs.doge, + accountName: 'Dogecoin #1', + }); + }); + + it('Import Cardano account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'ada', + xpub: xpubs.ada, + accountName: 'Cardano #1', + }); + }); + it('Import XRP account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'xrp', + xpub: xpubs.xrp, + accountName: 'Ripple #1', + }); + }); + + it('Import ETH account', async () => { + await onAccountImport.importAccount({ + networkSymbol: 'eth', + xpub: xpubs.eth, + accountName: 'Ethereum #1', + }); + }); +}); diff --git a/suite-native/app/e2e/utils.ts b/suite-native/app/e2e/utils.ts index fc7c5809975..347b9367881 100644 --- a/suite-native/app/e2e/utils.ts +++ b/suite-native/app/e2e/utils.ts @@ -86,5 +86,5 @@ export const scrollUntilVisible = async (matcher: Detox.NativeMatcher) => { export const appIsFullyLoaded = async () => { await waitFor(element(by.id('@screen/mainScrollView'))) .toBeVisible() - .withTimeout(20000); + .withTimeout(35000); }; From 49d390a153095aa0110b7ab654c05de5da362e0c Mon Sep 17 00:00:00 2001 From: yanas Date: Fri, 4 Oct 2024 10:35:45 +0200 Subject: [PATCH 020/624] fix(suite-native): use 20px border radius instead of 24px --- packages/theme/src/borders.ts | 3 +-- suite-native/atoms/src/Sheet/BottomSheet.tsx | 4 ++-- suite-native/graph/src/components/GraphError.tsx | 2 +- .../src/components/AccountImportOverviewCard.tsx | 2 +- .../src/components/passphrase/PassphraseForm.tsx | 8 +------- .../src/components/TransactionsEmptyState.tsx | 2 +- suite-native/video-assets/src/components/Video.tsx | 2 +- 7 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/theme/src/borders.ts b/packages/theme/src/borders.ts index ba141ab6b3d..ec86d988e23 100644 --- a/packages/theme/src/borders.ts +++ b/packages/theme/src/borders.ts @@ -17,7 +17,7 @@ export const borders = { export type Borders = typeof borders; -type NativeRadiusValue = 4 | 8 | 12 | 16 | 20 | 24; +type NativeRadiusValue = 4 | 8 | 12 | 16 | 20; export const nativeBorders = { widths: { @@ -31,7 +31,6 @@ export const nativeBorders = { r12: 12, r16: 16, r20: 20, - r24: 24, round: 100, // Equivalent to 50% on the web } satisfies { [V in NativeRadiusValue as `r${V}`]: V } & { round: 100 }, } as const; diff --git a/suite-native/atoms/src/Sheet/BottomSheet.tsx b/suite-native/atoms/src/Sheet/BottomSheet.tsx index 94e42f1a5a9..42dab87dc69 100644 --- a/suite-native/atoms/src/Sheet/BottomSheet.tsx +++ b/suite-native/atoms/src/Sheet/BottomSheet.tsx @@ -29,8 +29,8 @@ const DEFAULT_INSET_BOTTOM = 50; const sheetWrapperStyle = prepareNativeStyle((utils, { insetBottom }) => ({ backgroundColor: utils.colors.backgroundSurfaceElevation0, - borderTopLeftRadius: utils.borders.radii.r24, - borderTopRightRadius: utils.borders.radii.r24, + borderTopLeftRadius: utils.borders.radii.r20, + borderTopRightRadius: utils.borders.radii.r20, paddingBottom: Math.max(insetBottom, utils.spacings.sp16), maxHeight: '90%', })); diff --git a/suite-native/graph/src/components/GraphError.tsx b/suite-native/graph/src/components/GraphError.tsx index 570c4a1863a..773e6aef25a 100644 --- a/suite-native/graph/src/components/GraphError.tsx +++ b/suite-native/graph/src/components/GraphError.tsx @@ -14,7 +14,7 @@ type GraphErrorProps = { const errorIconStyle = prepareNativeStyle(({ borders, colors }) => ({ width: 48, height: 48, - borderRadius: borders.radii.r24, + borderRadius: borders.radii.round, backgroundColor: colors.backgroundAlertYellowSubtleOnElevation1, borderColor: colors.backgroundAlertYellowSubtleOnElevation0, borderWidth: 3, diff --git a/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx b/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx index 13d193076db..de4e3ce51ee 100644 --- a/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx +++ b/suite-native/module-accounts-import/src/components/AccountImportOverviewCard.tsx @@ -15,7 +15,7 @@ import { NetworkSymbol } from '@suite-common/wallet-config'; const assetCardStyle = prepareNativeStyle(utils => ({ padding: utils.spacings.sp24, - borderRadius: utils.borders.radii.r24, + borderRadius: utils.borders.radii.r20, width: '100%', })); diff --git a/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx b/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx index cb81d0162c1..4cf174d2b90 100644 --- a/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx +++ b/suite-native/module-authorize-device/src/components/passphrase/PassphraseForm.tsx @@ -42,12 +42,6 @@ type PassphraseFormProps = { noPassphraseEnabled?: boolean; }; -const formStyle = prepareNativeStyle(utils => ({ - backgroundColor: utils.colors.backgroundSurfaceElevation1, - borderRadius: utils.borders.radii.r24, - gap: utils.spacings.sp16, -})); - const cardStyle = prepareNativeStyle(_ => ({ padding: FORM_CARD_PADDING, })); @@ -126,7 +120,7 @@ export const PassphraseForm = ({
- + ({ width: '100%', paddingHorizontal: utils.spacings.sp24, paddingVertical: utils.spacings.sp32, - borderRadius: utils.borders.radii.r24, + borderRadius: utils.borders.radii.r20, })); const receiveButtonStyle = prepareNativeStyle(() => ({ diff --git a/suite-native/video-assets/src/components/Video.tsx b/suite-native/video-assets/src/components/Video.tsx index d954fb8c68a..75173120c00 100644 --- a/suite-native/video-assets/src/components/Video.tsx +++ b/suite-native/video-assets/src/components/Video.tsx @@ -25,7 +25,7 @@ const videoContainer = prepareNativeStyle((_, { aspectRatio }: VideoStyleProps) const videoStyle = prepareNativeStyle((utils, { aspectRatio }: VideoStyleProps) => ({ flex: 1, aspectRatio, - borderRadius: utils.borders.radii.r24, + borderRadius: utils.borders.radii.r20, })); const activityIndicatorStyle = prepareNativeStyle(_ => ({ From 9092fbfd22d638020ff7c90ae058123ab388ead9 Mon Sep 17 00:00:00 2001 From: Albina Nikiforova Date: Wed, 2 Oct 2024 15:16:52 +0100 Subject: [PATCH 021/624] feat(suite): highlight row on hover --- .../src/components/Table/Table.stories.tsx | 27 +++++++- .../components/src/components/Table/Table.tsx | 52 ++++++++++------ .../src/components/Table/TableCell.tsx | 5 +- .../src/components/Table/TableRow.tsx | 61 +++++++++++++++++-- .../tokens/common/TokensTable/TokensTable.tsx | 11 ++-- 5 files changed, 124 insertions(+), 32 deletions(-) diff --git a/packages/components/src/components/Table/Table.stories.tsx b/packages/components/src/components/Table/Table.stories.tsx index c55002ea096..6572cb605ba 100644 --- a/packages/components/src/components/Table/Table.stories.tsx +++ b/packages/components/src/components/Table/Table.stories.tsx @@ -14,8 +14,13 @@ const meta: Meta = { } as Meta; export default meta; +interface TableProps { + colWidths?: { minWidth?: string | undefined; maxWidth?: string | undefined }[]; + highlightRowOnHover?: boolean; +} + export const Table: StoryObj = { - render: props => ( + render: (props: TableProps) => ( @@ -26,7 +31,10 @@ export const Table: StoryObj = { {EXAMPLE_TOKENS.map((token, i) => ( - + {} : undefined} + > {token.name} {token.balance} {token.price} @@ -38,6 +46,7 @@ export const Table: StoryObj = { args: { ...getFramePropsStory(allowedTableFrameProps).args, colWidths: 'none', + highlightRowOnHover: 'true', }, argTypes: { ...getFramePropsStory(allowedTableFrameProps).argTypes, @@ -55,5 +64,19 @@ export const Table: StoryObj = { }, }, }, + highlightRowOnHover: { + options: ['true', 'false'], + mapping: { + true: true, + false: false, + }, + control: { + type: 'select', + labels: { + true: 'true', + false: 'false', + }, + }, + }, }, }; diff --git a/packages/components/src/components/Table/Table.tsx b/packages/components/src/components/Table/Table.tsx index acaba61153f..d1f0445077e 100644 --- a/packages/components/src/components/Table/Table.tsx +++ b/packages/components/src/components/Table/Table.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from 'react'; +import { createContext, ReactNode, useContext } from 'react'; import styled from 'styled-components'; import { mapElevationToBackgroundToken } from '@trezor/theme'; @@ -14,6 +14,14 @@ import { useElevation } from '../ElevationContext/ElevationContext'; export const allowedTableFrameProps = ['margin'] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; +interface TableContextProps { + highlightRowOnHover: boolean; +} + +const TableContext = createContext({ highlightRowOnHover: false }); + +export const useTable = () => useContext(TableContext); + const Container = styled.table>` width: 100%; border-collapse: collapse; @@ -33,30 +41,36 @@ export type TableProps = AllowedFrameProps & { minWidth?: string; maxWidth?: string; }[]; + highlightRowOnHover?: boolean; }; -export const Table = ({ children, margin, colWidths }: TableProps) => { +export const Table = ({ children, margin, colWidths, highlightRowOnHover = false }: TableProps) => { const { scrollElementRef, onScroll, ShadowContainer, ShadowRight } = useScrollShadow(); const { parentElevation } = useElevation(); return ( - - - - {colWidths && ( -
- {colWidths.map((widths, index) => ( - - ))} - - )} - {children} - - - - + + + + + {colWidths && ( + + {colWidths.map((widths, index) => ( + + ))} + + )} + {children} + + + + + ); }; diff --git a/packages/components/src/components/Table/TableCell.tsx b/packages/components/src/components/Table/TableCell.tsx index 1022b7a5c97..eef3b6b01a2 100644 --- a/packages/components/src/components/Table/TableCell.tsx +++ b/packages/components/src/components/Table/TableCell.tsx @@ -6,6 +6,7 @@ import { typography, spacingsPx, Elevation, mapElevationToBackground } from '@tr import { useTableHeader } from './TableHeader'; import { UIHorizontalAlignment } from '../../config/types'; import { useElevation } from '../ElevationContext/ElevationContext'; +import { useTable } from './Table'; export type TableCellProps = { children?: ReactNode; @@ -23,7 +24,7 @@ const mapAlignmentToJustifyContent = (align: UIHorizontalAlignment) => { return map[align]; }; -const Cell = styled.td<{ $isHeader: boolean; $elevation: Elevation }>` +const Cell = styled.td<{ $isHeader: boolean; $elevation: Elevation; $highlight: boolean }>` ${({ $isHeader }) => ($isHeader ? typography.hint : typography.body)} color: ${({ theme, $isHeader }) => ($isHeader ? theme.textSubdued : theme.textDefault)}; text-align: left; @@ -47,6 +48,7 @@ const Content = styled.div<{ $align: UIHorizontalAlignment }>` export const TableCell = ({ children, colSpan = 1, align = 'left' }: TableCellProps) => { const isHeader = useTableHeader(); const { parentElevation } = useElevation(); + const { highlightRowOnHover } = useTable(); return ( {children} diff --git a/packages/components/src/components/Table/TableRow.tsx b/packages/components/src/components/Table/TableRow.tsx index 8e547eb80a9..83780d134fa 100644 --- a/packages/components/src/components/Table/TableRow.tsx +++ b/packages/components/src/components/Table/TableRow.tsx @@ -1,17 +1,53 @@ import { ReactNode } from 'react'; import styled, { css } from 'styled-components'; -import { Elevation, mapElevationToBorder } from '@trezor/theme'; +import { + Elevation, + mapElevationToBackground, + mapElevationToBorder, + nextElevation, +} from '@trezor/theme'; import { useElevation } from '../ElevationContext/ElevationContext'; +import { useTable } from './Table'; +import { useTableHeader } from './TableHeader'; -export const Row = styled.tr<{ $elevation: Elevation; $isCollapsed: boolean }>` +export const Row = styled.tr<{ + $elevation: Elevation; + $isCollapsed: boolean; + $highlight: boolean; + $isHeader: boolean; +}>` border-top: 1px solid ${mapElevationToBorder}; &:first-child { border-top: 0; } + ${({ $highlight, theme, $elevation, $isHeader }) => + $highlight && + !$isHeader && + css` + &:hover { + background-color: ${mapElevationToBackground({ + theme, + $elevation: nextElevation[$elevation], + })}; + + & > td:first-child { + background: linear-gradient( + to right, + ${mapElevationToBackground({ + theme, + $elevation: nextElevation[$elevation], + })} + 90%, + rgba(0 0 0 / 0%) + ); + } + } + `} + ${({ $isCollapsed }) => $isCollapsed && css` @@ -19,18 +55,35 @@ export const Row = styled.tr<{ $elevation: Elevation; $isCollapsed: boolean }>` border-top: 0; opacity: 0; `} + + ${({ onClick }) => + onClick && + css` + &:hover { + cursor: pointer; + } + `} `; export interface TableRowProps { children: ReactNode; isCollapsed?: boolean; + onClick?: () => void; } -export const TableRow = ({ children, isCollapsed = false }: TableRowProps) => { +export const TableRow = ({ children, isCollapsed = false, onClick }: TableRowProps) => { const { elevation } = useElevation(); + const isHeader = useTableHeader(); + const { highlightRowOnHover } = useTable(); return ( - + {children} ); diff --git a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx index 5893bf96cf3..be65049b1aa 100644 --- a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx +++ b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokensTable.tsx @@ -16,7 +16,7 @@ const IconWrapper = styled.div<{ $isActive: boolean }>` `; const ZeroBalanceToggle = styled.div` - cursor: pointer; + user-select: none; `; interface TokensTableProps { @@ -59,6 +59,7 @@ export const TokensTable = ({ { minWidth: '200px', maxWidth: '250px' }, { minWidth: '140px', maxWidth: '250px' }, // due to HiddenPlaceholder - it changes content width when hovered ]} + highlightRowOnHover={true} > @@ -94,11 +95,9 @@ export const TokensTable = ({ ))} {tokensWithoutBalance.length !== 0 && ( <> - - - setIsZeroBalanceOpen(!isZeroBalanceOpen)} - > + setIsZeroBalanceOpen(!isZeroBalanceOpen)}> + + Date: Wed, 2 Oct 2024 15:17:16 +0100 Subject: [PATCH 022/624] feat(suite): rewrite asset table with new componen --- .../AssetsView/AssetCard/AssetCardInfo.tsx | 2 +- .../dashboard/AssetsView/AssetCoinLogo.tsx | 14 +- .../AssetsView/AssetTable/AssetRow.tsx | 256 ++++-------------- .../AssetTable/AssetRowSkeleton.tsx | 39 +++ .../AssetsView/AssetTable/AssetTable.tsx | 58 ++-- .../AssetTable/AssetTableHeader.tsx | 43 --- .../AssetTable/AssetTableRowGrid.tsx | 39 --- .../views/dashboard/AssetsView/AssetsView.tsx | 26 +- 8 files changed, 157 insertions(+), 320 deletions(-) create mode 100644 packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRowSkeleton.tsx delete mode 100644 packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableHeader.tsx delete mode 100644 packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableRowGrid.tsx diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetCard/AssetCardInfo.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetCard/AssetCardInfo.tsx index 115642dae6e..383a9953918 100644 --- a/packages/suite/src/views/dashboard/AssetsView/AssetCard/AssetCardInfo.tsx +++ b/packages/suite/src/views/dashboard/AssetsView/AssetCard/AssetCardInfo.tsx @@ -28,7 +28,7 @@ type AssetInfoSkeletonProps = { export const AssetCardInfoSkeleton = ({ animate }: AssetInfoSkeletonProps) => ( - + ); diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetCoinLogo.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetCoinLogo.tsx index a4a32706f6a..1da437c0c3a 100644 --- a/packages/suite/src/views/dashboard/AssetsView/AssetCoinLogo.tsx +++ b/packages/suite/src/views/dashboard/AssetsView/AssetCoinLogo.tsx @@ -5,16 +5,18 @@ import { } from '@suite-common/assets'; import { SkeletonCircle, Tooltip } from '@trezor/components'; import { NetworkSymbol } from '@suite-common/wallet-config'; -import { spacingsPx } from '@trezor/theme'; import styled from 'styled-components'; import { localizePercentage } from '@suite-common/wallet-utils'; import { selectLanguage } from 'src/reducers/suite/suiteReducer'; import { useSelector } from 'src/hooks/suite'; import { AssetShareIndicator } from '@trezor/product-components'; +import { spacingsPx } from '@trezor/theme'; const LogoWrapper = styled.div` - padding-right: ${spacingsPx.sm}; + display: flex; + padding-right: ${spacingsPx.md}; align-items: center; + justify-content: center; `; type AssetCoinLogoProps = { @@ -53,8 +55,12 @@ export const AssetCoinLogo = ({ symbol, assetsFiatBalances, index }: AssetCoinLo ); }; -export const AssetCoinLogoSkeleton = () => ( +type AssetCoinLogoSkeletonProps = { + animate?: boolean; +}; + +export const AssetCoinLogoSkeleton = ({ animate }: AssetCoinLogoSkeletonProps) => ( - + ); diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRow.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRow.tsx index 9cf0617f2d0..e53b7f5d89a 100644 --- a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRow.tsx +++ b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRow.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; -import styled, { useTheme } from 'styled-components'; +import { useTheme } from 'styled-components'; import { Network } from '@suite-common/wallet-config'; -import { Icon, variables, SkeletonRectangle } from '@trezor/components'; +import { Icon, Table, Row, IconButton, Column } from '@trezor/components'; import { AmountUnitSwitchWrapper, CoinBalance, @@ -12,119 +12,13 @@ import { } from 'src/components/suite'; import { isTestnet } from '@suite-common/wallet-utils'; import { goto } from 'src/actions/suite/routerActions'; -import { useAccountSearch, useDispatch, useLoadingSkeleton } from 'src/hooks/suite'; -import { spacingsPx, typography } from '@trezor/theme'; +import { useAccountSearch, useDispatch } from 'src/hooks/suite'; +import { spacings } from '@trezor/theme'; import { AssetFiatBalance } from '@suite-common/assets'; -import { AssetTableRowGrid } from './AssetTableRowGrid'; -import { ArrowIcon } from '../ArrowIcon'; -import { AssetCoinLogo, AssetCoinLogoSkeleton } from '../AssetCoinLogo'; +import { AssetCoinLogo } from '../AssetCoinLogo'; import { AssetCoinName } from '../AssetCoinName'; import { CoinmarketBuyButton } from '../CoinmarketBuyButton'; - -const Coin = styled.div` - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -`; - -const StyledCol = styled.div<{ $isLastRow?: boolean }>` - display: flex; - align-items: center; - padding: 16px 0; - border-bottom: ${({ $isLastRow, theme }) => - $isLastRow ? 'none' : `1px solid ${theme.borderElevation2}`}; -`; - -const CoinLogoWrapper = styled(StyledCol)` - padding-left: 18px; - text-overflow: ellipsis; - border: none; - - ${variables.SCREEN_QUERY.MOBILE} { - grid-column: 1 / 2; - padding-left: 20px; - border-bottom: none; - } - - &:hover { - ${Coin} { - text-decoration: underline; - } - } -`; - -const CoinNameWrapper = styled(StyledCol)` - ${typography.highlight} - overflow: hidden; - text-overflow: ellipsis; - - ${variables.SCREEN_QUERY.MOBILE} { - grid-column: 1 / 4; - padding-left: 20px; - border-bottom: none; - } -`; - -const CoinBalanceContainer = styled.div` - ${typography.hint} - color: ${({ theme }) => theme.textSubdued}; -`; - -const FailedCol = styled(StyledCol)` - color: ${({ theme }) => theme.textAlertRed}; - ${typography.hint} - - ${variables.SCREEN_QUERY.MOBILE} { - grid-column: 1 / 3; - margin-left: 20px; - } -`; - -const CryptoBalanceWrapper = styled(StyledCol)` - flex: 1; - white-space: nowrap; - flex-direction: column; - align-items: flex-start; - justify-content: center; - gap: ${spacingsPx.xxxs}; - - ${variables.SCREEN_QUERY.MOBILE} { - grid-column: 1 / 3; - margin-left: 20px; - } -`; - -const FiatBalanceWrapper = styled.div``; - -const ExchangeRateWrapper = styled(StyledCol)` - font-variant-numeric: tabular-nums; - justify-content: right; - padding-right: ${spacingsPx.xxxl}; -`; - -const ExchangeRateWrapper7Days = styled(StyledCol)` - font-variant-numeric: tabular-nums; - padding-right: 0; -`; - -const BuyButtonWrapper = styled(StyledCol)` - justify-content: right; -`; - -const StyledArrowIcon = styled(ArrowIcon)` - margin: 0 ${spacingsPx.md}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const SkeletonRectangleLast = styled(SkeletonRectangle)` - margin-right: ${spacingsPx.md}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledIcon = styled(Icon)` - padding-left: 4px; - padding-bottom: 2px; -`; +import { Text } from '@trezor/components'; interface AssetTableProps { network: Network; @@ -135,7 +29,7 @@ interface AssetTableProps { } export const AssetRow = memo( - ({ network, failed, cryptoValue, isLastRow, assetsFiatBalances }: AssetTableProps) => { + ({ network, failed, cryptoValue, assetsFiatBalances }: AssetTableProps) => { const { symbol } = network; const dispatch = useDispatch(); const theme = useTheme(); @@ -157,92 +51,62 @@ export const AssetRow = memo( }; return ( - - - - - - - - - - {!failed ? ( - - + + + + + + + + + + {!failed ? ( + - - - - - - - - ) : ( - - - - - - )} - - {!isTestnet(symbol) && } - - - {!isTestnet(symbol) && } - - - {!isTestnet(symbol) && ( - + + + + + + + ) : ( + + + + + + )} - - - + + {!isTestnet(symbol) && } + + {!isTestnet(symbol) && } + + + {!isTestnet(symbol) && ( + + )} + + + + ); }, ); - -export const AssetRowSkeleton = (props: { animate?: boolean }) => { - const { shouldAnimate } = useLoadingSkeleton(); - - const animate = props.animate ?? shouldAnimate; - - return ( - - - - - - - - - - - - - - - - - - - - - - - - ); -}; diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRowSkeleton.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRowSkeleton.tsx new file mode 100644 index 00000000000..144931ace3d --- /dev/null +++ b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetRowSkeleton.tsx @@ -0,0 +1,39 @@ +import { Row, Table, SkeletonRectangle } from '@trezor/components'; +import { AssetCoinLogoSkeleton } from '../AssetCoinLogo'; +import { useLoadingSkeleton } from 'src/hooks/suite'; + +type AssetRowSkeletonProps = { + isAnimating?: boolean; +}; + +export const AssetRowSkeleton = ({ isAnimating }: AssetRowSkeletonProps) => { + const { shouldAnimate } = useLoadingSkeleton(); + + const animate = isAnimating ?? shouldAnimate; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTable.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTable.tsx index cc7d228fc12..82ba9734c3e 100644 --- a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTable.tsx +++ b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTable.tsx @@ -1,17 +1,12 @@ import { AssetFiatBalance } from '@suite-common/assets'; -import { AssetRow, AssetRowSkeleton } from './AssetRow'; -import { AssetTableHeader } from './AssetTableHeader'; +import { AssetRow } from './AssetRow'; +import { AssetRowSkeleton } from './AssetRowSkeleton'; import { Network } from '@suite-common/wallet-config'; import { BigNumber } from '@trezor/utils/src/bigNumber'; -import styled from 'styled-components'; -import { spacingsPx } from '@trezor/theme'; -const Table = styled.div` - padding-left: ${spacingsPx.xxs}; - padding-right: ${spacingsPx.xxs}; - padding-bottom: ${spacingsPx.xxs}; - width: 100%; -`; +import { Table } from '@trezor/components'; +import { spacings } from '@trezor/theme'; +import { Translation } from 'src/components/suite'; export interface AssetTableRowType { symbol: string; @@ -31,18 +26,35 @@ export const AssetTable = ({ assetsData, assetsFiatBalances, }: AssetTableProps) => ( -
- - {assetsData.map((asset, i) => ( - - ))} - {discoveryInProgress && } +
+ + + + + + + + + + + + + + + + + + {assetsData.map((asset, i) => ( + + ))} + {discoveryInProgress && } +
); diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableHeader.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableHeader.tsx deleted file mode 100644 index 2fc928a4edd..00000000000 --- a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableHeader.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import styled from 'styled-components'; - -import { spacingsPx, typography } from '@trezor/theme'; - -import { Translation } from 'src/components/suite'; -import { AssetTableRowGrid } from './AssetTableRowGrid'; - -const Header = styled.div` - display: flex; - ${typography.hint} - color: ${({ theme }) => theme.textSubdued}; - align-items: center; - padding: ${spacingsPx.sm} 0; - border-bottom: 1px solid ${({ theme }) => theme.borderElevation2}; - - &:last-child { - padding-right: ${spacingsPx.md}; - } -`; - -const HeaderRight = styled(Header)` - justify-content: right; - padding-right: ${spacingsPx.xxxl}; -`; - -export const AssetTableHeader = () => ( - -
{/* Logo */} -
- -
-
- -
- - - -
- -
-
{/* Buy Button */} - -); diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableRowGrid.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableRowGrid.tsx deleted file mode 100644 index 95b330b5454..00000000000 --- a/packages/suite/src/views/dashboard/AssetsView/AssetTable/AssetTableRowGrid.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import styled, { css } from 'styled-components'; -import { borders, mapElevationToBackground } from '@trezor/theme'; -import { styledHoverOnParentOfArrowIcon } from '../ArrowIcon'; -import { Elevation, nextElevation } from '@trezor/theme/src/elevation'; -import { useElevation } from '@trezor/components'; -import { HTMLAttributes } from 'react'; - -const StyledAssetTableRowGrid = styled.div<{ $elevation: Elevation }>` - display: grid; - overflow: hidden; - grid-template-columns: 1fr 2fr 2fr 1fr 1fr 1fr; - border-radius: ${borders.radii.xs}; - - ${({ theme, $elevation, onClick }) => - onClick !== undefined - ? css` - cursor: pointer; - - ${styledHoverOnParentOfArrowIcon} - - &:hover { - background: ${mapElevationToBackground({ - theme, - $elevation: nextElevation[$elevation], - })}; - } - ` - : ''}; -`; - -export const AssetTableRowGrid = ({ children, ...props }: HTMLAttributes) => { - const { elevation } = useElevation(); - - return ( - - {children} - - ); -}; diff --git a/packages/suite/src/views/dashboard/AssetsView/AssetsView.tsx b/packages/suite/src/views/dashboard/AssetsView/AssetsView.tsx index 0e5dfc4c045..91e03616488 100644 --- a/packages/suite/src/views/dashboard/AssetsView/AssetsView.tsx +++ b/packages/suite/src/views/dashboard/AssetsView/AssetsView.tsx @@ -1,7 +1,7 @@ import styled, { useTheme } from 'styled-components'; import { BigNumber } from '@trezor/utils/src/bigNumber'; -import { Icon, Button, LoadingContent, Card, Column } from '@trezor/components'; +import { Icon, Button, LoadingContent, Card } from '@trezor/components'; import { selectCurrentFiatRates, selectDeviceSupportedNetworks } from '@suite-common/wallet-core'; import { DashboardSection } from 'src/components/dashboard'; @@ -203,19 +203,17 @@ export const AssetsView = () => { ) : ( - - - {isError && ( - - - - - )} - + + {isError && ( + + + + + )} )} From dc0147900dd371a1a7e0ed13d36eb38ffac70caa Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Mon, 7 Oct 2024 05:44:34 +0200 Subject: [PATCH 023/624] docs(connect-explorer): remove trailing commas from json excerpts --- .../src/pages/guides/webextension-implementation-tutorial.mdx | 2 +- packages/connect-explorer/src/pages/index.mdx | 2 +- packages/connect-webextension/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/connect-explorer/src/pages/guides/webextension-implementation-tutorial.mdx b/packages/connect-explorer/src/pages/guides/webextension-implementation-tutorial.mdx index 73b892938d4..bd43b6d8bd3 100644 --- a/packages/connect-explorer/src/pages/guides/webextension-implementation-tutorial.mdx +++ b/packages/connect-explorer/src/pages/guides/webextension-implementation-tutorial.mdx @@ -287,7 +287,7 @@ export const SectionCard = styled(TrezorCard)` }, "permissions": ["scripting"], "host_permissions": [ - "*://connect.trezor.io/9/*", + "*://connect.trezor.io/9/*" ] } ``` diff --git a/packages/connect-explorer/src/pages/index.mdx b/packages/connect-explorer/src/pages/index.mdx index 5a500b3980a..1d0e7c31414 100644 --- a/packages/connect-explorer/src/pages/index.mdx +++ b/packages/connect-explorer/src/pages/index.mdx @@ -441,7 +441,7 @@ export const ExampleHeading = styled.h3` "host_permissions": ["*://connect.trezor.io/9/*"] "background": { "service_worker": "serviceWorker.js" - }, + } ``` For manual content script injection, you can [find more information in the README](/readme/connect-webextension). diff --git a/packages/connect-webextension/README.md b/packages/connect-webextension/README.md index 2ba76ca491f..efb62810701 100644 --- a/packages/connect-webextension/README.md +++ b/packages/connect-webextension/README.md @@ -24,7 +24,7 @@ For a seamless integration, especially with background processes, modify your ex "host_permissions": ["*://connect.trezor.io/9/*"] "background": { "service_worker": "serviceWorker.js" - }, + } ``` The content script will be injected automatically by the library using the scripting permission. From 24bcb2e64432b1157ac5f51b4e41dbeb9418f657 Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Tue, 1 Oct 2024 10:50:48 +0200 Subject: [PATCH 024/624] feat(components): add ellipsis to text props --- .../src/components/NewModal/NewModal.tsx | 9 +- .../typography/Heading/Heading.stories.tsx | 4 +- .../components/typography/Heading/Heading.tsx | 155 ++++++------------ .../src/components/typography/Text/Text.tsx | 16 +- .../src/components/typography/utils.tsx | 29 +++- 5 files changed, 89 insertions(+), 124 deletions(-) diff --git a/packages/components/src/components/NewModal/NewModal.tsx b/packages/components/src/components/NewModal/NewModal.tsx index 616920f60ff..bb25103af7c 100644 --- a/packages/components/src/components/NewModal/NewModal.tsx +++ b/packages/components/src/components/NewModal/NewModal.tsx @@ -71,13 +71,6 @@ const HeadingContainer = styled.div` overflow: hidden; `; -// eslint-disable-next-line local-rules/no-override-ds-component -const Heading = styled(H3)` - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -`; - const ScrollContainer = styled.div` display: flex; flex-direction: column; @@ -170,7 +163,7 @@ const _NewModalBase = ({ )} - {heading && {heading}} + {heading &&

{heading}

} {description && ( {description} diff --git a/packages/components/src/components/typography/Heading/Heading.stories.tsx b/packages/components/src/components/typography/Heading/Heading.stories.tsx index c053fbcb0c9..9ff87b3ecfe 100644 --- a/packages/components/src/components/typography/Heading/Heading.stories.tsx +++ b/packages/components/src/components/typography/Heading/Heading.stories.tsx @@ -1,12 +1,13 @@ import styled from 'styled-components'; import { Meta, StoryObj } from '@storybook/react'; -import { H1, H2, H3, allowedHeadingFrameProps, allowedHeadingTextProps } from './Heading'; +import { H1, H2, H3, H4, allowedHeadingFrameProps, allowedHeadingTextProps } from './Heading'; import { getFramePropsStory } from '../../../utils/frameProps'; import { getTextPropsStory } from '../utils'; const Wrapper = styled.div` display: flex; flex-direction: column; + overflow: hidden; `; const meta: Meta = { @@ -20,6 +21,7 @@ export const Heading: StoryObj = {

This is heading 1

This is heading 2

This is heading 3

+

This is heading 4

), args: { diff --git a/packages/components/src/components/typography/Heading/Heading.tsx b/packages/components/src/components/typography/Heading/Heading.tsx index d9d511898f0..700fa280233 100644 --- a/packages/components/src/components/typography/Heading/Heading.tsx +++ b/packages/components/src/components/typography/Heading/Heading.tsx @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { Color } from '@trezor/theme'; +import { Color, TypographyStyle } from '@trezor/theme'; import { FrameProps, FramePropsKeys, @@ -8,9 +8,19 @@ import { withFrameProps, } from '../../../utils/frameProps'; import { makePropsTransient, TransientProps } from '../../../utils/transientProps'; -import { TextProps as TextPropsCommon, TextPropsKeys, withTextProps } from '../utils'; +import { + TextProps as TextPropsCommon, + TextPropsKeys, + withTextProps, + pickAndPrepareTextProps, +} from '../utils'; -export const allowedHeadingTextProps: TextPropsKeys[] = ['typographyStyle', 'textWrap', 'align']; +export const allowedHeadingTextProps: TextPropsKeys[] = [ + 'typographyStyle', + 'textWrap', + 'align', + 'ellipsisLineCount', +]; type AllowedHeadingTextProps = Pick; export const allowedHeadingFrameProps = ['margin'] as const satisfies FramePropsKeys[]; @@ -37,110 +47,39 @@ type HProps = AllowedFrameProps & 'data-testid'?: string; }; -export const H1 = ({ - color, - align, - typographyStyle = 'titleLarge', - textWrap, - onClick, - 'data-testid': dataTest, - children, - className, - ...rest -}: HProps) => { - const frameProps = pickAndPrepareFrameProps(rest, allowedHeadingFrameProps); - - return ( - - {children} - - ); -}; - -export const H2 = ({ - color, - align, - typographyStyle = 'titleMedium', - textWrap, - onClick, - 'data-testid': dataTest, - children, - className, - ...rest -}: HProps) => { - const frameProps = pickAndPrepareFrameProps(rest, allowedHeadingFrameProps); - - return ( - - {children} - - ); -}; +const createHeading = + (as: 'h1' | 'h2' | 'h3' | 'h4', defaultTypographyStyle: TypographyStyle) => + ({ + color, + typographyStyle = defaultTypographyStyle, + onClick, + 'data-testid': dataTestId, + children, + className, + ...rest + }: HProps) => { + const frameProps = pickAndPrepareFrameProps(rest, allowedHeadingFrameProps); + const textProps = pickAndPrepareTextProps( + { ...rest, typographyStyle }, + allowedHeadingTextProps, + ); -export const H3 = ({ - color, - align, - typographyStyle = 'titleSmall', - textWrap, - onClick, - 'data-testid': dataTest, - children, - className, - ...rest -}: HProps) => { - const frameProps = pickAndPrepareFrameProps(rest, allowedHeadingFrameProps); - - return ( - - {children} - - ); -}; - -export const H4 = ({ - color, - align, - typographyStyle = 'highlight', - textWrap, - onClick, - 'data-testid': dataTest, - children, - className, - ...rest -}: HProps) => { - const frameProps = pickAndPrepareFrameProps(rest, allowedHeadingFrameProps); + return ( + + {children} + + ); + }; - return ( - - {children} - - ); -}; +export const H1 = createHeading('h1', 'titleLarge'); +export const H2 = createHeading('h2', 'titleMedium'); +export const H3 = createHeading('h3', 'titleSmall'); +export const H4 = createHeading('h4', 'highlight'); diff --git a/packages/components/src/components/typography/Text/Text.tsx b/packages/components/src/components/typography/Text/Text.tsx index 5b342dcc382..5258b18e557 100644 --- a/packages/components/src/components/typography/Text/Text.tsx +++ b/packages/components/src/components/typography/Text/Text.tsx @@ -1,20 +1,26 @@ import styled from 'styled-components'; import { CSSColor, Color, Colors } from '@trezor/theme'; import { ReactNode } from 'react'; -import { makePropsTransient, TransientProps } from '../../../utils/transientProps'; +import { TransientProps } from '../../../utils/transientProps'; import { FrameProps, FramePropsKeys, pickAndPrepareFrameProps, withFrameProps, } from '../../../utils/frameProps'; -import { TextPropsKeys, withTextProps, TextProps as TextPropsCommon } from '../utils'; +import { + TextPropsKeys, + withTextProps, + TextProps as TextPropsCommon, + pickAndPrepareTextProps, +} from '../utils'; import { uiVariants } from '../../../config/types'; export const allowedTextTextProps = [ 'typographyStyle', 'textWrap', 'align', + 'ellipsisLineCount', ] as const satisfies TextPropsKeys[]; type AllowedTextTextProps = Pick; @@ -79,14 +85,12 @@ export const Text = ({ color, children, className, - typographyStyle, - textWrap, - align, as = 'span', 'data-testid': dataTest, ...rest }: TextProps) => { const frameProps = pickAndPrepareFrameProps(rest, allowedTextFrameProps); + const textProps = pickAndPrepareTextProps(rest, allowedTextTextProps); return ( {children} diff --git a/packages/components/src/components/typography/utils.tsx b/packages/components/src/components/typography/utils.tsx index f70136b73ee..95bf8bd61e8 100644 --- a/packages/components/src/components/typography/utils.tsx +++ b/packages/components/src/components/typography/utils.tsx @@ -11,6 +11,7 @@ export type TextProps = { typographyStyle?: TypographyStyle; textWrap?: TextWrap; align?: UIHorizontalAlignment; + ellipsisLineCount?: number; }; export type TextPropsKeys = keyof TextProps; @@ -25,7 +26,12 @@ export const pickAndPrepareTextProps = ( allowedTextProps.reduce((acc, item) => ({ ...acc, [item]: props[item] }), {}), ); -export const withTextProps = ({ $textWrap, $typographyStyle, $align }: TransientTextProps) => { +export const withTextProps = ({ + $textWrap, + $typographyStyle, + $align, + $ellipsisLineCount = 0, +}: TransientTextProps) => { return css` ${$textWrap && css` @@ -40,6 +46,19 @@ export const withTextProps = ({ $textWrap, $typographyStyle, $align }: Transient css` text-align: ${$align}; `} + ${$ellipsisLineCount > 0 && + css` + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + `} + ${$ellipsisLineCount > 1 && + css` + white-space: initial; + -webkit-line-clamp: ${$ellipsisLineCount}; + display: -webkit-box; + -webkit-box-orient: vertical; + `} `; }; @@ -66,6 +85,13 @@ const getStorybookType = (key: TextPropsKeys) => { type: 'select', }, }; + case 'ellipsisLineCount': + return { + control: { + type: 'number', + min: 0, + }, + }; default: return { control: { @@ -94,6 +120,7 @@ export const getTextPropsStory = (allowedTextProps: Array) => { ...(allowedTextProps.includes('textWrap') ? { textWrap: undefined } : {}), ...(allowedTextProps.includes('typographyStyle') ? { typographyStyle: undefined } : {}), ...(allowedTextProps.includes('align') ? { align: undefined } : {}), + ...(allowedTextProps.includes('ellipsisLineCount') ? { hasEllipsis: undefined } : {}), }, argTypes, }; From f78ae742794502cd449a0cb5235ac4159210d43f Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Tue, 1 Oct 2024 10:51:09 +0200 Subject: [PATCH 025/624] chore(suite): remove unused modals --- .../DeviceContextModal/DeviceContextModal.tsx | 3 - .../DeviceContextModal/DevicePromptModal.tsx | 90 ------------------- .../PassphraseSourceModal.tsx | 59 ------------ .../src/components/suite/modals/index.tsx | 1 - 4 files changed, 153 deletions(-) delete mode 100644 packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DevicePromptModal.tsx delete mode 100644 packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseSourceModal.tsx diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx index 4dce0b1c5b9..2ab21feae58 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx @@ -9,7 +9,6 @@ import { PinModal, PinInvalidModal, PassphraseModal, - PassphraseSourceModal, PassphraseOnDeviceModal, ConfirmActionModal, ConfirmFingerprintModal, @@ -52,8 +51,6 @@ export const DeviceContextModal = ({ return ; case 'WordRequestType_Matrix9': return ; - case 'ButtonRequest_PassphraseType': - return ; // T2T1 firmware case UI.REQUEST_PASSPHRASE_ON_DEVICE: case 'ButtonRequest_PassphraseEntry': diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DevicePromptModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DevicePromptModal.tsx deleted file mode 100644 index 526bf4a48fa..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DevicePromptModal.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { ComponentType, ReactNode } from 'react'; -import { createPortal } from 'react-dom'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -import TrezorConnect from '@trezor/connect'; -import { Modal as TrezorModal, ModalProps as TrezorModalProps } from '@trezor/components'; -import { Translation } from 'src/components/suite'; -import { selectIsActionAbortable } from 'src/reducers/suite/suiteReducer'; -import { useSelector } from 'src/hooks/suite/useSelector'; -import messages from 'src/support/messages'; -import { useDevice } from 'src/hooks/suite'; -import { useModalTarget } from 'src/support/suite/ModalContext'; -import { ModalEnvironment } from '../../ModalEnvironment'; -import { Modal } from '../../Modal/Modal'; -import { ConfirmOnDevice } from '@trezor/product-components'; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledTrezorModal = styled(TrezorModal)` - ${Modal.Header} { - padding: 24px 24px 0; - } - - ${Modal.Body} { - margin-top: ${({ headerComponent }) => !headerComponent && '60px'}; - padding: 24px; - } -`; - -export interface DevicePromptModalProps { - isPillShown?: boolean; - isConfirmed?: boolean; - pillTitle?: string; - renderer?: ComponentType; - isAbortable?: boolean; - onAbort?: () => void; - className?: string; - children?: ReactNode; - 'data-testid'?: string; -} - -const DevicePromptModalRenderer = ({ - isPillShown = true, - isConfirmed, - pillTitle, - isAbortable = true, - onAbort, - ...rest -}: DevicePromptModalProps) => { - const { device } = useDevice(); - const modalTarget = useModalTarget(); - - // duplicated because headerComponent should receive undefined if isAbortable === false - const isActionAbortable = useSelector(selectIsActionAbortable) || isAbortable; - - const intl = useIntl(); - - if (!onAbort) { - onAbort = () => TrezorConnect.cancel(intl.formatMessage(messages.TR_CANCELLED)); - } - - if (!modalTarget) return null; - - const deviceModelInternal = device?.features?.internal_model; - - const modalComponent = ( - - } - deviceModelInternal={deviceModelInternal} - deviceUnitColor={device?.features?.unit_color} - isConfirmed={isConfirmed} - onCancel={isActionAbortable ? onAbort : undefined} - /> - ) - } - {...rest} - /> - - ); - - return createPortal(modalComponent, modalTarget); -}; - -export const DevicePromptModal = (props: DevicePromptModalProps) => ( - -); diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseSourceModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseSourceModal.tsx deleted file mode 100644 index 96bd86dc4ee..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseSourceModal.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import styled from 'styled-components'; - -import { H2, variables } from '@trezor/components'; -import { - selectDeviceLabelOrName, - selectIsDiscoveryAuthConfirmationRequired, -} from '@suite-common/wallet-core'; - -import { Translation } from 'src/components/suite/Translation'; -import { DeviceConfirmImage } from 'src/components/suite'; -import { useSelector } from 'src/hooks/suite'; -import type { TrezorDevice } from 'src/types/suite'; -import { DevicePromptModal } from './DevicePromptModal'; - -const StyledDevicePromptModal = styled(DevicePromptModal)` - width: 360px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledH2 = styled(H2)` - margin-top: 12px; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; -`; - -interface PassphraseSourceModalProps { - device: TrezorDevice; -} - -/** - * Modal used with T2T1 with legacy firmware as result of 'ButtonRequest_PassphraseType' where passphrase source is requested on device - * @param {PassphraseSourceModalProps} - */ -export const PassphraseSourceModal = ({ device }: PassphraseSourceModalProps) => { - const authConfirmation = - useSelector(selectIsDiscoveryAuthConfirmationRequired) || device.authConfirm; - const deviceLabel = useSelector(selectDeviceLabelOrName); - - return ( - - - - - - - - ); -}; diff --git a/packages/suite/src/components/suite/modals/index.tsx b/packages/suite/src/components/suite/modals/index.tsx index 48d18ddb940..ec560a00949 100644 --- a/packages/suite/src/components/suite/modals/index.tsx +++ b/packages/suite/src/components/suite/modals/index.tsx @@ -2,7 +2,6 @@ export { PinModal } from './ReduxModal/DeviceContextModal/PinModal'; export { PinInvalidModal } from './ReduxModal/DeviceContextModal/PinInvalidModal'; export { PinMismatchModal } from './ReduxModal/UserContextModal/PinMismatchModal'; export { PassphraseModal } from './ReduxModal/DeviceContextModal/PassphraseModal'; -export { PassphraseSourceModal } from './ReduxModal/DeviceContextModal/PassphraseSourceModal'; export { PassphraseOnDeviceModal } from './ReduxModal/DeviceContextModal/PassphraseOnDeviceModal'; export { PassphraseDuplicateModal } from './ReduxModal/UserContextModal/PassphraseDuplicateModal'; export { ConfirmActionModal } from './ReduxModal/DeviceContextModal/ConfirmActionModal'; From 6ee39800d84ac21415c7a8608ae532679a792e15 Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Tue, 1 Oct 2024 10:52:44 +0200 Subject: [PATCH 026/624] chore(suite): update AuthenticateDeviceModal to use NewModal component --- .../AuthenticateDeviceModal.tsx | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceModal.tsx index 5028f5b2d8c..0dc5ece3a7b 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceModal.tsx @@ -1,13 +1,21 @@ import { useState } from 'react'; import { checkDeviceAuthenticityThunk } from '@suite-common/device-authenticity'; -import { Button } from '@trezor/components'; +import { NewModal, List, IconName, Paragraph, Icon } from '@trezor/components'; +import { selectSelectedDeviceAuthenticity } from '@suite-common/wallet-core'; +import { TranslationKey } from '@suite-common/intl-types'; +import { spacings } from '@trezor/theme'; import { onCancel, openModal } from 'src/actions/suite/modalActions'; -import { DeviceAuthenticationExplainer, Modal, Translation } from 'src/components/suite'; +import { Translation } from 'src/components/suite'; import { useDispatch, useSelector } from 'src/hooks/suite'; import { selectIsDebugModeActive } from 'src/reducers/suite/suiteReducer'; -import { selectSelectedDeviceAuthenticity } from '@suite-common/wallet-core'; + +const items: Array<{ icon: IconName; text: TranslationKey }> = [ + { icon: 'shieldCheck', text: 'TR_DEVICE_AUTHENTICITY_ITEM_1' }, + { icon: 'chip', text: 'TR_DEVICE_AUTHENTICITY_ITEM_2' }, + { icon: 'checklist', text: 'TR_DEVICE_AUTHENTICITY_ITEM_3' }, +]; export const AuthenticateDeviceModal = () => { const [isLoading, setIsLoading] = useState(false); @@ -30,17 +38,40 @@ export const AuthenticateDeviceModal = () => { const handleClose = () => dispatch(onCancel()); return ( - } - bottomBarComponents={ - + bottomContent={ + <> + + + + + + + } > - - + + {items.map(({ icon, text }) => ( + } + > + + + + + ))} + + ); }; From 0e3aa62021a6375d80f012ba0ca8167e2da96331 Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Tue, 1 Oct 2024 10:53:05 +0200 Subject: [PATCH 027/624] chore(suite): update ReconnectDevicePromp to use NewModal component --- .../firmware/ReconnectDevicePrompt.tsx | 258 +++++------------- 1 file changed, 68 insertions(+), 190 deletions(-) diff --git a/packages/suite/src/components/firmware/ReconnectDevicePrompt.tsx b/packages/suite/src/components/firmware/ReconnectDevicePrompt.tsx index 5cef9b478d2..803a695938c 100644 --- a/packages/suite/src/components/firmware/ReconnectDevicePrompt.tsx +++ b/packages/suite/src/components/firmware/ReconnectDevicePrompt.tsx @@ -1,137 +1,21 @@ -import { ReactNode } from 'react'; -import styled, { css } from 'styled-components'; import * as semver from 'semver'; - +import styled from 'styled-components'; import { getFirmwareVersion } from '@trezor/device-utils'; -import { H2, Button, variables, DeviceAnimation } from '@trezor/components'; +import { H2, DeviceAnimation, NewModal, Paragraph, List } from '@trezor/components'; import { DEVICE, Device, DeviceModelInternal, UI } from '@trezor/connect'; -import { Modal, Translation, WebUsbButton } from 'src/components/suite'; +import { Translation, WebUsbButton } from 'src/components/suite'; import { DeviceConfirmImage } from 'src/components/suite/DeviceConfirmImage'; import { useDevice, useFirmware, useSelector } from 'src/hooks/suite'; -import { AbortButton } from 'src/components/suite/modals/AbortButton'; import { ConfirmOnDevice } from '@trezor/product-components'; import { TranslationKey } from '@suite-common/intl-types'; import { spacings } from '@trezor/theme'; import { selectDeviceLabelOrName } from '@suite-common/wallet-core'; -const StyledModal = styled(Modal)` - width: 600px; - - ${Modal.Body} { - padding: 38px 22px 6px; - } -`; - -const Wrapper = styled.div` - display: flex; - align-items: center; - justify-content: space-around; - - ${variables.SCREEN_QUERY.MOBILE} { - flex-direction: column; - } -`; - -const Content = styled.div` - display: flex; - flex-direction: column; - padding: 10px 14px; - margin-left: 24px; -`; - -const BulletPointWrapper = styled.div` +const ImageWrapper = styled.div` display: flex; - align-items: center; - - & + & { - margin-top: 24px; - } -`; - -const BulletPointNumber = styled.div<{ $active?: boolean }>` - display: flex; - flex: 0 0 auto; - width: 28px; - height: 28px; - border-radius: 50%; justify-content: center; - align-items: center; - margin-right: 14px; - font-size: ${variables.FONT_SIZE.SMALL}; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; - background: ${({ theme }) => theme.legacy.BG_GREY}; - font-variant-numeric: tabular-nums; - - ${({ $active, theme }) => - $active && - css` - color: ${theme.legacy.TYPE_GREEN}; - background: ${theme.legacy.BG_LIGHT_GREEN}; - `} `; -const BulletPointText = styled.span<{ $active?: boolean }>` - font-size: ${variables.FONT_SIZE.NORMAL}; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; - color: ${({ theme, $active }) => - $active ? theme.legacy.TYPE_GREEN : theme.legacy.TYPE_LIGHT_GREY}; - text-align: left; -`; - -const CenteredPointText = styled(BulletPointText)` - text-align: center; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledDeviceAnimation = styled(DeviceAnimation)` - flex: 0 0 220px; - width: 220px; - height: 220px; - - ${variables.SCREEN_QUERY.MOBILE} { - align-self: center; - } -`; - -const StyledConfirmImage = styled(DeviceConfirmImage)` - flex: 0 0 200px; - width: 200px; - height: 200px; -`; - -const StyledWebUsbButton = styled(WebUsbButton)` - margin-top: 24px; -`; - -const StyledAbortButton = styled(AbortButton)` - position: absolute; - top: 12px; - right: 12px; -`; - -interface ReconnectStepProps { - order?: number; - active: boolean; - children: ReactNode; - 'data-testid'?: string; -} - -const ReconnectStep = ({ - order, - active, - 'data-testid': dataTest, - children, -}: ReconnectStepProps) => ( - - {order && {order}} - - - {children} - - -); - const RebootDeviceGraphics = ({ device, isManualRebootRequired, @@ -140,7 +24,7 @@ const RebootDeviceGraphics = ({ isManualRebootRequired: boolean; }) => { if (!isManualRebootRequired) { - return device ? : null; + return device ? : null; } const deviceModelInternal = device?.features?.internal_model; @@ -164,11 +48,10 @@ const RebootDeviceGraphics = ({ }; return ( - @@ -261,74 +144,69 @@ export const ReconnectDevicePrompt = ({ onClose, onSuccess }: ReconnectDevicePro }; return ( - } - deviceModelInternal={deviceModelInternal} - deviceUnitColor={device?.features?.unit_color} - isConfirmed={uiEvent?.type !== 'button'} - /> - ) - } - > - {isAbortable && } - - + + {!isManualRebootRequired && !isRebootDone && ( + } + deviceModelInternal={deviceModelInternal} + deviceUnitColor={device?.features?.unit_color} + isConfirmed={uiEvent?.type !== 'button'} + /> + )} + + + + ) + } + > {!isRebootDone && ( - + + + )} - - -

- -

- - {!isRebootDone ? ( - <> - {isManualRebootRequired ? ( - <> - {/* First step asks for disconnecting a device */} - - - - - {/* Second step reconnect in bootloader */} - - - - - ) : ( - - - - )} - {showWebUsbButton && } - - ) : ( - <> - - - )} -
-
-
+

+ +

+ {!isRebootDone && ( + <> + {isManualRebootRequired ? ( + + {/* First step asks for disconnecting a device */} + + + + + {/* Second step reconnect in bootloader */} + + + + + ) : ( + + + + )} + {showWebUsbButton && } + + )} + + ); }; From 1b39b90b3ad4f211961ffb431207a36f6d8b1dab Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Tue, 1 Oct 2024 10:54:16 +0200 Subject: [PATCH 028/624] chore(suite): update check backup modal to use NewModal component --- packages/suite/src/support/messages.ts | 4 + packages/suite/src/views/recovery/index.tsx | 268 +++++++++----------- 2 files changed, 124 insertions(+), 148 deletions(-) diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index c54caf906ee..cfc3f282eaa 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -8334,6 +8334,10 @@ export default defineMessages({ id: 'TR_STEP', defaultMessage: 'Step {number}', }, + TR_STEP_OF_TOTAL: { + id: 'TR_STEP_OF_TOTAL', + defaultMessage: 'Step {index} of {total}', + }, TR_COINJOIN_STEP_1_TITLE: { id: 'TR_COINJOIN_STEP_1_TITLE', defaultMessage: 'Add bitcoin', diff --git a/packages/suite/src/views/recovery/index.tsx b/packages/suite/src/views/recovery/index.tsx index a0a01bf29d8..9adab65637a 100644 --- a/packages/suite/src/views/recovery/index.tsx +++ b/packages/suite/src/views/recovery/index.tsx @@ -1,14 +1,14 @@ import { useState } from 'react'; import { useIntl } from 'react-intl'; -import styled from 'styled-components'; import { getCheckBackupUrl, isDeviceAcquired } from '@suite-common/suite-utils'; -import { Button, H2, Paragraph, Image } from '@trezor/components'; +import { H2, H3, Paragraph, Image, NewModal, Card, List } from '@trezor/components'; import { pickByDeviceModel } from '@trezor/device-utils'; import TrezorConnect, { DeviceModelInternal } from '@trezor/connect'; +import { spacings } from '@trezor/theme'; import { SelectWordCount, SelectRecoveryType } from 'src/components/recovery'; -import { Loading, Translation, CheckItem, Modal } from 'src/components/suite'; +import { Loading, Translation, CheckItem } from 'src/components/suite'; import { ReduxModal } from 'src/components/suite/modals/ReduxModal/ReduxModal'; import { checkSeed, @@ -19,57 +19,9 @@ import { import { useDevice, useDispatch, useSelector } from 'src/hooks/suite'; import type { ForegroundAppProps } from 'src/types/suite'; import type { WordCount } from 'src/types/recovery'; -import { InstructionStep } from 'src/components/suite/InstructionStep'; import messages from 'src/support/messages'; import { LearnMoreButton } from 'src/components/suite/LearnMoreButton'; -const StyledModal = styled(Modal)` - min-height: 450px; - - ${Modal.Content} { - justify-content: center; - } -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledButton = styled(Button)` - width: 224px; -`; - -const StepsContainer = styled.div` - margin: 40px 0; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledP = styled(Paragraph)` - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledImage = styled(Image)` - margin-bottom: 24px; - align-self: center; -`; - -const LeftAlignedP = styled(StyledP)` - text-align: left; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StatusImage = styled(Image)` - padding-bottom: 24px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StatusTitle = styled(H2)` - margin: 0 0 12px; -`; - -const VerticalCenter = styled.div` - margin-top: auto; - margin-bottom: auto; -`; - export const Recovery = ({ onCancel }: ForegroundAppProps) => { const recovery = useSelector(state => state.recovery); const modal = useSelector(state => state.modal); @@ -102,117 +54,101 @@ export const Recovery = ({ onCancel }: ForegroundAppProps) => { 'finished', ] : ['initial', 'in-progress', 'finished']; + const hasFinished = recovery.status === 'finished'; + const hasError = recovery.error !== undefined; if (!isDeviceAcquired(device) || !deviceModelInternal) { return ( - } - isCancelable onCancel={onCancel} data-testid="@recovery/no-device" + size="tiny" > - - + + ); } - const actionButtons = ( - <> - {recovery.status === 'initial' ? ( - - deviceModelInternal === DeviceModelInternal.T1B1 - ? dispatch(setStatus('select-word-count')) - : dispatch(checkSeed()) - } - isDisabled={!understood || isLocked()} - data-testid="@recovery/start-button" - > - - - ) : ( - onCancel()}> - - - )} - - ); - const getStep = () => { const isShamirBackupAvailable = device?.features?.capabilities?.includes('Capability_Shamir'); - // Shamir backup uses 20 and 33 word shares - const seedBackupLengthMessage = isShamirBackupAvailable - ? 'TR_SEED_BACKUP_LENGTH_INCLUDING_SHAMIR' - : 'TR_SEED_BACKUP_LENGTH'; - switch (recovery.status) { case 'initial': return ( <> - - - - - - + + - } - > - - - - } - > - - - - - } - description={} - isChecked={understood} - link={learnMoreUrl && } - onClick={() => setUnderstood(!understood)} - /> + + + + + + + + + + + + + + + + } + description={} + isChecked={understood} + link={learnMoreUrl && } + onClick={() => setUnderstood(!understood)} + /> + ); case 'select-word-count': return ( <> - +

- +

); case 'select-recovery-type': return ( <> - +

- +

); @@ -221,9 +157,9 @@ export const Recovery = ({ onCancel }: ForegroundAppProps) => { return modal.context !== '@modal/context-none' ? ( <> {device.features.capabilities.includes('Capability_PassphraseEntry') && ( - + - + )} @@ -231,41 +167,74 @@ export const Recovery = ({ onCancel }: ForegroundAppProps) => { ); case 'finished': - return !recovery.error ? ( - - + return !hasError ? ( + <>

- + - -
+ + ) : ( - - + <>

- + - -
+ + ); - // no default } }; return ( - } - totalProgressBarSteps={statesInProgressBar.length} - currentProgressBarStep={statesInProgressBar.findIndex(s => s === recovery.status) + 1} - bottomBarComponents={actionButtons} - isCancelable + description={ + + } + bottomContent={ + <> + {recovery.status === 'initial' && ( + + deviceModelInternal === DeviceModelInternal.T1B1 + ? dispatch(setStatus('select-word-count')) + : dispatch(checkSeed()) + } + isDisabled={!understood || isLocked()} + data-testid="@recovery/start-button" + > + + + )} + onCancel()} + > + + + + } onCancel={() => { if (['in-progress', 'waiting-for-confirmation'].includes(recovery.status)) { TrezorConnect.cancel(intl.formatMessage(messages.TR_CANCELLED)); @@ -273,8 +242,11 @@ export const Recovery = ({ onCancel }: ForegroundAppProps) => { onCancel(); } }} + variant={hasFinished && hasError ? 'warning' : 'primary'} + // eslint-disable-next-line no-nested-ternary + iconName={hasFinished ? (hasError ? 'warning' : 'check') : undefined} > {getStep()} - + ); }; From ddf91197535f2dacff3f942beba58c987606f1ff Mon Sep 17 00:00:00 2001 From: grdddj Date: Mon, 7 Oct 2024 09:51:30 +0200 Subject: [PATCH 029/624] chore(ci): do not build node bridge in CI for labeled pull requests --- .github/workflows/build-node-bridge.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build-node-bridge.yml b/.github/workflows/build-node-bridge.yml index f936e657975..b598c59b019 100644 --- a/.github/workflows/build-node-bridge.yml +++ b/.github/workflows/build-node-bridge.yml @@ -8,8 +8,6 @@ on: push: branches: - develop - pull_request: - types: [labeled] workflow_dispatch: jobs: From f5e8f256ae977152aeadae890dd0dd9bf3fe586f Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Mon, 7 Oct 2024 09:50:19 +0200 Subject: [PATCH 030/624] chore(connect): rename 'getAssetByUrl' to a more apt fn name 'tryLocalAssetRequire' --- packages/connect/src/utils/assetUtils.ts | 2 +- packages/connect/src/utils/assets.native.ts | 4 ++-- packages/connect/src/utils/assets.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/connect/src/utils/assetUtils.ts b/packages/connect/src/utils/assetUtils.ts index be07387c59b..abb5e9d9807 100644 --- a/packages/connect/src/utils/assetUtils.ts +++ b/packages/connect/src/utils/assetUtils.ts @@ -12,7 +12,7 @@ const firmwareAssets: Record = { [DeviceModelInternal.T3T1]: require('@trezor/connect-common/files/firmware/t3t1/releases.json'), }; -export const getAssetByUrl = (url: string) => { +export const tryLocalAssetRequire = (url: string) => { const fileUrl = url.split('?')[0]; switch (fileUrl) { diff --git a/packages/connect/src/utils/assets.native.ts b/packages/connect/src/utils/assets.native.ts index f0bac432de7..d5564403e9d 100644 --- a/packages/connect/src/utils/assets.native.ts +++ b/packages/connect/src/utils/assets.native.ts @@ -1,3 +1,3 @@ -import { getAssetByUrl } from './assetUtils'; +import { tryLocalAssetRequire } from './assetUtils'; -export const httpRequest = (url: string, _type: string): any => getAssetByUrl(url); +export const httpRequest = (url: string, _type: string): any => tryLocalAssetRequire(url); diff --git a/packages/connect/src/utils/assets.ts b/packages/connect/src/utils/assets.ts index 2439e3ab2e3..ac62bf5b07d 100644 --- a/packages/connect/src/utils/assets.ts +++ b/packages/connect/src/utils/assets.ts @@ -3,7 +3,7 @@ import fetch from 'cross-fetch'; import { promises as fs } from 'fs'; import { httpRequest as browserHttpRequest } from './assets-browser'; -import { getAssetByUrl } from './assetUtils'; +import { tryLocalAssetRequire } from './assetUtils'; if (global && typeof global.fetch !== 'function') { global.fetch = fetch; @@ -36,7 +36,7 @@ export function httpRequest( options?: RequestInit, skipLocalForceDownload?: boolean, ) { - const asset = skipLocalForceDownload ? null : getAssetByUrl(url); + const asset = skipLocalForceDownload ? null : tryLocalAssetRequire(url); if (!asset) { return /^https?/.test(url) ? browserHttpRequest(url, type, options) : fs.readFile(url); From 03d398390665c7c1d3a044d5d93ea0d6adde5dac Mon Sep 17 00:00:00 2001 From: Jan Komarek Date: Wed, 2 Oct 2024 08:56:34 +0200 Subject: [PATCH 031/624] chore(suite): update security check URLs --- .../suite/SecurityCheck/DeviceCompromised.tsx | 12 ++++++++---- .../suite/SecurityCheck/SecurityCheckFail.tsx | 6 +++--- .../UserContextModal/AuthenticateDeviceFailModal.tsx | 5 +++-- .../steps/SecurityCheck/DeviceAuthenticity.tsx | 7 ++++--- packages/urls/src/urls.ts | 6 ++++-- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx index eb3611d69a8..006c0ece990 100644 --- a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx +++ b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx @@ -1,14 +1,15 @@ import { useEffect } from 'react'; +import { isDeviceAcquired } from '@suite-common/suite-utils'; +import { deviceActions } from '@suite-common/wallet-core'; import { Card } from '@trezor/components'; import { getFirmwareVersion } from '@trezor/device-utils'; -import { isDeviceAcquired } from '@suite-common/suite-utils'; +import { TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL } from '@trezor/urls'; import { WelcomeLayout } from 'src/components/suite'; import { useDevice, useDispatch } from 'src/hooks/suite'; import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; -import { SecurityCheckFail } from '../SecurityCheck/SecurityCheckFail'; -import { deviceActions } from '@suite-common/wallet-core'; +import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; export const DeviceCompromised = () => { const dispatch = useDispatch(); @@ -45,7 +46,10 @@ export const DeviceCompromised = () => { return ( - + ); diff --git a/packages/suite/src/components/suite/SecurityCheck/SecurityCheckFail.tsx b/packages/suite/src/components/suite/SecurityCheck/SecurityCheckFail.tsx index d6069d5f90b..f0e45408358 100644 --- a/packages/suite/src/components/suite/SecurityCheck/SecurityCheckFail.tsx +++ b/packages/suite/src/components/suite/SecurityCheck/SecurityCheckFail.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import { TranslationKey } from '@suite-common/intl-types'; import { Button, Divider, H2, Row, Text } from '@trezor/components'; import { spacings, spacingsPx } from '@trezor/theme'; -import { TREZOR_SUPPORT_FW_CHECK_FAILED, Url } from '@trezor/urls'; +import { Url } from '@trezor/urls'; import { Translation } from 'src/components/suite'; import { SecurityChecklist } from '../../../views/onboarding/steps/SecurityCheck/SecurityChecklist'; @@ -38,14 +38,14 @@ interface SecurityCheckFailProps { goBack?: () => void; heading?: TranslationKey; text?: TranslationKey; - supportUrl?: Url; + supportUrl: Url; } export const SecurityCheckFail = ({ goBack, heading = 'TR_DEVICE_COMPROMISED_HEADING', text = 'TR_DEVICE_COMPROMISED_TEXT', - supportUrl = TREZOR_SUPPORT_FW_CHECK_FAILED, + supportUrl, }: SecurityCheckFailProps) => { const chatUrl = `${supportUrl}#open-chat`; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceFailModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceFailModal.tsx index 99cc74c7142..6f58c39d687 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceFailModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/AuthenticateDeviceFailModal.tsx @@ -1,7 +1,8 @@ import styled from 'styled-components'; import { Modal } from 'src/components/suite'; -import { SecurityCheckFail } from '../../../SecurityCheck/SecurityCheckFail'; +import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; +import { TREZOR_SUPPORT_DEVICE_AUTHENTICATION_FAILED_URL } from '@trezor/urls'; const StyledModal = styled(Modal)` text-align: left; @@ -9,6 +10,6 @@ const StyledModal = styled(Modal)` export const AuthenticateDeviceFailModal = () => ( - + ); diff --git a/packages/suite/src/views/onboarding/steps/SecurityCheck/DeviceAuthenticity.tsx b/packages/suite/src/views/onboarding/steps/SecurityCheck/DeviceAuthenticity.tsx index 117a3a70d4a..f7421fb7ff0 100644 --- a/packages/suite/src/views/onboarding/steps/SecurityCheck/DeviceAuthenticity.tsx +++ b/packages/suite/src/views/onboarding/steps/SecurityCheck/DeviceAuthenticity.tsx @@ -4,14 +4,15 @@ import styled from 'styled-components'; import { checkDeviceAuthenticityThunk } from '@suite-common/device-authenticity'; import { selectDevice, selectSelectedDeviceAuthenticity } from '@suite-common/wallet-core'; import { variables } from '@trezor/components'; +import { spacingsPx } from '@trezor/theme'; +import { TREZOR_SUPPORT_DEVICE_AUTHENTICATION_FAILED_URL } from '@trezor/urls'; import { OnboardingButtonCta, OnboardingStepBox } from 'src/components/onboarding'; import { CollapsibleOnboardingCard } from 'src/components/onboarding/CollapsibleOnboardingCard'; import { DeviceAuthenticationExplainer, Translation } from 'src/components/suite'; import { useDispatch, useSelector } from 'src/hooks/suite'; import { selectIsDebugModeActive } from 'src/reducers/suite/suiteReducer'; -import { SecurityCheckFail } from '../../../../components/suite/SecurityCheck/SecurityCheckFail'; -import { spacingsPx } from '@trezor/theme'; +import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; const StyledCard = styled(CollapsibleOnboardingCard)` padding: ${spacingsPx.md}; @@ -109,7 +110,7 @@ export const DeviceAuthenticity = ({ goToNext }: DeviceAuthenticityProps) => { if (isCheckFailed) { return ( - + ); } diff --git a/packages/urls/src/urls.ts b/packages/urls/src/urls.ts index 21fc334d76c..8d6f9c21a7c 100644 --- a/packages/urls/src/urls.ts +++ b/packages/urls/src/urls.ts @@ -25,8 +25,10 @@ export const TREZOR_SUPPORT_DEVICE_URL: Url = 'https://trezor.io/support/a/trezor-suite-doesn-t-see-my-device'; export const TREZOR_SUPPORT_RECOVERY_ISSUES_URL: Url = 'https://trezor.io/support/a/trezor-recovery-issues'; -export const TREZOR_SUPPORT_FW_CHECK_FAILED: Url = - 'https://trezor.io/support/a/trezor-firmware-revision-check-failed'; +export const TREZOR_SUPPORT_DEVICE_AUTHENTICATION_FAILED_URL: Url = + 'https://trezor.io/support/a/trezor-safe-device-authentication-check-failed'; +export const TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL: Url = + 'https://trezor.io/support/a/trezor-fw-revision-check-failed'; export const TREZOR_SUPPORT_FW_ALREADY_INSTALLED: Url = 'https://trezor.io/support/a/firmware-is-already-installed'; export const TREZOR_SUPPORT_IS_MY_DEVICE_SAFE: Url = From d7efe8896020ef234c21324e53dd1dc1b4d1d4b1 Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Thu, 3 Oct 2024 15:18:52 +0200 Subject: [PATCH 032/624] chore(coinmarket): remove unused files, types --- .../__tests__/coinmarketBuyActions.test.ts | 2 +- .../coinmarketExchangeActions.test.ts | 2 +- .../wallet/coinmarketExchangeActions.ts | 5 - .../actions/wallet/coinmarketSellActions.ts | 5 - .../UserContextModal/CoinmarketTermsModal.tsx | 3 +- .../src/hooks/wallet/useCoinmarketRedirect.ts | 6 +- .../__tests__/coinmarketReducer.test.ts | 22 -- .../src/reducers/wallet/coinmarketReducer.ts | 6 - packages/suite/src/support/messages.ts | 30 --- .../suite/src/types/coinmarket/coinmarket.ts | 2 +- .../src/types/coinmarket/coinmarketForm.ts | 20 +- .../src/types/coinmarket/coinmarketOffers.ts | 52 +--- .../src/types/wallet/coinmarketCommonTypes.ts | 4 - .../types/wallet/coinmarketExchangeForm.ts | 52 ---- .../src/types/wallet/coinmarketSellForm.ts | 61 ----- .../CoinmarketFormOfferCryptoAmount.tsx | 2 +- .../CoinmarketLayout/CoinmarketLayout.tsx | 92 ------- .../CoinmarketOfferExchangeSendSwap.tsx | 8 +- .../wallet/coinmarket/common/NoOffers.tsx | 95 ------- .../views/wallet/coinmarket/common/index.ts | 2 - .../CoinmarketExchangeOfferInfo.tsx | 237 ------------------ 21 files changed, 17 insertions(+), 691 deletions(-) delete mode 100644 packages/suite/src/types/wallet/coinmarketExchangeForm.ts delete mode 100644 packages/suite/src/types/wallet/coinmarketSellForm.ts delete mode 100644 packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx delete mode 100644 packages/suite/src/views/wallet/coinmarket/common/NoOffers.tsx delete mode 100644 packages/suite/src/views/wallet/coinmarket/exchange_new/components/ExchangeForm/CoinmarketExchangeOfferInfo.tsx diff --git a/packages/suite/src/actions/wallet/__tests__/coinmarketBuyActions.test.ts b/packages/suite/src/actions/wallet/__tests__/coinmarketBuyActions.test.ts index 635ff884668..35f3437d172 100644 --- a/packages/suite/src/actions/wallet/__tests__/coinmarketBuyActions.test.ts +++ b/packages/suite/src/actions/wallet/__tests__/coinmarketBuyActions.test.ts @@ -6,7 +6,7 @@ import * as coinmarketBuyActions from '../coinmarketBuyActions'; import invityAPI from 'src/services/suite/invityAPI'; import { BuyTrade, BuyTradeQuoteRequest, CryptoId } from 'invity-api'; -export const getInitialState = () => ({ +const getInitialState = () => ({ wallet: { coinmarket: coinmarketReducer(undefined, { type: 'foo' } as any), }, diff --git a/packages/suite/src/actions/wallet/__tests__/coinmarketExchangeActions.test.ts b/packages/suite/src/actions/wallet/__tests__/coinmarketExchangeActions.test.ts index ee90499d172..914a0465c8d 100644 --- a/packages/suite/src/actions/wallet/__tests__/coinmarketExchangeActions.test.ts +++ b/packages/suite/src/actions/wallet/__tests__/coinmarketExchangeActions.test.ts @@ -6,7 +6,7 @@ import * as coinmarketExchangeActions from '../coinmarketExchangeActions'; import invityAPI from 'src/services/suite/invityAPI'; import { CryptoId, ExchangeTrade, ExchangeTradeQuoteRequest } from 'invity-api'; -export const getInitialState = () => ({ +const getInitialState = () => ({ wallet: { coinmarket: coinmarketReducer(undefined, { type: 'foo' } as any), }, diff --git a/packages/suite/src/actions/wallet/coinmarketExchangeActions.ts b/packages/suite/src/actions/wallet/coinmarketExchangeActions.ts index 6ad38d612af..a1106021b0b 100644 --- a/packages/suite/src/actions/wallet/coinmarketExchangeActions.ts +++ b/packages/suite/src/actions/wallet/coinmarketExchangeActions.ts @@ -35,7 +35,6 @@ export type CoinmarketExchangeAction = type: typeof COINMARKET_EXCHANGE.SAVE_QUOTE; quote: ExchangeTrade | undefined; } - | { type: typeof COINMARKET_EXCHANGE.CLEAR_QUOTES } | { type: typeof COINMARKET_EXCHANGE.SET_COINMARKET_ACCOUNT; account: Account | undefined } | { type: typeof COINMARKET_COMMON.SAVE_TRADE; @@ -141,10 +140,6 @@ export const saveSelectedQuote = (quote: ExchangeTrade | undefined): CoinmarketE quote, }); -export const clearQuotes = (): CoinmarketExchangeAction => ({ - type: COINMARKET_EXCHANGE.CLEAR_QUOTES, -}); - export const verifyAddress = (account: Account, address?: string, path?: string) => verifyExchangeAddress(account, address, path, COINMARKET_EXCHANGE.VERIFY_ADDRESS); diff --git a/packages/suite/src/actions/wallet/coinmarketSellActions.ts b/packages/suite/src/actions/wallet/coinmarketSellActions.ts index 60191a1d8ba..18d0d4924fb 100644 --- a/packages/suite/src/actions/wallet/coinmarketSellActions.ts +++ b/packages/suite/src/actions/wallet/coinmarketSellActions.ts @@ -32,7 +32,6 @@ export type CoinmarketSellAction = type: typeof COINMARKET_SELL.SAVE_QUOTE; quote: SellFiatTrade | undefined; } - | { type: typeof COINMARKET_SELL.CLEAR_QUOTES } | { type: typeof COINMARKET_COMMON.SAVE_TRADE; date: string; @@ -117,10 +116,6 @@ export const saveSelectedQuote = (quote: SellFiatTrade | undefined): CoinmarketS quote, }); -export const clearQuotes = (): CoinmarketSellAction => ({ - type: COINMARKET_SELL.CLEAR_QUOTES, -}); - export const setIsFromRedirect = (isFromRedirect: boolean): CoinmarketSellAction => ({ type: COINMARKET_SELL.SET_IS_FROM_REDIRECT, isFromRedirect, diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/CoinmarketTermsModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/CoinmarketTermsModal.tsx index 4c0dbf8d86e..14eafd644b8 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/CoinmarketTermsModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/CoinmarketTermsModal.tsx @@ -27,7 +27,7 @@ const FooterContent = styled.div` place-content: center space-between; `; -export type CoinmarketTermsModalProps = { +type CoinmarketTermsModalProps = { decision: Deferred; onCancel: () => void; type: 'BUY' | 'SELL' | 'COINMARKET_SWAP' | 'COINMARKET_SWAP_DEX'; @@ -36,6 +36,7 @@ export type CoinmarketTermsModalProps = { toCryptoCurrency?: CryptoId; fromCryptoCurrency?: CryptoId; }; + export const CoinmarketTermsModal = ({ decision, onCancel, diff --git a/packages/suite/src/hooks/wallet/useCoinmarketRedirect.ts b/packages/suite/src/hooks/wallet/useCoinmarketRedirect.ts index c620413a949..15985d575b4 100644 --- a/packages/suite/src/hooks/wallet/useCoinmarketRedirect.ts +++ b/packages/suite/src/hooks/wallet/useCoinmarketRedirect.ts @@ -7,7 +7,7 @@ import * as coinmarketSellActions from 'src/actions/wallet/coinmarketSellActions import { saveComposedTransactionInfo } from 'src/actions/wallet/coinmarket/coinmarketCommonActions'; import { FeeLevel } from '@trezor/connect'; -export interface OfferRedirectParams { +interface OfferRedirectParams { symbol: Account['symbol']; index: Account['index']; accountType: Account['accountType']; @@ -18,7 +18,7 @@ export interface OfferRedirectParams { country: string; } -export interface SellOfferRedirectParams { +interface SellOfferRedirectParams { symbol: Account['symbol']; index: Account['index']; accountType: Account['accountType']; @@ -33,7 +33,7 @@ export interface SellOfferRedirectParams { feeLimit?: string; } -export interface DetailRedirectParams { +interface DetailRedirectParams { symbol: Account['symbol']; index: Account['index']; accountType: Account['accountType']; diff --git a/packages/suite/src/reducers/wallet/__tests__/coinmarketReducer.test.ts b/packages/suite/src/reducers/wallet/__tests__/coinmarketReducer.test.ts index fc99a90d893..e1980956285 100644 --- a/packages/suite/src/reducers/wallet/__tests__/coinmarketReducer.test.ts +++ b/packages/suite/src/reducers/wallet/__tests__/coinmarketReducer.test.ts @@ -419,28 +419,6 @@ describe('settings reducer', () => { }); }); - it('COINMARKET_EXCHANGE.CLEAR_QUOTES', () => { - expect( - reducer(undefined, { - type: COINMARKET_EXCHANGE.CLEAR_QUOTES, - }), - ).toEqual({ - ...initialState, - exchange: { ...initialState.exchange, quotes: undefined }, - }); - }); - - it('COINMARKET_SELL.CLEAR_QUOTES', () => { - expect( - reducer(undefined, { - type: COINMARKET_SELL.CLEAR_QUOTES, - }), - ).toEqual({ - ...initialState, - sell: { ...initialState.sell, quotes: undefined }, - }); - }); - it('COINMARKET_BUY.SAVE_QUOTE', () => { expect( reducer(undefined, { diff --git a/packages/suite/src/reducers/wallet/coinmarketReducer.ts b/packages/suite/src/reducers/wallet/coinmarketReducer.ts index 9a5497a76c0..b50288a4ffc 100644 --- a/packages/suite/src/reducers/wallet/coinmarketReducer.ts +++ b/packages/suite/src/reducers/wallet/coinmarketReducer.ts @@ -212,9 +212,6 @@ const coinmarketReducer = ( case COINMARKET_EXCHANGE.SAVE_QUOTE: draft.exchange.selectedQuote = action.quote; break; - case COINMARKET_EXCHANGE.CLEAR_QUOTES: - draft.exchange.quotes = undefined; - break; case COINMARKET_EXCHANGE.VERIFY_ADDRESS: draft.exchange.addressVerified = action.addressVerified; break; @@ -239,9 +236,6 @@ const coinmarketReducer = ( case COINMARKET_SELL.SAVE_QUOTE: draft.sell.selectedQuote = action.quote; break; - case COINMARKET_SELL.CLEAR_QUOTES: - draft.sell.quotes = undefined; - break; case COINMARKET_SELL.SET_IS_FROM_REDIRECT: draft.sell.isFromRedirect = action.isFromRedirect; break; diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index cfc3f282eaa..e37d12ad49b 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -189,10 +189,6 @@ export default defineMessages({ defaultMessage: 'All', id: 'TR_FRACTION_BUTTONS_ALL', }, - TR_EXCHANGE_PROVIDER: { - defaultMessage: 'Provider', - id: 'TR_EXCHANGE_PROVIDER', - }, TR_EXCHANGE_FIXED_OFFERS_INFO: { id: 'TR_EXCHANGE_FIXED_OFFERS_INFO', defaultMessage: @@ -1307,32 +1303,6 @@ export default defineMessages({ defaultMessage: "Go to provider's site", id: 'TR_BUY_DETAIL_WAITING_FOR_USER_GATE', }, - TR_COINMARKET_NO_OFFERS_AUTORELOADING_IN: { - defaultMessage: 'Auto-reloading in', - id: 'TR_COINMARKET_NO_OFFERS_AUTORELOADING_IN', - }, - TR_COINMARKET_NO_OFFERS_HEADER: { - defaultMessage: 'No offers', - id: 'TR_COINMARKET_NO_OFFERS_HEADER', - }, - TR_COINMARKET_NO_OFFERS_MESSAGE: { - defaultMessage: - "Sorry, we don't have any offers at the moment. Try to reload the page or change your query.", - id: 'TR_COINMARKET_NO_OFFERS_MESSAGE', - }, - TR_COINMARKET_NO_OFFERS_LOADING_FAILED_MESSAGE: { - defaultMessage: - "Sorry, we don't have any offers at the moment due to a server connectivity issue.", - id: 'TR_COINMARKET_NO_OFFERS_LOADING_FAILED_MESSAGE', - }, - TR_COINMARKET_NO_OFFERS_BACK_BUTTON: { - defaultMessage: 'Back to Trade', - id: 'TR_COINMARKET_NO_OFFERS_BACK_BUTTON', - }, - TR_COINMARKET_NO_OFFERS_RELOAD_PAGE_BUTTON: { - defaultMessage: 'Reload page', - id: 'TR_COINMARKET_NO_OFFERS_RELOAD_PAGE_BUTTON', - }, TR_COINMARKET_OFFERS_EMPTY: { defaultMessage: 'No offers available for your request. Change country or buy amount.', id: 'TR_COINMARKET_OFFERS_EMPTY', diff --git a/packages/suite/src/types/coinmarket/coinmarket.ts b/packages/suite/src/types/coinmarket/coinmarket.ts index ab4ef4e3180..50571762a09 100644 --- a/packages/suite/src/types/coinmarket/coinmarket.ts +++ b/packages/suite/src/types/coinmarket/coinmarket.ts @@ -55,7 +55,7 @@ export interface UseCoinmarketCommonReturnProps { setCallInProgress: (state: boolean) => void; checkQuotesTimer: (callback: () => Promise) => void; } -export type CoinmarketPageType = 'form' | 'offers' | 'confirm'; +type CoinmarketPageType = 'form' | 'offers' | 'confirm'; export type UseCoinmarketFormProps = UseCoinmarketProps & { /** * Difference between form and offers is that on the offers page are used all data filled in the form diff --git a/packages/suite/src/types/coinmarket/coinmarketForm.ts b/packages/suite/src/types/coinmarket/coinmarketForm.ts index ba2538c2eae..9c66c413e87 100644 --- a/packages/suite/src/types/coinmarket/coinmarketForm.ts +++ b/packages/suite/src/types/coinmarket/coinmarketForm.ts @@ -144,7 +144,7 @@ interface CoinmarketFormStateProps { toggleAmountInCrypto: () => void; } -export interface CoinmarketCommonFormProps { +interface CoinmarketCommonFormProps { device: AppState['device']['selectedDevice']; callInProgress: boolean; timer: Timer; @@ -154,7 +154,7 @@ export interface CoinmarketCommonFormProps { goToOffers: () => Promise; } -export interface CoinmarketCommonFormBuySellProps { +interface CoinmarketCommonFormBuySellProps { defaultCountry: Option; defaultCurrency: Option; defaultPaymentMethod: CoinmarketPaymentMethodListProps; @@ -265,7 +265,7 @@ export interface CoinmarketExchangeFormContextProps verifyAddress: CoinmarketVerifyAccountProps; } -export type CoinmarketFormMapProps = { +type CoinmarketFormMapProps = { buy: CoinmarketBuyFormContextProps; sell: CoinmarketSellFormContextProps; exchange: CoinmarketExchangeFormContextProps; @@ -288,17 +288,7 @@ export interface CoinmarketFormInputLabelProps extends PropsWithChildren { label?: ExtendedMessageDescriptor['id']; } -export type CoinmarketFormInputCommonProps = {}; - -export interface CoinmarketFormInputDefaultProps - extends CoinmarketFormInputLabelProps, - CoinmarketFormInputCommonProps {} - -export type CoinmarketFormStateMapProps = { - buy: CoinmarketBuyFormProps; - sell: CoinmarketSellFormProps; - exchange: CoinmarketExchangeFormProps; -}; +export interface CoinmarketFormInputDefaultProps extends CoinmarketFormInputLabelProps {} export interface CoinmarketFormInputCryptoSelectProps extends CoinmarketFormInputDefaultProps { @@ -331,7 +321,7 @@ export interface CoinmarketFormInputAccountProps; } -export interface CoinmarketFormInputCurrencyProps extends CoinmarketFormInputCommonProps { +export interface CoinmarketFormInputCurrencyProps { isClean?: boolean; size?: 'small' | 'large'; isDarkLabel?: boolean; diff --git a/packages/suite/src/types/coinmarket/coinmarketOffers.ts b/packages/suite/src/types/coinmarket/coinmarketOffers.ts index db19c72f503..6d66a7a5220 100644 --- a/packages/suite/src/types/coinmarket/coinmarketOffers.ts +++ b/packages/suite/src/types/coinmarket/coinmarketOffers.ts @@ -1,10 +1,4 @@ -import { Account } from '@suite-common/wallet-types'; -import { AppState } from '../suite'; -import { ExchangeInfo } from 'src/actions/wallet/coinmarketExchangeActions'; -import { BankAccount, CryptoId, ExchangeTrade, SellFiatTrade } from 'invity-api'; -import { Timer } from '@trezor/react-utils'; -import { TradeSell } from '../wallet/coinmarketCommonTypes'; -import { SellInfo } from 'src/actions/wallet/coinmarketSellActions'; +import { CryptoId } from 'invity-api'; import { CoinmarketTradeType } from './coinmarket'; import { CoinmarketBuyFormContextProps, @@ -12,61 +6,17 @@ import { CoinmarketSellFormContextProps, } from './coinmarketForm'; -type CoinmarketOffersContextProps = { - type: CoinmarketTradeType; - device: AppState['device']['selectedDevice']; - account: Account; - callInProgress: boolean; - timer: Timer; - getQuotes: () => Promise; -}; - export type CoinmarketBuyAddressOptionsType = { address?: string; }; export type CoinmarketSellStepType = 'BANK_ACCOUNT' | 'SEND_TRANSACTION'; -export type CoinmarketSellOffersContextProps = CoinmarketOffersContextProps & { - quotes: AppState['wallet']['coinmarket']['sell']['quotes']; - quotesRequest: AppState['wallet']['coinmarket']['sell']['quotesRequest']; - selectedQuote?: SellFiatTrade; - trade?: TradeSell; - suiteReceiveAccounts?: AppState['wallet']['accounts']; - sellInfo?: SellInfo; - sellStep: CoinmarketSellStepType; - setSellStep: (step: CoinmarketSellStepType) => void; - addBankAccount: () => void; - confirmTrade: (bankAccount: BankAccount) => void; - sendTransaction: () => void; - needToRegisterOrVerifyBankAccount: (quote: SellFiatTrade) => boolean; - selectQuote: (quote: SellFiatTrade) => void; -}; - export type CoinmarketExchangeStepType = | 'RECEIVING_ADDRESS' | 'SEND_TRANSACTION' | 'SEND_APPROVAL_TRANSACTION'; -export type CoinmarketExchangeOffersContextProps = CoinmarketOffersContextProps & { - quotes: AppState['wallet']['coinmarket']['exchange']['quotes']; - quotesRequest: AppState['wallet']['coinmarket']['exchange']['quotesRequest']; - selectedQuote?: ExchangeTrade; - setSelectedQuote: (quote: ExchangeTrade | undefined) => void; - suiteReceiveAccounts?: AppState['wallet']['accounts']; - addressVerified: AppState['wallet']['coinmarket']['exchange']['addressVerified']; - exchangeInfo?: ExchangeInfo; - exchangeStep: CoinmarketExchangeStepType; - setExchangeStep: (step: CoinmarketExchangeStepType) => void; - verifyAddress: (account: Account, address?: string, path?: string) => Promise; - receiveSymbol?: string; - receiveAccount?: Account; - setReceiveAccount: (account?: Account) => void; - confirmTrade: (address: string, extraField?: string) => Promise; - sendTransaction: () => void; - selectQuote: (quote: ExchangeTrade) => void; -}; - // TODO: delete export type CoinmarketOffersMapProps = { buy: CoinmarketBuyFormContextProps; // temporary diff --git a/packages/suite/src/types/wallet/coinmarketCommonTypes.ts b/packages/suite/src/types/wallet/coinmarketCommonTypes.ts index db8889d2ac4..f54fe0b9a8d 100644 --- a/packages/suite/src/types/wallet/coinmarketCommonTypes.ts +++ b/packages/suite/src/types/wallet/coinmarketCommonTypes.ts @@ -1,4 +1,3 @@ -import type { ReactElement } from 'react'; import type { Account } from 'src/types/wallet'; import type { BuyTrade, SellFiatTrade, ExchangeTrade, FiatCurrencyCode } from 'invity-api'; import type { FlagProps } from '@trezor/components'; @@ -22,14 +21,11 @@ export type Trade = TradeBuy | TradeSell | TradeExchange; export type Option = { value: string; label: string }; export type CountryOption = { value: FlagProps['country']; label: string }; export type DefaultCountryOption = { value: string; label: string }; -export type TranslationOption = { value: string; label?: ReactElement }; export type FiatCurrencyOption = { value: FiatCurrencyCode; label: string; }; -export type PaymentFrequencyOption = Option & { label: JSX.Element }; - export interface CryptoAmountLimits { currency: string; minCrypto?: number; diff --git a/packages/suite/src/types/wallet/coinmarketExchangeForm.ts b/packages/suite/src/types/wallet/coinmarketExchangeForm.ts deleted file mode 100644 index 9dc544c2539..00000000000 --- a/packages/suite/src/types/wallet/coinmarketExchangeForm.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { AppState } from 'src/types/suite'; -import type { FormState as ReactHookFormState, UseFormReturn } from 'react-hook-form'; -import type { Account } from 'src/types/wallet'; -import { Network } from '@suite-common/wallet-config'; -import type { FeeLevel } from '@trezor/connect'; -import type { ExchangeInfo } from 'src/actions/wallet/coinmarketExchangeActions'; -import type { - FeeInfo, - FormState, - PrecomposedLevels, - PrecomposedLevelsCardano, -} from '@suite-common/wallet-types'; -import type { AmountLimits, CryptoAmountLimits, Option } from './coinmarketCommonTypes'; -import { Rate } from '@suite-common/wallet-types'; -import { SendContextValues } from 'src/types/wallet/sendForm'; - -export const CRYPTO_INPUT = 'outputs.0.amount'; -export const CRYPTO_TOKEN = 'outputs.0.token'; -export const FIAT_INPUT = 'outputs.0.fiat'; -export const FIAT_CURRENCY = 'outputs.0.currency'; - -export type ExchangeFormState = FormState & { - // NOTE: react-select value type cannot be undefined, but at least null works - receiveCryptoSelect: Option | null; - sendCryptoSelect: Option; -}; - -export interface ExchangeFormContextValues extends UseFormReturn { - onSubmit: () => void; - account: Account; - isComposing: boolean; - changeFeeLevel: (level: FeeLevel['label']) => void; - exchangeInfo?: ExchangeInfo; - defaultCurrency: Option; - composeRequest: SendContextValues['composeTransaction']; - updateFiatCurrency: (selectedCurrency: { value: string; label: string }, rate: number) => void; - updateSendCryptoValue: (fiatValue: string, decimals: number) => void; - amountLimits?: AmountLimits; - composedLevels?: PrecomposedLevels | PrecomposedLevelsCardano; - fiatRate?: Rate; - setAmountLimits: (limits?: CryptoAmountLimits) => void; - quotesRequest: AppState['wallet']['coinmarket']['exchange']['quotesRequest']; - isLoading: boolean; - updateFiatValue: (amount: string) => void; - noProviders: boolean; - network: Network; - feeInfo: FeeInfo; - removeDraft: (key: string) => void; - formState: ReactHookFormState; - handleClearFormButtonClick: () => void; - isDraft: boolean; -} diff --git a/packages/suite/src/types/wallet/coinmarketSellForm.ts b/packages/suite/src/types/wallet/coinmarketSellForm.ts deleted file mode 100644 index b3fb2e2cf93..00000000000 --- a/packages/suite/src/types/wallet/coinmarketSellForm.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { AppState } from 'src/types/suite'; -import type { FormState as ReactHookFormState, UseFormReturn } from 'react-hook-form'; -import type { Account } from 'src/types/wallet'; -import { Network } from '@suite-common/wallet-config'; -import type { FeeLevel } from '@trezor/connect'; -import type { SellInfo } from 'src/actions/wallet/coinmarketSellActions'; -import type { - FeeInfo, - FormState, - PrecomposedLevels, - PrecomposedLevelsCardano, -} from '@suite-common/wallet-types'; -import { Rate } from '@suite-common/wallet-types'; -import { SendContextValues } from 'src/types/wallet/sendForm'; -import type { - Option, - DefaultCountryOption, - AmountLimits, -} from 'src/types/wallet/coinmarketCommonTypes'; -import { CoinmarketCryptoListProps } from 'src/types/coinmarket/coinmarket'; - -export const OUTPUT_AMOUNT = 'outputs.0.amount'; -export const CRYPTO_TOKEN = 'outputs.0.token'; -export const FIAT_INPUT = 'fiatInput'; -export const FIAT_CURRENCY_SELECT = 'fiatCurrencySelect'; -export const CRYPTO_INPUT = 'cryptoInput'; -export const CRYPTO_CURRENCY_SELECT = 'cryptoCurrencySelect'; - -export interface SellFormState extends FormState { - fiatInput?: string; - fiatCurrencySelect: Option; - cryptoInput?: string; - cryptoCurrencySelect: CoinmarketCryptoListProps; - countrySelect: Option; -} - -export type SellFormContextValues = UseFormReturn & { - onSubmit: () => void; - account: Account; - defaultCountry: DefaultCountryOption; - defaultCurrency: Option; - isComposing: boolean; - changeFeeLevel: (level: FeeLevel['label']) => void; - sellInfo?: SellInfo; - localCurrencyOption: { label: string; value: string }; - composeRequest: SendContextValues['composeTransaction']; - amountLimits?: AmountLimits; - composedLevels?: PrecomposedLevels | PrecomposedLevelsCardano; - fiatRate?: Rate; - setAmountLimits: (limits?: AmountLimits) => void; - quotesRequest: AppState['wallet']['coinmarket']['sell']['quotesRequest']; - isLoading: boolean; - noProviders: boolean; - network: Network; - feeInfo: FeeInfo; - onCryptoAmountChange: (amount: string) => void; - onFiatAmountChange: (amount: string) => void; - handleClearFormButtonClick: () => void; - formState: ReactHookFormState; - isDraft: boolean; -}; diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormOfferCryptoAmount.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormOfferCryptoAmount.tsx index 62d4926ef79..6e1def388d7 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormOfferCryptoAmount.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormOfferCryptoAmount.tsx @@ -4,7 +4,7 @@ import { useCoinmarketInfo } from 'src/hooks/wallet/coinmarket/useCoinmarketInfo import { CoinmarketCoinLogo } from 'src/views/wallet/coinmarket/common/CoinmarketCoinLogo'; import { CryptoId } from 'invity-api'; -export interface CoinmarketCryptoAmountProps { +interface CoinmarketCryptoAmountProps { amount: string | number; cryptoId: CryptoId; } diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx deleted file mode 100644 index 34066fe522d..00000000000 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { ReactNode } from 'react'; -import styled from 'styled-components'; - -import { WalletLayout, WalletSubpageHeading } from 'src/components/wallet'; -import { Card, Button, variables } from '@trezor/components'; -import { Translation } from 'src/components/suite'; -import type { SelectedAccountLoaded } from '@suite-common/wallet-types'; -import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common'; -import CoinmarketLayoutNavigation from 'src/views/wallet/coinmarket/common/CoinmarketLayoutNew/CoinmarketLayoutNavigation/CoinmarketLayoutNavigation'; -import { spacingsPx } from '@trezor/theme'; -import { SCREEN_QUERY } from '@trezor/components/src/config/variables'; - -const Content = styled.div` - padding: 29px 41px; - - @media (max-width: ${variables.SCREEN_SIZE.SM}) { - padding: 29px 20px; - } -`; - -const CoinmarketWrapper = styled.div` - padding: 0 ${spacingsPx.lg}; - - ${SCREEN_QUERY.BELOW_DESKTOP} { - padding: 0; - } -`; - -const CardWrapper = styled.div` - flex: 1; - align-self: flex-start; -`; - -const BottomContent = styled.div` - flex: 1; - display: flex; - flex-direction: column; - padding-top: ${spacingsPx.xxxl}; -`; - -const Layout = styled.div` - display: flex; - flex-direction: row; - margin-top: ${spacingsPx.xl}; - - ${variables.SCREEN_QUERY.BELOW_LAPTOP} { - flex-direction: column; - } -`; - -interface CoinmarketLayoutProps { - children: ReactNode; - selectedAccount: SelectedAccountLoaded; - onClearFormButtonClick?: () => void; -} - -export const CoinmarketLayout = ({ - children, - selectedAccount, - onClearFormButtonClick, -}: CoinmarketLayoutProps) => ( - - - - {onClearFormButtonClick && ( - - )} - - - - - - - - {children} - - - - - - - - - -); diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketOfferExchange/CoinmarketOfferExchangeSendSwap.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketOfferExchange/CoinmarketOfferExchangeSendSwap.tsx index 02d89a3b11f..af68c28ebe7 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketOfferExchange/CoinmarketOfferExchangeSendSwap.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketSelectedOffer/CoinmarketOfferExchange/CoinmarketOfferExchangeSendSwap.tsx @@ -139,11 +139,7 @@ const slippageOptions = [ }, ]; -export function formatCryptoAmountAsAmount( - amount: number, - baseAmount: number, - decimals = 8, -): string { +const formatCryptoAmountAsAmount = (amount: number, baseAmount: number, decimals = 8): string => { let digits = 4; if (baseAmount < 1) { digits = 6; @@ -153,7 +149,7 @@ export function formatCryptoAmountAsAmount( } return amount.toFixed(digits); -} +}; export const CoinmarketOfferExchangeSendSwap = () => { const theme = useTheme(); diff --git a/packages/suite/src/views/wallet/coinmarket/common/NoOffers.tsx b/packages/suite/src/views/wallet/coinmarket/common/NoOffers.tsx deleted file mode 100644 index b08a3ea236b..00000000000 --- a/packages/suite/src/views/wallet/coinmarket/common/NoOffers.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import styled from 'styled-components'; - -import { Translation } from 'src/components/suite'; -import { Button, Image } from '@trezor/components'; -import { InvityAPIReloadQuotesAfterSeconds } from 'src/constants/wallet/coinmarket/metadata'; -import { CoinmarketRefreshTime } from './CoinmarketRefreshTime'; - -const NoOffersWrapper = styled.div` - display: flex; - justify-content: center; - flex-direction: column; - min-height: 300px; - align-items: center; - flex: 1; -`; - -const NoOffersImage = styled.div` - padding-bottom: 40px; -`; - -const NoOffersHeader = styled.h3` - padding-bottom: 20px; -`; -const NoOffersMessage = styled.span``; - -const CoinmarketRefreshTimeWrapper = styled.div` - margin-top: 20px; -`; - -const ButtonsWrapper = styled.div` - margin-top: 20px; - display: flex; - justify-content: space-between; - - & > * + * { - margin-left: 12px; - } -`; - -interface NoOffersProps { - coinmarketRefreshTimeIsLoading: boolean; - coinmarketRefreshTimeSeconds: number; - onBackButtonClick: () => void; - onReloadOffersButtonClick: () => void; - hasLoadingFailed: boolean; -} - -export const NoOffers = ({ - coinmarketRefreshTimeIsLoading, - coinmarketRefreshTimeSeconds, - onBackButtonClick, - onReloadOffersButtonClick, - hasLoadingFailed, -}: NoOffersProps) => ( - - - - - - - - - - - {hasLoadingFailed && ( - - } - /> - - )} - - - {hasLoadingFailed && ( - - )} - - -); diff --git a/packages/suite/src/views/wallet/coinmarket/common/index.ts b/packages/suite/src/views/wallet/coinmarket/common/index.ts index f0dc42be300..b36d1f7e1a4 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/index.ts +++ b/packages/suite/src/views/wallet/coinmarket/common/index.ts @@ -3,10 +3,8 @@ export { CoinmarketCryptoAmount } from './CoinmarketCryptoAmount'; export { CoinmarketFiatAmount } from './CoinmarketFiatAmount'; export { CoinmarketFooter } from './CoinmarketFooter/CoinmarketFooter'; export { CoinmarketFractionButtons } from './CoinmarketFractionButtons'; -export { CoinmarketLayout } from './CoinmarketLayout/CoinmarketLayout'; export { CoinmarketPaymentType } from './CoinmarketPaymentType'; export { CoinmarketProviderInfo } from './CoinmarketProviderInfo'; export { CoinmarketRefreshTime } from './CoinmarketRefreshTime'; export { CoinmarketTag } from './CoinmarketTag'; export { CoinmarketTransactionId } from './CoinmarketTransactionId'; -export { NoOffers } from './NoOffers'; diff --git a/packages/suite/src/views/wallet/coinmarket/exchange_new/components/ExchangeForm/CoinmarketExchangeOfferInfo.tsx b/packages/suite/src/views/wallet/coinmarket/exchange_new/components/ExchangeForm/CoinmarketExchangeOfferInfo.tsx deleted file mode 100644 index 8c149c2a492..00000000000 --- a/packages/suite/src/views/wallet/coinmarket/exchange_new/components/ExchangeForm/CoinmarketExchangeOfferInfo.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import styled from 'styled-components'; -import { ExchangeTrade } from 'invity-api'; -import { variables } from '@trezor/components'; -import { - CoinmarketProviderInfo, - CoinmarketTransactionId, -} from 'src/views/wallet/coinmarket/common'; -import { Account } from 'src/types/wallet'; -import { - AccountLabeling, - FormattedCryptoAmount, - QuestionTooltip, - Translation, -} from 'src/components/suite'; -import { ExchangeInfo } from 'src/actions/wallet/coinmarketExchangeActions'; -import { typography } from '@trezor/theme'; -import { CoinmarketCoinLogo } from 'src/views/wallet/coinmarket/common/CoinmarketCoinLogo'; -import { useCoinmarketInfo } from 'src/hooks/wallet/coinmarket/useCoinmarketInfo'; - -const Wrapper = styled.div` - margin: 0 0 0 30px; - - @media screen and (max-width: ${variables.SCREEN_SIZE.LG}) { - margin: 0; - } -`; - -const AccountText = styled.div` - color: ${({ theme }) => theme.textSubdued}; - padding-left: 7px; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; -`; - -const Info = styled.div` - display: flex; - flex-direction: column; - min-width: 350px; - - padding-top: 10px; - min-height: 200px; - border: 1px solid ${({ theme }) => theme.legacy.STROKE_GREY}; - border-radius: 4px; - - @media screen and (max-width: ${variables.SCREEN_SIZE.LG}) { - flex: 1; - margin: 20px 0 10px; - width: 100%; - } -`; - -const LeftColumn = styled.div` - display: flex; - flex: 1; - ${typography.label} - text-transform: capitalize; - color: ${({ theme }) => theme.textSubdued}; -`; - -const RightColumn = styled.div` - display: flex; - justify-content: flex-end; - flex: 1; - font-size: ${variables.FONT_SIZE.TINY}; - color: ${({ theme }) => theme.textSubdued}; -`; - -const Row = styled.div` - display: flex; - margin: 18px 24px; - white-space: nowrap; - justify-content: space-between; -`; - -const AdjacentRow = styled.div` - display: flex; - margin: -15px 24px 10px; -`; - -const Dark = styled.div` - display: flex; - align-items: center; - font-size: ${variables.FONT_SIZE.NORMAL}; - justify-content: flex-end; - flex: 1; - font-weight: ${variables.FONT_WEIGHT.DEMI_BOLD}; - color: ${({ theme }) => theme.legacy.TYPE_DARK_GREY}; -`; - -const RowWithBorder = styled(Row)` - border-top: 1px solid ${({ theme }) => theme.legacy.STROKE_GREY}; - border-bottom: 1px solid ${({ theme }) => theme.legacy.STROKE_GREY}; - margin-bottom: 0; - margin-top: 10px; - padding-bottom: 10px; - padding-top: 10px; -`; - -const Middle = styled.div` - display: flex; - justify-content: center; - align-items: center; - flex: 1; - color: ${({ theme }) => theme.textSubdued}; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; -`; - -const Amount = styled.span` - padding-left: 5px; -`; - -const StyledQuestionTooltip = styled(QuestionTooltip)` - padding-left: 3px; -`; - -const AccountType = styled.span` - color: ${({ theme }) => theme.textSubdued}; - padding-left: 5px; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; -`; - -interface CoinmarketExchangeOfferInfoProps { - selectedQuote: ExchangeTrade; - transactionId?: string; - exchangeInfo?: ExchangeInfo; - account: Account; - receiveAccount?: Account; -} - -export const CoinmarketExchangeOfferInfo = ({ - selectedQuote, - transactionId, - exchangeInfo, - account, - receiveAccount, -}: CoinmarketExchangeOfferInfoProps) => { - const { exchange, receiveStringAmount, receive, sendStringAmount, send } = selectedQuote; - const provider = - exchangeInfo?.providerInfos && exchange ? exchangeInfo?.providerInfos[exchange] : undefined; - - const { cryptoIdToCoinSymbol } = useCoinmarketInfo(); - - if (!provider) return null; - - return ( - - - - - - - - - - - - - - - - - - - - - {account.accountType !== 'normal' ? account.accountType : ''} - - - - - - - - - - - - - {(!provider.isFixedRate || selectedQuote.isDex) && '≈ '} - - - - - - {receiveAccount && ( - - - - - - {receiveAccount.accountType !== 'normal' - ? receiveAccount.accountType - : ''} - - - - - )} - - - {provider.isFixedRate && !selectedQuote.isDex && ( - <> - - - - )} - {!provider.isFixedRate && !selectedQuote.isDex && ( - <> - - - - )} - {selectedQuote.isDex && } - - - - - - - - - - - - {transactionId && } - - ); -}; From 54e7cf9e1d4a03aabad01c6a65937b3e38eb292e Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Thu, 3 Oct 2024 15:27:08 +0200 Subject: [PATCH 033/624] chore(coinmarket): rename constants to upper snake case --- packages/suite/src/constants/wallet/coinmarket/metadata.ts | 4 ++-- .../wallet/coinmarket/offers/useCoinmarketCommonOffers.ts | 4 ++-- packages/suite/src/middlewares/wallet/coinmarketMiddleware.ts | 4 ++-- .../coinmarket/common/CoinmarketHeader/CoinmarketHeader.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/suite/src/constants/wallet/coinmarket/metadata.ts b/packages/suite/src/constants/wallet/coinmarket/metadata.ts index fa5e4ee3142..937f4f70aae 100644 --- a/packages/suite/src/constants/wallet/coinmarket/metadata.ts +++ b/packages/suite/src/constants/wallet/coinmarket/metadata.ts @@ -1,2 +1,2 @@ -export const InvityAPIReloadDataAfterMs = 10 * 60 * 1000; // 10 minutes -export const InvityAPIReloadQuotesAfterSeconds = 30; +export const INVITY_API_RELOAD_DATA_AFTER_MS = 10 * 60 * 1000; // 10 minutes +export const INVITY_API_RELOAD_QUOTES_AFTER_SECONDS = 30; diff --git a/packages/suite/src/hooks/wallet/coinmarket/offers/useCoinmarketCommonOffers.ts b/packages/suite/src/hooks/wallet/coinmarket/offers/useCoinmarketCommonOffers.ts index be214d1f0f9..a9f1c9a32d3 100644 --- a/packages/suite/src/hooks/wallet/coinmarket/offers/useCoinmarketCommonOffers.ts +++ b/packages/suite/src/hooks/wallet/coinmarket/offers/useCoinmarketCommonOffers.ts @@ -1,6 +1,6 @@ import { useTimer } from '@trezor/react-utils'; import { useDevice } from 'src/hooks/suite'; -import { InvityAPIReloadQuotesAfterSeconds } from 'src/constants/wallet/coinmarket/metadata'; +import { INVITY_API_RELOAD_QUOTES_AFTER_SECONDS } from 'src/constants/wallet/coinmarket/metadata'; import { createContext, useContext, useState } from 'react'; import { CoinmarketTradeBuyType, @@ -53,7 +53,7 @@ export const useCoinmarketCommonOffers = ({ timer.stop(); } - if (timer.timeSpend.seconds === InvityAPIReloadQuotesAfterSeconds) { + if (timer.timeSpend.seconds === INVITY_API_RELOAD_QUOTES_AFTER_SECONDS) { callback(); } } diff --git a/packages/suite/src/middlewares/wallet/coinmarketMiddleware.ts b/packages/suite/src/middlewares/wallet/coinmarketMiddleware.ts index 680ae08516f..2212e452ed5 100644 --- a/packages/suite/src/middlewares/wallet/coinmarketMiddleware.ts +++ b/packages/suite/src/middlewares/wallet/coinmarketMiddleware.ts @@ -1,7 +1,7 @@ import { MiddlewareAPI } from 'redux'; import { AppState, Action, Dispatch } from 'src/types/suite'; import { COINMARKET_COMMON } from 'src/actions/wallet/constants'; -import { InvityAPIReloadDataAfterMs } from 'src/constants/wallet/coinmarket/metadata'; +import { INVITY_API_RELOAD_DATA_AFTER_MS } from 'src/constants/wallet/coinmarket/metadata'; import invityAPI from 'src/services/suite/invityAPI'; import * as coinmarketCommonActions from 'src/actions/wallet/coinmarket/coinmarketCommonActions'; import * as coinmarketInfoAction from 'src/actions/wallet/coinmarketInfoActions'; @@ -34,7 +34,7 @@ const coinmarketMiddleware = account && !isLoading && (isDifferentAccount || - lastLoadedTimestamp + InvityAPIReloadDataAfterMs < Date.now()) + lastLoadedTimestamp + INVITY_API_RELOAD_DATA_AFTER_MS < Date.now()) ) { api.dispatch(coinmarketCommonActions.setLoading(true)); diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketHeader/CoinmarketHeader.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketHeader/CoinmarketHeader.tsx index d68fe03d926..7f09d3e30fb 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketHeader/CoinmarketHeader.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketHeader/CoinmarketHeader.tsx @@ -1,7 +1,7 @@ import { H2 } from '@trezor/components'; import { Translation } from 'src/components/suite'; import { ExtendedMessageDescriptor } from 'src/types/suite'; -import { InvityAPIReloadQuotesAfterSeconds } from 'src/constants/wallet/coinmarket/metadata'; +import { INVITY_API_RELOAD_QUOTES_AFTER_SECONDS } from 'src/constants/wallet/coinmarket/metadata'; import styled from 'styled-components'; import { spacingsPx } from '@trezor/theme'; import { SCREEN_QUERY } from '@trezor/components/src/config/variables'; @@ -77,7 +77,7 @@ const CoinmarketHeader = ({ title, titleTimer }: CoinmarketHeaderProps) => { } /> From beece0507ae60a851f0e97bf8bcd73efbead7fc5 Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Fri, 4 Oct 2024 10:56:00 +0200 Subject: [PATCH 034/624] chore(coinmarket): delete unused styles and eliminate overriding components --- .../detail/components/PaymentFailed/index.tsx | 27 +++--- .../components/PaymentProcessing/index.tsx | 18 ++-- .../components/WaitingForUser/index.tsx | 15 +-- .../CoinmarketFooter/CoinmarketFooter.tsx | 18 ++-- .../CoinmarketProvidedByInvity.tsx | 17 ++-- .../CoinmarketFormInputCountry.tsx | 1 + .../CoinmarketFormInputCurrency.tsx | 49 +++++----- .../CoinmarketFormSwitcherCryptoFiat.tsx | 6 +- .../CoinmarketForm/CoinmarketFormOffer.tsx | 1 + .../common/CoinmarketFractionButtons.tsx | 55 ++++++----- .../CoinmarketHeaderFilter.tsx | 2 +- .../CoinmarketAccountTransactions.tsx | 13 +-- .../CoinmarketLayoutNavigationItem.tsx | 10 +- .../CoinmarketOffersEmpty.tsx | 7 +- .../common/CoinmarketRefreshTime.tsx | 7 +- .../CoinmarketOfferExchangeSendSwap.tsx | 67 +++++++------ .../CoinmarketOfferSellBankAccount.tsx | 56 +++++------ .../CoinmarketOfferSellTransaction.tsx | 10 +- .../coinmarket/common/ConfirmedOnTrezor.tsx | 1 + .../components/PaymentConverting/index.tsx | 18 ++-- .../detail/components/PaymentFailed/index.tsx | 20 ++-- .../detail/components/PaymentKYC/index.tsx | 20 ++-- .../components/PaymentSending/index.tsx | 18 ++-- .../src/views/wallet/coinmarket/index.tsx | 95 ++---------------- .../detail/components/PaymentFailed/index.tsx | 20 ++-- .../components/PaymentPending/index.tsx | 18 ++-- .../wallet/coinmarket/skeleton/index.tsx | 96 ------------------- 27 files changed, 249 insertions(+), 436 deletions(-) delete mode 100644 packages/suite/src/views/wallet/coinmarket/skeleton/index.tsx diff --git a/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentFailed/index.tsx b/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentFailed/index.tsx index 98edf3e5403..a1256ce1b27 100644 --- a/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentFailed/index.tsx +++ b/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentFailed/index.tsx @@ -4,6 +4,7 @@ import { useDispatch } from 'src/hooks/suite'; import { Account } from 'src/types/wallet'; import { Translation } from 'src/components/suite/Translation'; import { goto } from 'src/actions/suite/routerActions'; +import { spacings, spacingsPx } from '@trezor/theme'; const Wrapper = styled.div` display: flex; @@ -29,14 +30,8 @@ const Description = styled.div` text-align: center; `; -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledLink = styled(Link)` - margin-bottom: 30px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledButton = styled(Button)` - margin-top: 30px; +const LinkWrapper = styled.div` + margin-top: ${spacingsPx.xxl}; `; interface PaymentFailedProps { @@ -68,15 +63,17 @@ const PaymentFailed = ({ supportUrl, account }: PaymentFailedProps) => { {supportUrl && ( - - - + + + + + )} - + ); }; diff --git a/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentProcessing/index.tsx b/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentProcessing/index.tsx index ad138816c80..a79b35b6b2b 100644 --- a/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentProcessing/index.tsx +++ b/packages/suite/src/views/wallet/coinmarket/buy/detail/components/PaymentProcessing/index.tsx @@ -1,6 +1,7 @@ import styled from 'styled-components'; import { variables, Spinner, Button, Link } from '@trezor/components'; import { Translation } from 'src/components/suite/Translation'; +import { spacingsPx } from '@trezor/theme'; const Wrapper = styled.div` display: flex; @@ -15,9 +16,8 @@ const Title = styled.div` font-weight: ${variables.FONT_WEIGHT.DEMI_BOLD}; `; -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledLink = styled(Link)` - margin-top: 50px; +const LinkWrapper = styled.div` + margin-top: ${spacingsPx.xxxxl}; `; interface PaymentProcessingProps { @@ -31,11 +31,13 @@ const PaymentProcessing = ({ supportUrl }: PaymentProcessingProps) => ( {supportUrl && ( - - - + + + + + )} ); diff --git a/packages/suite/src/views/wallet/coinmarket/buy/detail/components/WaitingForUser/index.tsx b/packages/suite/src/views/wallet/coinmarket/buy/detail/components/WaitingForUser/index.tsx index 0f76b207d0d..14d81858555 100644 --- a/packages/suite/src/views/wallet/coinmarket/buy/detail/components/WaitingForUser/index.tsx +++ b/packages/suite/src/views/wallet/coinmarket/buy/detail/components/WaitingForUser/index.tsx @@ -8,6 +8,7 @@ import invityAPI from 'src/services/suite/invityAPI'; import { createTxLink } from 'src/utils/wallet/coinmarket/buyUtils'; import { submitRequestForm } from 'src/actions/wallet/coinmarket/coinmarketCommonActions'; import { useDispatch } from 'src/hooks/suite'; +import { spacings } from '@trezor/theme'; const Wrapper = styled.div` display: flex; @@ -32,11 +33,6 @@ const Description = styled.div` text-align: center; `; -// eslint-disable-next-line local-rules/no-override-ds-component -const PaymentButton = styled(Button)` - margin-top: 30px; -`; - const getTranslations = (tradeStatus: BuyTradeStatus | undefined) => { if (tradeStatus === 'WAITING_FOR_USER') { return { @@ -83,9 +79,14 @@ const WaitingForUser = ({ trade, account, providerName }: WaitingForUserProps) = - + {/* TODO add a possibility in the future to cancel the transaction by the user */} ); diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx index 4a6da743aa9..929ddbd9ecd 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx @@ -6,6 +6,7 @@ import { DATA_TOS_INVITY_URL, INVITY_URL } from '@trezor/urls'; import { CoinmarketProvidedByInvity } from './CoinmarketProvidedByInvity'; import { Translation } from 'src/components/suite'; import { borders, spacingsPx, zIndices } from '@trezor/theme'; +import { CoinmarketFooterLogoWrapper } from 'src/views/wallet/coinmarket'; const Wrapper = styled.div` display: flex; @@ -61,14 +62,6 @@ const BoxRight = styled.div` align-items: center; `; -// eslint-disable-next-line local-rules/no-override-ds-component -const InvityLink = styled(Link)` - display: flex; - flex: 1; - padding-top: 1px; - align-items: center; -`; - const IconWrapper = styled.div` cursor: pointer; margin-left: 10px; @@ -91,6 +84,7 @@ const linkStyle = css` } `; +// reason: different design then basic Link // eslint-disable-next-line local-rules/no-override-ds-component const StyledLink = styled(Link)` ${linkStyle} @@ -131,9 +125,11 @@ export const CoinmarketFooter = () => {
- - - + + + + + invity.io diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketProvidedByInvity.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketProvidedByInvity.tsx index 604797eb712..4f932fca524 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketProvidedByInvity.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketProvidedByInvity.tsx @@ -2,6 +2,7 @@ import styled from 'styled-components'; import { Translation } from 'src/components/suite'; import { INVITY_URL } from '@trezor/urls'; import { variables, Link, Image } from '@trezor/components'; +import { CoinmarketFooterLogoWrapper } from 'src/views/wallet/coinmarket'; const Wrapper = styled.div` display: flex; @@ -10,19 +11,13 @@ const Wrapper = styled.div` color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; `; -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledLink = styled(Link)` - display: flex; - flex: 1; - padding-top: 1px; - align-items: center; -`; - export const CoinmarketProvidedByInvity = () => ( - - - + + + + + ); diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCountry.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCountry.tsx index 27be839f890..63a2856abda 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCountry.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCountry.tsx @@ -24,6 +24,7 @@ const FlagContainer = styled.div` margin-right: ${spacingsPx.xs}; `; +// reason: set cover size of flag for circle shape // eslint-disable-next-line local-rules/no-override-ds-component const FlagWrapper = styled(Flag)` position: absolute; diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCurrency.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCurrency.tsx index 1fc44687182..1ca87e1de2b 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCurrency.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketForm/CoinmarketFormInput/CoinmarketFormInputCurrency.tsx @@ -26,8 +26,7 @@ import { buildFiatOption } from 'src/utils/wallet/coinmarket/coinmarketUtils'; import { CoinmarketFormOption, CoinmarketFormOptionLabel } from 'src/views/wallet/coinmarket'; import styled from 'styled-components'; -// eslint-disable-next-line local-rules/no-override-ds-component -const SelectWrapper = styled(Select)` +const SelectWrapper = styled.div` /* stylelint-disable selector-class-pattern */ .react-select__value-container { padding: 0; @@ -74,29 +73,31 @@ const CoinmarketFormInputCurrency = ({ defaultValue={defaultCurrency} control={control as Control} render={({ field: { onChange, value } }) => ( - { - onChange(selected); - setAmountLimits(undefined); + + + + )} @@ -333,7 +338,7 @@ export const CoinmarketOfferExchangeSendSwap = () => { ) : null} )} - + @@ -377,15 +382,15 @@ export const CoinmarketOfferExchangeSendSwap = () => { - - + + {dexTx.data} - + + + + - {formatter.format(networkSymbol)} - - } - /> + + + {formatter.format(networkSymbol)} + + } + /> + ); }; diff --git a/suite-native/module-send/src/components/FiatAmountInput.tsx b/suite-native/module-send/src/components/FiatAmountInput.tsx index b84cea01924..649a58f9b8e 100644 --- a/suite-native/module-send/src/components/FiatAmountInput.tsx +++ b/suite-native/module-send/src/components/FiatAmountInput.tsx @@ -1,3 +1,4 @@ +import { Pressable } from 'react-native'; import Animated, { useAnimatedStyle } from 'react-native-reanimated'; import { useSelector } from 'react-redux'; @@ -19,6 +20,7 @@ export const FiatAmountInput = ({ translateValue, inputRef, networkSymbol, + onPress, onFocus, isDisabled = false, }: SendAmountInputProps) => { @@ -61,24 +63,27 @@ export const FiatAmountInput = ({ - - {fiatCurrencyCode.toUpperCase()} - - } - /> + + + {fiatCurrencyCode.toUpperCase()} + + } + /> + ); }; diff --git a/suite-native/module-send/src/components/SwitchAmountsButton.tsx b/suite-native/module-send/src/components/SwitchAmountsButton.tsx index f29ae2ae6b3..48212e2073d 100644 --- a/suite-native/module-send/src/components/SwitchAmountsButton.tsx +++ b/suite-native/module-send/src/components/SwitchAmountsButton.tsx @@ -6,14 +6,11 @@ import { Box } from '@suite-native/atoms'; type SwitchAmountsButtonProps = { onPress: () => void }; -const BUTTON_TOP_OFFSET = 40; +const BUTTON_TOP_OFFSET = 42; const BUTTON_PADDING = 6; const buttonWrapperStyle = prepareNativeStyle(() => ({ - position: 'absolute', - alignItems: 'center', - justifyContent: 'center', - width: '100%', + alignSelf: 'center', top: BUTTON_TOP_OFFSET, zIndex: 3, // To stay above both of the absolute inputs. })); diff --git a/suite-native/module-send/src/types.ts b/suite-native/module-send/src/types.ts index 09a1259912c..f1891456a32 100644 --- a/suite-native/module-send/src/types.ts +++ b/suite-native/module-send/src/types.ts @@ -17,5 +17,6 @@ export type SendAmountInputProps = { scaleValue: SharedValue; translateValue: SharedValue; isDisabled?: boolean; + onPress?: TextInputProps['onPress']; onFocus?: TextInputProps['onFocus']; }; From 93d9d5a0564d223050e9877a3448ef01c0f57f69 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Thu, 10 Oct 2024 09:42:55 +0200 Subject: [PATCH 081/624] chore(suite-native): bump app version to 24.10.1 --- suite-native/app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suite-native/app/package.json b/suite-native/app/package.json index dd06171a07f..42c20b726e5 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -1,7 +1,7 @@ { "name": "@suite-native/app", "version": "1.0.0", - "suiteNativeVersion": "24.9.2", + "suiteNativeVersion": "24.10.1", "main": "index.js", "scripts": { "android": "expo run:android", From a7c472bb1673c869907dff021eb100114413b24b Mon Sep 17 00:00:00 2001 From: tomasklim Date: Thu, 6 Jun 2024 18:08:11 +0200 Subject: [PATCH 082/624] feat(suite): eth data --- .../AdvancedTxDetails/AdvancedTxDetails.tsx | 17 ++++- .../TxDetailModal/AdvancedTxDetails/Data.tsx | 64 +++++++++++++++++++ packages/suite/src/support/messages.ts | 24 +++++++ 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/Data.tsx diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/AdvancedTxDetails.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/AdvancedTxDetails.tsx index 45e8797b7f8..1af6970b025 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/AdvancedTxDetails.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/AdvancedTxDetails.tsx @@ -9,6 +9,7 @@ import { AmountDetails } from './AmountDetails'; import { IODetails } from './IODetails/IODetails'; import { ChainedTxs } from '../ChainedTxs'; import { Elevation, mapElevationToBorder, spacingsPx } from '@trezor/theme'; +import { Data } from './Data'; const Wrapper = styled.div` padding: 0 ${spacingsPx.xl} ${spacingsPx.sm}; @@ -46,7 +47,7 @@ const TabButton = styled.button<{ $selected: boolean; $elevation: Elevation }>` } `; -export type TabID = 'amount' | 'io' | 'chained'; +export type TabID = 'amount' | 'io' | 'chained' | 'data'; interface AdvancedTxDetailsProps { defaultTab?: TabID; @@ -80,10 +81,12 @@ export const AdvancedTxDetails = ({ ); + } else if (selectedTab === 'data') { + content = ; } const { elevation } = useElevation(); @@ -117,6 +120,16 @@ export const AdvancedTxDetails = ({ )} + + {network.networkType === 'ethereum' && tx.ethereumSpecific && ( + setSelectedTab('data')} + > + + + )} {content} diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/Data.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/Data.tsx new file mode 100644 index 00000000000..d7e96fe4968 --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/AdvancedTxDetails/Data.tsx @@ -0,0 +1,64 @@ +import { WalletAccountTransaction } from '@suite-common/wallet-types'; +import { Paragraph, Row } from '@trezor/components'; +import { palette, spacingsPx } from '@trezor/theme'; +import styled from 'styled-components'; +import { Translation } from 'src/components/suite'; +import { TranslationKey } from '@suite-common/intl-types'; + +const Container = styled.div` + display: grid; + grid-template-columns: 130px 3fr; + gap: ${spacingsPx.md}; + margin-top: ${spacingsPx.xxl}; +`; + +const ParagraphWrapper = styled.div` + white-space: pre-wrap; + overflow-wrap: anywhere; +`; + +interface DataRowProps { + translationId: TranslationKey; + content: string; +} + +const DataRow = ({ translationId, content }: DataRowProps) => ( + <> + + + + + + + + {content} + + + +); + +interface DataProps { + tx: WalletAccountTransaction; +} + +export const Data = ({ tx }: DataProps) => { + const { data, parsedData } = tx.ethereumSpecific || {}; + const { function: fn, methodId, name, params } = parsedData || {}; + + return ( + + {methodId && name && ( + + )} + {methodId && !name && } + {fn && } + {params && ( + + )} + {data && } + + ); +}; diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 743fa9ee6e9..a710def385c 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -6113,6 +6113,10 @@ export default defineMessages({ id: 'TR_CHAINED_TXS', defaultMessage: 'Chained transactions', }, + TR_DATA: { + id: 'TR_DATA', + defaultMessage: 'Data', + }, TR_AFFECTED_TXS: { id: 'TR_AFFECTED_TXS', defaultMessage: 'This operation will remove the following transactions from the mempool', @@ -8413,6 +8417,26 @@ export default defineMessages({ defaultMessage: 'You can only send {network} tokens to a receive address on the {network} network, otherwise your tokens may be lost.', }, + TR_TX_DATA_METHOD_NAME: { + id: 'TR_TX_DATA_METHOD_NAME', + defaultMessage: 'Method name', + }, + TR_TX_DATA_METHOD: { + id: 'TR_TX_DATA_METHOD', + defaultMessage: 'Method', + }, + TR_TX_DATA_FUNCTION: { + id: 'TR_TX_DATA_FUNCTION', + defaultMessage: 'Function', + }, + TR_TX_DATA_PARAMS: { + id: 'TR_TX_DATA_PARAMS', + defaultMessage: 'Params', + }, + TR_TX_DATA_INPUT_DATA: { + id: 'TR_TX_DATA_INPUT_DATA', + defaultMessage: 'Input data', + }, TR_FROM: { id: 'TR_FROM', defaultMessage: 'From', From a6934fc996abf5789fa644f22a4177270835d74f Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Mon, 7 Oct 2024 16:42:52 +0200 Subject: [PATCH 083/624] chore(wallet-core): deduplicate code with getBinFilesBaseUrlThunk --- packages/suite/src/reducers/desktop/index.ts | 2 -- packages/suite/src/support/extraDependencies.ts | 1 + .../src/firmware/checkFirmwareHashThunk.ts | 14 +++++--------- .../wallet-core/src/firmware/firmwareThunks.ts | 12 ++++-------- .../src/firmware/getBinFilesBaseUrlThunk.ts | 15 +++++++++++++++ 5 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts diff --git a/packages/suite/src/reducers/desktop/index.ts b/packages/suite/src/reducers/desktop/index.ts index 00aeb45a245..392cfab94a8 100644 --- a/packages/suite/src/reducers/desktop/index.ts +++ b/packages/suite/src/reducers/desktop/index.ts @@ -18,5 +18,3 @@ export const desktopReducer = ( return state; } }; - -export const selectDesktopBinDir = (state: DesktopState) => state?.paths?.binDir; diff --git a/packages/suite/src/support/extraDependencies.ts b/packages/suite/src/support/extraDependencies.ts index bd0fdef91e4..5049708a444 100644 --- a/packages/suite/src/support/extraDependencies.ts +++ b/packages/suite/src/support/extraDependencies.ts @@ -78,6 +78,7 @@ export const extraDependencies: ExtraDependencies = { selectLocalCurrency: (state: AppState) => state.wallet.settings.localCurrency, selectIsPendingTransportEvent, selectDebugSettings: (state: AppState) => state.suite.settings.debug, + // FW binaries on desktop are stored in "*/static/connect/data/firmware/*/*.bin" (see "connect-common" package) selectDesktopBinDir: (state: AppState) => state.desktop?.paths?.binDir, selectDevice: (state: AppState) => state.device.selectedDevice, selectLanguage: (state: AppState) => state.suite.settings.language, diff --git a/suite-common/wallet-core/src/firmware/checkFirmwareHashThunk.ts b/suite-common/wallet-core/src/firmware/checkFirmwareHashThunk.ts index 07330fb9ff0..02b441a3238 100644 --- a/suite-common/wallet-core/src/firmware/checkFirmwareHashThunk.ts +++ b/suite-common/wallet-core/src/firmware/checkFirmwareHashThunk.ts @@ -1,12 +1,12 @@ import { createThunk } from '@suite-common/redux-utils'; import TrezorConnect from '@trezor/connect'; -import { getFwUpdateVersion, resolveStaticPath } from '@suite-common/suite-utils'; +import { getFwUpdateVersion } from '@suite-common/suite-utils'; import { getFirmwareVersion } from '@trezor/device-utils'; -import { isDesktop } from '@trezor/env-utils'; import { TrezorDevice } from '@suite-common/suite-types'; import { FIRMWARE_MODULE_PREFIX } from './firmwareActions'; import { selectFirmware } from './firmwareReducer'; +import { getBinFilesBaseUrlThunk } from './getBinFilesBaseUrlThunk'; type CheckFirmwareHashThunkParams = { device: TrezorDevice; @@ -18,7 +18,7 @@ export const validateFirmwareHashThunk = createThunk< { rejectValue: { success: 'unable-to-verify'; error: string } } >( `${FIRMWARE_MODULE_PREFIX}/checkFirmwareHashThunk`, - async ({ device }, { getState, extra, rejectWithValue, fulfillWithValue }) => { + async ({ device }, { dispatch, getState, rejectWithValue, fulfillWithValue }) => { const currentFwVersion = getFirmwareVersion(device); const availableFwVersion = getFwUpdateVersion(device); @@ -29,13 +29,9 @@ export const validateFirmwareHashThunk = createThunk< }); } - const desktopBinDir = extra.selectors.selectDesktopBinDir(getState()); + const binFilesBaseUrl = await dispatch(getBinFilesBaseUrlThunk()).unwrap(); const { useDevkit } = selectFirmware(getState()); - - // FW binaries are stored in "*/static/connect/data/firmware/*/*.bin". see "connect-common" package - const baseUrl = `${isDesktop() ? desktopBinDir : resolveStaticPath('connect/data')}${ - useDevkit ? '/devkit' : '' - }`; + const baseUrl = `${binFilesBaseUrl}${useDevkit ? '/devkit' : ''}`; const result = await TrezorConnect.checkFirmwareAuthenticity({ // For current version of the FW (the one known by the Suite) we dont need to download it diff --git a/suite-common/wallet-core/src/firmware/firmwareThunks.ts b/suite-common/wallet-core/src/firmware/firmwareThunks.ts index 46377d18259..21663959015 100644 --- a/suite-common/wallet-core/src/firmware/firmwareThunks.ts +++ b/suite-common/wallet-core/src/firmware/firmwareThunks.ts @@ -4,14 +4,13 @@ import { hasBitcoinOnlyFirmware, isBitcoinOnlyDevice, } from '@trezor/device-utils'; -import { isDesktop } from '@trezor/env-utils'; -import { resolveStaticPath } from '@suite-common/suite-utils'; import { analytics, EventType } from '@trezor/suite-analytics'; import TrezorConnect, { Device, FirmwareType } from '@trezor/connect'; import { createThunk } from '@suite-common/redux-utils'; import { selectFirmware } from './firmwareReducer'; import { FIRMWARE_MODULE_PREFIX, firmwareActions } from './firmwareActions'; +import { getBinFilesBaseUrlThunk } from './getBinFilesBaseUrlThunk'; const handleFwHashError = createThunk( `${FIRMWARE_MODULE_PREFIX}/handleFwHashError`, @@ -56,11 +55,11 @@ export const firmwareUpdate = createThunk( } const { - selectors: { selectDevice, selectDesktopBinDir, selectLanguage }, + selectors: { selectDevice, selectLanguage }, } = extra; const device = selectDevice(getState()); - const desktopBinDir = selectDesktopBinDir(getState()); + const binFilesBaseUrl = await dispatch(getBinFilesBaseUrlThunk()).unwrap(); const suiteLanguage = selectLanguage(getState()); const { useDevkit, cachedDevice, error } = selectFirmware(getState()); @@ -81,10 +80,7 @@ export const firmwareUpdate = createThunk( dispatch(firmwareActions.cacheDevice(device)); } - // FW binaries are stored in "*/static/connect/data/firmware/*/*.bin". see "connect-common" package - const baseUrl = `${isDesktop() ? desktopBinDir : resolveStaticPath('connect/data')}${ - useDevkit ? '/devkit' : '' - }`; + const baseUrl = `${binFilesBaseUrl}${useDevkit ? '/devkit' : ''}`; // update to same variant as is currently installed or to the regular one if device does not have any fw (new/wiped device), // unless the user wants to switch firmware type diff --git a/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts b/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts new file mode 100644 index 00000000000..9f184bac67d --- /dev/null +++ b/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts @@ -0,0 +1,15 @@ +import { isDesktop } from '@trezor/env-utils'; +import { resolveStaticPath } from '@suite-common/suite-utils'; +import { createThunk } from '@suite-common/redux-utils'; +import { FIRMWARE_MODULE_PREFIX } from './firmwareActions'; + +/** + * Get URL for firmware binaries, which may be local (suite desktop) or remote (suite web) + */ +export const getBinFilesBaseUrlThunk = createThunk( + `${FIRMWARE_MODULE_PREFIX}/getBinFilesBaseUrlThunk`, + (_params, { getState, extra }) => + isDesktop() + ? extra.selectors.selectDesktopBinDir(getState()) + : resolveStaticPath('connect/data'), +); From 1150abeef6bdb9026be5acf7c9587914da4ea45e Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Mon, 7 Oct 2024 19:16:08 +0200 Subject: [PATCH 084/624] test(suite-native): send e2e --- .../e2e/pageObjects/accountDetailActions.ts | 12 ++ .../app/e2e/pageObjects/alertSheetActions.ts | 17 ++ .../e2e/pageObjects/coinEnablingActions.ts | 18 +- .../app/e2e/pageObjects/homeActions.ts | 6 + .../app/e2e/pageObjects/myAssetsActions.ts | 6 + .../send/sendAddressReviewActions.ts | 10 ++ .../e2e/pageObjects/send/sendFeesActions.ts | 35 ++++ .../send/sendOutputsFormActions.ts | 32 ++++ .../send/sendOutputsReviewActions.ts | 36 ++++ .../app/e2e/tests/onboardAndConnect.test.ts | 30 +--- suite-native/app/e2e/tests/send.test.ts | 156 ++++++++++++++++++ suite-native/app/e2e/utils.ts | 30 ++++ suite-native/app/package.json | 2 + suite-native/app/tsconfig.json | 8 +- .../discovery/src/discoveryConfigSlice.ts | 3 +- .../src/components/TransactionListHeader.tsx | 14 +- .../src/components/AddressReviewStepList.tsx | 2 +- .../src/components/ScreenSubHeader.tsx | 6 +- yarn.lock | 2 + 19 files changed, 384 insertions(+), 41 deletions(-) create mode 100644 suite-native/app/e2e/pageObjects/alertSheetActions.ts create mode 100644 suite-native/app/e2e/pageObjects/send/sendAddressReviewActions.ts create mode 100644 suite-native/app/e2e/pageObjects/send/sendFeesActions.ts create mode 100644 suite-native/app/e2e/pageObjects/send/sendOutputsFormActions.ts create mode 100644 suite-native/app/e2e/pageObjects/send/sendOutputsReviewActions.ts create mode 100644 suite-native/app/e2e/tests/send.test.ts diff --git a/suite-native/app/e2e/pageObjects/accountDetailActions.ts b/suite-native/app/e2e/pageObjects/accountDetailActions.ts index 75cf7d0ebe1..9396e38a151 100644 --- a/suite-native/app/e2e/pageObjects/accountDetailActions.ts +++ b/suite-native/app/e2e/pageObjects/accountDetailActions.ts @@ -1,11 +1,23 @@ import { expect as detoxExpect } from 'detox'; class AccountDetailActions { + async waitForScreen() { + await waitFor(element(by.id('@screen/AccountDetail'))) + .toBeVisible() + .withTimeout(5000); + } + async openSettings() { await element(by.id('@account-detail/settings-button')).tap(); await detoxExpect(element(by.id('@screen/AccountSettings'))).toBeVisible(); } + + async openSend() { + await element(by.id('@account-detail/send-button')).tap(); + + await detoxExpect(element(by.id('@screen/SendOutputs'))).toBeVisible(); + } } export const onAccountDetail = new AccountDetailActions(); diff --git a/suite-native/app/e2e/pageObjects/alertSheetActions.ts b/suite-native/app/e2e/pageObjects/alertSheetActions.ts new file mode 100644 index 00000000000..b6c3b110c69 --- /dev/null +++ b/suite-native/app/e2e/pageObjects/alertSheetActions.ts @@ -0,0 +1,17 @@ +class AlertSheetActions { + async tapPrimaryButton() { + await waitFor(element(by.id('@alert-sheet/primary-button'))) + .toBeVisible() + .withTimeout(10000); + await element(by.id('@alert-sheet/primary-button')).tap(); + } + + async tapSecondaryButton() { + await waitFor(element(by.id('@alert-sheet/secondary-button'))) + .toBeVisible() + .withTimeout(10000); + await element(by.id('@alert-sheet/secondary-button')).tap(); + } +} + +export const onAlertSheet = new AlertSheetActions(); diff --git a/suite-native/app/e2e/pageObjects/coinEnablingActions.ts b/suite-native/app/e2e/pageObjects/coinEnablingActions.ts index b6d0ced7adb..232dcd389a5 100644 --- a/suite-native/app/e2e/pageObjects/coinEnablingActions.ts +++ b/suite-native/app/e2e/pageObjects/coinEnablingActions.ts @@ -1,18 +1,18 @@ +import { scrollUntilVisible } from '../utils'; + class OnCoinEnablingInit { - async waitForBtcToBeVisible() { - await waitFor(element(by.id('@coin-enabling/toggle-btc'))) + async waitForScreen() { + await waitFor(element(by.id('@screen/CoinEnablingInit'))) .toBeVisible() - .withTimeout(3000); + .withTimeout(10000); } async enableNetwork(networkSymbol: string) { - await element(by.id(`@coin-enabling/toggle-${networkSymbol}`)).tap(); + const networkIdMatcher = by.id(`@coin-enabling/toggle-${networkSymbol}`); + await scrollUntilVisible(networkIdMatcher); + await element(networkIdMatcher).tap(); } - async save() { - await waitFor(element(by.id('@coin-enabling/button-save'))) - .toBeVisible() - .withTimeout(3000); - + async clickOnConfirmButton() { await element(by.id('@coin-enabling/button-save')).tap(); } } diff --git a/suite-native/app/e2e/pageObjects/homeActions.ts b/suite-native/app/e2e/pageObjects/homeActions.ts index 6318b436765..d5259cfc70f 100644 --- a/suite-native/app/e2e/pageObjects/homeActions.ts +++ b/suite-native/app/e2e/pageObjects/homeActions.ts @@ -1,6 +1,12 @@ import { expect as detoxExpect } from 'detox'; class HomeActions { + async waitForScreen() { + await waitFor(element(by.id('@screen/Home'))) + .toBeVisible() + .withTimeout(10000); + } + async tapSyncCoinsButton() { await element(by.id('@screen/mainScrollView')).scrollTo('bottom'); await element(by.id('@home/portfolio/sync-coins-button')).tap(); diff --git a/suite-native/app/e2e/pageObjects/myAssetsActions.ts b/suite-native/app/e2e/pageObjects/myAssetsActions.ts index f91a54f58c7..bdf568ddb93 100644 --- a/suite-native/app/e2e/pageObjects/myAssetsActions.ts +++ b/suite-native/app/e2e/pageObjects/myAssetsActions.ts @@ -1,6 +1,12 @@ import { expect as detoxExpect } from 'detox'; class MyAssetsActions { + async waitForScreen() { + await waitFor(element(by.id('@screen/MyAssets'))) + .toBeVisible() + .withTimeout(5000); + } + async addAccount() { await element(by.id('@screen/mainScrollView')).scrollTo('top'); await element(by.id('@myAssets/addAccountButton')).tap(); diff --git a/suite-native/app/e2e/pageObjects/send/sendAddressReviewActions.ts b/suite-native/app/e2e/pageObjects/send/sendAddressReviewActions.ts new file mode 100644 index 00000000000..6cf72dbb34a --- /dev/null +++ b/suite-native/app/e2e/pageObjects/send/sendAddressReviewActions.ts @@ -0,0 +1,10 @@ +import { expect as detoxExpect } from 'detox'; + +class SendAddressReviewActions { + async nextStep() { + await detoxExpect(element(by.id('@screen/SendAddressReview'))).toBeVisible(); + await element(by.id('@send/address-review-continue')).tap(); + } +} + +export const onSendAddressReview = new SendAddressReviewActions(); diff --git a/suite-native/app/e2e/pageObjects/send/sendFeesActions.ts b/suite-native/app/e2e/pageObjects/send/sendFeesActions.ts new file mode 100644 index 00000000000..0588ee8aec9 --- /dev/null +++ b/suite-native/app/e2e/pageObjects/send/sendFeesActions.ts @@ -0,0 +1,35 @@ +import { expect as detoxExpect } from 'detox'; + +import { FeeLevelLabel } from '@suite-common/wallet-types'; + +class SendFeesActions { + async waitForScreen() { + await waitFor(element(by.id('@screen/SendFees'))) + .toBeVisible() + .withTimeout(5000); + } + + async selectFee(feeType: FeeLevelLabel) { + await detoxExpect(element(by.id('@screen/SendFees'))).toBeVisible(); + + switch (feeType) { + case 'low': + await element(by.id('@send/fees-level-low')).tap(); + break; + case 'normal': + await element(by.id('@send/fees-level-normal')).tap(); + break; + case 'high': + await element(by.id('@send/fees-level-high')).tap(); + break; + default: + throw new Error(`SendFeesActions.selectFee(): Unsupported fee type: ${feeType}`); + } + } + + async submitFee() { + await element(by.id('@send/fees-submit-button')).tap(); + } +} + +export const onSendFees = new SendFeesActions(); diff --git a/suite-native/app/e2e/pageObjects/send/sendOutputsFormActions.ts b/suite-native/app/e2e/pageObjects/send/sendOutputsFormActions.ts new file mode 100644 index 00000000000..a9c08809c0b --- /dev/null +++ b/suite-native/app/e2e/pageObjects/send/sendOutputsFormActions.ts @@ -0,0 +1,32 @@ +import { expect as detoxExpect } from 'detox'; + +class SendOutputsFormActions { + async waitForScreen() { + await waitFor(element(by.id('@screen/SendOutputs'))).toBeVisible(); + } + + async fillForm(values: { address?: string; amount?: string }[]) { + await detoxExpect(element(by.id(`@screen/SendOutputs`))).toBeVisible(); + + for (const [index, value] of values.entries()) { + const { address, amount } = value; + if (address) { + await element(by.id(`outputs.${index}.address`)).typeText(address); + } + if (amount) { + await element(by.id(`outputs.${index}.amount`)).typeText(amount); + } + } + } + + async clearForm() { + await element(by.id(/^outputs\.\d+\.address$/)).clearText(); + await element(by.id(/^outputs\.\d+\.amount$/)).clearText(); + } + + async submitForm() { + await element(by.id('@send/form-submit-button')).tap(); + } +} + +export const onSendOutputsForm = new SendOutputsFormActions(); diff --git a/suite-native/app/e2e/pageObjects/send/sendOutputsReviewActions.ts b/suite-native/app/e2e/pageObjects/send/sendOutputsReviewActions.ts new file mode 100644 index 00000000000..f4d77c257e8 --- /dev/null +++ b/suite-native/app/e2e/pageObjects/send/sendOutputsReviewActions.ts @@ -0,0 +1,36 @@ +import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; + +const sendButton = element(by.id('@send/send-transaction-button')); + +class SendOutputsReviewActions { + async waitForScreen() { + await waitFor(element(by.id('@screen/SendOutputsReview'))) + .toBeVisible() + .withTimeout(3000); + } + + async confirmTransactionOutputs() { + let isReviewInProgress = true; + do { + await TrezorUserEnvLink.pressYes(); + + try { + await waitFor(sendButton).toBeVisible().withTimeout(3000); + isReviewInProgress = false; + } catch { + // continue loop, there are more outputs to review + } + } while (isReviewInProgress); + } + + async clickSendTransaction() { + await waitFor(sendButton).toBeVisible().withTimeout(15000); + await sendButton.tap(); + + await waitFor(element(by.id('@screen/TransactionDetail'))) + .toBeVisible() + .withTimeout(3000); + } +} + +export const onSendOutputsReview = new SendOutputsReviewActions(); diff --git a/suite-native/app/e2e/tests/onboardAndConnect.test.ts b/suite-native/app/e2e/tests/onboardAndConnect.test.ts index ed53ff49b40..46e3eb3fa2e 100644 --- a/suite-native/app/e2e/tests/onboardAndConnect.test.ts +++ b/suite-native/app/e2e/tests/onboardAndConnect.test.ts @@ -1,39 +1,21 @@ // `expect` keyword is already used by jest. import { expect as detoxExpect } from 'detox'; -import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; - -import { openApp } from '../utils'; +import { disconnectTrezorUserEnv, openApp, prepareTrezorEmulator } from '../utils'; import { onOnboarding } from '../pageObjects/onboardingActions'; import { onCoinEnablingInit } from '../pageObjects/coinEnablingActions'; -const TREZOR_DEVICE_LABEL = 'Trezor T - Tester'; -// Contains only one BTC account with a single transaction to make the discovery as fast as possible. -const SIMPLE_SEED = 'immune enlist rule measure fan swarm mandate track point menu security fan'; const platform = device.getPlatform(); describe('Go through onboarding and connect Trezor.', () => { beforeAll(async () => { - if (platform === 'android') { - // Prepare Trezor device for test scenario and turn it off. - await TrezorUserEnvLink.disconnect(); - await TrezorUserEnvLink.connect(); - await TrezorUserEnvLink.startEmu({ wipe: true }); - await TrezorUserEnvLink.setupEmu({ - label: TREZOR_DEVICE_LABEL, - mnemonic: SIMPLE_SEED, - }); - await TrezorUserEnvLink.startBridge(); - await TrezorUserEnvLink.stopEmu(); - } + await prepareTrezorEmulator(); await openApp({ newInstance: true }); }); afterAll(async () => { - if (platform === 'android') { - await TrezorUserEnvLink.stopEmu(); - } + disconnectTrezorUserEnv(); await device.terminateApp(); }); @@ -41,18 +23,16 @@ describe('Go through onboarding and connect Trezor.', () => { await onOnboarding.finishOnboarding(); if (platform === 'android') { - await TrezorUserEnvLink.startEmu(); - await waitFor(element(by.id('@screen/CoinEnablingInit'))) .toBeVisible() .withTimeout(10000); - await onCoinEnablingInit.waitForBtcToBeVisible(); + await onCoinEnablingInit.waitForScreen(); await onCoinEnablingInit.enableNetwork('btc'); await onCoinEnablingInit.enableNetwork('eth'); - await onCoinEnablingInit.save(); + await onCoinEnablingInit.clickOnConfirmButton(); await waitFor(element(by.id('skip-view-only-mode'))) .toBeVisible() diff --git a/suite-native/app/e2e/tests/send.test.ts b/suite-native/app/e2e/tests/send.test.ts new file mode 100644 index 00000000000..64505655e55 --- /dev/null +++ b/suite-native/app/e2e/tests/send.test.ts @@ -0,0 +1,156 @@ +import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; + +import { + appIsFullyLoaded, + disconnectTrezorUserEnv, + openApp, + prepareTrezorEmulator, + restartApp, + wait, +} from '../utils'; +import { onMyAssets } from '../pageObjects/myAssetsActions'; +import { onOnboarding } from '../pageObjects/onboardingActions'; +import { onCoinEnablingInit } from '../pageObjects/coinEnablingActions'; +import { onTabBar } from '../pageObjects/tabBarActions'; +import { onAccountDetail } from '../pageObjects/accountDetailActions'; +import { onSendOutputsForm } from '../pageObjects/send/sendOutputsFormActions'; +import { onSendFees } from '../pageObjects/send/sendFeesActions'; +import { onSendAddressReview } from '../pageObjects/send/sendAddressReviewActions'; +import { onSendOutputsReview } from '../pageObjects/send/sendOutputsReviewActions'; +import { onHome } from '../pageObjects/homeActions'; +import { onAlertSheet } from '../pageObjects/alertSheetActions'; + +export const SEND_FORM_ERROR_MESSAGES = { + invalidAddress: 'The address format is incorrect.', + invalidDecimalValue: 'Invalid decimal value.', + dustAmount: 'The value is lower than the dust limit.', + higherThanBalance: 'You don’t have enough balance to send this amount.', + tooManyDecimals: 'Too many decimals.', + addressRequired: 'Address is required.', + amountRequired: 'Amount is required.', +}; + +const INITIAL_ACCOUNT_BALANCE = 3.14; + +const platform = device.getPlatform(); + +const prepareTransactionForOnDeviceReview = async (isFormEmpty: boolean = true) => { + if (isFormEmpty) { + await onSendOutputsForm.fillForm([ + { address: 'bcrt1q34up3cga3fkmph47t22mpk5d0xxj3ppghph9da', amount: '0.5' }, + ]); + } + + await onSendOutputsForm.submitForm(); + + await onSendFees.selectFee('normal'); + await onSendFees.submitFee(); +}; + +describe('Send transaction flow.', () => { + beforeAll(async () => { + await prepareTrezorEmulator(); + await openApp({ newInstance: true }); + await onOnboarding.finishOnboarding(); + + await TrezorUserEnvLink.sendToAddressAndMineBlock({ + address: 'bcrt1q34up3cga3fkmph47t22mpk5d0xxj3ppghph9da', + btc_amount: INITIAL_ACCOUNT_BALANCE, + }); + + await onCoinEnablingInit.waitForScreen(); + await onCoinEnablingInit.enableNetwork('regtest'); + await onCoinEnablingInit.clickOnConfirmButton(); + + await waitFor(element(by.id('skip-view-only-mode'))) + .toBeVisible() + .withTimeout(10000); // communication between connected Trezor and app takes some time. + + await element(by.id('skip-view-only-mode')).tap(); + }); + + beforeEach(async () => { + await prepareTrezorEmulator(); + await restartApp(); + + await appIsFullyLoaded(); + if (platform !== 'android') + return test.skip(`Sending transactions is not supported on ${platform}.`); + + await waitFor(element(by.id('@screen/ConnectingDevice'))) + .toBeVisible() + .withTimeout(10000); + + await onHome.waitForScreen(); + await onTabBar.navigateToMyAssets(); + + await onMyAssets.openAccountDetail({ accountName: 'Bitcoin Regtest #1' }); + + await onAccountDetail.openSend(); + await onSendOutputsForm.waitForScreen(); + }); + + afterAll(() => { + disconnectTrezorUserEnv(); + }); + + it('Compose and dispatch a regtest transaction.', async () => { + await prepareTransactionForOnDeviceReview(); + + await onSendAddressReview.nextStep(); + await onSendAddressReview.nextStep(); + await TrezorUserEnvLink.pressYes(); + + await onSendOutputsReview.waitForScreen(); + await onSendOutputsReview.confirmTransactionOutputs(); + await onSendOutputsReview.clickSendTransaction(); + }); + + it('Validate send form input errors.', async () => { + await onSendOutputsForm.fillForm([{ address: 'wrong address', amount: '200' }]); + + await waitFor(element(by.text(SEND_FORM_ERROR_MESSAGES.invalidAddress))).toBeVisible(); + await waitFor(element(by.text(SEND_FORM_ERROR_MESSAGES.higherThanBalance))).toBeVisible(); + + await onSendOutputsForm.clearForm(); + + await waitFor(element(by.text(SEND_FORM_ERROR_MESSAGES.addressRequired))).toBeVisible(); + await waitFor(element(by.text(SEND_FORM_ERROR_MESSAGES.amountRequired))).toBeVisible(); + + await onSendOutputsForm.fillForm([{ amount: '0.00000001' }]); + await waitFor(element(by.text(SEND_FORM_ERROR_MESSAGES.dustAmount))).toBeVisible(); + + await onSendOutputsForm.clearForm(); + + await onSendOutputsForm.fillForm([{ amount: '0.10000000000' }]); + await waitFor(element(by.text(SEND_FORM_ERROR_MESSAGES.tooManyDecimals))).toBeVisible(); + }); + + it('Review cancellation and error handling.', async () => { + await prepareTransactionForOnDeviceReview(); + + // Cancel button should go back if the on device review was not started yet. + await element(by.id('@screen/sub-header/icon-left')).tap(); + await onSendFees.waitForScreen(); + + // Cancel button should restart the review if it already started. + await onSendFees.submitFee(); + await onSendAddressReview.nextStep(); + await onSendAddressReview.nextStep(); + await element(by.id('@screen/sub-header/icon-left')).tap(); + await onAlertSheet.tapPrimaryButton(); + await onAccountDetail.waitForScreen(); + + // Disconnecting not remembered device should exit the send flow and display alert. + await onAccountDetail.openSend(); + const isFormEmpty = false; + await prepareTransactionForOnDeviceReview(isFormEmpty); + await onSendAddressReview.nextStep(); + await onSendAddressReview.nextStep(); + + await wait(3000); // Wait for the device to get info about the transaction. + await TrezorUserEnvLink.stopEmu(); + await onAlertSheet.tapSecondaryButton(); + await onHome.waitForScreen(); + }); +}); diff --git a/suite-native/app/e2e/utils.ts b/suite-native/app/e2e/utils.ts index 347b9367881..95c7e860f24 100644 --- a/suite-native/app/e2e/utils.ts +++ b/suite-native/app/e2e/utils.ts @@ -1,12 +1,17 @@ import { resolveConfig } from 'detox/internals'; import { expect as detoxExpect } from 'detox'; +import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; + const APP_LAUNCH_ARGS = { // Do not synchronize communication with the trezor bridge and metro server running on localhost. Since the trezor // bridge is exchanging messages with the app all the time, the test runner would wait forever otherwise. detoxURLBlacklistRegex: '\\("^.*127.0.0.1.*",".*localhost.*","^*clients3\\.google\\.com*"\\)', }; +// Contains only one BTC account with a single transaction to make the discovery as fast as possible. +const SIMPLE_SEED = 'immune enlist rule measure fan swarm mandate track point menu security fan'; +const TREZOR_DEVICE_LABEL = 'Trezor T - Tester'; const platform = device.getPlatform(); export const sleep = (ms: number) => new Promise(res => setTimeout(res, ms)); @@ -88,3 +93,28 @@ export const appIsFullyLoaded = async () => { .toBeVisible() .withTimeout(35000); }; + +export const prepareTrezorEmulator = async (seed: string = SIMPLE_SEED) => { + if (platform === 'android') { + // Prepare Trezor device for test scenario + await TrezorUserEnvLink.disconnect(); + await TrezorUserEnvLink.connect(); + await TrezorUserEnvLink.startEmu({ wipe: true }); + await TrezorUserEnvLink.setupEmu({ + label: TREZOR_DEVICE_LABEL, + mnemonic: seed, + }); + await TrezorUserEnvLink.startBridge(); + } +}; + +export const disconnectTrezorUserEnv = async () => { + // Clear the connection to the Trezor emulator so the test does not synchronize with it when not necessary. + await TrezorUserEnvLink.stopEmu(); + await TrezorUserEnvLink.disconnect(); + await TrezorUserEnvLink.stopBridge(); +}; + +export const wait = async (ms: number) => { + await new Promise(resolve => setTimeout(resolve, ms)); +}; diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 42c20b726e5..5f1c8e93558 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -41,6 +41,7 @@ "@suite-common/suite-constants": "workspace:*", "@suite-common/token-definitions": "workspace:*", "@suite-common/wallet-core": "workspace:*", + "@suite-common/wallet-types": "workspace:*", "@suite-native/accounts": "workspace:*", "@suite-native/alerts": "workspace:*", "@suite-native/analytics": "workspace:*", @@ -79,6 +80,7 @@ "@trezor/react-native-usb": "workspace:*", "@trezor/styles": "workspace:*", "@trezor/theme": "workspace:*", + "@trezor/trezor-user-env-link": "workspace:*", "buffer": "^6.0.3", "expo": "51.0.31", "expo-av": "14.0.7", diff --git a/suite-native/app/tsconfig.json b/suite-native/app/tsconfig.json index 5c5b2a56ff8..788629957a7 100644 --- a/suite-native/app/tsconfig.json +++ b/suite-native/app/tsconfig.json @@ -29,6 +29,9 @@ { "path": "../../suite-common/wallet-core" }, + { + "path": "../../suite-common/wallet-types" + }, { "path": "../accounts" }, { "path": "../alerts" }, { "path": "../analytics" }, @@ -72,7 +75,10 @@ "path": "../../packages/react-native-usb" }, { "path": "../../packages/styles" }, - { "path": "../../packages/theme" } + { "path": "../../packages/theme" }, + { + "path": "../../packages/trezor-user-env-link" + } ], "include": [".", "**.json"] } diff --git a/suite-native/discovery/src/discoveryConfigSlice.ts b/suite-native/discovery/src/discoveryConfigSlice.ts index c49f0d97b8f..55a8cb32ce8 100644 --- a/suite-native/discovery/src/discoveryConfigSlice.ts +++ b/suite-native/discovery/src/discoveryConfigSlice.ts @@ -10,6 +10,7 @@ import { import { filterBlacklistedNetworks, filterTestnetNetworks, + isDetoxTestBuild, sortNetworks, } from '@suite-native/config'; import { NetworkSymbol } from '@suite-common/wallet-config'; @@ -36,7 +37,7 @@ export type DiscoveryConfigSliceRootState = { }; const discoveryConfigInitialState: DiscoveryConfigState = { - areTestnetsEnabled: false, + areTestnetsEnabled: isDetoxTestBuild(), discoveryInfo: null, isCoinEnablingInitFinished: false, enabledDiscoveryNetworkSymbols: [], diff --git a/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx b/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx index 64fbf734d4b..393b9d7616c 100644 --- a/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx +++ b/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx @@ -150,13 +150,23 @@ export const TransactionListHeader = memo( {accountHasTransactions && ( - {isSendButtonDisplayed && ( - diff --git a/suite-native/module-send/src/components/AddressReviewStepList.tsx b/suite-native/module-send/src/components/AddressReviewStepList.tsx index fd2cbb6559d..a2ad4d1fd61 100644 --- a/suite-native/module-send/src/components/AddressReviewStepList.tsx +++ b/suite-native/module-send/src/components/AddressReviewStepList.tsx @@ -126,7 +126,7 @@ export const AddressReviewStepList = () => { stepHeights={childHeights} initialOffset={OVERLAY_INITIAL_POSITION} > - diff --git a/suite-native/navigation/src/components/ScreenSubHeader.tsx b/suite-native/navigation/src/components/ScreenSubHeader.tsx index 88a17166061..1ef42a61895 100644 --- a/suite-native/navigation/src/components/ScreenSubHeader.tsx +++ b/suite-native/navigation/src/components/ScreenSubHeader.tsx @@ -53,7 +53,7 @@ export const ScreenSubHeader = ({ customHorizontalPadding: nativeSpacingToNumber(customHorizontalPadding), })} > - + {leftIcon || } @@ -70,7 +70,9 @@ export const ScreenSubHeader = ({ content )} - {rightIcon} + + {rightIcon} + ); }; diff --git a/yarn.lock b/yarn.lock index f13b65f8594..4e061f831af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9563,6 +9563,7 @@ __metadata: "@suite-common/suite-constants": "workspace:*" "@suite-common/token-definitions": "workspace:*" "@suite-common/wallet-core": "workspace:*" + "@suite-common/wallet-types": "workspace:*" "@suite-native/accounts": "workspace:*" "@suite-native/alerts": "workspace:*" "@suite-native/analytics": "workspace:*" @@ -9601,6 +9602,7 @@ __metadata: "@trezor/react-native-usb": "workspace:*" "@trezor/styles": "workspace:*" "@trezor/theme": "workspace:*" + "@trezor/trezor-user-env-link": "workspace:*" "@types/jest": "npm:^29.5.12" "@types/node": "npm:^20.11.24" babel-plugin-transform-inline-environment-variables: "npm:^0.4.4" From 37705ca721355e77136f3afcbc1bcfae2d420a10 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Mon, 7 Oct 2024 19:17:42 +0200 Subject: [PATCH 085/624] test(suite-native): regtest poc removed --- .../e2e/pageObjects/accountDetailActions.ts | 2 - .../app/e2e/pageObjects/alertSheetActions.ts | 16 +++---- suite-native/app/e2e/tests/regtestPOC.test.ts | 48 ------------------- suite-native/app/e2e/tests/send.test.ts | 1 - 4 files changed, 8 insertions(+), 59 deletions(-) delete mode 100644 suite-native/app/e2e/tests/regtestPOC.test.ts diff --git a/suite-native/app/e2e/pageObjects/accountDetailActions.ts b/suite-native/app/e2e/pageObjects/accountDetailActions.ts index 9396e38a151..9e2de003803 100644 --- a/suite-native/app/e2e/pageObjects/accountDetailActions.ts +++ b/suite-native/app/e2e/pageObjects/accountDetailActions.ts @@ -15,8 +15,6 @@ class AccountDetailActions { async openSend() { await element(by.id('@account-detail/send-button')).tap(); - - await detoxExpect(element(by.id('@screen/SendOutputs'))).toBeVisible(); } } diff --git a/suite-native/app/e2e/pageObjects/alertSheetActions.ts b/suite-native/app/e2e/pageObjects/alertSheetActions.ts index b6c3b110c69..b7ddc79050e 100644 --- a/suite-native/app/e2e/pageObjects/alertSheetActions.ts +++ b/suite-native/app/e2e/pageObjects/alertSheetActions.ts @@ -1,16 +1,16 @@ class AlertSheetActions { async tapPrimaryButton() { - await waitFor(element(by.id('@alert-sheet/primary-button'))) - .toBeVisible() - .withTimeout(10000); - await element(by.id('@alert-sheet/primary-button')).tap(); + const primaryButtonElement = element(by.id('@alert-sheet/primary-button')); + + await waitFor(primaryButtonElement).toBeVisible().withTimeout(10000); + await primaryButtonElement.tap(); } async tapSecondaryButton() { - await waitFor(element(by.id('@alert-sheet/secondary-button'))) - .toBeVisible() - .withTimeout(10000); - await element(by.id('@alert-sheet/secondary-button')).tap(); + const secondaryButtonElement = element(by.id('@alert-sheet/secondary-button')); + + await waitFor(secondaryButtonElement).toBeVisible().withTimeout(10000); + await secondaryButtonElement.tap(); } } diff --git a/suite-native/app/e2e/tests/regtestPOC.test.ts b/suite-native/app/e2e/tests/regtestPOC.test.ts deleted file mode 100644 index 80592468b76..00000000000 --- a/suite-native/app/e2e/tests/regtestPOC.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { expect as detoxExpect } from 'detox'; - -import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; - -import { appIsFullyLoaded, openApp, restartApp } from '../utils'; -import { xpubs } from '../fixtures/xpubs'; -import { onAccountImport } from '../pageObjects/accountImportActions'; -import { onMyAssets } from '../pageObjects/myAssetsActions'; -import { onOnboarding } from '../pageObjects/onboardingActions'; -import { onHome } from '../pageObjects/homeActions'; - -// TODO: This is not a full test suite, just a proof of concept of regtest <---> suite-native integration. -// The suite will be extended/modified in the future by the QA team. -describe('Regtest integration proof of concept.', () => { - beforeAll(async () => { - await openApp({ newInstance: true }); - await onOnboarding.finishOnboarding(); - }); - - beforeEach(async () => { - await restartApp(); - await appIsFullyLoaded(); - }); - - it('Mine regtest transaction and check that it is present in the account transaction list.', async () => { - const amountToSend = 42; - - // send transaction of 42 BTC and mine it - await TrezorUserEnvLink.sendToAddressAndMineBlock({ - address: 'bcrt1qjf6qnquchwl6drvrf2ar73l6p9m3gzwlev9qd4', - btc_amount: amountToSend, - }); - - await onHome.tapSyncCoinsButton(); - - const accountName = 'Regtest #1'; - await onAccountImport.importAccount({ - networkSymbol: 'regtest', - xpub: xpubs.regtest, - accountName, - }); - - await onMyAssets.openAccountDetail({ accountName }); - - // Check if the transaction is present in the account transaction list. - await detoxExpect(element(by.text(`${amountToSend} BTC REGTEST`)).atIndex(0)).toBeVisible(); - }); -}); diff --git a/suite-native/app/e2e/tests/send.test.ts b/suite-native/app/e2e/tests/send.test.ts index 64505655e55..745978b543b 100644 --- a/suite-native/app/e2e/tests/send.test.ts +++ b/suite-native/app/e2e/tests/send.test.ts @@ -43,7 +43,6 @@ const prepareTransactionForOnDeviceReview = async (isFormEmpty: boolean = true) await onSendOutputsForm.submitForm(); - await onSendFees.selectFee('normal'); await onSendFees.submitFee(); }; From 44ed16a45d2f3b7816980beb75f7961a9c83a01d Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Fri, 8 Mar 2024 15:36:25 +0100 Subject: [PATCH 086/624] docs(connect-web): Support matrix --- packages/connect-web/README.md | 15 +++++++++++++++ packages/connect-web/src/webextension/README.md | 2 +- packages/connect-webextension/README.md | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/connect-web/README.md b/packages/connect-web/README.md index b466017c9a4..f8a7e674524 100644 --- a/packages/connect-web/README.md +++ b/packages/connect-web/README.md @@ -54,3 +54,18 @@ For more instructions [refer to this document](https://github.com/trezor/trezor- - install node_modules: `yarn && yarn build:libs` - generate certs `yarn workspace @trezor/connect-web predev` - It is possible to run local dev server with iframe and popup using: `yarn workspace @trezor/connect-web dev` Note: don't forget to visit `https://localhost:8088/` and allow self-signed certificate. No UI is displayed here. + +## TrezorConnect Support Matrix + +The table below details the support for different environments by TrezorConnect for integrating Trezor devices, including the use of WebUSB and the need for Trezor Bridge. + +| Environment | Chrome | Firefox | Safari | Chrome Android | Firefox Android | Notes | +| ----------------------------- | :----: | :-----: | :----: | :------------: | :-------------: | ----------------------------------------------------------------------- | +| Web (WebUSB) | ✓ | ✗ | ✗ | ✓ | ✗ | WebUSB is fully supported where indicated. (Chromium based browsers) | +| Web (Bridge) | ✓ | ✓ | ✗ | ✗ | ✗ | Trezor Bridge is required where WebUSB is not supported. (e.g. Firefox) | +| WebExtension (WebUSB, Bridge) | ✓ | ✓ | ✗ | ✓ | ✗ | Requires Trezor Bridge on platforms not supporting WebUSB. | + +## Key Differences + +- **WebUSB**: Allows direct communication with Trezor devices via the browser. Supported by most modern browsers but may have limitations on mobile devices and is not supported by Safari. +- **Trezor Bridge**: A service that runs with Trezor Suite or Standalone that facilitates communication between your Trezor device and a web browser. Required for browsers that do not support WebUSB or for a more stable connection on desktop environments. diff --git a/packages/connect-web/src/webextension/README.md b/packages/connect-web/src/webextension/README.md index 77dedb276f0..5c5a5b494ab 100644 --- a/packages/connect-web/src/webextension/README.md +++ b/packages/connect-web/src/webextension/README.md @@ -1,6 +1,6 @@ # Integrate @trezor/connect with a web extension -**Note: only manifest version 2 is supported for now** +**Note: Only manifest version 2 web extensions are supported by this package. For manifest version 3, use the [@trezor/connect-webextension](https://github.com/trezor/trezor-suite/tree/develop/packages/connect-webextension) package** [Example of a web extension project for both Google Chrome & Firefox](../../../connect-examples/webextension/README.md) diff --git a/packages/connect-webextension/README.md b/packages/connect-webextension/README.md index efb62810701..fff1e52e097 100644 --- a/packages/connect-webextension/README.md +++ b/packages/connect-webextension/README.md @@ -4,7 +4,7 @@ [![NPM](https://img.shields.io/npm/v/@trezor/connect-webextension.svg)](https://www.npmjs.org/package/@trezor/connect-webextension) [![Known Vulnerabilities](https://snyk.io/test/github/trezor/connect-webextension/badge.svg?targetFile=package.json)](https://snyk.io/test/github/trezor/trezor-suite?targetFile=packages/connect-webextension/package.json) -The @trezor/connect-webextension package provides an implementation of @trezor/connect designed specifically for use within web extensions. Key features include: +The `@trezor/connect-webextension` package provides an implementation of `@trezor/connect` designed specifically for use within web extensions. Key features include: - Compatibility with service worker environments. - Full access to the TrezorConnect API. From 65a8499db01e2226de44c748e725e0bf976b3ee5 Mon Sep 17 00:00:00 2001 From: yanas Date: Thu, 10 Oct 2024 15:12:04 +0200 Subject: [PATCH 087/624] refactor(suite-native): extract layout component for device settings card --- .../src/components/DeviceModelIcon.tsx | 4 +- .../src/components/DeviceFirmwareCard.tsx | 53 ++++++++----------- .../src/components/DeviceSettingsCard.tsx | 44 +++++++++++++++ 3 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 suite-native/device/src/components/DeviceSettingsCard.tsx diff --git a/suite-common/icons-deprecated/src/components/DeviceModelIcon.tsx b/suite-common/icons-deprecated/src/components/DeviceModelIcon.tsx index f1f1986cf96..9600d98c3eb 100644 --- a/suite-common/icons-deprecated/src/components/DeviceModelIcon.tsx +++ b/suite-common/icons-deprecated/src/components/DeviceModelIcon.tsx @@ -17,6 +17,8 @@ const icons = { T3T1: 'trezorT3T1', } as const satisfies Record; +export const deviceModelToIconName = (deviceModel: DeviceModelInternal) => icons[deviceModel]; + export const DeviceModelIcon = ({ deviceModel, size }: DeviceModelIconProps) => ( - + ); diff --git a/suite-native/device/src/components/DeviceFirmwareCard.tsx b/suite-native/device/src/components/DeviceFirmwareCard.tsx index 4929eb7eae3..5cccefcbd00 100644 --- a/suite-native/device/src/components/DeviceFirmwareCard.tsx +++ b/suite-native/device/src/components/DeviceFirmwareCard.tsx @@ -4,18 +4,20 @@ import { useSelector } from 'react-redux'; import { G } from '@mobily/ts-belt'; import { getFwUpdateVersion } from '@suite-common/suite-utils'; -import { DeviceModelIcon } from '@suite-common/icons-deprecated'; +import { deviceModelToIconName } from '@suite-common/icons-deprecated'; import { selectDevice, selectDeviceModel, selectDeviceReleaseInfo, } from '@suite-common/wallet-core'; -import { AlertBox, Box, Card, HStack, Text, VStack } from '@suite-native/atoms'; +import { HStack, Text, VStack } from '@suite-native/atoms'; import { Translation } from '@suite-native/intl'; import { getFirmwareVersion, hasBitcoinOnlyFirmware } from '@trezor/device-utils'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; -const vStackStyle = prepareNativeStyle(() => ({ +import { DeviceSettingsCard } from './DeviceSettingsCard'; + +const firmwareInfoStyle = prepareNativeStyle(() => ({ flexGrow: 1, })); @@ -28,7 +30,7 @@ const FirmwareInfo = ({ label, value }: DeviceInfoProps) => { const { applyStyle } = useNativeStyles(); return ( - + {label} @@ -38,8 +40,6 @@ const FirmwareInfo = ({ label, value }: DeviceInfoProps) => { }; export const DeviceFirmwareCard = () => { - const { applyStyle } = useNativeStyles(); - const device = useSelector(selectDevice); const deviceModel = useSelector(selectDeviceModel); const deviceReleaseInfo = useSelector(selectDeviceReleaseInfo); @@ -79,32 +79,21 @@ export const DeviceFirmwareCard = () => { })(); return ( - - - - - - - - - - - } - value={firmwareVersion} - /> - } - value={} - /> - - + } + alertBoxProps={firmwareUpdateProps} + > + + } + value={firmwareVersion} + /> + } + value={} + /> - {firmwareUpdateProps && ( - - - - )} - + ); }; diff --git a/suite-native/device/src/components/DeviceSettingsCard.tsx b/suite-native/device/src/components/DeviceSettingsCard.tsx new file mode 100644 index 00000000000..21f28e1e3f0 --- /dev/null +++ b/suite-native/device/src/components/DeviceSettingsCard.tsx @@ -0,0 +1,44 @@ +import { ReactNode } from 'react'; + +import { Icon, IconName } from '@suite-common/icons-deprecated'; +import { AlertBox, AlertBoxProps, Box, Card, HStack, Text, VStack } from '@suite-native/atoms'; +import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; + +const contentStyle = prepareNativeStyle(() => ({ + flexGrow: 1, +})); + +export type DeviceSettingsCardProps = { + icon: IconName; + title: ReactNode; + children: ReactNode; + alertBoxProps?: Omit; +}; + +export const DeviceSettingsCard = ({ + icon, + title, + children, + alertBoxProps, +}: DeviceSettingsCardProps) => { + const { applyStyle } = useNativeStyles(); + + return ( + + + + + + + {title} + {children} + + + {alertBoxProps && ( + + + + )} + + ); +}; From 5186cc90edbd6cbfa555e5ee17b18c959b8a01db Mon Sep 17 00:00:00 2001 From: Matej Kriz Date: Fri, 4 Oct 2024 17:45:01 +0200 Subject: [PATCH 088/624] fix(suite-native): enable to confirm receive address outside our app - We are closing device connection on going to background, so we have to reopen it once needed. We can open the device even on background. But Suite has to be still running, not killed. - Closing all the devices OnActivityEntersBackground is a good thing because we want to allow other apps (like browser) to work with the Trezor too and it is a good practice to frees up system resources. --- .../io/trezor/rnusb/ReactNativeUsbModule.kt | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/react-native-usb/android/src/main/java/io/trezor/rnusb/ReactNativeUsbModule.kt b/packages/react-native-usb/android/src/main/java/io/trezor/rnusb/ReactNativeUsbModule.kt index e87aa1508dd..14cdf92544f 100644 --- a/packages/react-native-usb/android/src/main/java/io/trezor/rnusb/ReactNativeUsbModule.kt +++ b/packages/react-native-usb/android/src/main/java/io/trezor/rnusb/ReactNativeUsbModule.kt @@ -150,7 +150,15 @@ class ReactNativeUsbModule : Module() { for (device in devicesList) { if (usbManager.hasPermission(device)) { Log.d(LOG_TAG, "Has permission, send event onDeviceConnected: $device") - val webUsbDevice = openDevice(device.deviceName) + + val webUsbDevice = if (hasOpenedConnection(device.deviceName)) { + Log.d(LOG_TAG, "Device already opened: $device") + getWebUSBDevice(device) + } else { + Log.d(LOG_TAG, "Opening device: $device") + openDevice(device.deviceName) + } + sendEvent(ON_DEVICE_CONNECT_EVENT_NAME, webUsbDevice) devicesHistory[device.deviceName] = webUsbDevice } else if (!devicesRequestedPermissions.contains( @@ -218,7 +226,7 @@ class ReactNativeUsbModule : Module() { Log.e(LOG_TAG, "Failed to open device ${device.deviceName}") throw Exception("Failed to open device ${device.deviceName}") } - Log.d(LOG_TAG, "Opening device ${device.deviceName}") + openedConnections[device.deviceName] = usbConnection // log all endpoints for debug purposes @@ -300,7 +308,10 @@ class ReactNativeUsbModule : Module() { val dataByteArray = data.split(",").map { it.toInt().toByte() }.toByteArray() Log.d(LOG_TAG, "dataByteArray: $dataByteArray") val device = getDeviceByName(deviceName) - val usbConnection = getOpenedConnection(deviceName) + val usbConnection = openedConnections.getOrPut(device.deviceName) { + Log.d(LOG_TAG, "Reopening device ${device.deviceName}") + usbManager.openDevice(device) ?: throw Exception("Failed to open device ${device.deviceName}") + } val usbEndpoint = device.getInterface(INTERFACE_INDEX).getEndpoint(1) if (usbEndpoint == null) { @@ -315,7 +326,11 @@ class ReactNativeUsbModule : Module() { private fun transferIn(deviceName: String, endpointNumber: Int, length: Int): IntArray { Log.d(LOG_TAG, "Reading data from device $deviceName") val device = getDeviceByName(deviceName) - val usbConnection = getOpenedConnection(deviceName) + + val usbConnection = openedConnections.getOrPut(device.deviceName) { + Log.d(LOG_TAG, "Reopening device ${device.deviceName}") + usbManager.openDevice(device) ?: throw Exception("Failed to open device ${device.deviceName}") + } val usbEndpoint = device.getInterface(INTERFACE_INDEX).getEndpoint(0) From 1265005187b95dc484f5b5ecb90a94a121919ac3 Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Tue, 8 Oct 2024 10:06:21 +0200 Subject: [PATCH 089/624] feat(coinmarket): add footer in the whole the section --- .../coinmarket/buy/CoinmarketBuyOffers.tsx | 2 - .../coinmarket/common/CoinmarketContainer.tsx | 8 +- .../CoinmarketFooter/CoinmarketFooter.tsx | 94 ++++++++++--------- .../CoinmarketLayout/CoinmarketLayout.tsx | 2 - .../exchange/CoinmarketExchangeOffers.tsx | 2 - .../coinmarket/sell/CoinmarketSellOffers.tsx | 2 - .../transactions/CoinmarketTransactions.tsx | 12 +-- 7 files changed, 57 insertions(+), 65 deletions(-) diff --git a/packages/suite/src/views/wallet/coinmarket/buy/CoinmarketBuyOffers.tsx b/packages/suite/src/views/wallet/coinmarket/buy/CoinmarketBuyOffers.tsx index 645de53290d..6dd1313441c 100644 --- a/packages/suite/src/views/wallet/coinmarket/buy/CoinmarketBuyOffers.tsx +++ b/packages/suite/src/views/wallet/coinmarket/buy/CoinmarketBuyOffers.tsx @@ -1,7 +1,6 @@ import { useCoinmarketBuyForm } from 'src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm'; import { CoinmarketFormContext } from 'src/hooks/wallet/coinmarket/form/useCoinmarketCommonForm'; import { UseCoinmarketProps } from 'src/types/coinmarket/coinmarket'; -import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common'; import { CoinmarketContainer } from 'src/views/wallet/coinmarket/common/CoinmarketContainer'; import { CoinmarketOffers } from 'src/views/wallet/coinmarket/common/CoinmarketOffers/CoinmarketOffers'; @@ -14,7 +13,6 @@ const CoinmarketBuyOffersComponent = ({ selectedAccount }: UseCoinmarketProps) = return ( - ); }; diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketContainer.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketContainer.tsx index b2d2993c6eb..c606f37427b 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketContainer.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketContainer.tsx @@ -5,6 +5,7 @@ import { PageHeader } from 'src/components/suite/layouts/SuiteLayout'; import { WalletLayout } from 'src/components/wallet'; import { useLayout, useSelector, useTranslation } from 'src/hooks/suite'; import { UseCoinmarketProps } from 'src/types/coinmarket/coinmarket'; +import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter'; interface CoinmarketContainerProps { title?: Extract< @@ -36,5 +37,10 @@ export const CoinmarketContainer = ({ return ; } - return ; + return ( + <> + + + + ); }; diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx index cec4bd1a73f..4ee46c32e32 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketFooter.tsx @@ -1,20 +1,20 @@ -import { variables, Icon, Link, Image } from '@trezor/components'; +import { variables, Icon, Link, Image, Row } from '@trezor/components'; import { useState, useRef } from 'react'; import styled, { css } from 'styled-components'; import { useOnClickOutside } from '@trezor/react-utils'; import { DATA_TOS_INVITY_URL, INVITY_URL } from '@trezor/urls'; import { Translation } from 'src/components/suite'; -import { borders, spacingsPx, zIndices } from '@trezor/theme'; +import { borders, spacings, spacingsPx, zIndices } from '@trezor/theme'; import { CoinmarketFooterLogoWrapper } from 'src/views/wallet/coinmarket'; import { CoinmarketProvidedByInvity } from 'src/views/wallet/coinmarket/common/CoinmarketFooter/CoinmarketProvidedByInvity'; const Wrapper = styled.div` - display: flex; - width: 100%; - align-items: center; - justify-content: center; - padding-top: 20px; margin-top: ${spacingsPx.xxxl}; + padding: ${spacings.zero} ${spacingsPx.lg}; +`; + +const WrapperBorder = styled.div` + padding-top: ${spacingsPx.lg}; border-top: 1px solid ${({ theme }) => theme.borderElevation1}; `; @@ -117,44 +117,48 @@ export const CoinmarketFooter = () => { return ( - - - - - {toggled && ( - -
- - - - - - - - - invity.io - setToggled(false)}> - - - -
- - - - - - -
- )} - - - - - - setToggled(true)}> - - -
+ + + + + + + {toggled && ( + +
+ + + + + + + + + invity.io + setToggled(false)}> + + + +
+ + + + + + +
+ )} + + + + + + setToggled(true)}> + + +
+
+
); }; diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx index 3c9bbd8b863..65dbdb858fd 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayout.tsx @@ -3,7 +3,6 @@ import styled from 'styled-components'; import { WalletLayout, WalletSubpageHeading } from 'src/components/wallet'; import type { SelectedAccountLoaded } from '@suite-common/wallet-types'; -import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common'; import { spacingsPx } from '@trezor/theme'; import { SCREEN_QUERY } from '@trezor/components/src/config/variables'; import { CoinmarketLayoutNavigation } from 'src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketLayoutNavigation/CoinmarketLayoutNavigation'; @@ -31,7 +30,6 @@ export const CoinmarketLayout = ({ children, selectedAccount }: CoinmarketLayout {children} -
); diff --git a/packages/suite/src/views/wallet/coinmarket/exchange/CoinmarketExchangeOffers.tsx b/packages/suite/src/views/wallet/coinmarket/exchange/CoinmarketExchangeOffers.tsx index 1d0692a5eff..eefc3d700dc 100644 --- a/packages/suite/src/views/wallet/coinmarket/exchange/CoinmarketExchangeOffers.tsx +++ b/packages/suite/src/views/wallet/coinmarket/exchange/CoinmarketExchangeOffers.tsx @@ -1,6 +1,5 @@ import { UseCoinmarketProps } from 'src/types/coinmarket/coinmarket'; import { CoinmarketOffers } from 'src/views/wallet/coinmarket/common/CoinmarketOffers/CoinmarketOffers'; -import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common'; import { useCoinmarketExchangeForm } from 'src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm'; import { CoinmarketContainer } from 'src/views/wallet/coinmarket/common/CoinmarketContainer'; import { CoinmarketFormContext } from 'src/hooks/wallet/coinmarket/form/useCoinmarketCommonForm'; @@ -14,7 +13,6 @@ const CoinmarketExchangeOffersComponent = ({ selectedAccount }: UseCoinmarketPro return ( - ); }; diff --git a/packages/suite/src/views/wallet/coinmarket/sell/CoinmarketSellOffers.tsx b/packages/suite/src/views/wallet/coinmarket/sell/CoinmarketSellOffers.tsx index af216b5dd13..686d9d88832 100644 --- a/packages/suite/src/views/wallet/coinmarket/sell/CoinmarketSellOffers.tsx +++ b/packages/suite/src/views/wallet/coinmarket/sell/CoinmarketSellOffers.tsx @@ -1,7 +1,6 @@ import { UseCoinmarketProps } from 'src/types/coinmarket/coinmarket'; import { CoinmarketFormContext } from 'src/hooks/wallet/coinmarket/form/useCoinmarketCommonForm'; import { useCoinmarketSellForm } from 'src/hooks/wallet/coinmarket/form/useCoinmarketSellForm'; -import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common'; import { CoinmarketOffers } from 'src/views/wallet/coinmarket/common/CoinmarketOffers/CoinmarketOffers'; import { CoinmarketContainer } from 'src/views/wallet/coinmarket/common/CoinmarketContainer'; @@ -14,7 +13,6 @@ const CoinmarketSellOffersComponent = ({ selectedAccount }: UseCoinmarketProps) return ( - ); }; diff --git a/packages/suite/src/views/wallet/coinmarket/transactions/CoinmarketTransactions.tsx b/packages/suite/src/views/wallet/coinmarket/transactions/CoinmarketTransactions.tsx index 236afd4e159..3fc95d07587 100644 --- a/packages/suite/src/views/wallet/coinmarket/transactions/CoinmarketTransactions.tsx +++ b/packages/suite/src/views/wallet/coinmarket/transactions/CoinmarketTransactions.tsx @@ -1,20 +1,10 @@ -import { CoinmarketFooter } from 'src/views/wallet/coinmarket/common'; import { CoinmarketAccountTransactions } from 'src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/CoinmarketAccountTransactions'; import { CoinmarketContainer } from 'src/views/wallet/coinmarket/common/CoinmarketContainer'; -const CoinmarketTransactionsComponent = () => { - return ( - <> - - - - ); -}; - export const CoinmarketTransactions = () => ( ); From 7ff9d263e8e2d30b8744737f616932a580daaabd Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Tue, 8 Oct 2024 10:12:41 +0200 Subject: [PATCH 090/624] fix(coinamarket): replaced exchange with swap --- packages/suite/src/support/messages.ts | 17 +++++------------ .../CoinmarketAccountTransactions.tsx | 12 ++++++++---- .../ExchangeTransaction.tsx | 6 ++++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index a710def385c..ed46588d612 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -1166,6 +1166,10 @@ export default defineMessages({ defaultMessage: 'Last transactions', id: 'TR_COINMARKET_LAST_TRANSACTIONS', }, + TR_COINMARKET_TRANSACTION_COUNTER: { + defaultMessage: '{totalBuys} buys • {totalSells} sells • {totalSwaps} swaps', + id: 'TR_COINMARKET_TRANSACTION_COUNTER', + }, TR_COINMARKET_PAYMENT_METHOD: { defaultMessage: 'Payment method', id: 'TR_COINMARKET_PAYMENT_METHOD', @@ -1419,6 +1423,7 @@ export default defineMessages({ defaultMessage: 'Swap', id: 'TR_COINMARKET_SWAP', }, + TR_ADDRESS_MODAL_CLIPBOARD: { defaultMessage: 'Copy address', id: 'TR_ADDRESS_MODAL_CLIPBOARD', @@ -4440,18 +4445,6 @@ export default defineMessages({ defaultMessage: 'This is the specific alphanumeric address that will receive your coins. Verify this address on your Trezor.', }, - TR_TRADE_BUYS: { - id: 'TR_TRADE_BUYS', - defaultMessage: 'buys', - }, - TR_TRADE_SELLS: { - id: 'TR_TRADE_SELLS', - defaultMessage: 'sells', - }, - TR_TRADE_EXCHANGES: { - id: 'TR_TRADE_EXCHANGES', - defaultMessage: 'exchanges', - }, TR_PAYMENT_METHOD_CREDITCARD: { id: 'TR_PAYMENT_METHOD_CREDITCARD', defaultMessage: 'Credit Card', diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/CoinmarketAccountTransactions.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/CoinmarketAccountTransactions.tsx index 4c9d000696f..75afd061885 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/CoinmarketAccountTransactions.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/CoinmarketAccountTransactions.tsx @@ -81,10 +81,14 @@ export const CoinmarketAccountTransactions = () => {

- {buyTransactions.length} •{' '} - {sellTransactions.length} •{' '} - {exchangeTransactions.length}{' '} - +

diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx index b9ac0266ca3..aa75db49db8 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx @@ -8,7 +8,7 @@ import { goto } from 'src/actions/suite/routerActions'; import { saveTransactionId } from 'src/actions/wallet/coinmarketExchangeActions'; import { Account } from 'src/types/wallet'; import { Translation, FormattedDate, FormattedCryptoAmount } from 'src/components/suite'; -import { useDispatch } from 'src/hooks/suite'; +import { useDispatch, useTranslation } from 'src/hooks/suite'; import { useCoinmarketWatchTrade } from 'src/hooks/wallet/coinmarket/useCoinmarketWatchTrade'; import { useCoinmarketInfo } from 'src/hooks/wallet/coinmarket/useCoinmarketInfo'; import { CoinmarketTransactionStatus } from 'src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/CoinmarketTransactionStatus'; @@ -109,6 +109,7 @@ interface ExchangeTransactionProps { export const ExchangeTransaction = ({ trade, providers, account }: ExchangeTransactionProps) => { const dispatch = useDispatch(); + const { translationString } = useTranslation(); const theme = useTheme(); useCoinmarketWatchTrade({ account, trade }); const { cryptoIdToCoinSymbol } = useCoinmarketInfo(); @@ -147,7 +148,8 @@ export const ExchangeTransaction = ({ trade, providers, account }: ExchangeTrans {/* */} - {trade.tradeType.toUpperCase()} • •{' '} + {translationString('TR_COINMARKET_SWAP').toUpperCase()} •{' '} + •{' '} From 45d34290dcc655e5326d9f84c64af10cef4672de Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Tue, 8 Oct 2024 10:47:15 +0200 Subject: [PATCH 091/624] fix(coinmarket): buy empty array in request --- .../coinmarket/form/useCoinmarketBuyForm.tsx | 83 +++++++++---------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx index 4c76c4f24b2..44e9e376f5f 100644 --- a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx +++ b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketBuyForm.tsx @@ -204,54 +204,51 @@ export const useCoinmarketBuyForm = ({ const quoteRequest = getQuoteRequestData(); const allQuotes = await getQuotesRequest(quoteRequest, offLoading); - if (Array.isArray(allQuotes)) { - if (allQuotes.length === 0) { - timer.stop(); - - return; - } + if (!Array.isArray(allQuotes) || allQuotes.length === 0) { + timer.stop(); + setInnerQuotes([]); + setIsSubmittingHelper(false); - // processed quotes and without alternative quotes - const quotesDefault = filterQuotesAccordingTags( - addIdsToQuotes(allQuotes, 'buy'), - ); - // without errors - const quotesSuccess = - coinmarketGetSuccessQuotes(quotesDefault) ?? []; - - const bestQuote = quotesSuccess?.[0]; - const bestQuotePaymentMethod = bestQuote?.paymentMethod; - const bestQuotePaymentMethodName = - bestQuote?.paymentMethodName ?? bestQuotePaymentMethod; - const paymentMethodSelected = values.paymentMethod?.value; - const paymentMethodsFromQuotes = getPaymentMethods(quotesSuccess); - const isSelectedPaymentMethodAvailable = - paymentMethodsFromQuotes.find(item => item.value === paymentMethodSelected) !== - undefined; - const limits = getAmountLimits(quoteRequest, quotesDefault); // from all quotes except alternative - if (limits && quoteRequest.wantCrypto) { - limits.currency = - cryptoIdToCoinSymbol(quoteRequest.receiveCurrency) ?? limits.currency; - } + return; + } - setInnerQuotes(quotesSuccess); - dispatch(coinmarketBuyActions.saveQuotes(quotesSuccess)); - dispatch(coinmarketBuyActions.saveQuoteRequest(quoteRequest)); - dispatch(coinmarketInfoActions.savePaymentMethods(paymentMethodsFromQuotes)); - setAmountLimits(limits); - - if (!paymentMethodSelected || !isSelectedPaymentMethodAvailable) { - setValue(FORM_PAYMENT_METHOD_SELECT, { - value: bestQuotePaymentMethod ?? '', - label: bestQuotePaymentMethodName ?? '', - }); - } + // processed quotes and without alternative quotes + const quotesDefault = filterQuotesAccordingTags( + addIdsToQuotes(allQuotes, 'buy'), + ); + // without errors + const quotesSuccess = + coinmarketGetSuccessQuotes(quotesDefault) ?? []; + + const bestQuote = quotesSuccess?.[0]; + const bestQuotePaymentMethod = bestQuote?.paymentMethod; + const bestQuotePaymentMethodName = + bestQuote?.paymentMethodName ?? bestQuotePaymentMethod; + const paymentMethodSelected = values.paymentMethod?.value; + const paymentMethodsFromQuotes = getPaymentMethods(quotesSuccess); + const isSelectedPaymentMethodAvailable = + paymentMethodsFromQuotes.find(item => item.value === paymentMethodSelected) !== + undefined; + const limits = getAmountLimits(quoteRequest, quotesDefault); // from all quotes except alternative + if (limits && quoteRequest.wantCrypto) { + limits.currency = + cryptoIdToCoinSymbol(quoteRequest.receiveCurrency) ?? limits.currency; + } - setIsSubmittingHelper(false); - } else { - setInnerQuotes([]); + setInnerQuotes(quotesSuccess); + dispatch(coinmarketBuyActions.saveQuotes(quotesSuccess)); + dispatch(coinmarketBuyActions.saveQuoteRequest(quoteRequest)); + dispatch(coinmarketInfoActions.savePaymentMethods(paymentMethodsFromQuotes)); + setAmountLimits(limits); + + if (!paymentMethodSelected || !isSelectedPaymentMethodAvailable) { + setValue(FORM_PAYMENT_METHOD_SELECT, { + value: bestQuotePaymentMethod ?? '', + label: bestQuotePaymentMethodName ?? '', + }); } + setIsSubmittingHelper(false); timer.reset(); }, [ From ba1b0b4f559dd3a40ece38f2ece446932deefb05 Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Tue, 8 Oct 2024 12:46:36 +0200 Subject: [PATCH 092/624] fix(coinmarket): saving trades to selected account --- .../coinmarket/form/useCoinmarketExchangeForm.ts | 10 +++++++--- .../coinmarket/form/useCoinmarketSellForm.ts | 14 +++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts index 94fe7c9958e..55d025519c8 100644 --- a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts +++ b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketExchangeForm.ts @@ -397,7 +397,11 @@ export const useCoinmarketExchangeForm = ({ } else { // CONFIRMING, SUCCESS dispatch( - coinmarketExchangeActions.saveTrade(response, account, new Date().toISOString()), + coinmarketExchangeActions.saveTrade( + response, + selectedAccount.account, + new Date().toISOString(), + ), ); dispatch(coinmarketExchangeActions.saveTransactionId(response.orderId)); ok = true; @@ -437,7 +441,7 @@ export const useCoinmarketExchangeForm = ({ dispatch( coinmarketExchangeActions.saveTrade( quote, - account, + selectedAccount.account, new Date().toISOString(), ), ); @@ -490,7 +494,7 @@ export const useCoinmarketExchangeForm = ({ dispatch( coinmarketExchangeActions.saveTrade( selectedQuote, - account, + selectedAccount.account, new Date().toISOString(), ), ); diff --git a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketSellForm.ts b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketSellForm.ts index 630a850e9fd..4c3aec96f04 100644 --- a/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketSellForm.ts +++ b/packages/suite/src/hooks/wallet/coinmarket/form/useCoinmarketSellForm.ts @@ -355,7 +355,7 @@ export const useCoinmarketSellForm = ({ dispatch( coinmarketSellActions.saveTrade( response.trade, - account, + selectedAccount.account, new Date().toISOString(), ), ); @@ -499,15 +499,19 @@ export const useCoinmarketSellForm = ({ } dispatch( - coinmarketSellActions.saveTrade(response, account, new Date().toISOString()), + coinmarketSellActions.saveTrade( + response, + selectedAccount.account, + new Date().toISOString(), + ), ); dispatch(coinmarketSellActions.saveTransactionId(selectedQuote.orderId)); dispatch( routerActions.goto('wallet-coinmarket-sell-detail', { params: { - symbol: account.symbol, - accountIndex: account.index, - accountType: account.accountType, + symbol: selectedAccount.account.symbol, + accountIndex: selectedAccount.account.index, + accountType: selectedAccount.account.accountType, }, }), ); From 2270b00b5fca5accec55c5ef43a4049a598f3ddd Mon Sep 17 00:00:00 2001 From: Martin Homola Date: Tue, 8 Oct 2024 12:53:27 +0200 Subject: [PATCH 093/624] fix(coinmarket): exchange send cryptocurrency --- .../ExchangeTransaction.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx index aa75db49db8..ee33df7bcd8 100644 --- a/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx +++ b/packages/suite/src/views/wallet/coinmarket/common/CoinmarketLayout/CoinmarketAccountTransactions/ExchangeTransaction.tsx @@ -130,19 +130,24 @@ export const ExchangeTransaction = ({ trade, providers, account }: ExchangeTrans ); }; + if (!send || !receive) return null; + return ( - + {/* TODO FIX THIS LOGO */} {/* */} From 5080309d582cb056fa720bbdaf1f6d64fa180110 Mon Sep 17 00:00:00 2001 From: Matej Kriz Date: Thu, 10 Oct 2024 17:39:32 +0200 Subject: [PATCH 094/624] chore(suite-native): add adhoc distribution --- .gitignore | 1 + package.json | 1 + suite-native/app/.env.preview | 3 +++ suite-native/app/app.config.ts | 21 +++++++++++++++--- .../assets/{staging => preview}/appIcon.png | Bin suite-native/app/eas.json | 10 +++++++++ suite-native/app/package.json | 1 + suite-native/config/src/environment.ts | 5 ++++- 8 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 suite-native/app/.env.preview rename suite-native/app/assets/{staging => preview}/appIcon.png (100%) diff --git a/.gitignore b/.gitignore index 9f221c73a26..2a677115d90 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ local.properties !**/suite-native/app/.env.debug !**/suite-native/app/.env.develop +!**/suite-native/app/.env.preview !**/suite-native/app/.env.production !**/suite-native/app/.env.staging diff --git a/package.json b/package.json index 0206503c0f3..095a6c3dcdf 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "native:ios": "yarn workspace @suite-native/app ios", "native:prebuild": "yarn workspace @suite-native/app prebuild", "native:prebuild:clean": "yarn workspace @suite-native/app prebuild:clean", + "native:adhoc": "yarn workspace @suite-native/app build:adhoc", "native:reverse-ports": "yarn workspace @suite-native/app reverse-ports", "_______ Aliases _______": "Aliases for longer commands which we often have to run manually. Names don't have to be pretty or make total sense.", "refs": "yarn update-project-references", diff --git a/suite-native/app/.env.preview b/suite-native/app/.env.preview new file mode 100644 index 00000000000..605b5f252dd --- /dev/null +++ b/suite-native/app/.env.preview @@ -0,0 +1,3 @@ +EXPO_PUBLIC_ENVIRONMENT=preview +EXPO_PUBLIC_CODESIGN_BUILD=false +EXPO_PUBLIC_BLUETOOTH_ENABLED=true diff --git a/suite-native/app/app.config.ts b/suite-native/app/app.config.ts index 2af7e4ae253..d09f43cf9c7 100644 --- a/suite-native/app/app.config.ts +++ b/suite-native/app/app.config.ts @@ -5,18 +5,20 @@ import { ExpoConfig, ConfigContext } from 'expo/config'; import { suiteNativeVersion } from './package.json'; -type BuildType = 'debug' | 'develop' | 'production'; +type BuildType = 'debug' | 'preview' | 'develop' | 'production'; type ExpoPlugins = ExpoConfig['plugins']; const bundleIdentifiers = { debug: 'io.trezor.suite.debug', + preview: 'io.trezor.suite.preview', develop: 'io.trezor.suite.develop', production: 'io.trezor.suite', } as const satisfies Record; const appIconsIos = { debug: './assets/debug/appIcon.png', + preview: './assets/preview/appIcon.png', develop: './assets/develop/appIcon.png', production: './assets/production/appIcon.png', } as const satisfies Record; @@ -25,6 +27,9 @@ const appIconsAndroid = { debug: { backgroundColor: '#2587A5', }, + preview: { + backgroundColor: '#E59D17', + }, develop: { backgroundColor: '#900B0B', }, @@ -35,18 +40,28 @@ const appIconsAndroid = { const appNames = { debug: 'Trezor Suite Lite Debug', + preview: 'Trezor Suite Lite Preview', develop: 'Trezor Suite Lite Develop', production: 'Trezor Suite Lite', } as const satisfies Record; const appSlugs = { debug: 'trezor-suite-debug', + preview: 'trezor-suite-preview', develop: 'trezor-suite-develop', production: 'trezor-suite', } as const satisfies Record; +const appOwners = { + debug: 'trezorcompany-develop', + preview: 'trezorcompany-develop', + develop: 'trezorcompany-develop', + production: 'trezorcompany', +} as const satisfies Record; + const projectIds = { - develop: '3e4ea82b-6c9f-4cd3-8975-54bddda3ec2d', + develop: '7deae0c5-11be-49ff-a872-f538223c57de', + preview: '15998f8a-e75c-4b60-959d-6f68e5ff4936', production: 'b9bbf16c-3d44-4d58-8f0c-ba9e6265276a', debug: '', } as const satisfies Record; @@ -152,7 +167,7 @@ export default ({ config }: ConfigContext): ExpoConfig => { name, scheme: buildType === 'production' ? undefined : 'trezorsuitelite', slug: appSlugs[buildType], - owner: 'trezorcompany', + owner: appOwners[buildType], version: suiteNativeVersion, orientation: 'portrait', splash: { diff --git a/suite-native/app/assets/staging/appIcon.png b/suite-native/app/assets/preview/appIcon.png similarity index 100% rename from suite-native/app/assets/staging/appIcon.png rename to suite-native/app/assets/preview/appIcon.png diff --git a/suite-native/app/eas.json b/suite-native/app/eas.json index 077696f82d2..f84a7c3be0d 100644 --- a/suite-native/app/eas.json +++ b/suite-native/app/eas.json @@ -19,6 +19,16 @@ "resourceClass": "large" } }, + "adhoc": { + "env": { + "EXPO_PUBLIC_ENVIRONMENT": "preview", + "EXPO_PUBLIC_BLUETOOTH_ENABLED": "true", + "EXPO_PUBLIC_CODESIGN_BUILD": "false" + }, + "autoIncrement": true, + "credentialsSource": "remote", + "distribution": "internal" + }, "production": { "env": { "EXPO_PUBLIC_ENVIRONMENT": "production", diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 5f1c8e93558..18f2e18aa2e 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -12,6 +12,7 @@ "type-check": "yarn g:tsc -b", "pods": "npx pod-install", "prebuild": "expo prebuild", + "build:adhoc": "npx eas-cli build --profile adhoc", "eas-build-post-install": "yarn workspace @suite-common/message-system sign-config", "eas-build-on-success": "./eas-post-success.sh", "prebuild:clean": "expo prebuild --clean", diff --git a/suite-native/config/src/environment.ts b/suite-native/config/src/environment.ts index e41ecc8d5fa..b6df17e25f3 100644 --- a/suite-native/config/src/environment.ts +++ b/suite-native/config/src/environment.ts @@ -1,5 +1,8 @@ export const isDebugEnv = () => process.env.EXPO_PUBLIC_ENVIRONMENT === 'debug'; -export const isDevelopEnv = () => process.env.EXPO_PUBLIC_ENVIRONMENT === 'develop'; +// From app perspective, develop and preview are the same environment. The difference is in the build process. +export const isDevelopEnv = () => + process.env.EXPO_PUBLIC_ENVIRONMENT === 'develop' || + process.env.EXPO_PUBLIC_ENVIRONMENT === 'preview'; export const isProduction = () => process.env.EXPO_PUBLIC_ENVIRONMENT === 'production'; export const isDevelopOrDebugEnv = () => isDebugEnv() || isDevelopEnv(); From c51e1f54dc0c2d956e4bd54c4c63e95b11eebcd1 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Mon, 7 Oct 2024 20:20:10 +0200 Subject: [PATCH 095/624] feat(suite-native): report send review app exit to analytics --- suite-native/analytics/src/events.ts | 1 + suite-native/module-send/package.json | 1 + .../src/atoms/wasAppLeftDuringReviewAtom.ts | 3 +++ .../src/components/AddressReviewStepList.tsx | 25 ++++++++++++++++--- .../src/components/OutputsReviewFooter.tsx | 6 ++++- yarn.lock | 1 + 6 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 suite-native/module-send/src/atoms/wasAppLeftDuringReviewAtom.ts diff --git a/suite-native/analytics/src/events.ts b/suite-native/analytics/src/events.ts index 12aa8c0cf1f..2070c5521f1 100644 --- a/suite-native/analytics/src/events.ts +++ b/suite-native/analytics/src/events.ts @@ -266,6 +266,7 @@ export type SuiteNativeAnalyticsEvent = symbol: NetworkSymbol; outputsCount: number; selectedFee: FeeLevelLabel; + wasAppLeftDuringReview: boolean; tokenSymbols?: TokenSymbol[]; tokenAddresses?: TokenAddress[]; hasEthereumData?: boolean; diff --git a/suite-native/module-send/package.json b/suite-native/module-send/package.json index 2c518606a5a..e8734368a0e 100644 --- a/suite-native/module-send/package.json +++ b/suite-native/module-send/package.json @@ -44,6 +44,7 @@ "@trezor/transport": "workspace:*", "@trezor/utils": "workspace:*", "expo-linear-gradient": "13.0.2", + "jotai": "1.9.1", "react": "18.2.0", "react-hook-form": "^7.53.0", "react-native": "0.75.2", diff --git a/suite-native/module-send/src/atoms/wasAppLeftDuringReviewAtom.ts b/suite-native/module-send/src/atoms/wasAppLeftDuringReviewAtom.ts new file mode 100644 index 00000000000..492b3cfe4f0 --- /dev/null +++ b/suite-native/module-send/src/atoms/wasAppLeftDuringReviewAtom.ts @@ -0,0 +1,3 @@ +import { atom } from 'jotai'; + +export const wasAppLeftDuringReviewAtom = atom(false); diff --git a/suite-native/module-send/src/components/AddressReviewStepList.tsx b/suite-native/module-send/src/components/AddressReviewStepList.tsx index a2ad4d1fd61..2e9c96f2b11 100644 --- a/suite-native/module-send/src/components/AddressReviewStepList.tsx +++ b/suite-native/module-send/src/components/AddressReviewStepList.tsx @@ -1,9 +1,10 @@ +import { useCallback, useEffect, useState } from 'react'; +import { LayoutChangeEvent, View, AppState } from 'react-native'; import { useDispatch, useSelector } from 'react-redux'; -import { useEffect, useState } from 'react'; -import { LayoutChangeEvent, View } from 'react-native'; +import { useSetAtom } from 'jotai'; import { isRejected } from '@reduxjs/toolkit'; -import { useNavigation, useRoute } from '@react-navigation/native'; +import { useNavigation, useRoute, useFocusEffect } from '@react-navigation/native'; import { RootStackParamList, @@ -27,6 +28,7 @@ import { AddressReviewStep } from '../components/AddressReviewStep'; import { CompareAddressHelpButton } from '../components/CompareAddressHelpButton'; import { AddressOriginHelpButton } from '../components/AddressOriginHelpButton'; import { useHandleSendReviewFailure } from '../hooks/useHandleSendReviewFailure'; +import { wasAppLeftDuringReviewAtom } from '../atoms/wasAppLeftDuringReviewAtom'; const NUMBER_OF_STEPS = 3; const OVERLAY_INITIAL_POSITION = 75; @@ -48,6 +50,23 @@ export const AddressReviewStepList = () => { const [childHeights, setChildHeights] = useState([]); const [stepIndex, setStepIndex] = useState(0); const handleSendReviewFailure = useHandleSendReviewFailure({ accountKey, transaction }); + const setWasAppLeftDuringReview = useSetAtom(wasAppLeftDuringReviewAtom); + + useFocusEffect( + useCallback(() => { + setWasAppLeftDuringReview(false); + + const subscription = AppState.addEventListener('change', nextAppState => { + if (nextAppState === 'background') { + setWasAppLeftDuringReview(true); + } + }); + + return () => { + subscription.remove(); + }; + }, [setWasAppLeftDuringReview]), + ); const areAllStepsDone = stepIndex === NUMBER_OF_STEPS - 1; const isLayoutReady = childHeights.length === NUMBER_OF_STEPS; diff --git a/suite-native/module-send/src/components/OutputsReviewFooter.tsx b/suite-native/module-send/src/components/OutputsReviewFooter.tsx index 9f97f7e7a1d..697118e1468 100644 --- a/suite-native/module-send/src/components/OutputsReviewFooter.tsx +++ b/suite-native/module-send/src/components/OutputsReviewFooter.tsx @@ -1,7 +1,8 @@ +import { useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import Animated, { SlideInDown } from 'react-native-reanimated'; -import { useState } from 'react'; +import { useAtomValue } from 'jotai'; import { CommonActions, useNavigation } from '@react-navigation/native'; import { isFulfilled } from '@reduxjs/toolkit'; @@ -21,6 +22,7 @@ import { analytics, EventType } from '@suite-native/analytics'; import { SendConfirmOnDeviceImage } from '../components/SendConfirmOnDeviceImage'; import { sendTransactionAndCleanupSendFormThunk } from '../sendFormThunks'; +import { wasAppLeftDuringReviewAtom } from '../atoms/wasAppLeftDuringReviewAtom'; const navigateToAccountDetail = ({ accountKey, @@ -64,6 +66,7 @@ export const OutputsReviewFooter = ({ accountKey }: { accountKey: AccountKey }) const navigation = useNavigation(); const { applyStyle } = useNativeStyles(); const [isSendInProgress, setIsSendInProgress] = useState(false); + const wasAppLeftDuringReview = useAtomValue(wasAppLeftDuringReviewAtom); const account = useSelector((state: AccountsRootState) => selectAccountByKey(state, accountKey), @@ -94,6 +97,7 @@ export const OutputsReviewFooter = ({ accountKey }: { accountKey: AccountKey }) symbol: account.symbol, outputsCount: formValues.outputs.length, selectedFee: formValues.selectedFee ?? 'normal', + wasAppLeftDuringReview, }, }); } diff --git a/yarn.lock b/yarn.lock index 4e061f831af..badb9c5bc1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10368,6 +10368,7 @@ __metadata: "@trezor/transport": "workspace:*" "@trezor/utils": "workspace:*" expo-linear-gradient: "npm:13.0.2" + jotai: "npm:1.9.1" react: "npm:18.2.0" react-hook-form: "npm:^7.53.0" react-native: "npm:0.75.2" From cb2d5d1861c74fab0d9744842a68ef1e6730b129 Mon Sep 17 00:00:00 2001 From: Matej Kriz Date: Fri, 11 Oct 2024 11:37:00 +0200 Subject: [PATCH 096/624] fix(suite-native): fix development CI builds broken while adding adhoc builds --- suite-native/app/app.config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/suite-native/app/app.config.ts b/suite-native/app/app.config.ts index d09f43cf9c7..21822a214c1 100644 --- a/suite-native/app/app.config.ts +++ b/suite-native/app/app.config.ts @@ -53,14 +53,14 @@ const appSlugs = { } as const satisfies Record; const appOwners = { - debug: 'trezorcompany-develop', + debug: 'trezorcompany', preview: 'trezorcompany-develop', - develop: 'trezorcompany-develop', + develop: 'trezorcompany', production: 'trezorcompany', } as const satisfies Record; const projectIds = { - develop: '7deae0c5-11be-49ff-a872-f538223c57de', + develop: '3e4ea82b-6c9f-4cd3-8975-54bddda3ec2d', preview: '15998f8a-e75c-4b60-959d-6f68e5ff4936', production: 'b9bbf16c-3d44-4d58-8f0c-ba9e6265276a', debug: '', From decfe32132516cbbd8ac78fc0c7ec235a5e1cf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Such=C3=BD?= Date: Fri, 11 Oct 2024 13:25:13 +0200 Subject: [PATCH 097/624] feat(mobile): bottom sheet flashlist (#14681) --- suite-native/accounts/package.json | 1 - .../components/AccountSelectBottomSheet.tsx | 35 ++--- .../AccountsList/AccountsListItemBase.tsx | 2 +- suite-native/accounts/src/selectors.ts | 2 +- suite-native/atoms/package.json | 1 + suite-native/atoms/src/Sheet/BottomSheet.tsx | 2 +- .../atoms/src/Sheet/BottomSheetContainer.tsx | 28 ++-- .../atoms/src/Sheet/BottomSheetFlashList.tsx | 145 ++++++++++++++++++ suite-native/atoms/src/index.ts | 1 + suite-native/intl/src/en.ts | 1 + .../src/components/DevXpub.tsx | 12 +- .../screens/AccountsScreen/AccountsScreen.tsx | 9 +- yarn.lock | 2 +- 13 files changed, 207 insertions(+), 34 deletions(-) create mode 100644 suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx diff --git a/suite-native/accounts/package.json b/suite-native/accounts/package.json index 4fe2085c925..f23f9cb090b 100644 --- a/suite-native/accounts/package.json +++ b/suite-native/accounts/package.json @@ -14,7 +14,6 @@ "dependencies": { "@mobily/ts-belt": "^3.13.1", "@react-navigation/native": "6.1.18", - "@shopify/flash-list": "1.7.1", "@suite-common/formatters": "workspace:*", "@suite-common/icons-deprecated": "workspace:*", "@suite-common/token-definitions": "workspace:*", diff --git a/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx b/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx index 6ebeae195cc..b6e71496c73 100644 --- a/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx +++ b/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx @@ -1,10 +1,8 @@ import React, { useCallback } from 'react'; -import { FlashList } from '@shopify/flash-list'; - -import { BottomSheet } from '@suite-native/atoms'; -import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; -import { useToast } from '@suite-native/toasts'; +import { BottomSheetFlashList } from '@suite-native/atoms'; +import { ToastRenderer, useToast } from '@suite-native/toasts'; +import { Translation } from '@suite-native/intl'; import { AccountSelectBottomSheetSection, OnSelectAccount } from '../types'; import { AccountsListItem } from './AccountsList/AccountsListItem'; @@ -19,9 +17,7 @@ type AccountSelectBottomSheetProps = { onClose: () => void; }; -const contentContainerStyle = prepareNativeStyle(utils => ({ - paddingHorizontal: utils.spacings.sp16, -})); +const ESTIMATED_ITEM_SIZE = 76; export const AccountSelectBottomSheet = React.memo( ({ @@ -30,7 +26,6 @@ export const AccountSelectBottomSheet = React.memo( isStakingPressable = false, onClose, }: AccountSelectBottomSheetProps) => { - const { applyStyle } = useNativeStyles(); const { showToast } = useToast(); const renderItem = useCallback( @@ -63,7 +58,9 @@ export const AccountSelectBottomSheet = React.memo( } else { showToast({ variant: 'warning', - message: 'Staking is not available in this context.', + message: ( + + ), }); } }} @@ -93,14 +90,16 @@ export const AccountSelectBottomSheet = React.memo( ); return ( - - - + + isVisible + isCloseDisplayed={false} + onClose={onClose} + data={data} + renderItem={renderItem} + estimatedItemSize={ESTIMATED_ITEM_SIZE} + estimatedListHeight={ESTIMATED_ITEM_SIZE * data.length} + ExtraProvider={ToastRenderer} + /> ); }, ); diff --git a/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx b/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx index 9fecf9fb354..14c72c72d8d 100644 --- a/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx +++ b/suite-native/accounts/src/components/AccountsList/AccountsListItemBase.tsx @@ -54,7 +54,7 @@ const accountListItemStyle = prepareNativeStyle<{ style: { borderBottomLeftRadius: utils.borders.radii.r16, borderBottomRightRadius: utils.borders.radii.r16, - marginBottom: utils.spacings.sp32, + marginBottom: utils.spacings.sp16, ...utils.boxShadows.small, }, }, diff --git a/suite-native/accounts/src/selectors.ts b/suite-native/accounts/src/selectors.ts index 653f57ec1dd..ada96607a17 100644 --- a/suite-native/accounts/src/selectors.ts +++ b/suite-native/accounts/src/selectors.ts @@ -87,7 +87,7 @@ export const selectAccountFiatBalance = (state: NativeAccountsRootState, account return totalBalance; }; -const EMPTY_ARRAY: any[] = []; +const EMPTY_ARRAY: AccountSelectBottomSheetSection[] = []; export const selectAccountListSections = memoizeWithArgs( (state: NativeAccountsRootState, accountKey?: AccountKey | null, hideStaking?: boolean) => { diff --git a/suite-native/atoms/package.json b/suite-native/atoms/package.json index 9df528f06bb..f29f32097ad 100644 --- a/suite-native/atoms/package.json +++ b/suite-native/atoms/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@mobily/ts-belt": "^3.13.1", + "@shopify/flash-list": "1.7.1", "@shopify/react-native-skia": "1.3.11", "@suite-common/icons-deprecated": "workspace:*", "@suite-native/config": "workspace:*", diff --git a/suite-native/atoms/src/Sheet/BottomSheet.tsx b/suite-native/atoms/src/Sheet/BottomSheet.tsx index 42dab87dc69..809dc62a09b 100644 --- a/suite-native/atoms/src/Sheet/BottomSheet.tsx +++ b/suite-native/atoms/src/Sheet/BottomSheet.tsx @@ -95,7 +95,7 @@ export const BottomSheet = ({ void; + ExtraProvider?: React.ComponentType; }; const ContentWrapperStyle = prepareNativeStyle(_ => ({ flex: 1 })); @@ -21,19 +22,28 @@ const BottomSheetGestureHandler = gestureHandlerRootHOC<{ children: ReactNode }> <>{children} )); -export const BottomSheetContainer = ({ children, isVisible, onClose }: SheetProps) => { +export const BottomSheetContainer = ({ + children, + isVisible, + onClose, + ExtraProvider, +}: SheetProps) => { const { applyStyle } = useNativeStyles(); return ( - - - {children} - - + <> + + + {children} + + + + {ExtraProvider && } + ); }; diff --git a/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx b/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx new file mode 100644 index 00000000000..d234fc26366 --- /dev/null +++ b/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx @@ -0,0 +1,145 @@ +import { useEffect, useRef, ReactNode } from 'react'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import Animated from 'react-native-reanimated'; +import { PanGestureHandler } from 'react-native-gesture-handler'; +import { GestureResponderEvent, Pressable, Dimensions } from 'react-native'; + +import { FlashList, FlashListProps } from '@shopify/flash-list'; + +import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; + +import { Box } from '../Box'; +import { BottomSheetContainer } from './BottomSheetContainer'; +import { useBottomSheetAnimation } from './useBottomSheetAnimation'; +import { BottomSheetHeader } from './BottomSheetHeader'; + +export type BottomSheetFlashListProps = { + isVisible: boolean; + isCloseDisplayed?: boolean; + onClose: (isVisible: boolean) => void; + title?: ReactNode; + subtitle?: ReactNode; + ExtraProvider?: React.ComponentType; + estimatedListHeight?: number; +} & FlashListProps; + +const DEFAULT_INSET_BOTTOM = 50; + +const sheetWrapperStyle = prepareNativeStyle(utils => ({ + backgroundColor: utils.colors.backgroundSurfaceElevation0, + borderTopLeftRadius: utils.borders.radii.r20, + borderTopRightRadius: utils.borders.radii.r20, + maxHeight: '80%', +})); + +const sheetContentContainerStyle = prepareNativeStyle<{ + insetBottom: number; +}>((utils, { insetBottom }) => ({ + paddingBottom: Math.max(insetBottom, utils.spacings.sp16), + paddingHorizontal: utils.spacings.sp16, +})); + +const sheetWithOverlayStyle = prepareNativeStyle(_ => ({ + flex: 1, + justifyContent: 'flex-end', +})); + +export const BottomSheetFlashList = ({ + isVisible, + isCloseDisplayed = true, + onClose, + title, + subtitle, + ExtraProvider, + estimatedListHeight = 0, + ...flashListProps +}: BottomSheetFlashListProps) => { + const { applyStyle } = useNativeStyles(); + const insets = useSafeAreaInsets(); + const { + animatedSheetWithOverlayStyle, + animatedSheetWrapperStyle, + closeSheetAnimated, + openSheetAnimated, + panGestureEvent, + scrollEvent, + } = useBottomSheetAnimation({ + onClose, + isVisible, + }); + const panGestureRef = useRef(null); + const scrollViewRef = useRef(null); + + useEffect(() => { + if (isVisible) { + openSheetAnimated(); + } + }, [isVisible, openSheetAnimated]); + + const handlePressOutside = (event: GestureResponderEvent) => { + if (event.target === event.currentTarget) closeSheetAnimated(); + }; + + const insetBottom = Math.max(insets.bottom, DEFAULT_INSET_BOTTOM); + + return ( + + + + + + + + + + + + + + + + ); +}; diff --git a/suite-native/atoms/src/index.ts b/suite-native/atoms/src/index.ts index 238c5a61e19..d6945c4a605 100644 --- a/suite-native/atoms/src/index.ts +++ b/suite-native/atoms/src/index.ts @@ -18,6 +18,7 @@ export * from './DiscreetText/useDiscreetMode'; export * from './BottomSheetListItem'; export * from './OrderedListIcon'; export * from './Sheet/BottomSheet'; +export * from './Sheet/BottomSheetFlashList'; export * from './Sheet/useBottomSheetAnimation'; export * from './Button/Button'; export * from './Button/IconButton'; diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts index 845586915d4..635ec3b84d0 100644 --- a/suite-native/intl/src/en.ts +++ b/suite-native/intl/src/en.ts @@ -88,6 +88,7 @@ export const en = { numberOfTokens: '+{numberOfTokens, plural, one{1 Token} other{# Tokens}}', tokens: 'Tokens', staking: 'Staking', + stakingDisabled: 'Staking is not available in this context.', }, assets: { dashboard: { diff --git a/suite-native/module-accounts-import/src/components/DevXpub.tsx b/suite-native/module-accounts-import/src/components/DevXpub.tsx index 848921b073c..f9902fa387a 100644 --- a/suite-native/module-accounts-import/src/components/DevXpub.tsx +++ b/suite-native/module-accounts-import/src/components/DevXpub.tsx @@ -9,7 +9,17 @@ type DevXpubProps = { }; const devXpubs: Partial> = { - btc: 'zpub6rjNNddoAVvuYaD6WPdxiqFEToQHgrERjWMg7kM9gGGk6rhPMWNEmL5X745FGqBq8Wp136LfA3A7UjRGEYdJrf8dUfshzNrb5rvaryNfVJf', + btc: [ + { + title: 'Use dev xPub', + address: + 'zpub6rjNNddoAVvuYaD6WPdxiqFEToQHgrERjWMg7kM9gGGk6rhPMWNEmL5X745FGqBq8Wp136LfA3A7UjRGEYdJrf8dUfshzNrb5rvaryNfVJf', + }, + { + title: 'Taproot (zero value)', + address: `tr([5c9e228d/86'/0'/0']xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk/<0;1>/*)`, + }, + ], test: 'vpub5ZjRPuuMiEQnbwEDi9jtH1FaJMajZW78uZ1t3RJXKhxyMoTnPraKwGxiDo9SguDYvSieqjoLJxW5n2t9156RR1oeqRnURuftNZTzejBc4pa', regtest: 'vpub5ZjRPuuMiEQnbwEDi9jtH1FaJMajZW78uZ1t3RJXKhxyMoTnPraKwGxiDo9SguDYvSieqjoLJxW5n2t9156RR1oeqRnURuftNZTzejBc4pa', diff --git a/suite-native/module-accounts-management/src/screens/AccountsScreen/AccountsScreen.tsx b/suite-native/module-accounts-management/src/screens/AccountsScreen/AccountsScreen.tsx index f3da492a200..36f108ef96b 100644 --- a/suite-native/module-accounts-management/src/screens/AccountsScreen/AccountsScreen.tsx +++ b/suite-native/module-accounts-management/src/screens/AccountsScreen/AccountsScreen.tsx @@ -21,7 +21,14 @@ export const AccountsScreen = () => { const [accountsFilterValue, setAccountsFilterValue] = useState(''); - const handleSelectAccount: OnSelectAccount = ({ account, tokenAddress }) => { + const handleSelectAccount: OnSelectAccount = ({ account, tokenAddress, isStaking }) => { + if (isStaking) { + navigation.navigate(RootStackRoutes.StakingDetail, { + accountKey: account.key, + }); + + return; + } navigation.navigate(RootStackRoutes.AccountDetail, { accountKey: account.key, tokenContract: tokenAddress, diff --git a/yarn.lock b/yarn.lock index badb9c5bc1d..97caef7886d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9472,7 +9472,6 @@ __metadata: dependencies: "@mobily/ts-belt": "npm:^3.13.1" "@react-navigation/native": "npm:6.1.18" - "@shopify/flash-list": "npm:1.7.1" "@suite-common/formatters": "workspace:*" "@suite-common/icons-deprecated": "workspace:*" "@suite-common/token-definitions": "workspace:*" @@ -9685,6 +9684,7 @@ __metadata: resolution: "@suite-native/atoms@workspace:suite-native/atoms" dependencies: "@mobily/ts-belt": "npm:^3.13.1" + "@shopify/flash-list": "npm:1.7.1" "@shopify/react-native-skia": "npm:1.3.11" "@suite-common/icons-deprecated": "workspace:*" "@suite-native/config": "workspace:*" From 47e50e7577c2a6c15545319625dce381dbbeefab Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Fri, 4 Oct 2024 10:48:48 +0200 Subject: [PATCH 098/624] feat: Refactor Update Flow into NotificationBanener and add support for Silent Update --- .../src/components/Image/Image.stories.tsx | 2 +- .../components/src/components/Image/images.ts | 2 - .../src/components/Tooltip/TooltipBox.tsx | 3 +- .../files/images/svg/early-access-disable.svg | 10 - .../files/images/svg/early-access.svg | 8 - packages/suite-desktop-ui/package.json | 3 +- .../src/support/DesktopUpdater.tsx | 49 ++--- .../src/support/DesktopUpdater/Available.tsx | 186 +++++++++--------- .../support/DesktopUpdater/JustUpdated.tsx | 70 +++++++ .../DesktopUpdater/changelogComponents.tsx | 20 ++ .../support/DesktopUpdater/getVersionName.ts | 20 ++ .../src/support/DesktopUpdater/styles.ts | 52 ----- packages/suite-desktop-ui/styled.d.ts | 8 + packages/suite/package.json | 2 +- .../suite/__fixtures__/suiteActions.ts | 1 + .../suite/constants/desktopUpdateConstants.ts | 1 + .../src/actions/suite/desktopUpdateActions.ts | 7 +- .../suite/src/actions/suite/initAction.ts | 41 ++-- .../QuickActions/DebugAndExperimental.tsx | 2 +- .../Sidebar/QuickActions/TooltipRow.tsx | 40 ++-- .../Update/UpdateNotificationBanner.tsx | 127 ++++++++++++ .../Update/UpdateStatusActionBarIcon.tsx | 81 ++++---- .../QuickActions/Update/UpdateTooltip.tsx | 21 +- .../Update/updateQuickActionTypes.ts | 40 +++- .../QuickActions/Update/useUpdateStatus.ts | 79 ++++++-- .../layouts/SuiteLayout/Sidebar/Sidebar.tsx | 28 +++ .../suite/src/constants/suite/experimental.ts | 16 +- .../reducers/suite/desktopUpdateReducer.ts | 15 +- .../suite/src/reducers/suite/suiteReducer.ts | 2 + packages/suite/src/support/messages.ts | 63 +++++- .../SettingsDebug/DeviceAuthenticity.tsx | 2 +- .../SettingsGeneral/AutomaticUpdate.tsx | 4 +- .../SettingsGeneral/VersionWithUpdate.tsx | 6 +- .../src/desktopAppUpdateState.ts | 26 ++- yarn.lock | 1 + 35 files changed, 697 insertions(+), 341 deletions(-) delete mode 100644 packages/suite-data/files/images/svg/early-access-disable.svg delete mode 100644 packages/suite-data/files/images/svg/early-access.svg create mode 100644 packages/suite-desktop-ui/src/support/DesktopUpdater/JustUpdated.tsx create mode 100644 packages/suite-desktop-ui/src/support/DesktopUpdater/changelogComponents.tsx create mode 100644 packages/suite-desktop-ui/src/support/DesktopUpdater/getVersionName.ts delete mode 100644 packages/suite-desktop-ui/src/support/DesktopUpdater/styles.ts create mode 100644 packages/suite-desktop-ui/styled.d.ts create mode 100644 packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx diff --git a/packages/components/src/components/Image/Image.stories.tsx b/packages/components/src/components/Image/Image.stories.tsx index 9efd31fcea7..c596964890c 100644 --- a/packages/components/src/components/Image/Image.stories.tsx +++ b/packages/components/src/components/Image/Image.stories.tsx @@ -10,7 +10,7 @@ export default meta; export const Image: StoryObj = { args: { - image: 'EARLY_ACCESS', + image: 'BACKUP', width: undefined, height: undefined, imageSrc: undefined, diff --git a/packages/components/src/components/Image/images.ts b/packages/components/src/components/Image/images.ts index c8450adc9ee..9c9507f04d6 100644 --- a/packages/components/src/components/Image/images.ts +++ b/packages/components/src/components/Image/images.ts @@ -18,8 +18,6 @@ export const SVG_IMAGES = { DEVICE_ANOTHER_SESSION: 'device-another-session.svg', CONNECT_DEVICE: 'connect-device.svg', ERROR_404: 'error-404.svg', - EARLY_ACCESS: 'early-access.svg', - EARLY_ACCESS_DISABLE: 'early-access-disable.svg', INVITY_LOGO: 'invity-logo.svg', COINMARKET_AVATAR: 'coinmarket-avatar.svg', COINMARKET_SUCCESS: 'coinmarket-success.svg', diff --git a/packages/components/src/components/Tooltip/TooltipBox.tsx b/packages/components/src/components/Tooltip/TooltipBox.tsx index b48a1b6c31b..b40fff1b387 100644 --- a/packages/components/src/components/Tooltip/TooltipBox.tsx +++ b/packages/components/src/components/Tooltip/TooltipBox.tsx @@ -29,9 +29,10 @@ const TooltipContainerStyled = styled.div` border-radius: ${TOOLTIP_BORDER_RADIUS}; text-align: left; border: solid 1.5px ${palette.darkGray100}; + margin: ${spacingsPx.xxxs}; max-width: ${props => props.$maxWidth}px; - ${typography.hint} + ${typography.hint} > div { padding: ${({ $isLarge, $isWithHeader }) => getContainerPadding($isLarge, $isWithHeader)}; } diff --git a/packages/suite-data/files/images/svg/early-access-disable.svg b/packages/suite-data/files/images/svg/early-access-disable.svg deleted file mode 100644 index 301d81441ab..00000000000 --- a/packages/suite-data/files/images/svg/early-access-disable.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/suite-data/files/images/svg/early-access.svg b/packages/suite-data/files/images/svg/early-access.svg deleted file mode 100644 index 4930936c1f9..00000000000 --- a/packages/suite-data/files/images/svg/early-access.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/packages/suite-desktop-ui/package.json b/packages/suite-desktop-ui/package.json index 4314ebe24a7..46c1e64c40c 100644 --- a/packages/suite-desktop-ui/package.json +++ b/packages/suite-desktop-ui/package.json @@ -36,6 +36,7 @@ "@types/react": "18.2.79", "@types/react-dom": "18.2.19", "stylelint": "^16.2.1", - "stylelint-config-standard": "^36.0.0" + "stylelint-config-standard": "^36.0.0", + "typescript-styled-plugin": "^0.18.3" } } diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater.tsx index 98b01928851..90c2511f0d9 100644 --- a/packages/suite-desktop-ui/src/support/DesktopUpdater.tsx +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater.tsx @@ -18,13 +18,13 @@ import { import { UpdateState } from 'src/reducers/suite/desktopUpdateReducer'; import { ModalContextProvider } from 'src/support/suite/ModalContext'; import { getAppUpdatePayload } from 'src/utils/suite/analytics'; -import { selectRouteName } from 'src/reducers/suite/routerReducer'; import { Available } from './DesktopUpdater/Available'; import { Downloading } from './DesktopUpdater/Downloading'; import { Ready } from './DesktopUpdater/Ready'; import { EarlyAccessEnable } from './DesktopUpdater/EarlyAccessEnable'; import { EarlyAccessDisable } from './DesktopUpdater/EarlyAccessDisable'; +import { JustUpdated } from './DesktopUpdater/JustUpdated'; interface DesktopUpdaterProps { children: ReactNode; @@ -36,12 +36,6 @@ export const DesktopUpdater = ({ children }: DesktopUpdaterProps) => { const desktopUpdateState = desktopUpdate.state; - const routeName = useSelector(selectRouteName); - - // Closing a modal opened by auto updater outside of device settings might confuse some users, - // especially on app start if closing it unexpectedly by clicking outside. - const isSettingsRoute = routeName === 'settings-index'; - useEffect(() => { desktopApi.on('update/allow-prerelease', params => dispatch(allowPrerelease(params))); desktopApi.on('update/set-automatic-update-enabled', isEnabled => @@ -97,45 +91,30 @@ export const DesktopUpdater = ({ children }: DesktopUpdaterProps) => { return false; } - const isEarlyAccessState = [ + const isHackyModalOpen = [ UpdateState.EarlyAccessDisable, UpdateState.EarlyAccessEnable, + UpdateState.JustUpdated, ].includes(desktopUpdateState); // Enable to setup Early Access even after updater error (when desktopUpdate.latest is undefined). - if (!isEarlyAccessState && !desktopUpdate.latest) { - return false; - } - - return true; + return isHackyModalOpen || desktopUpdate.latest !== undefined; }, [desktopUpdate.modalVisibility, desktopUpdateState, desktopUpdate.latest]); - const getUpdateModal = () => { - switch (desktopUpdateState) { - case UpdateState.EarlyAccessEnable: - return ; - case UpdateState.EarlyAccessDisable: - return ; - case UpdateState.Available: - return ( - - ); - case UpdateState.Downloading: - return ; - case UpdateState.Ready: - return ; - default: - return null; - } + const updateModalMap: Record = { + 'early-access-disable': , + 'early-access-enable': , + 'just-updated': , + 'not-available': null, + available: , + checking: null, + downloading: , + ready: , }; return ( <> - {isVisible && getUpdateModal()} + {isVisible && updateModalMap[desktopUpdateState]} {children} ); diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/Available.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater/Available.tsx index f720c81dc87..e697de5275d 100644 --- a/packages/suite-desktop-ui/src/support/DesktopUpdater/Available.tsx +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/Available.tsx @@ -1,119 +1,127 @@ import styled from 'styled-components'; -import { Button, H2, Link, Markdown } from '@trezor/components'; +import { + Card, + Checkbox, + Column, + Icon, + Markdown, + NewModal, + Paragraph, + Row, + Text, +} from '@trezor/components'; import { desktopApi, UpdateInfo } from '@trezor/suite-desktop-api'; -import { borders } from '@trezor/theme'; +import { borders, spacings, spacingsPx } from '@trezor/theme'; -import { Translation, Modal } from 'src/components/suite'; -import { useDispatch } from 'src/hooks/suite'; -import { getReleaseUrl } from 'src/services/github'; +import { Translation } from 'src/components/suite'; +import { useDispatch, useSelector } from 'src/hooks/suite'; import { download } from 'src/actions/suite/desktopUpdateActions'; +import { selectSuiteFlags } from 'src/reducers/suite/suiteReducer'; +import { setFlag } from 'src/actions/suite/suiteActions'; -// eslint-disable-next-line local-rules/no-override-ds-component -const GreenH2 = styled(H2)` - text-align: left; - color: ${({ theme }) => theme.legacy.TYPE_GREEN}; -`; - -const ChangelogWrapper = styled.div` - margin: 20px 0; - background: ${({ theme }) => theme.legacy.BG_GREY}; - border-radius: ${borders.radii.xs}; - max-height: 400px; - overflow-y: auto; - padding: 16px 20px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledLink = styled(Link)` - align-self: start; -`; +import { Changelog } from './changelogComponents'; +import { getVersionName } from './getVersionName'; -const StyledModal = styled(Modal)` - ${Modal.BottomBar} { - > * { - flex: 1; - } - } +const GreenTag = styled.div` + display: flex; + align-items: center; + gap: ${spacingsPx.xxs}; + border-radius: ${borders.radii.full}; + background-color: ${({ theme }) => theme.backgroundPrimarySubtleOnElevation0}; + padding: ${spacingsPx.xxxs} ${spacingsPx.xs}; `; -interface VersionNameProps { - latestVersion?: string; - prerelease: boolean; -} - -const getVersionName = ({ latestVersion, prerelease }: VersionNameProps): string => { - if (!latestVersion) { - // fallback for undefined version - return ''; - } - if (!prerelease) { - // regular case - return latestVersion; - } - if (!latestVersion.includes('-')) { - // add beta label for pre-releases, but prevent versions like '21.10.1-alpha-beta' - return `${latestVersion}-beta`; - } - - // fallback for pre-release versions already including some pre-release components - return latestVersion; -}; +const NewTag = () => ( + + + + + + +); interface AvailableProps { - hideWindow: () => void; - isCancelable: boolean; - latest?: UpdateInfo; + onCancel: () => void; + latest: UpdateInfo | undefined; } -export const Available = ({ hideWindow, isCancelable, latest }: AvailableProps) => { +export const Available = ({ onCancel, latest }: AvailableProps) => { const dispatch = useDispatch(); + const { enableAutoupdateOnNextRun } = useSelector(selectSuiteFlags); const downloadUpdate = () => { dispatch(download()); desktopApi.downloadUpdate(); }; + const suiteCurrentVersion = process.env.VERSION || ''; + const suiteNewVersion = getVersionName({ + latestVersion: latest?.version, + prerelease: !!latest?.prerelease, + }); + + const handleToggleAutoUpdateClick = () => + dispatch(setFlag('enableAutoupdateOnNextRun', !enableAutoupdateOnNextRun)); + return ( - } - isCancelable={isCancelable} - onCancel={hideWindow} - bottomBarComponents={ + description={ + + } + onCancel={onCancel} + bottomContent={ <> - - + + + + } > - - - + +
+ + + + + + +
+ + + {latest?.changelog ? ( + {latest?.changelog} + ) : ( + + )} + + + + {latest?.releaseDate && {latest?.releaseDate}} + - - {latest?.changelog ? ( - {latest?.changelog} - ) : ( - - )} - - - - -
+ + + + + + + + +
+ ); }; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/JustUpdated.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater/JustUpdated.tsx new file mode 100644 index 00000000000..cf3d6ae449f --- /dev/null +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/JustUpdated.tsx @@ -0,0 +1,70 @@ +import { useState, useCallback, useEffect } from 'react'; + +import { Column, Markdown, NewModal, Paragraph } from '@trezor/components'; +import { desktopApi } from '@trezor/suite-desktop-api'; +import { spacings } from '@trezor/theme'; + +import { Translation } from 'src/components/suite'; +import { useDispatch } from 'src/hooks/suite'; +import { download } from 'src/actions/suite/desktopUpdateActions'; + +import { Changelog } from './changelogComponents'; + +interface AvailableProps { + onCancel: () => void; +} + +export const JustUpdated = ({ onCancel }: AvailableProps) => { + const [changelog, setChangelog] = useState(null); + + const dispatch = useDispatch(); + + const downloadUpdate = () => { + dispatch(download()); + desktopApi.downloadUpdate(); + }; + + const suiteCurrentVersion = process.env.VERSION || ''; + + const getReleaseNotes = useCallback(async () => { + const releaseNotesPath = process.env.ASSET_PREFIX + '/release-notes.md'; + const result = await (await fetch(releaseNotesPath)).text(); + setChangelog(result); + }, []); + + useEffect(() => { + getReleaseNotes(); + }, [getReleaseNotes]); + + return ( + + + + } + description={} + onCancel={onCancel} + bottomContent={ + <> + + + + + } + > + + + {changelog !== null ? ( + {changelog} + ) : ( + + )} + + + + ); +}; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/changelogComponents.tsx b/packages/suite-desktop-ui/src/support/DesktopUpdater/changelogComponents.tsx new file mode 100644 index 00000000000..ecc7a2be2b8 --- /dev/null +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/changelogComponents.tsx @@ -0,0 +1,20 @@ +import { ReactNode } from 'react'; + +import styled from 'styled-components'; + +import { borders, Elevation, mapElevationToBackground, spacingsPx } from '@trezor/theme'; +import { useElevation } from '@trezor/components'; + +const ChangelogWrapper = styled.div<{ $elevation: Elevation }>` + background-color: ${({ theme, $elevation }) => mapElevationToBackground({ theme, $elevation })}; + border-radius: ${borders.radii.md}; + max-height: 400px; + overflow-y: auto; + padding: ${spacingsPx.md} ${spacingsPx.xl}; +`; + +export const Changelog = ({ children }: { children: ReactNode }) => { + const { elevation } = useElevation(); + + return {children}; +}; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/getVersionName.ts b/packages/suite-desktop-ui/src/support/DesktopUpdater/getVersionName.ts new file mode 100644 index 00000000000..9f8e672d3af --- /dev/null +++ b/packages/suite-desktop-ui/src/support/DesktopUpdater/getVersionName.ts @@ -0,0 +1,20 @@ +interface VersionNameProps { + latestVersion?: string; + prerelease: boolean; +} + +export const getVersionName = ({ latestVersion, prerelease }: VersionNameProps): string => { + if (latestVersion === undefined) { + return ''; + } + + if (prerelease !== undefined) { + return latestVersion; + } + + if (!latestVersion.includes('-')) { + return `${latestVersion}-beta`; + } + + return latestVersion; +}; diff --git a/packages/suite-desktop-ui/src/support/DesktopUpdater/styles.ts b/packages/suite-desktop-ui/src/support/DesktopUpdater/styles.ts deleted file mode 100644 index 77dfb237be0..00000000000 --- a/packages/suite-desktop-ui/src/support/DesktopUpdater/styles.ts +++ /dev/null @@ -1,52 +0,0 @@ -import styled from 'styled-components'; - -import { H2, Paragraph, variables } from '@trezor/components'; - -export const Row = styled.div` - display: flex; - justify-content: space-between; - align-items: center; -`; - -export const LeftCol = styled.div` - display: flex; - flex: 1 1 calc(100% - 40px); -`; - -export const RightCol = styled.div` - display: flex; - margin-left: 40px; - max-width: 280px; - flex: 1 1 100%; -`; - -export const Divider = styled.div` - width: 100%; - height: 1px; - margin: 30px 0; - background: ${({ theme }) => theme.legacy.STROKE_GREY}; -`; - -export const ImageWrapper = styled.div` - top: 50px; - left: 0; - right: 0; -`; - -export const ButtonWrapper = styled.div` - display: flex; - justify-content: center; - padding-top: 24px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -export const Title = styled(H2)` - padding-top: 24px; - padding-bottom: 12px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -export const Description = styled(Paragraph)` - font-size: ${variables.FONT_SIZE.SMALL}; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; -`; diff --git a/packages/suite-desktop-ui/styled.d.ts b/packages/suite-desktop-ui/styled.d.ts new file mode 100644 index 00000000000..743c8b46f0a --- /dev/null +++ b/packages/suite-desktop-ui/styled.d.ts @@ -0,0 +1,8 @@ +// import original module declarations +import 'styled-components'; +import { SuiteThemeColors } from '@trezor/components'; +import { BoxShadows, Colors } from '@trezor/theme'; + +declare module 'styled-components' { + export interface DefaultTheme extends SuiteThemeColors, Colors, BoxShadows {} +} diff --git a/packages/suite/package.json b/packages/suite/package.json index 77bea05f7dd..a7b1e73c463 100644 --- a/packages/suite/package.json +++ b/packages/suite/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/suite", - "suiteVersion": "24.11.0", + "suiteVersion": "0.0.0", "version": "1.0.0", "private": true, "scripts": { diff --git a/packages/suite/src/actions/suite/__fixtures__/suiteActions.ts b/packages/suite/src/actions/suite/__fixtures__/suiteActions.ts index 47f10d4f0d8..5c212ac752b 100644 --- a/packages/suite/src/actions/suite/__fixtures__/suiteActions.ts +++ b/packages/suite/src/actions/suite/__fixtures__/suiteActions.ts @@ -247,6 +247,7 @@ const initialRun = [ isDashboardPassphraseBannerVisible: true, showCopyAddressModal: true, showUnhideTokenModal: true, + enableAutoupdateOnNextRun: false, }, }, }, diff --git a/packages/suite/src/actions/suite/constants/desktopUpdateConstants.ts b/packages/suite/src/actions/suite/constants/desktopUpdateConstants.ts index 40aeb19c508..95b67d5e6cc 100644 --- a/packages/suite/src/actions/suite/constants/desktopUpdateConstants.ts +++ b/packages/suite/src/actions/suite/constants/desktopUpdateConstants.ts @@ -4,6 +4,7 @@ export const NOT_AVAILABLE = '@desktop-update/not-available'; export const DOWNLOAD = '@desktop-update/download'; export const DOWNLOADING = '@desktop-update/downloading'; export const READY = '@desktop-update/ready'; +export const OPEN_JUST_UPDATED_CHANGELOG = '@desktop-update/just-updated'; export const MODAL_VISIBILITY = '@desktop-update/modal-visibility'; export const OPEN_EARLY_ACCESS_ENABLE = '@desktop-update/open-early-access-enable'; export const OPEN_EARLY_ACCESS_DISABLE = '@desktop-update/open-early-access-disable'; diff --git a/packages/suite/src/actions/suite/desktopUpdateActions.ts b/packages/suite/src/actions/suite/desktopUpdateActions.ts index 4814ce974fb..24e593f16d6 100644 --- a/packages/suite/src/actions/suite/desktopUpdateActions.ts +++ b/packages/suite/src/actions/suite/desktopUpdateActions.ts @@ -19,7 +19,8 @@ export type DesktopUpdateAction = | { type: typeof DESKTOP_UPDATE.OPEN_EARLY_ACCESS_ENABLE } | { type: typeof DESKTOP_UPDATE.OPEN_EARLY_ACCESS_DISABLE } | { type: typeof DESKTOP_UPDATE.ALLOW_PRERELEASE; payload: boolean } - | { type: typeof DESKTOP_UPDATE.SET_AUTOMATIC_UPDATES; payload: { isEnabled: boolean } }; + | { type: typeof DESKTOP_UPDATE.SET_AUTOMATIC_UPDATES; payload: { isEnabled: boolean } } + | { type: typeof DESKTOP_UPDATE.OPEN_JUST_UPDATED_CHANGELOG }; export const checking = (): DesktopUpdateAction => ({ type: DESKTOP_UPDATE.CHECKING }); @@ -65,6 +66,10 @@ export const downloading = (progress: UpdateProgress): DesktopUpdateAction => ({ payload: progress, }); +export const openJustUpdatedChangelog = (): DesktopUpdateAction => ({ + type: DESKTOP_UPDATE.OPEN_JUST_UPDATED_CHANGELOG, +}); + export const ready = (info: UpdateInfo) => (dispatch: Dispatch, getState: GetState) => { const { latest, allowPrerelease } = getState().desktopUpdate; diff --git a/packages/suite/src/actions/suite/initAction.ts b/packages/suite/src/actions/suite/initAction.ts index dfe3d19630d..79ae4741804 100644 --- a/packages/suite/src/actions/suite/initAction.ts +++ b/packages/suite/src/actions/suite/initAction.ts @@ -16,13 +16,16 @@ import * as languageActions from 'src/actions/settings/languageActions'; import type { Dispatch, GetState } from 'src/types/suite'; import { SUITE } from './constants'; -import { onSuiteReady } from './suiteActions'; +import { onSuiteReady, setFlag } from './suiteActions'; +import { desktopApi } from '@trezor/suite-desktop-api'; +import { isDesktop } from '@trezor/env-utils'; export const init = () => async (dispatch: Dispatch, getState: GetState) => { const { suite: { settings: { language }, lifecycle: { status }, + flags: { enableAutoupdateOnNextRun }, }, wallet: { settings: { localCurrency }, @@ -35,7 +38,15 @@ export const init = () => async (dispatch: Dispatch, getState: GetState) => { dispatch(initDevices()); - // right after storage is loaded, we might start: + /** + * ---------------------------------------------- + * Right after storage is loaded, we might start: + * ---------------------------------------------- + * + * Todo: This is good place to be refactored into separate functions. + * Those number-comments are very strong indicator that this code + * has many responsibilities and should be split into smaller parts. + */ // 1. init analytics dispatch(analyticsActions.init()); @@ -46,10 +57,16 @@ export const init = () => async (dispatch: Dispatch, getState: GetState) => { // 3. fetch message system config dispatch(initMessageSystemThunk()); - // 4. redirecting user into welcome screen (if needed) + // 4. turn on auto updates if needed + if (isDesktop() && enableAutoupdateOnNextRun) { + dispatch(setFlag('enableAutoupdateOnNextRun', false)); + desktopApi.setAutomaticUpdateEnabled(true); + } + + // 5. redirecting user into welcome screen (if needed) dispatch(routerActions.initialRedirection()); - // 5. init connect (could throw an error, + // 6. init connect (could throw an error, // then the error is caught in in Main.tsx try { // it is necessary to unwrap the result here because init calls async thunk from redux-toolkit which is always resolved @@ -60,15 +77,15 @@ export const init = () => async (dispatch: Dispatch, getState: GetState) => { throw err; } - // 6. init backends + // 7. init backends await dispatch(initBlockchainThunk()) .unwrap() .catch(err => console.error(err)); - // 7. fetch token definitions (has to be fetched before fiat rates) + // 8. fetch token definitions (has to be fetched before fiat rates) await dispatch(periodicCheckTokenDefinitionsThunk()); - // 8. init periodic fetching of fiat rates + // 9. init periodic fetching of fiat rates await dispatch( periodicFetchFiatRatesThunk({ rateType: 'current', @@ -82,20 +99,20 @@ export const init = () => async (dispatch: Dispatch, getState: GetState) => { }), ); - // 9. fetch rates for transactions with missing rates + // 10. fetch rates for transactions with missing rates await dispatch(updateMissingTxFiatRatesThunk({ localCurrency })); - // 10. dispatch initial location change + // 11. dispatch initial location change dispatch(routerActions.init()); - // 11. fetch metadata. metadata is not saved together with other data in storage. + // 12. fetch metadata. metadata is not saved together with other data in storage. // historically it was saved in indexedDB together with devices and accounts and we did not need to load them // immediately after suite start. dispatch(metadataLabelingActions.fetchAndSaveMetadataForAllDevices()); - // 12. start fetching staking data if needed, does need to be waited + // 13. start fetching staking data if needed, does need to be waited dispatch(periodicCheckStakeDataThunk()); - // 13. backend connected, suite is ready to use + // 14. backend connected, suite is ready to use dispatch(onSuiteReady()); }; diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/DebugAndExperimental.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/DebugAndExperimental.tsx index 1fb83af383a..6847a110e05 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/DebugAndExperimental.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/DebugAndExperimental.tsx @@ -19,7 +19,7 @@ const DebugAndExperimentalTooltip = ({ isEapEnabled, isExperimental, }: DebugAndExperimentalTooltipProps) => ( - + {isExperimental && ( ` padding: ${spacingsPx.xxxs}; `; +const Pointer = styled.div` + cursor: ${({ onClick }) => (onClick ? 'pointer' : undefined)}; +`; + type UpdateRowProps = { children: ReactNode; leftItem: ReactNode; header: ReactNode; variant: IconVariant; circleIconName: IconName; + onClick?: () => void; }; export const TooltipRow = ({ @@ -45,25 +50,28 @@ export const TooltipRow = ({ header, variant, circleIconName, + onClick, }: UpdateRowProps) => { const theme = useTheme(); return ( - - {leftItem} - - {header} - - - - - {children} - - - + + + {leftItem} + + {header} + + + + + {children} + + + + ); }; diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx new file mode 100644 index 00000000000..1692be91f63 --- /dev/null +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx @@ -0,0 +1,127 @@ +import styled from 'styled-components'; +import { Column, ElevationContext, Icon, Row, Text } from '@trezor/components'; +import { borders, Elevation, mapElevationToBackground, spacingsPx } from '@trezor/theme'; +import { + UpdateStatus, + UpdateStatusSuite, + UpdateStatusDevice, + mapSuiteUpdateToClick, + mapDeviceUpdateToClick, +} from './updateQuickActionTypes'; +import { Translation, TranslationKey } from '../../../../../Translation'; +import { useDispatch } from '../../../../../../../hooks/suite'; +import { MouseEvent } from 'react'; + +type ContainerProps = { $elevation: Elevation }; + +const Container = styled.div` + margin: ${spacingsPx.md}; + display: flex; + flex-direction: column; + padding: ${spacingsPx.xs} ${spacingsPx.sm}; + background: ${mapElevationToBackground}; + border-radius: ${borders.radii.sm}; + box-shadow: ${({ theme }) => theme.boxShadowElevated}; + cursor: ${({ onClick }) => (onClick !== undefined ? 'pointer' : undefined)}; +`; + +const CloseIconBackground = styled.div` + width: 36px; + height: 36px; + + display: flex; + justify-content: center; + align-items: center; + background-color: ${({ theme }) => theme.backgroundSurfaceElevation2}; + border-radius: ${borders.radii.full}; + cursor: ${({ onClick }) => (onClick !== undefined ? 'pointer' : undefined)}; +`; + +type UpdateNotificationBannerProps = { + updateStatusDevice: UpdateStatusDevice; + updateStatusSuite: UpdateStatusSuite; + onClose: () => void; +}; + +const mapDeviceUpdateStatusToTranslation: Record = { + 'up-to-date': null, + 'update-available': 'TR_QUICK_ACTION_UPDATE_POPOVER_TREZOR_UPDATE_AVAILABLE', +}; + +const mapSuiteUpdateStatusToHeaderTranslation: Record = { + 'update-downloaded-auto-restart-to-update': + 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_HAS_BEEN_UPDATED', + 'update-downloaded-manual': 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_DOWNLOADED', + 'just-updated': 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_HAS_BEEN_UPDATED', + 'up-to-date': null, + 'update-available': 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_UPDATE_AVAILABLE', +}; + +const mapSuiteUpdateStatusToCallToActionTranslation: Record = { + 'just-updated': 'TR_QUICK_ACTION_UPDATE_POPOVER_WHATS_NEW', + 'up-to-date': null, + 'update-available': 'TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE', + 'update-downloaded-auto-restart-to-update': + 'TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_RESTART_AND_UPDATE', + 'update-downloaded-manual': 'TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE', +}; + +export const UpdateNotificationBanner = ({ + updateStatusDevice, + updateStatusSuite, + onClose, +}: UpdateNotificationBannerProps) => { + const dispatch = useDispatch(); + + const translationHeader = + updateStatusSuite !== 'up-to-date' // Update suite first, because it will contain the newest firmware + ? mapSuiteUpdateStatusToHeaderTranslation[updateStatusSuite] + : mapDeviceUpdateStatusToTranslation[updateStatusDevice]; + + const translationCallToAction = + mapSuiteUpdateStatusToCallToActionTranslation[ + updateStatusSuite !== 'up-to-date' ? updateStatusSuite : updateStatusDevice + ]; + + if (translationHeader === null || translationCallToAction === null) { + return null; + } + + const handleOnClick = () => { + const onClick = + updateStatusSuite !== 'up-to-date' + ? mapSuiteUpdateToClick[updateStatusSuite] + : mapDeviceUpdateToClick[updateStatusDevice]; + + if (onClick !== null) { + onClick({ dispatch }); + onClose(); + } + }; + + const handleOnClose = (e: MouseEvent) => { + // Click on whole banner has onClick, so prevent the activation when closing the modal + e.stopPropagation(); + onClose(); + }; + + return ( + + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx index 6059101dd33..c75f3472dd2 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx @@ -7,6 +7,8 @@ import { borders, Color, CSSColor } from '@trezor/theme'; import { useUpdateStatus } from './useUpdateStatus'; import { UpdateTooltip } from './UpdateTooltip'; import { + mapDeviceUpdateToClick, + mapSuiteUpdateToClick, mapUpdateStatusToIcon, mapUpdateStatusToVariant, UpdateStatus, @@ -14,8 +16,6 @@ import { } from './updateQuickActionTypes'; import { isDesktop } from '@trezor/env-utils'; import { useDispatch } from 'react-redux'; -import { goto } from 'src/actions/suite/routerActions'; -import { SettingsAnchor } from '../../../../../../../constants/suite/anchors'; import { mapTrezorModelToIcon } from '@trezor/product-components'; type MapArgs = { @@ -142,7 +142,9 @@ const SuiteUpdateIcon = ({ iconSize, updateStatus, variant }: SuiteUpdateIconPro export const UpdateStatusActionBarIcon = () => { const theme = useTheme(); - const { updateStatus, updateStatusDevice, updateStatusSuite } = useUpdateStatus(); + const { updateStatus, updateStatusDevice, updateStatusSuite, showBannerNotification } = + useUpdateStatus(); + const { device } = useDevice(); const dispatch = useDispatch(); @@ -156,47 +158,54 @@ export const UpdateStatusActionBarIcon = () => { return null; } - const handleOnClick = () => { - if (updateStatusSuite === 'update-available') { - dispatch(goto('settings-index', { anchor: SettingsAnchor.VersionWithUpdate })); - } else if (updateStatusDevice === 'update-available') { - dispatch(goto('settings-device', { anchor: SettingsAnchor.FirmwareVersion })); + const suiteOnClick = () => mapSuiteUpdateToClick[updateStatusSuite]?.({ dispatch }); + const deviceOnClick = () => mapDeviceUpdateToClick[updateStatusDevice]?.({ dispatch }); + + const handleClick = () => { + if (updateStatusSuite !== 'up-to-date') { + suiteOnClick(); + } else if (updateStatusDevice !== 'up-to-date') { + deviceOnClick(); } }; return ( - - } - onClick={handleOnClick} - > - + + ) + } + onClick={handleClick} > - - - {isDesktopSuite && ( - + + - )} - - - + {isDesktopSuite && ( + + )} + + + + ); }; diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateTooltip.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateTooltip.tsx index 98b281c9e1a..a48c9a71478 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateTooltip.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateTooltip.tsx @@ -5,6 +5,8 @@ import { mapUpdateStatusToIcon, mapUpdateStatusToVariant, UpdateStatus, + UpdateStatusSuite, + UpdateStatusDevice, } from './updateQuickActionTypes'; import { Translation } from '../../../../../Translation'; import { spacings } from '@trezor/theme'; @@ -27,17 +29,19 @@ const SuiteIconRectangle = styled.div<{ $size: IconSize }>` `; const mapUpdateStatusToTranslation: Record = { + 'update-downloaded-manual': 'TR_QUICK_ACTION_TOOLTIP_UPDATE_AVAILABLE', + 'update-downloaded-auto-restart-to-update': 'TR_QUICK_ACTION_TOOLTIP_RESTART_TO_UPDATE', 'up-to-date': 'TR_QUICK_ACTION_TOOLTIP_UP_TO_DATE', 'update-available': 'TR_QUICK_ACTION_TOOLTIP_UPDATE_AVAILABLE', - 'restart-to-update': 'TR_QUICK_ACTION_TOOLTIP_RESTART_TO_UPDATE', 'just-updated': 'TR_QUICK_ACTION_TOOLTIP_JUST_UPDATED', }; type DeviceRowProps = { - updateStatus: UpdateStatus; + updateStatus: UpdateStatusDevice; + onClick?: () => void; }; -const DeviceRow = ({ updateStatus }: DeviceRowProps) => { +const DeviceRow = ({ updateStatus, onClick }: DeviceRowProps) => { const { device } = useDevice(); if (device?.features === undefined) { @@ -49,6 +53,7 @@ const DeviceRow = ({ updateStatus }: DeviceRowProps) => { return ( { }; type SuiteRowProps = { - updateStatus: UpdateStatus; + updateStatus: UpdateStatusSuite; + onClick?: () => void; }; -const SuiteRow = ({ updateStatus }: SuiteRowProps) => { +const SuiteRow = ({ updateStatus, onClick }: SuiteRowProps) => { const theme = useTheme(); const { desktopUpdate } = useSelector(state => state); @@ -84,6 +90,7 @@ const SuiteRow = ({ updateStatus }: SuiteRowProps) => { return ( @@ -102,8 +109,8 @@ const SuiteRow = ({ updateStatus }: SuiteRowProps) => { }; type UpdateTooltipProps = { - updateStatusDevice: UpdateStatus; - updateStatusSuite: UpdateStatus; + updateStatusDevice: UpdateStatusDevice; + updateStatusSuite: UpdateStatusSuite; }; export const UpdateTooltip = ({ updateStatusDevice, updateStatusSuite }: UpdateTooltipProps) => { diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/updateQuickActionTypes.ts b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/updateQuickActionTypes.ts index 558d41c0b10..8b4a8756909 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/updateQuickActionTypes.ts +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/updateQuickActionTypes.ts @@ -2,26 +2,60 @@ import { IconName } from '@trezor/components'; import { UIVariant } from '@trezor/components/src/config/types'; import { Color, CSSColor } from '@trezor/theme'; import { DefaultTheme } from 'styled-components'; +import { goto } from '../../../../../../../actions/suite/routerActions'; +import { + installUpdate, + openJustUpdatedChangelog, + setUpdateModalVisibility, +} from '../../../../../../../actions/suite/desktopUpdateActions'; +import { Dispatch } from '../../../../../../../types/suite'; export const updateVariants = ['tertiary', 'info', 'purple'] as const; export type UpdateVariant = Extract | 'purple'; -export type UpdateStatus = 'up-to-date' | 'update-available' | 'restart-to-update' | 'just-updated'; +export type UpdateStatusDevice = 'up-to-date' | 'update-available'; + +export type UpdateStatusSuite = + | 'up-to-date' + | 'update-available' + | 'update-downloaded-manual' + | 'update-downloaded-auto-restart-to-update' + | 'just-updated'; + +export type UpdateStatus = UpdateStatusDevice | UpdateStatusSuite; export const mapUpdateStatusToIcon: Record = { + 'update-downloaded-manual': 'arrowDown', + 'update-downloaded-auto-restart-to-update': 'arrowsClockwiseFilled', 'up-to-date': 'check', 'update-available': 'arrowDown', - 'restart-to-update': 'arrowsClockwiseFilled', 'just-updated': 'check', }; export const mapUpdateStatusToVariant: Record = { + 'update-downloaded-manual': 'info', + 'update-downloaded-auto-restart-to-update': 'info', 'up-to-date': 'tertiary', 'update-available': 'info', - 'restart-to-update': 'info', 'just-updated': 'purple', }; +type OnClickCallbackCallback = ((params: { dispatch: Dispatch }) => void) | null; + +export const mapDeviceUpdateToClick: Record = { + 'up-to-date': null, + 'update-available': ({ dispatch }) => dispatch(goto('firmware-index')), +}; + +export const mapSuiteUpdateToClick: Record = { + 'up-to-date': null, + 'update-downloaded-auto-restart-to-update': ({ dispatch }) => + dispatch(installUpdate({ shouldInstallOnQuit: false })), + 'update-downloaded-manual': ({ dispatch }) => dispatch(setUpdateModalVisibility('maximized')), + 'just-updated': ({ dispatch }) => dispatch(openJustUpdatedChangelog()), + 'update-available': ({ dispatch }) => dispatch(setUpdateModalVisibility('maximized')), +}; + type MapArgs = { $variant: UpdateVariant; theme: DefaultTheme; diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/useUpdateStatus.ts b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/useUpdateStatus.ts index dfe89855fdb..d221640c91e 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/useUpdateStatus.ts +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/useUpdateStatus.ts @@ -1,49 +1,92 @@ +import { useState } from 'react'; + import { useDevice, useSelector } from '../../../../../../../hooks/suite'; import { DesktopUpdateState, UpdateState, } from '../../../../../../../reducers/suite/desktopUpdateReducer'; -import { UpdateStatus } from './updateQuickActionTypes'; +import { UpdateStatus, UpdateStatusSuite, UpdateStatusDevice } from './updateQuickActionTypes'; type UpdateStatusData = { updateStatus: UpdateStatus; - updateStatusDevice: UpdateStatus; - updateStatusSuite: UpdateStatus; + updateStatusDevice: UpdateStatusDevice; + updateStatusSuite: UpdateStatusSuite; + + showBannerNotification: boolean; + setClosedNotificationSuite: (value: boolean) => void; + setClosedNotificationDevice: (value: boolean) => void; }; -const getSuiteUpdateStatus = ({ desktopUpdate }: { desktopUpdate: DesktopUpdateState }) => { - const isSuiteJustUpdated = desktopUpdate.firstRunAfterUpdate; +type GetSuiteUpdateStatusArgs = { + desktopUpdate: DesktopUpdateState; +}; - const isSuiteOutdated = [UpdateState.Available, UpdateState.Downloading].includes( - desktopUpdate.state, - ); +const getSuiteUpdateStatus = ({ desktopUpdate }: GetSuiteUpdateStatusArgs): UpdateStatusSuite => { + const isSuiteJustUpdated = desktopUpdate.firstRunAfterUpdate; - const isSuiteRestartRequired = desktopUpdate.state === UpdateState.Ready; + if (isSuiteJustUpdated && !desktopUpdate.justUpdatedInteractedWith) { + return 'just-updated'; + } - if (isSuiteRestartRequired) { - return 'restart-to-update'; + // We don't show update-availability in case of auto-updates until the update is downloaded + if (desktopUpdate.isAutomaticUpdateEnabled && desktopUpdate.state === UpdateState.Ready) { + return 'update-downloaded-auto-restart-to-update'; } - if (isSuiteOutdated) { - return 'update-available'; + if (!desktopUpdate.isAutomaticUpdateEnabled) { + const isUpdateAvailable = [UpdateState.Available, UpdateState.Downloading].includes( + desktopUpdate.state, + ); + if (isUpdateAvailable) { + return 'update-available'; + } + + if (desktopUpdate.state === UpdateState.Ready) { + return 'update-downloaded-manual'; + } } - return isSuiteJustUpdated ? 'just-updated' : 'up-to-date'; + return 'up-to-date'; }; export const useUpdateStatus = (): UpdateStatusData => { + const [closedNotificationDevice, setClosedNotificationDevice] = useState(false); + const [closedNotificationSuite, setClosedNotificationSuite] = useState(false); + const { device } = useDevice(); const { desktopUpdate } = useSelector(state => state); const isFirmwareOutdated = device?.firmware === 'outdated'; + // If firmware is outdated and suite update download/check is in progress, + // we suppress the Firmware notification as it can be there just for a second and then + // it will be replaced with Suite update notification + const isSuiteUpdateInProgress = [UpdateState.Downloading, UpdateState.Checking].includes( + desktopUpdate.state, + ); + + const updateStatusSuite = getSuiteUpdateStatus({ desktopUpdate }); + + const updateStatusDevice = + isFirmwareOutdated && !isSuiteUpdateInProgress ? 'update-available' : 'up-to-date'; + + const showBannerNotification = + (updateStatusSuite !== 'up-to-date' && !closedNotificationSuite) || + (updateStatusDevice !== 'up-to-date' && !closedNotificationDevice); + const common: Omit = { - updateStatusDevice: isFirmwareOutdated ? 'update-available' : 'up-to-date', - updateStatusSuite: getSuiteUpdateStatus({ desktopUpdate }), + updateStatusDevice, + updateStatusSuite, + showBannerNotification, + setClosedNotificationDevice, + setClosedNotificationSuite, }; - if (common.updateStatusSuite === 'restart-to-update') { - return { updateStatus: 'restart-to-update', ...common }; + if ( + common.updateStatusSuite === 'update-downloaded-auto-restart-to-update' || + common.updateStatusSuite === 'update-downloaded-manual' + ) { + return { updateStatus: common.updateStatusSuite, ...common }; } if ( diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx index 9233d704a85..43d6e62902a 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx @@ -9,6 +9,8 @@ import { Elevation, mapElevationToBackground, mapElevationToBorder, zIndices } f import { useActions, useSelector } from 'src/hooks/suite'; import * as suiteActions from 'src/actions/suite/suiteActions'; import { TrafficLightOffset } from '../../../TrafficLightOffset'; +import { UpdateNotificationBanner } from './QuickActions/Update/UpdateNotificationBanner'; +import { useUpdateStatus } from './QuickActions/Update/useUpdateStatus'; const Container = styled.nav<{ $elevation: Elevation }>` display: flex; @@ -31,11 +33,28 @@ const Content = styled.div` export const Sidebar = () => { const { elevation } = useElevation(); + const { + updateStatusDevice, + updateStatusSuite, + showBannerNotification, + setClosedNotificationDevice, + setClosedNotificationSuite, + } = useUpdateStatus(); + const sidebarWidth = useSelector(state => state.suite.settings.sidebarWidth); const { setSidebarWidth } = useActions({ setSidebarWidth: (width: number) => suiteActions.setSidebarWidth({ width }), }); + const onNotificationBannerClosed = () => { + if (updateStatusSuite !== 'up-to-date') { + setClosedNotificationSuite(true); + } + if (updateStatusDevice !== 'up-to-date') { + setClosedNotificationDevice(true); + } + }; + return ( { + + {showBannerNotification && ( + + )} + diff --git a/packages/suite/src/constants/suite/experimental.ts b/packages/suite/src/constants/suite/experimental.ts index 263fa5b234b..1a3205299b5 100644 --- a/packages/suite/src/constants/suite/experimental.ts +++ b/packages/suite/src/constants/suite/experimental.ts @@ -1,15 +1,9 @@ import { TranslationKey } from '@suite-common/intl-types'; import { EXPERIMENTAL_PASSWORD_MANAGER_KB_URL, TOR_SNOWFLAKE_KB_URL, Url } from '@trezor/urls'; -import { isDesktop } from '@trezor/env-utils'; -import { desktopApi } from '@trezor/suite-desktop-api'; import { Dispatch } from '../../types/suite'; -export type ExperimentalFeature = - | 'password-manager' - | 'optimism' - | 'tor-snowflake' - | 'automatic-update'; +export type ExperimentalFeature = 'password-manager' | 'optimism' | 'tor-snowflake'; export type ExperimentalFeatureConfig = { title: TranslationKey; @@ -25,14 +19,6 @@ export const EXPERIMENTAL_FEATURES: Record !isDesktop(), - onToggle: ({ newValue }) => { - desktopApi.setAutomaticUpdateEnabled(newValue); - }, - }, optimism: { title: 'TR_EXPERIMENTAL_OP_ETHEREUM', description: 'TR_EXPERIMENTAL_OP_ETHEREUM_DESCRIPTION', diff --git a/packages/suite/src/reducers/suite/desktopUpdateReducer.ts b/packages/suite/src/reducers/suite/desktopUpdateReducer.ts index 44cf708a06c..9e7f63a05e1 100644 --- a/packages/suite/src/reducers/suite/desktopUpdateReducer.ts +++ b/packages/suite/src/reducers/suite/desktopUpdateReducer.ts @@ -26,6 +26,12 @@ export interface DesktopUpdateState { allowPrerelease: boolean; isAutomaticUpdateEnabled: boolean; firstRunAfterUpdate: boolean; + + /** + * This flag suppresses the "just updated" notification state + * when user already interacted with it. + */ + justUpdatedInteractedWith: boolean; } const initialState: DesktopUpdateState = { @@ -35,6 +41,7 @@ const initialState: DesktopUpdateState = { allowPrerelease: false, isAutomaticUpdateEnabled: false, firstRunAfterUpdate: false, + justUpdatedInteractedWith: false, }; const desktopUpdateReducer = ( @@ -58,9 +65,6 @@ const desktopUpdateReducer = ( case DESKTOP_UPDATE.AVAILABLE: draft.state = UpdateState.Available; draft.latest = action.payload; - draft.modalVisibility = draft.isAutomaticUpdateEnabled - ? draft.modalVisibility - : 'maximized'; break; case DESKTOP_UPDATE.NOT_AVAILABLE: draft.state = UpdateState.NotAvailable; @@ -76,6 +80,11 @@ const desktopUpdateReducer = ( draft.state = UpdateState.Ready; draft.latest = action.payload; break; + case DESKTOP_UPDATE.OPEN_JUST_UPDATED_CHANGELOG: + draft.state = UpdateState.JustUpdated; + draft.modalVisibility = 'maximized'; + draft.justUpdatedInteractedWith = true; + break; case DESKTOP_UPDATE.MODAL_VISIBILITY: draft.modalVisibility = action.payload; break; diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts index 0b29d72aa18..d43cdf5212e 100644 --- a/packages/suite/src/reducers/suite/suiteReducer.ts +++ b/packages/suite/src/reducers/suite/suiteReducer.ts @@ -75,6 +75,7 @@ export interface Flags { viewOnlyTooltipClosed: boolean; showUnhideTokenModal: boolean; showCopyAddressModal: boolean; + enableAutoupdateOnNextRun: boolean; } export interface EvmSettings { @@ -144,6 +145,7 @@ const initialState: SuiteState = { isDashboardPassphraseBannerVisible: true, showCopyAddressModal: true, showUnhideTokenModal: true, + enableAutoupdateOnNextRun: false, }, evmSettings: { confirmExplanationModalClosed: {}, diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index ed46588d612..b893c2a948d 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -3875,6 +3875,38 @@ export default defineMessages({ id: 'TR_QUICK_ACTION_TOOLTIP_JUST_UPDATED', defaultMessage: 'Just updated ({currentVersion})', }, + + TR_QUICK_ACTION_UPDATE_POPOVER_APP_UPDATE_AVAILABLE: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_UPDATE_AVAILABLE', + defaultMessage: 'App update available', + }, + TR_QUICK_ACTION_UPDATE_POPOVER_APP_HAS_BEEN_UPDATED: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_HAS_BEEN_UPDATED', + defaultMessage: 'App’s been updated!', + }, + TR_QUICK_ACTION_UPDATE_POPOVER_APP_DOWNLOADED: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_DOWNLOADED', + defaultMessage: 'Suite downloaded a new Trezor update!', + }, + + TR_QUICK_ACTION_UPDATE_POPOVER_TREZOR_UPDATE_AVAILABLE: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_TREZOR_UPDATE_AVAILABLE', + defaultMessage: 'Trezor update available', + }, + + TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE', + defaultMessage: 'Click to start update', + }, + TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_RESTART_AND_UPDATE: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_RESTART_AND_UPDATE', + defaultMessage: 'Click to restart & update', + }, + TR_QUICK_ACTION_UPDATE_POPOVER_WHATS_NEW: { + id: 'TR_QUICK_ACTION_UPDATE_POPOVER_WHATS_NEW', + defaultMessage: 'What’s new?', + }, + TR_QUICK_ACTION_DEBUG_EAP_EXPERIMENTAL_ENABLED: { id: 'TR_QUICK_ACTION_DEBUG_EAP_EXPERIMENTAL_ENABLED', defaultMessage: 'Enabled', @@ -6148,6 +6180,22 @@ export default defineMessages({ id: 'TR_UPDATE_MODAL_AVAILABLE_HEADING', defaultMessage: 'Update available', }, + TR_UPDATE_MODAL_WHATS_NEW: { + id: 'TR_UPDATE_MODAL_WHATS_NEW', + defaultMessage: 'What’s new', + }, + TR_UPDATE_MODAL_YOUR_VERSION: { + id: 'TR_UPDATE_MODAL_YOUR_VERSION', + defaultMessage: 'Your version: v{version}', + }, + TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES: { + id: 'TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES', + defaultMessage: 'Enable automatic updates', + }, + TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES_NEW_TAG: { + id: 'TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES_NEW_TAG', + defaultMessage: 'New', + }, TR_UPDATE_MODAL_NOT_NOW: { id: 'TR_UPDATE_MODAL_NOT_NOW', defaultMessage: 'Not now', @@ -6176,13 +6224,18 @@ export default defineMessages({ id: 'TR_MANAGE', defaultMessage: 'manage', }, - TR_VERSION_HAS_BEEN_RELEASED: { + TR_VERSION_HAS_RELEASED: { id: 'TR_VERSION_HAS_BEEN_RELEASED', - defaultMessage: 'Version {version} has been released!', + defaultMessage: 'v{version} has released!', }, - TR_CHANGELOG_ON_GITHUB: { - id: 'TR_CHANGELOG_ON_GITHUB', - defaultMessage: 'Changelog on GitHub', + TR_READ_ALL_ON_GITHUB: { + id: 'TR_READ_ALL_ON_GITHUB', + defaultMessage: 'Read all on Github', + }, + TR_WERE_CONSTANTLY_WORKING_TO_IMPROVE: { + id: 'TR_WERE_CONSTANTLY_WORKING_TO_IMPROVE', + defaultMessage: + 'We’re constantly working to improve your Trezor experience, here’s what has changed:', }, TR_UPDATE_MODAL_UPDATE_DOWNLOADED: { id: 'TR_UPDATE_MODAL_UPDATE_DOWNLOADED', diff --git a/packages/suite/src/views/settings/SettingsDebug/DeviceAuthenticity.tsx b/packages/suite/src/views/settings/SettingsDebug/DeviceAuthenticity.tsx index 1ce600c6e88..c4da500a03e 100644 --- a/packages/suite/src/views/settings/SettingsDebug/DeviceAuthenticity.tsx +++ b/packages/suite/src/views/settings/SettingsDebug/DeviceAuthenticity.tsx @@ -18,7 +18,7 @@ export const DeviceAuthenticity = () => { description="Skip device authenticity check when bootloader is unlocked." /> - + ); diff --git a/packages/suite/src/views/settings/SettingsGeneral/AutomaticUpdate.tsx b/packages/suite/src/views/settings/SettingsGeneral/AutomaticUpdate.tsx index 3346953d320..21d17a880c2 100644 --- a/packages/suite/src/views/settings/SettingsGeneral/AutomaticUpdate.tsx +++ b/packages/suite/src/views/settings/SettingsGeneral/AutomaticUpdate.tsx @@ -5,7 +5,6 @@ import { Switch } from '@trezor/components'; import { SettingsSectionItem } from 'src/components/settings'; import { ActionColumn, TextColumn, Translation } from 'src/components/suite'; import { SettingsAnchor } from 'src/constants/suite/anchors'; -import { selectHasExperimentalFeature } from '../../../reducers/suite/suiteReducer'; import { isDesktop } from '@trezor/env-utils'; import { useSelector } from '../../../hooks/suite'; import { desktopApi } from '@trezor/suite-desktop-api'; @@ -15,12 +14,11 @@ const PositionedSwitch = styled.div` `; export const AutomaticUpdate = () => { - const isExperimentalEnabled = useSelector(selectHasExperimentalFeature('automatic-update')); const isAutomaticUpdateEnabled = useSelector( state => state.desktopUpdate.isAutomaticUpdateEnabled, ); - if (!isDesktop() || !isExperimentalEnabled) { + if (!isDesktop()) { return null; } diff --git a/packages/suite/src/views/settings/SettingsGeneral/VersionWithUpdate.tsx b/packages/suite/src/views/settings/SettingsGeneral/VersionWithUpdate.tsx index a52f75b9b1b..a69528f3147 100644 --- a/packages/suite/src/views/settings/SettingsGeneral/VersionWithUpdate.tsx +++ b/packages/suite/src/views/settings/SettingsGeneral/VersionWithUpdate.tsx @@ -101,11 +101,7 @@ export const VersionWithUpdate = () => { )} - {[ - UpdateState.NotAvailable, - UpdateState.EarlyAccessDisable, - UpdateState.EarlyAccessEnable, - ].includes(desktopUpdateState.state) && ( + {desktopUpdateState.state === UpdateState.NotAvailable && ( diff --git a/suite-common/suite-constants/src/desktopAppUpdateState.ts b/suite-common/suite-constants/src/desktopAppUpdateState.ts index 075467bf747..20db5a8d703 100644 --- a/suite-common/suite-constants/src/desktopAppUpdateState.ts +++ b/suite-common/suite-constants/src/desktopAppUpdateState.ts @@ -1,19 +1,15 @@ -// TODO: this probably should be placed in suite-common because it desktop app specific but we need it for @suite-common/toast-notifications -// In future we should introduce some kind of "injecting" notification types depends on platform context -/** - * state: Current updater state - * - checking: Checking Github for newer releases - * - available: Newer version is available - * - not-available: Currently on the latest version - * - downloading: Currently downloading the latest version - * - ready: Latest version is downloaded and going to be installed on the next restart - */ +// TODO: This probably should be placed in suite-common because it desktop app specific but we need it for `@suite-common/toast-notifications`. +// In future we should introduce some kind of "injecting" notification types depends on platform context. export enum DesktopAppUpdateState { - Checking = 'checking', - Available = 'available', - NotAvailable = 'not-available', - Downloading = 'downloading', - Ready = 'ready', + Checking = 'checking', // Checking Github for newer releases + Available = 'available', // Newer version is available + NotAvailable = 'not-available', // Currently on the latest version + Downloading = 'downloading', // Currently downloading the latest version + Ready = 'ready', // Latest version is downloaded and going to be installed on the next restart + + // This is here, because the code from here *cannot* be imported in the `@trezor/suite` package, + // and therefore the modals cannot be done via `UserContextModal`. EarlyAccessEnable = 'early-access-enable', EarlyAccessDisable = 'early-access-disable', + JustUpdated = 'just-updated', } diff --git a/yarn.lock b/yarn.lock index 97caef7886d..e7145504d3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11932,6 +11932,7 @@ __metadata: styled-components: "npm:^6.1.8" stylelint: "npm:^16.2.1" stylelint-config-standard: "npm:^36.0.0" + typescript-styled-plugin: "npm:^0.18.3" languageName: unknown linkType: soft From 9e739c0dd91402b9b2311ff86de4ec03c0d215bb Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Fri, 11 Oct 2024 12:35:43 +0200 Subject: [PATCH 099/624] fix: User proper state to handle notification-banner vs tooltip --- packages/suite/package.json | 2 +- .../Sidebar/QuickActions/QuickActions.tsx | 8 +++++-- .../Update/UpdateStatusActionBarIcon.tsx | 13 ++++++---- .../QuickActions/Update/useUpdateStatus.ts | 16 ------------- .../layouts/SuiteLayout/Sidebar/Sidebar.tsx | 24 ++++++++++--------- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/packages/suite/package.json b/packages/suite/package.json index a7b1e73c463..77bea05f7dd 100644 --- a/packages/suite/package.json +++ b/packages/suite/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/suite", - "suiteVersion": "0.0.0", + "suiteVersion": "24.11.0", "version": "1.0.0", "private": true, "scripts": { diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/QuickActions.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/QuickActions.tsx index 24c3f6fac82..9684cf39040 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/QuickActions.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/QuickActions.tsx @@ -20,9 +20,13 @@ const ActionsContainer = styled.div` } `; -export const QuickActions = () => ( +type QuickActionsProps = { + showUpdateBannerNotification: boolean; +}; + +export const QuickActions = ({ showUpdateBannerNotification }: QuickActionsProps) => ( - + diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx index c75f3472dd2..fb53e397bac 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateStatusActionBarIcon.tsx @@ -139,11 +139,16 @@ const SuiteUpdateIcon = ({ iconSize, updateStatus, variant }: SuiteUpdateIconPro ); }; -export const UpdateStatusActionBarIcon = () => { +type UpdateStatusActionBarIconProps = { + showUpdateBannerNotification: boolean; +}; + +export const UpdateStatusActionBarIcon = ({ + showUpdateBannerNotification, +}: UpdateStatusActionBarIconProps) => { const theme = useTheme(); - const { updateStatus, updateStatusDevice, updateStatusSuite, showBannerNotification } = - useUpdateStatus(); + const { updateStatus, updateStatusDevice, updateStatusSuite } = useUpdateStatus(); const { device } = useDevice(); const dispatch = useDispatch(); @@ -173,7 +178,7 @@ export const UpdateStatusActionBarIcon = () => {
void; - setClosedNotificationDevice: (value: boolean) => void; }; type GetSuiteUpdateStatusArgs = { @@ -50,9 +44,6 @@ const getSuiteUpdateStatus = ({ desktopUpdate }: GetSuiteUpdateStatusArgs): Upda }; export const useUpdateStatus = (): UpdateStatusData => { - const [closedNotificationDevice, setClosedNotificationDevice] = useState(false); - const [closedNotificationSuite, setClosedNotificationSuite] = useState(false); - const { device } = useDevice(); const { desktopUpdate } = useSelector(state => state); @@ -70,16 +61,9 @@ export const useUpdateStatus = (): UpdateStatusData => { const updateStatusDevice = isFirmwareOutdated && !isSuiteUpdateInProgress ? 'update-available' : 'up-to-date'; - const showBannerNotification = - (updateStatusSuite !== 'up-to-date' && !closedNotificationSuite) || - (updateStatusDevice !== 'up-to-date' && !closedNotificationDevice); - const common: Omit = { updateStatusDevice, updateStatusSuite, - showBannerNotification, - setClosedNotificationDevice, - setClosedNotificationSuite, }; if ( diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx index 43d6e62902a..c55dd90541e 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/Sidebar.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import styled from 'styled-components'; import { DeviceSelector } from '../DeviceSelector/DeviceSelector'; import { Navigation } from './Navigation'; @@ -31,15 +31,11 @@ const Content = styled.div` `; export const Sidebar = () => { - const { elevation } = useElevation(); + const [closedNotificationDevice, setClosedNotificationDevice] = useState(false); + const [closedNotificationSuite, setClosedNotificationSuite] = useState(false); - const { - updateStatusDevice, - updateStatusSuite, - showBannerNotification, - setClosedNotificationDevice, - setClosedNotificationSuite, - } = useUpdateStatus(); + const { elevation } = useElevation(); + const { updateStatusDevice, updateStatusSuite } = useUpdateStatus(); const sidebarWidth = useSelector(state => state.suite.settings.sidebarWidth); const { setSidebarWidth } = useActions({ @@ -55,6 +51,10 @@ export const Sidebar = () => { } }; + const showUpdateBannerNotification = + (updateStatusSuite !== 'up-to-date' && !closedNotificationSuite) || + (updateStatusDevice !== 'up-to-date' && !closedNotificationDevice); + return ( { - {showBannerNotification && ( + {showUpdateBannerNotification && ( { /> )} - + From 733a3fa95d19217a0176ee008f2ef6ce438974c5 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Wed, 2 Oct 2024 15:52:10 +0200 Subject: [PATCH 100/624] feat(suite): remove automatic fw hash check from debug settings --- .../suite/src/reducers/suite/suiteReducer.ts | 2 - .../suite/src/support/extraDependencies.ts | 2 - .../CheckFirmwareAuthenticity.tsx | 53 ++++++------------- .../redux-utils/src/extraDependenciesType.ts | 1 - .../test-utils/src/extraDependenciesMock.ts | 1 - .../wallet-core/src/device/deviceThunks.ts | 7 --- 6 files changed, 17 insertions(+), 49 deletions(-) diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts index d43cdf5212e..1919781641d 100644 --- a/packages/suite/src/reducers/suite/suiteReducer.ts +++ b/packages/suite/src/reducers/suite/suiteReducer.ts @@ -34,7 +34,6 @@ export interface DebugModeOptions { invityServerEnvironment?: InvityServerEnvironment; oauthServerEnvironment?: OAuthServerEnvironment; showDebugMenu: boolean; - checkFirmwareAuthenticity: boolean; transports: Extract[number], string>[]; isUnlockedBootloaderAllowed: boolean; } @@ -168,7 +167,6 @@ const initialState: SuiteState = { debug: { invityServerEnvironment: undefined, showDebugMenu: false, - checkFirmwareAuthenticity: false, transports: [], isUnlockedBootloaderAllowed: false, }, diff --git a/packages/suite/src/support/extraDependencies.ts b/packages/suite/src/support/extraDependencies.ts index 5049708a444..946795d4e46 100644 --- a/packages/suite/src/support/extraDependencies.ts +++ b/packages/suite/src/support/extraDependencies.ts @@ -87,8 +87,6 @@ export const extraDependencies: ExtraDependencies = { selectDiscoveryByDeviceState(state, state.device.selectedDevice?.state), selectRouterApp: (state: AppState) => state.router.app, selectRoute: (state: AppState) => state.router.route, - selectCheckFirmwareAuthenticity: (state: AppState) => - state.suite.settings.debug.checkFirmwareAuthenticity, selectAddressDisplayType: (state: AppState) => state.suite.settings.addressDisplayType, selectSelectedAccountStatus: (state: AppState) => state.wallet.selectedAccount.status, selectSuiteSettings, diff --git a/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx b/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx index dec26255dd8..e2a1867ad16 100644 --- a/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx +++ b/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx @@ -1,21 +1,16 @@ import { useState } from 'react'; -import { Button, Switch } from '@trezor/components'; +import { Button } from '@trezor/components'; import { ActionColumn, SectionItem, TextColumn } from 'src/components/suite'; -import { useDispatch, useSelector } from 'src/hooks/suite'; -import { setDebugMode } from 'src/actions/suite/suiteActions'; +import { useDispatch } from 'src/hooks/suite'; import { manualFirmwareHashCheckThunk } from '@suite-common/wallet-core'; export const CheckFirmwareAuthenticity = () => { const [inProgress, setInProgress] = useState(false); - const debug = useSelector(state => state.suite.settings.debug); const dispatch = useDispatch(); - const onChangeRegularCheck = (state?: boolean) => - dispatch(setDebugMode({ checkFirmwareAuthenticity: state })); - const onCheckFirmwareAuthenticity = async () => { setInProgress(true); await dispatch(manualFirmwareHashCheckThunk()); @@ -23,34 +18,20 @@ export const CheckFirmwareAuthenticity = () => { }; return ( - <> - - - - - - - - - - - - - + + + + + + ); }; diff --git a/suite-common/redux-utils/src/extraDependenciesType.ts b/suite-common/redux-utils/src/extraDependenciesType.ts index 6b2344fa051..c2d7c2a8f92 100644 --- a/suite-common/redux-utils/src/extraDependenciesType.ts +++ b/suite-common/redux-utils/src/extraDependenciesType.ts @@ -76,7 +76,6 @@ export type ExtraDependencies = { selectRoute: SuiteCompatibleSelector; selectMetadata: SuiteCompatibleSelector; selectDeviceDiscovery: SuiteCompatibleSelector; - selectCheckFirmwareAuthenticity: SuiteCompatibleSelector; selectAddressDisplayType: SuiteCompatibleSelector; selectSelectedAccountStatus: SuiteCompatibleSelector; selectSuiteSettings: SuiteCompatibleSelector<{ diff --git a/suite-common/test-utils/src/extraDependenciesMock.ts b/suite-common/test-utils/src/extraDependenciesMock.ts index f209087a9b5..8f215c42ea2 100644 --- a/suite-common/test-utils/src/extraDependenciesMock.ts +++ b/suite-common/test-utils/src/extraDependenciesMock.ts @@ -93,7 +93,6 @@ export const extraDependenciesMock: ExtraDependencies = { }), selectLanguage: mockSelector('selectLanguage', 'en'), selectDeviceDiscovery: mockSelector('selectDeviceDiscovery', undefined), - selectCheckFirmwareAuthenticity: mockSelector('selectCheckFirmwareAuthenticity', false), selectAddressDisplayType: mockSelector( 'selectAddressDisplayType', AddressDisplayOptions.CHUNKED, diff --git a/suite-common/wallet-core/src/device/deviceThunks.ts b/suite-common/wallet-core/src/device/deviceThunks.ts index b7be1ef5e73..10eb277a192 100644 --- a/suite-common/wallet-core/src/device/deviceThunks.ts +++ b/suite-common/wallet-core/src/device/deviceThunks.ts @@ -41,7 +41,6 @@ import { import { deviceActions, DEVICE_MODULE_PREFIX, DeviceConnectActionPayload } from './deviceActions'; import { PORTFOLIO_TRACKER_DEVICE_ID, portfolioTrackerDevice } from './deviceConstants'; import { selectAccountByKey } from '../accounts/accountsReducer'; -import { manualFirmwareHashCheckThunk } from '../firmware/manualFirmwareHashCheckThunk'; type SelectDeviceThunkParams = { device: Device | TrezorDevice | undefined; @@ -309,11 +308,9 @@ export const authorizeDeviceThunk = createThunk< { dispatch, getState, extra, rejectWithValue }, ) => { const { - selectors: { selectCheckFirmwareAuthenticity }, actions: { openModal }, } = extra; - const selectedCheckFirmwareAuthenticity = selectCheckFirmwareAuthenticity(getState()); const device = selectDeviceSelector(getState()); if (!device) return rejectWithValue({ error: 'no-device' }); @@ -329,10 +326,6 @@ export const authorizeDeviceThunk = createThunk< if (!isDeviceReady) return rejectWithValue({ error: 'device-not-ready', device }); - if (selectedCheckFirmwareAuthenticity) { - await dispatch(manualFirmwareHashCheckThunk()); - } - const deviceParams: Parameters[0] = { device: { path: device.path, From 0fd023dbe89e77037f7ab75118ee10d83047449b Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Mon, 7 Oct 2024 10:10:43 +0200 Subject: [PATCH 101/624] feat(connect): fw hash check automatically for T1B1 --- .../connect/src/api/firmware/getBinary.ts | 8 +++ packages/connect/src/api/firmware/index.ts | 2 +- packages/connect/src/constants/firmware.ts | 3 + packages/connect/src/constants/index.ts | 1 + .../connect/src/core/onCallFirmwareUpdate.ts | 5 +- packages/connect/src/data/connectSettings.ts | 4 ++ packages/connect/src/device/Device.ts | 63 ++++++++++++++++++- packages/connect/src/types/device.ts | 12 +++- packages/connect/src/types/settings.ts | 2 + .../connect-init/src/connectInitThunks.ts | 9 ++- suite-common/test-utils/src/mocks.ts | 1 + .../wallet-core/src/device/deviceConstants.ts | 1 + .../src/firmware/getBinFilesBaseUrlThunk.ts | 1 + suite-common/wallet-core/src/index.ts | 1 + 14 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 packages/connect/src/constants/firmware.ts diff --git a/packages/connect/src/api/firmware/getBinary.ts b/packages/connect/src/api/firmware/getBinary.ts index 316dc472704..b9ca25a33d3 100644 --- a/packages/connect/src/api/firmware/getBinary.ts +++ b/packages/connect/src/api/firmware/getBinary.ts @@ -13,3 +13,11 @@ export const getBinary = ({ baseUrl, btcOnly, release }: GetBinaryProps) => { return httpRequest(url, 'binary'); }; + +export const getBinaryOptional = (props: GetBinaryProps) => { + try { + return getBinary(props); + } catch (error) { + return null; + } +}; diff --git a/packages/connect/src/api/firmware/index.ts b/packages/connect/src/api/firmware/index.ts index 47130d817b2..fe8e1d9aab7 100644 --- a/packages/connect/src/api/firmware/index.ts +++ b/packages/connect/src/api/firmware/index.ts @@ -1,5 +1,5 @@ export { getBinaryForFirmwareUpgrade } from './getBinaryForFirmwareUpgrade'; -export { getBinary } from './getBinary'; +export { getBinary, getBinaryOptional } from './getBinary'; export { getLanguage } from '../../data/getLanguage'; export { shouldStripFwHeaders, stripFwHeaders } from './modifyFirmware'; export { uploadFirmware } from './uploadFirmware'; diff --git a/packages/connect/src/constants/firmware.ts b/packages/connect/src/constants/firmware.ts new file mode 100644 index 00000000000..d6473fe1e80 --- /dev/null +++ b/packages/connect/src/constants/firmware.ts @@ -0,0 +1,3 @@ +// given that firmware hash is a security feature, we prefer to hardcode the version rather than to query the device capabilities +// (a counterfeit device could simply declare it's incapable of hash check) +export const FW_HASH_SUPPORTED_VERSIONS = ['1.11.1', '2.5.1']; diff --git a/packages/connect/src/constants/index.ts b/packages/connect/src/constants/index.ts index b8003479228..8748fcd4e5c 100644 --- a/packages/connect/src/constants/index.ts +++ b/packages/connect/src/constants/index.ts @@ -2,4 +2,5 @@ export * as ERRORS from './errors'; export * as NETWORK from './network'; export * as CARDANO from './cardano'; export * as NEM from './nem'; +export * as FIRMWARE from './firmware'; export { MessagesSchema as PROTO } from '@trezor/protobuf'; diff --git a/packages/connect/src/core/onCallFirmwareUpdate.ts b/packages/connect/src/core/onCallFirmwareUpdate.ts index 0abdc690c2b..c322414c723 100644 --- a/packages/connect/src/core/onCallFirmwareUpdate.ts +++ b/packages/connect/src/core/onCallFirmwareUpdate.ts @@ -15,7 +15,7 @@ import { } from '../api/firmware'; import { getReleases } from '../data/firmwareInfo'; import { CommonParams, IntermediaryVersion } from '../types'; -import { PROTO, ERRORS } from '../constants'; +import { FIRMWARE, PROTO, ERRORS } from '../constants'; import type { Log } from '../utils/debug'; import type { Device } from '../device/Device'; import { isNewer } from '@trezor/utils/src/versionUtils'; @@ -493,7 +493,8 @@ export const onCallFirmwareUpdate = async ({ } } - const checkSupported = reconnectedDevice.atLeast(['1.11.1', '2.5.1']) && !params.binary; + const checkSupported = + reconnectedDevice.atLeast(FIRMWARE.FW_HASH_SUPPORTED_VERSIONS) && !params.binary; if (checkSupported) { try { diff --git a/packages/connect/src/data/connectSettings.ts b/packages/connect/src/data/connectSettings.ts index f278b0eb778..fa7e193e39d 100644 --- a/packages/connect/src/data/connectSettings.ts +++ b/packages/connect/src/data/connectSettings.ts @@ -148,5 +148,9 @@ export const parseConnectSettings = (input: Partial = {}) => { settings._sessionsBackgroundUrl = input._sessionsBackgroundUrl; } + if (typeof input.binFilesBaseUrl === 'string') { + settings.binFilesBaseUrl = input.binFilesBaseUrl; + } + return settings; }; diff --git a/packages/connect/src/device/Device.ts b/packages/connect/src/device/Device.ts index 2c755ab62c3..44ab951eeef 100644 --- a/packages/connect/src/device/Device.ts +++ b/packages/connect/src/device/Device.ts @@ -3,7 +3,7 @@ import { versionUtils, createDeferred, Deferred, TypedEmitter } from '@trezor/ut import { Session } from '@trezor/transport'; import { TransportProtocol, v1 as v1Protocol } from '@trezor/protocol'; import { DeviceCommands } from './DeviceCommands'; -import { PROTO, ERRORS, NETWORK } from '../constants'; +import { PROTO, ERRORS, NETWORK, FIRMWARE } from '../constants'; import { DEVICE, DeviceButtonRequestPayload, @@ -35,12 +35,17 @@ import { VersionArray, KnownDevice, StaticSessionId, + FirmwareHashCheckResult, + FirmwareHashCheckError, + DeviceModelInternal, } from '../types'; import { models } from '../data/models'; import { getLanguage } from '../data/getLanguage'; import { checkFirmwareRevision } from './checkFirmwareRevision'; import { IStateStorage } from './StateStorage'; import type { PromptCallback } from './prompts'; +import { calculateFirmwareHash, getBinaryOptional, stripFwHeaders } from '../api/firmware'; +import { randomBytes } from 'crypto'; // custom log const _log = initLog('Device'); @@ -156,6 +161,7 @@ export class Device extends TypedEmitter { authenticityChecks: NonNullable = { firmwareRevision: null, + firmwareHash: null, }; private useCardanoDerivation = false; @@ -567,6 +573,10 @@ export class Device extends TypedEmitter { const { message } = await this.getCommands().typedCall('GetFeatures', 'Features', {}); this._updateFeatures(message); + if (this.authenticityChecks.firmwareHash === null) { + this.authenticityChecks.firmwareHash = await this.checkFirmwareHash(); + } + if ( // The check was not yet performed this.authenticityChecks.firmwareRevision === null || @@ -595,6 +605,57 @@ export class Device extends TypedEmitter { } } + async checkFirmwareHash(): Promise { + const createFailResult = (error: FirmwareHashCheckError) => ({ success: false, error }); + + const firmwareVersion = this.getVersion(); + // device has no features (not yet connected) or no firmware + if (firmwareVersion === undefined || !this.features || this.features.bootloader_mode) { + return null; + } + + // optional setting for `connect`, see types/settings.ts + const baseUrl = DataManager.getSettings('binFilesBaseUrl'); + // Initially rolled out only for Model One; in the future we may remove that condition and do it for all models + const isModelOne = this.features.internal_model === DeviceModelInternal.T1B1; + if (baseUrl === undefined || !isModelOne) return createFailResult('check-skipped'); + + const checkSupported = this.atLeast(FIRMWARE.FW_HASH_SUPPORTED_VERSIONS); + if (!checkSupported) return createFailResult('check-unsupported'); + + const release = getReleases(this.features.internal_model).find(r => + versionUtils.isEqual(r.version, firmwareVersion), + ); + // if version is expected to support hash check, but the release is unknown, then firmware is considered unofficial + if (release === undefined) return createFailResult('unknown-release'); + + const btcOnly = this.firmwareType === FirmwareType.BitcoinOnly; + const binary = await getBinaryOptional({ baseUrl, btcOnly, release }); + if (binary === null) { + // release was found, but not its binary - happens on desktop, where only local files are searched + return createFailResult('check-unsupported'); + } + + const strippedBinary = stripFwHeaders(binary); + const { hash: expectedHash, challenge } = calculateFirmwareHash( + this.features.major_version, + strippedBinary, + randomBytes(32), + ); + + const deviceResponse = await this.getCommands().typedCall( + 'GetFirmwareHash', + 'FirmwareHash', + { challenge }, + ); + + if (!deviceResponse.message.hash) return createFailResult('other-error'); + + if (deviceResponse.message.hash !== expectedHash) return createFailResult('hash-mismatch'); + + return { success: true }; + } + async checkFirmwareRevision() { const firmwareVersion = this.getVersion(); diff --git a/packages/connect/src/types/device.ts b/packages/connect/src/types/device.ts index 6d33de38522..974d6b1bc85 100644 --- a/packages/connect/src/types/device.ts +++ b/packages/connect/src/types/device.ts @@ -55,6 +55,16 @@ export type FirmwareRevisionCheckResult = error: FirmwareRevisionCheckError; }; +export type FirmwareHashCheckError = + | 'hash-mismatch' + | 'check-skipped' + | 'check-unsupported' + | 'unknown-release' + | 'other-error'; +export type FirmwareHashCheckResult = + | { success: true } + | { success: false; error: FirmwareHashCheckError }; + type BaseDevice = { path: string; name: string; @@ -79,7 +89,7 @@ export type KnownDevice = BaseDevice & { availableTranslations: string[]; authenticityChecks?: { firmwareRevision: FirmwareRevisionCheckResult | null; - // Maybe add FirmwareHashCheck result here? + firmwareHash: FirmwareHashCheckResult | null; // Maybe add AuthenticityCheck result here? }; }; diff --git a/packages/connect/src/types/settings.ts b/packages/connect/src/types/settings.ts index 842b2fdbe66..915427f7650 100644 --- a/packages/connect/src/types/settings.ts +++ b/packages/connect/src/types/settings.ts @@ -34,6 +34,8 @@ export interface ConnectSettingsPublic { deeplinkOpen?: (url: string) => void; deeplinkCallbackUrl?: string; deeplinkUrl?: string; + // URL for binary files such as firmware, may be local or remote. If not provided, firmware hash check won't be done. + binFilesBaseUrl?: string; } // internal part, not to be accepted from .init() diff --git a/suite-common/connect-init/src/connectInitThunks.ts b/suite-common/connect-init/src/connectInitThunks.ts index 02c760d59e6..ee8ca9c7522 100644 --- a/suite-common/connect-init/src/connectInitThunks.ts +++ b/suite-common/connect-init/src/connectInitThunks.ts @@ -9,7 +9,7 @@ import TrezorConnect, { import { getSynchronize } from '@trezor/utils'; import { deviceConnectThunks } from '@suite-common/wallet-core'; import { resolveStaticPath } from '@suite-common/suite-utils'; -import { isNative } from '@trezor/env-utils'; +import { isDesktop, isNative } from '@trezor/env-utils'; import { cardanoConnectPatch } from './cardanoConnectPatch'; @@ -124,9 +124,16 @@ export const connectInitThunk = createThunk( ); } + // Duplicates `getBinFilesBaseUrlThunk`, because calling any other thunk would change store.getActions() history, + // and it would be impossible to test this thunk in isolation (many unit tests depend on it). + const binFilesBaseUrl = isDesktop() + ? extra.selectors.selectDesktopBinDir(getState()) + : resolveStaticPath('connect/data'); + try { await TrezorConnect.init({ ...connectInitSettings, + binFilesBaseUrl, pendingTransportEvent: selectIsPendingTransportEvent(getState()), transports: selectDebugSettings(getState()).transports, _sessionsBackgroundUrl: sessionsBackground, diff --git a/suite-common/test-utils/src/mocks.ts b/suite-common/test-utils/src/mocks.ts index 355a4364db8..c812fe731d5 100644 --- a/suite-common/test-utils/src/mocks.ts +++ b/suite-common/test-utils/src/mocks.ts @@ -186,6 +186,7 @@ const getConnectDevice = (dev?: Partial, feat?: Partial): Devi type: 'acquired', authenticityChecks: { firmwareRevision: { success: true }, + firmwareHash: { success: true }, }, }; }; diff --git a/suite-common/wallet-core/src/device/deviceConstants.ts b/suite-common/wallet-core/src/device/deviceConstants.ts index 63f5a14901c..c387c055b23 100644 --- a/suite-common/wallet-core/src/device/deviceConstants.ts +++ b/suite-common/wallet-core/src/device/deviceConstants.ts @@ -70,5 +70,6 @@ export const portfolioTrackerDevice: TrezorDevice = { remember: true, authenticityChecks: { firmwareRevision: { success: true }, + firmwareHash: { success: true }, }, }; diff --git a/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts b/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts index 9f184bac67d..6e5d898890b 100644 --- a/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts +++ b/suite-common/wallet-core/src/firmware/getBinFilesBaseUrlThunk.ts @@ -1,6 +1,7 @@ import { isDesktop } from '@trezor/env-utils'; import { resolveStaticPath } from '@suite-common/suite-utils'; import { createThunk } from '@suite-common/redux-utils'; + import { FIRMWARE_MODULE_PREFIX } from './firmwareActions'; /** diff --git a/suite-common/wallet-core/src/index.ts b/suite-common/wallet-core/src/index.ts index aef67593869..0932894f41b 100644 --- a/suite-common/wallet-core/src/index.ts +++ b/suite-common/wallet-core/src/index.ts @@ -23,6 +23,7 @@ export * from './firmware/firmwareActions'; export * from './firmware/firmwareThunks'; export * from './firmware/firmwareReducer'; export * from './firmware/manualFirmwareHashCheckThunk'; +export * from './firmware/getBinFilesBaseUrlThunk'; export * from './send/sendFormActions'; export * from './send/sendFormReducer'; export * from './send/sendFormThunks'; From 6a811f1d1fa43428ebd67c8df90ab5f122ddef4d Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Tue, 8 Oct 2024 14:16:10 +0200 Subject: [PATCH 102/624] feat(suite): fw hash check failed modal --- .../actions/suite/constants/suiteConstants.ts | 1 + .../suite/src/actions/suite/suiteActions.ts | 12 ++++ .../components/suite/Preloader/Preloader.tsx | 25 +++++-- .../DeviceCompromisedHashCheck.tsx | 58 ++++++++++++++++ ...tsx => DeviceCompromisedRevisionCheck.tsx} | 4 +- .../SuiteBanners/FirmwareHashCheckBanner.tsx | 50 ++++++++++++++ .../banners/SuiteBanners/SuiteBanners.tsx | 19 ++++- .../FirmwareHashOptOutModal.tsx | 69 +++++++++++++++++++ .../UserContextModal/UserContextModal.tsx | 3 + .../middlewares/wallet/storageMiddleware.ts | 1 + .../suite/src/reducers/suite/suiteReducer.ts | 34 ++++++--- .../SettingsDevice/FirmwareHashCheck.tsx | 68 ++++++++++++++++++ .../SettingsDevice/SettingsDevice.tsx | 2 + .../receive/components/FreshAddress.tsx | 11 ++- .../receive/components/UsedAddresses.tsx | 15 ++-- .../message-system/src/messageSystemTypes.ts | 1 + suite-common/suite-types/src/modal.ts | 3 + .../wallet-core/src/device/deviceActions.ts | 6 ++ .../wallet-core/src/device/deviceReducer.ts | 23 +++++-- 19 files changed, 374 insertions(+), 31 deletions(-) create mode 100644 packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx rename packages/suite/src/components/suite/SecurityCheck/{DeviceCompromised.tsx => DeviceCompromisedRevisionCheck.tsx} (94%) create mode 100644 packages/suite/src/components/suite/banners/SuiteBanners/FirmwareHashCheckBanner.tsx create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx create mode 100644 packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx diff --git a/packages/suite/src/actions/suite/constants/suiteConstants.ts b/packages/suite/src/actions/suite/constants/suiteConstants.ts index 4af71e8b165..aa4bf4a4060 100644 --- a/packages/suite/src/actions/suite/constants/suiteConstants.ts +++ b/packages/suite/src/actions/suite/constants/suiteConstants.ts @@ -21,6 +21,7 @@ export const COINJOIN_RECEIVE_WARNING = '@suite/coinjoin-receive-warning'; export const DESKTOP_SUITE_PROMO = '@suite/desktop-suite-promo'; export const DEVICE_AUTHENTICITY_OPT_OUT = '@suite/device-authenticity-opt-out'; export const DEVICE_FIRMWARE_REVISION_CHECK = '@suite/firmware-revision-opt-out-check'; +export const DEVICE_FIRMWARE_HASH_CHECK = '@suite/firmware-hash-opt-out-check'; export const EVM_CONFIRM_EXPLANATION_MODAL = '@suite/evm-confirm-explanation-modal'; export const EVM_CLOSE_EXPLANATION_BANNER = '@suite/evm-close-explanation-banner'; export const LOCK_UI = '@suite/lock-ui'; diff --git a/packages/suite/src/actions/suite/suiteActions.ts b/packages/suite/src/actions/suite/suiteActions.ts index 7196eae184f..1f980bd1b9d 100644 --- a/packages/suite/src/actions/suite/suiteActions.ts +++ b/packages/suite/src/actions/suite/suiteActions.ts @@ -40,6 +40,7 @@ export type SuiteAction = | { type: typeof SUITE.COINJOIN_RECEIVE_WARNING; payload: boolean } | { type: typeof SUITE.DEVICE_AUTHENTICITY_OPT_OUT; payload: boolean } | { type: typeof SUITE.DEVICE_FIRMWARE_REVISION_CHECK; payload: { isDisabled: boolean } } + | { type: typeof SUITE.DEVICE_FIRMWARE_HASH_CHECK; payload: { isDisabled: boolean } } | { type: typeof SUITE.COINJOIN_RECEIVE_WARNING; payload: boolean } | { type: typeof SUITE.LOCK_UI; payload: boolean } | ReturnType @@ -311,6 +312,17 @@ export const checkFirmwareRevision = }); }; +export const checkFirmwareHash = + ({ isDisabled }: { isDisabled: boolean }) => + (dispatch: Dispatch) => { + dispatch(notificationsActions.addToast({ type: 'settings-applied' })); + + dispatch({ + type: SUITE.DEVICE_FIRMWARE_HASH_CHECK, + payload: { isDisabled }, + }); + }; + /** * Called from `suiteMiddleware` * Set `loaded` field in suite reducer diff --git a/packages/suite/src/components/suite/Preloader/Preloader.tsx b/packages/suite/src/components/suite/Preloader/Preloader.tsx index 476884eb5e9..9ed9f163993 100644 --- a/packages/suite/src/components/suite/Preloader/Preloader.tsx +++ b/packages/suite/src/components/suite/Preloader/Preloader.tsx @@ -14,15 +14,21 @@ import { selectIsLoggedOut, selectSuiteFlags, selectIsFirmwareRevisionCheckEnabledAndFailed, + selectIsFirmwareHashCheckEnabledAndFailed, } from 'src/reducers/suite/suiteReducer'; import { SuiteStart } from 'src/views/start/SuiteStart'; import { PrerequisitesGuide } from '../PrerequisitesGuide/PrerequisitesGuide'; import { LoggedOutLayout } from '../layouts/LoggedOutLayout'; import { WelcomeLayout } from '../layouts/WelcomeLayout/WelcomeLayout'; import { ViewOnlyPromo } from 'src/views/view-only/ViewOnlyPromo'; -import { selectDevice, selectIsFirmwareRevisionCheckDismissed } from '@suite-common/wallet-core'; -import { DeviceCompromised } from '../SecurityCheck/DeviceCompromised'; +import { + selectDevice, + selectIsFirmwareHashCheckDismissed, + selectIsFirmwareRevisionCheckDismissed, +} from '@suite-common/wallet-core'; +import { DeviceCompromisedRevisionCheck } from '../SecurityCheck/DeviceCompromisedRevisionCheck'; import { RouterAppWithParams } from '../../../constants/suite/routes'; +import { DeviceCompromisedHashCheck } from '../SecurityCheck/DeviceCompromisedHashCheck'; const ROUTES_TO_SKIP_REVISION_CHECK: RouterAppWithParams['app'][] = [ 'settings', @@ -57,7 +63,9 @@ export const Preloader = ({ children }: PreloaderProps) => { const selectedDevice = useSelector(selectDevice); const { initialRun, viewOnlyPromoClosed } = useSelector(selectSuiteFlags); const isRevisionCheckFailed = useSelector(selectIsFirmwareRevisionCheckEnabledAndFailed); + const isFwHashCheckFailed = useSelector(selectIsFirmwareHashCheckEnabledAndFailed); const isFirmwareRevisionCheckDismissed = useSelector(selectIsFirmwareRevisionCheckDismissed); + const isFirmwareHashCheckDismissed = useSelector(selectIsFirmwareHashCheckDismissed); const dispatch = useDispatch(); @@ -82,12 +90,15 @@ export const Preloader = ({ children }: PreloaderProps) => { } if ( - (router.route?.app === undefined || - !ROUTES_TO_SKIP_REVISION_CHECK.includes(router.route?.app)) && - !isFirmwareRevisionCheckDismissed && - isRevisionCheckFailed + router.route?.app === undefined || + !ROUTES_TO_SKIP_REVISION_CHECK.includes(router.route?.app) ) { - return ; + if (!isFirmwareRevisionCheckDismissed && isRevisionCheckFailed) { + return ; + } + if (!isFirmwareHashCheckDismissed && isFwHashCheckFailed) { + return ; + } } if ( diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx new file mode 100644 index 00000000000..1c18bf09f34 --- /dev/null +++ b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx @@ -0,0 +1,58 @@ +import { useEffect } from 'react'; + +import { isDeviceAcquired } from '@suite-common/suite-utils'; +import { deviceActions } from '@suite-common/wallet-core'; +import { Card } from '@trezor/components'; +import { getFirmwareVersion } from '@trezor/device-utils'; +import { TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL } from '@trezor/urls'; + +import { WelcomeLayout } from 'src/components/suite'; +import { useDevice, useDispatch } from 'src/hooks/suite'; +import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; +import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; + +export const DeviceCompromisedHashCheck = () => { + const dispatch = useDispatch(); + const { device } = useDevice(); + + const revision = device?.features?.revision; + const version = getFirmwareVersion(device); + const vendor = device?.features?.fw_vendor; + const authenticityError = + isDeviceAcquired(device) && device.authenticityChecks?.firmwareHash?.success === false + ? device.authenticityChecks.firmwareHash?.error + : undefined; + + const goToSuite = () => { + // Condition to satisfy TypeScript, device.id is always defined at this point. + if (device?.id) { + dispatch(deviceActions.dismissFirmwareHashCheck(device.id)); + } + }; + + useEffect(() => { + const contextData = { revision, version, vendor, authenticityError }; + + withSentryScope(scope => { + scope.setLevel('error'); + scope.setTag('deviceAuthenticityError', 'firmware hash check failed'); + captureSentryMessage( + `Firmware hash check failed! ${JSON.stringify(contextData)}`, + scope, + ); + }); + }, [authenticityError, revision, vendor, version]); + + return ( + + + {/* TODO #14766 REMOVE ME ! */} + (THIS IS HASH CHECK..) + + + + ); +}; diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx similarity index 94% rename from packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx rename to packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx index 006c0ece990..e7e79cf1647 100644 --- a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx +++ b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx @@ -11,7 +11,7 @@ import { useDevice, useDispatch } from 'src/hooks/suite'; import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; -export const DeviceCompromised = () => { +export const DeviceCompromisedRevisionCheck = () => { const dispatch = useDispatch(); const { device } = useDevice(); @@ -45,7 +45,7 @@ export const DeviceCompromised = () => { return ( - + , + TranslationKey | string +> = { + // TODO #14766 use actual translation ids, remove the `string` type and use it in the component + 'hash-mismatch': 'Compromised FW (hash mismatch)', + 'check-unsupported': 'Update STRONGLY recommended to get security...', + 'unknown-release': 'Compromised FW (unrecognized version)', + 'other-error': 'Compromised FW (unexpected device behavior)', +}; + +export const FirmwareHashCheckBanner = () => { + const device = useSelector(selectDevice); + + if ( + !isDeviceAcquired(device) || + device.authenticityChecks?.firmwareHash?.success !== false || + device.authenticityChecks?.firmwareHash?.error === 'check-skipped' + ) { + return null; + } + + return ( + + + + + + } + > + {/*TODO #14766 see above*/} + {messages[device.authenticityChecks.firmwareHash.error]} + {/**/} + + ); +}; diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx index 60f3e8caea1..056d7ee5657 100644 --- a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx +++ b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx @@ -20,6 +20,7 @@ import { SafetyChecksBanner } from './SafetyChecksBanner'; import { TranslationMode } from './TranslationModeBanner'; import { FirmwareHashMismatch } from './FirmwareHashMismatchBanner'; import { FirmwareRevisionCheckBanner } from './FirmwareRevisionCheckBanner'; +import { FirmwareHashCheckBanner } from './FirmwareHashCheckBanner'; const Container = styled.div<{ $isVisible?: boolean }>` width: 100%; @@ -36,7 +37,9 @@ export const SuiteBanners = () => { const isOnline = useSelector(state => state.suite.online); const firmwareHashInvalid = useSelector(state => state.firmware.firmwareHashInvalid); const bannerMessage = useSelector(selectBannerMessage); - const { isFirmwareRevisionCheckDisabled } = useSelector(state => state.suite.settings); + const { isFirmwareRevisionCheckDisabled, isFirmwareHashCheckDisabled } = useSelector( + state => state.suite.settings, + ); // The dismissal doesn't need to outlive the session. Use local state. const [safetyChecksDismissed, setSafetyChecksDismissed] = useState(false); @@ -58,14 +61,26 @@ export const SuiteBanners = () => { let banner = null; let priority = 0; + // firmware hash invalid after a firmware update, not the regular check if (device?.id && firmwareHashInvalid.includes(device.id)) { banner = ; priority = 92; + } + // the regular firmware check + else if ( + !isFirmwareHashCheckDisabled && + isDeviceAcquired(device) && + device.authenticityChecks !== undefined && + device.authenticityChecks.firmwareHash !== null && // only if check was performed + device.authenticityChecks.firmwareHash.success === false + ) { + banner = ; + priority = 91.1; } else if ( !isFirmwareRevisionCheckDisabled && isDeviceAcquired(device) && device.authenticityChecks !== undefined && - device.authenticityChecks.firmwareRevision !== null && // check was performed + device.authenticityChecks.firmwareRevision !== null && // only if check was performed device.authenticityChecks.firmwareRevision.success === false ) { banner = ; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx new file mode 100644 index 00000000000..09e3b63179a --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx @@ -0,0 +1,69 @@ +import { useState } from 'react'; + +import { Column, NewModal, Banner, Card, H3, Paragraph } from '@trezor/components'; +import { Translation, CheckItem } from 'src/components/suite'; +import { checkFirmwareHash } from 'src/actions/suite/suiteActions'; +import { useDispatch } from 'src/hooks/suite'; +import { spacings } from '@trezor/theme'; + +type DeviceAuthenticityOptOutModalProps = { + onCancel: () => void; +}; + +export const FirmwareHashOptOutModal = ({ onCancel }: DeviceAuthenticityOptOutModalProps) => { + const [isConfirmed, setIsConfirmed] = useState(false); + const dispatch = useDispatch(); + + const handleTurningOffHashCheck = () => { + dispatch(checkFirmwareHash({ isDisabled: true })); + onCancel(); + }; + + return ( + + + + + + + + + } + variant="warning" + > +

+ + {/* TODO #14766 REMOVE ME ! */} + (HASH) +

+ + + + + + + + + + + + + } + isChecked={isConfirmed} + onClick={() => setIsConfirmed(!isConfirmed)} + data-testid="@device-firmware-hash/checkbox" + /> + +
+ ); +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx index 4d757eb60bc..304881de9f8 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx @@ -47,6 +47,7 @@ import { CryptoId } from 'invity-api'; import { EverstakeModal } from './UnstakeModal/EverstakeModal'; import { PassphraseMismatchModal } from './PassphraseMismatchModal'; import { FirmwareRevisionOptOutModal } from './FirmwareRevisionOptOutModal'; +import { FirmwareHashOptOutModal } from './FirmwareHashOptOutModal'; /** Modals opened as a result of user action */ export const UserContextModal = ({ @@ -92,6 +93,8 @@ export const UserContextModal = ({ return ; case 'firmware-revision-opt-out': return ; + case 'firmware-hash-opt-out': + return ; case 'qr-reader': return ; case 'transaction-detail': diff --git a/packages/suite/src/middlewares/wallet/storageMiddleware.ts b/packages/suite/src/middlewares/wallet/storageMiddleware.ts index aa647763049..793b633bf57 100644 --- a/packages/suite/src/middlewares/wallet/storageMiddleware.ts +++ b/packages/suite/src/middlewares/wallet/storageMiddleware.ts @@ -236,6 +236,7 @@ const storageMiddleware = (api: MiddlewareAPI) => { case SUITE.SET_SIDEBAR_WIDTH: case SUITE.DEVICE_AUTHENTICITY_OPT_OUT: case SUITE.DEVICE_FIRMWARE_REVISION_CHECK: + case SUITE.DEVICE_FIRMWARE_HASH_CHECK: case SUITE.EVM_CONFIRM_EXPLANATION_MODAL: case SUITE.EVM_CLOSE_EXPLANATION_BANNER: api.dispatch(storageActions.saveSuiteSettings()); diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts index 1919781641d..d470fc5ecb9 100644 --- a/packages/suite/src/reducers/suite/suiteReducer.ts +++ b/packages/suite/src/reducers/suite/suiteReducer.ts @@ -99,6 +99,7 @@ export interface SuiteSettings { autodetect: AutodetectSettings; isDeviceAuthenticityCheckDisabled: boolean; isFirmwareRevisionCheckDisabled: boolean; + isFirmwareHashCheckDisabled: boolean; addressDisplayType: AddressDisplayOptions; defaultWalletLoading: WalletType; experimental?: ExperimentalFeature[]; @@ -164,6 +165,7 @@ const initialState: SuiteState = { isDesktopSuitePromoHidden: false, isDeviceAuthenticityCheckDisabled: false, isFirmwareRevisionCheckDisabled: false, + isFirmwareHashCheckDisabled: false, debug: { invityServerEnvironment: undefined, showDebugMenu: false, @@ -330,6 +332,9 @@ const suiteReducer = (state: SuiteState = initialState, action: Action): SuiteSt case SUITE.DEVICE_FIRMWARE_REVISION_CHECK: draft.settings.isFirmwareRevisionCheckDisabled = action.payload.isDisabled; break; + case SUITE.DEVICE_FIRMWARE_HASH_CHECK: + draft.settings.isFirmwareHashCheckDisabled = action.payload.isDisabled; + break; case SUITE.LOCK_UI: changeLock(draft, SUITE.LOCK_TYPE.UI, action.payload); break; @@ -436,14 +441,8 @@ export const selectIsFirmwareRevisionCheckEnabledAndFailed = ( state: SuiteRootState & DeviceRootState & MessageSystemRootState, ) => { const { isFirmwareRevisionCheckDisabled } = state.suite.settings; - const isFirmwareRevisionCheckDisabledByMessageSystem = selectIsFeatureDisabled( - state, - Feature.firmwareRevisionCheck, - ); - - if (isFirmwareRevisionCheckDisabled || isFirmwareRevisionCheckDisabledByMessageSystem) { - return false; - } + const isDisabledByMessageSystem = selectIsFeatureDisabled(state, Feature.firmwareRevisionCheck); + if (isFirmwareRevisionCheckDisabled || isDisabledByMessageSystem) return false; const device = selectDevice(state); @@ -458,4 +457,23 @@ export const selectIsFirmwareRevisionCheckEnabledAndFailed = ( ); }; +export const selectIsFirmwareHashCheckEnabledAndFailed = ( + state: SuiteRootState & DeviceRootState & MessageSystemRootState, +) => { + const { isFirmwareHashCheckDisabled } = state.suite.settings; + const isDisabledByMessageSystem = selectIsFeatureDisabled(state, Feature.firmwareHashCheck); + if (isFirmwareHashCheckDisabled || isDisabledByMessageSystem) return false; + + const device = selectDevice(state); + + return ( + isDeviceAcquired(device) && + // If `check` is null, it means that it was not performed yet. + device.authenticityChecks?.firmwareHash?.success === false && + !['check-skipped', 'check-unsupported'].includes( + device.authenticityChecks.firmwareHash.error, + ) + ); +}; + export default suiteReducer; diff --git a/packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx b/packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx new file mode 100644 index 00000000000..8bf4c894fe2 --- /dev/null +++ b/packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx @@ -0,0 +1,68 @@ +import { + ActionButton, + ActionColumn, + SectionItem, + TextColumn, + Translation, +} from 'src/components/suite'; +import { useDispatch, useSelector } from 'src/hooks/suite'; +import { openModal } from 'src/actions/suite/modalActions'; +import { checkFirmwareHash } from 'src/actions/suite/suiteActions'; +import { HELP_CENTER_FIRMWARE_REVISION_CHECK } from '@trezor/urls'; + +export const FirmwareHashCheck = () => { + const dispatch = useDispatch(); + const isFirmwareHashCheckDisabled = useSelector( + state => state.suite.settings.isFirmwareHashCheckDisabled, + ); + + const handleClick = () => + dispatch( + isFirmwareHashCheckDisabled + ? checkFirmwareHash({ isDisabled: false }) + : openModal({ type: 'firmware-hash-opt-out' }), + ); + + return ( + + + } + description={ + + } + buttonLink={HELP_CENTER_FIRMWARE_REVISION_CHECK} + /> + + + + {/* TODO #14766 REMOVE ME ! */} + (HASH) + + + + ); +}; diff --git a/packages/suite/src/views/settings/SettingsDevice/SettingsDevice.tsx b/packages/suite/src/views/settings/SettingsDevice/SettingsDevice.tsx index 3f9f436b611..0e0759d1334 100644 --- a/packages/suite/src/views/settings/SettingsDevice/SettingsDevice.tsx +++ b/packages/suite/src/views/settings/SettingsDevice/SettingsDevice.tsx @@ -32,6 +32,7 @@ import { HapticFeedback } from './HapticFeedback'; import { Brightness } from './Brightness'; import { DefaultWalletLoading } from './DefaultWalletLoading'; import { FirmwareRevisionCheck } from './FirmwareRevisionCheck'; +import { FirmwareHashCheck } from './FirmwareHashCheck'; import { SUPPORTS_DEVICE_AUTHENTICITY_CHECK } from '../../../constants/suite/device'; const deviceSettingsUnavailable = (device?: TrezorDevice, transport?: Partial) => { @@ -176,6 +177,7 @@ export const SettingsDevice = () => { {supportsDeviceAuthentication && } + ); diff --git a/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx b/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx index e35fc42be98..31d9c8ea829 100644 --- a/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx +++ b/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx @@ -11,7 +11,10 @@ import { AccountsRootState, selectIsAccountUtxoBased } from '@suite-common/walle import { networks } from '@suite-common/wallet-config'; import { EvmExplanationBox } from 'src/components/wallet/EvmExplanationBox'; import { spacingsPx, typography } from '@trezor/theme'; -import { selectIsFirmwareRevisionCheckEnabledAndFailed } from 'src/reducers/suite/suiteReducer'; +import { + selectIsFirmwareHashCheckEnabledAndFailed, + selectIsFirmwareRevisionCheckEnabledAndFailed, +} from 'src/reducers/suite/suiteReducer'; // eslint-disable-next-line local-rules/no-override-ds-component const StyledCard = styled(Card)` @@ -127,6 +130,7 @@ export const FreshAddress = ({ selectIsAccountUtxoBased(state, account?.key ?? ''), ); const isRevisionCheckFailed = useSelector(selectIsFirmwareRevisionCheckEnabledAndFailed); + const isFwHashCheckFailed = useSelector(selectIsFirmwareHashCheckEnabledAndFailed); const dispatch = useDispatch(); const firstFreshAddress = useMemo(() => { @@ -158,7 +162,7 @@ export const FreshAddress = ({ if (!firstFreshAddress) { return ; } - if (isRevisionCheckFailed) { + if (isRevisionCheckFailed || isFwHashCheckFailed) { return ; } @@ -173,7 +177,8 @@ export const FreshAddress = ({ locked || coinjoinDisallowReveal || !firstFreshAddress || - isRevisionCheckFailed, + isRevisionCheckFailed || + isFwHashCheckFailed, isLoading: locked, }; diff --git a/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx b/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx index a807422cb0b..e376a01ea2f 100644 --- a/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx +++ b/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx @@ -22,7 +22,10 @@ import { MetadataAddPayload } from 'src/types/suite/metadata'; import { showAddress } from 'src/actions/wallet/receiveActions'; import { useDispatch, useSelector } from 'src/hooks/suite/'; import { selectLabelingDataForSelectedAccount } from 'src/reducers/suite/metadataReducer'; -import { selectIsFirmwareRevisionCheckEnabledAndFailed } from 'src/reducers/suite/suiteReducer'; +import { + selectIsFirmwareHashCheckEnabledAndFailed, + selectIsFirmwareRevisionCheckEnabledAndFailed, +} from 'src/reducers/suite/suiteReducer'; const AddressActions = styled.div<{ $isVisible?: boolean }>` opacity: ${({ $isVisible }) => ($isVisible ? '1' : '0')}; @@ -48,15 +51,17 @@ type ItemProps = { const Item = ({ addr, locked, symbol, onClick, metadataPayload, index }: ItemProps) => { const isRevisionCheckFailed = useSelector(selectIsFirmwareRevisionCheckEnabledAndFailed); + const isFwHashCheckFailed = useSelector(selectIsFirmwareHashCheckEnabledAndFailed); const [isHovered, setIsHovered] = useState(false); const amount = formatNetworkAmount(addr.received || '0', symbol); const fresh = !addr.transfers; const address = addr.address.substring(0, 20); - const isDisabled = locked || isRevisionCheckFailed; - const tooltipContent = isRevisionCheckFailed ? ( - - ) : null; + const isDisabled = locked || isRevisionCheckFailed || isFwHashCheckFailed; + const tooltipContent = + isRevisionCheckFailed || isFwHashCheckFailed ? ( + + ) : null; return ( diff --git a/suite-common/message-system/src/messageSystemTypes.ts b/suite-common/message-system/src/messageSystemTypes.ts index 4f1067014ab..05c3d336c07 100644 --- a/suite-common/message-system/src/messageSystemTypes.ts +++ b/suite-common/message-system/src/messageSystemTypes.ts @@ -23,6 +23,7 @@ export const Feature = { ethUnstake: 'eth.staking.unstake', ethClaim: 'eth.staking.claim', firmwareRevisionCheck: 'security.firmware.check', + firmwareHashCheck: 'security.firmware.hashCheck', } as const; export type FeatureDomain = (typeof Feature)[keyof typeof Feature]; diff --git a/suite-common/suite-types/src/modal.ts b/suite-common/suite-types/src/modal.ts index 5e0ff9e328f..33637e03f7a 100644 --- a/suite-common/suite-types/src/modal.ts +++ b/suite-common/suite-types/src/modal.ts @@ -101,6 +101,9 @@ export type UserContextPayload = | { type: 'firmware-revision-opt-out'; } + | { + type: 'firmware-hash-opt-out'; + } | { type: 'disconnect-device'; } diff --git a/suite-common/wallet-core/src/device/deviceActions.ts b/suite-common/wallet-core/src/device/deviceActions.ts index f78e5e75cc0..078a4ad7d6c 100644 --- a/suite-common/wallet-core/src/device/deviceActions.ts +++ b/suite-common/wallet-core/src/device/deviceActions.ts @@ -85,12 +85,18 @@ const dismissFirmwareRevisionCheck = createAction( (payload: string) => ({ payload }), ); +const dismissFirmwareHashCheck = createAction( + `${DEVICE_MODULE_PREFIX}/dismissFirmwareHashCheck`, + (payload: string) => ({ payload }), +); + export const deviceActions = { connectDevice, connectUnacquiredDevice, deviceChanged, deviceDisconnect, dismissFirmwareRevisionCheck, + dismissFirmwareHashCheck, updatePassphraseMode, receiveAuthConfirm, rememberDevice, diff --git a/suite-common/wallet-core/src/device/deviceReducer.ts b/suite-common/wallet-core/src/device/deviceReducer.ts index 52ffba9a2d1..be11a22ec9b 100644 --- a/suite-common/wallet-core/src/device/deviceReducer.ts +++ b/suite-common/wallet-core/src/device/deviceReducer.ts @@ -34,6 +34,7 @@ export type State = { deviceAuthenticity?: Record; dismissedSecurityChecks?: { firmwareRevision?: string[]; + firmwareHash?: string[]; }; }; @@ -593,10 +594,16 @@ export const prepareDeviceReducer = createReducerWithExtraDeps(initialState, (bu if (!state.dismissedSecurityChecks.firmwareRevision) { state.dismissedSecurityChecks.firmwareRevision = []; } - state.dismissedSecurityChecks.firmwareRevision = [ - payload, - ...state.dismissedSecurityChecks.firmwareRevision, - ]; + state.dismissedSecurityChecks.firmwareRevision.unshift(payload); + }) + .addCase(deviceActions.dismissFirmwareHashCheck, (state, { payload }) => { + if (!state.dismissedSecurityChecks) { + state.dismissedSecurityChecks = {}; + } + if (!state.dismissedSecurityChecks.firmwareHash) { + state.dismissedSecurityChecks.firmwareHash = []; + } + state.dismissedSecurityChecks.firmwareHash.unshift(payload); }) .addCase(extra.actionTypes.setDeviceMetadata, extra.reducers.setDeviceMetadataReducer) .addCase( @@ -790,6 +797,14 @@ export const selectIsFirmwareRevisionCheckDismissed = (state: DeviceRootState): ); }; +export const selectIsFirmwareHashCheckDismissed = (state: DeviceRootState): boolean => { + const device = selectDevice(state); + + return !!( + device?.id && state.device.dismissedSecurityChecks?.firmwareHash?.includes(device.id) + ); +}; + export const selectIsPortfolioTrackerDevice = (state: DeviceRootState) => { const device = selectDevice(state); From 3c5d3fd0cde1b03f5e49cd41e1c2d14f9e1882e4 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Thu, 10 Oct 2024 10:24:05 +0200 Subject: [PATCH 103/624] feat(suite): single UI for fw revision & hash check --- .../suite/src/actions/suite/suiteActions.ts | 9 +-- .../components/suite/Preloader/Preloader.tsx | 40 ++++------ .../suite/SecurityCheck/DeviceCompromised.tsx | 61 ++++++++++++++ .../DeviceCompromisedHashCheck.tsx | 58 -------------- .../DeviceCompromisedRevisionCheck.tsx | 56 ------------- .../SuiteBanners/FirmwareHashCheckBanner.tsx | 50 ------------ .../FirmwareRevisionCheckBanner.tsx | 48 +++++++---- .../banners/SuiteBanners/SuiteBanners.tsx | 30 +++---- .../FirmwareHashOptOutModal.tsx | 69 ---------------- .../FirmwareRevisionOptOutModal.tsx | 4 +- .../UserContextModal/UserContextModal.tsx | 3 - .../suite/src/reducers/suite/suiteReducer.ts | 79 ++++++++++++------- packages/suite/src/support/messages.ts | 18 +++++ .../SettingsDevice/FirmwareHashCheck.tsx | 68 ---------------- .../SettingsDevice/FirmwareRevisionCheck.tsx | 23 +++--- .../SettingsDevice/SettingsDevice.tsx | 2 - .../receive/components/FreshAddress.tsx | 15 ++-- .../receive/components/UsedAddresses.tsx | 19 ++--- suite-common/suite-types/src/modal.ts | 3 - .../wallet-core/src/device/deviceActions.ts | 12 +-- .../wallet-core/src/device/deviceReducer.ts | 33 ++------ 21 files changed, 230 insertions(+), 470 deletions(-) create mode 100644 packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx delete mode 100644 packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx delete mode 100644 packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx delete mode 100644 packages/suite/src/components/suite/banners/SuiteBanners/FirmwareHashCheckBanner.tsx delete mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx delete mode 100644 packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx diff --git a/packages/suite/src/actions/suite/suiteActions.ts b/packages/suite/src/actions/suite/suiteActions.ts index 1f980bd1b9d..787efda20b7 100644 --- a/packages/suite/src/actions/suite/suiteActions.ts +++ b/packages/suite/src/actions/suite/suiteActions.ts @@ -301,7 +301,7 @@ export const deviceAuthenticityOptOut = (payload: boolean) => (dispatch: Dispatc }); }; -export const checkFirmwareRevision = +export const toggleCheckFirmwareAuthenticity = ({ isDisabled }: { isDisabled: boolean }) => (dispatch: Dispatch) => { dispatch(notificationsActions.addToast({ type: 'settings-applied' })); @@ -310,13 +310,6 @@ export const checkFirmwareRevision = type: SUITE.DEVICE_FIRMWARE_REVISION_CHECK, payload: { isDisabled }, }); - }; - -export const checkFirmwareHash = - ({ isDisabled }: { isDisabled: boolean }) => - (dispatch: Dispatch) => { - dispatch(notificationsActions.addToast({ type: 'settings-applied' })); - dispatch({ type: SUITE.DEVICE_FIRMWARE_HASH_CHECK, payload: { isDisabled }, diff --git a/packages/suite/src/components/suite/Preloader/Preloader.tsx b/packages/suite/src/components/suite/Preloader/Preloader.tsx index 9ed9f163993..1e77dd4b58d 100644 --- a/packages/suite/src/components/suite/Preloader/Preloader.tsx +++ b/packages/suite/src/components/suite/Preloader/Preloader.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect } from 'react'; +import { FC, useEffect, PropsWithChildren } from 'react'; import { useDispatch, useSelector } from 'src/hooks/suite'; import { Onboarding } from 'src/views/onboarding'; @@ -13,8 +13,7 @@ import { selectPrerequisite, selectIsLoggedOut, selectSuiteFlags, - selectIsFirmwareRevisionCheckEnabledAndFailed, - selectIsFirmwareHashCheckEnabledAndFailed, + selectIsFirmwareAuthenticityCheckEnabledAndFailed, } from 'src/reducers/suite/suiteReducer'; import { SuiteStart } from 'src/views/start/SuiteStart'; import { PrerequisitesGuide } from '../PrerequisitesGuide/PrerequisitesGuide'; @@ -23,14 +22,12 @@ import { WelcomeLayout } from '../layouts/WelcomeLayout/WelcomeLayout'; import { ViewOnlyPromo } from 'src/views/view-only/ViewOnlyPromo'; import { selectDevice, - selectIsFirmwareHashCheckDismissed, - selectIsFirmwareRevisionCheckDismissed, + selectIsFirmwareAuthenticityCheckDismissed, } from '@suite-common/wallet-core'; -import { DeviceCompromisedRevisionCheck } from '../SecurityCheck/DeviceCompromisedRevisionCheck'; +import { DeviceCompromised } from '../SecurityCheck/DeviceCompromised'; import { RouterAppWithParams } from '../../../constants/suite/routes'; -import { DeviceCompromisedHashCheck } from '../SecurityCheck/DeviceCompromisedHashCheck'; -const ROUTES_TO_SKIP_REVISION_CHECK: RouterAppWithParams['app'][] = [ +const ROUTES_TO_SKIP_FIRMWARE_CHECK: RouterAppWithParams['app'][] = [ 'settings', 'firmware', 'firmware-type', @@ -48,13 +45,9 @@ const getFullscreenApp = (route: AppState['router']['route']): FC | undefined => } }; -interface PreloaderProps { - children: React.ReactNode; -} - // Preloader is a top level wrapper used in _app.tsx. // Decides which content should be displayed basing on route and prerequisites. -export const Preloader = ({ children }: PreloaderProps) => { +export const Preloader = ({ children }: PropsWithChildren) => { const lifecycle = useSelector(state => state.suite.lifecycle); const transport = useSelector(state => state.suite.transport); const router = useSelector(state => state.router); @@ -62,10 +55,10 @@ export const Preloader = ({ children }: PreloaderProps) => { const isLoggedOut = useSelector(selectIsLoggedOut); const selectedDevice = useSelector(selectDevice); const { initialRun, viewOnlyPromoClosed } = useSelector(selectSuiteFlags); - const isRevisionCheckFailed = useSelector(selectIsFirmwareRevisionCheckEnabledAndFailed); - const isFwHashCheckFailed = useSelector(selectIsFirmwareHashCheckEnabledAndFailed); - const isFirmwareRevisionCheckDismissed = useSelector(selectIsFirmwareRevisionCheckDismissed); - const isFirmwareHashCheckDismissed = useSelector(selectIsFirmwareHashCheckDismissed); + const isFirmwareCheckFailed = useSelector(selectIsFirmwareAuthenticityCheckEnabledAndFailed); + const isFirmwareAuthenticityCheckDismissed = useSelector( + selectIsFirmwareAuthenticityCheckDismissed, + ); const dispatch = useDispatch(); @@ -90,15 +83,12 @@ export const Preloader = ({ children }: PreloaderProps) => { } if ( - router.route?.app === undefined || - !ROUTES_TO_SKIP_REVISION_CHECK.includes(router.route?.app) + (router.route?.app === undefined || + !ROUTES_TO_SKIP_FIRMWARE_CHECK.includes(router.route?.app)) && + !isFirmwareAuthenticityCheckDismissed && + isFirmwareCheckFailed ) { - if (!isFirmwareRevisionCheckDismissed && isRevisionCheckFailed) { - return ; - } - if (!isFirmwareHashCheckDismissed && isFwHashCheckFailed) { - return ; - } + return ; } if ( diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx new file mode 100644 index 00000000000..48f489c8ef7 --- /dev/null +++ b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx @@ -0,0 +1,61 @@ +import { useEffect } from 'react'; +import { deviceActions } from '@suite-common/wallet-core'; +import { Card } from '@trezor/components'; +import { getFirmwareVersion } from '@trezor/device-utils'; +import { TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL } from '@trezor/urls'; + +import { WelcomeLayout } from 'src/components/suite'; +import { useDevice, useDispatch, useSelector } from 'src/hooks/suite'; +import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; +import { + selectFirmwareHashCheckError, + selectFirmwareRevisionCheckError, +} from 'src/reducers/suite/suiteReducer'; +import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; + +const reportCheckFail = (checkType: 'revision' | 'hash', contextData: any) => { + withSentryScope(scope => { + scope.setLevel('error'); + scope.setTag('deviceAuthenticityError', `firmware ${checkType} check failed`); + captureSentryMessage( + `Firmware ${checkType} check failed! ${JSON.stringify(contextData)}`, + scope, + ); + }); +}; + +export const DeviceCompromised = () => { + const dispatch = useDispatch(); + const { device } = useDevice(); + + const revision = device?.features?.revision; + const version = getFirmwareVersion(device); + const vendor = device?.features?.fw_vendor; + + const revisionCheckError = useSelector(selectFirmwareRevisionCheckError); + const hashCheckError = useSelector(selectFirmwareHashCheckError); + + const goToSuite = () => { + // Condition to satisfy TypeScript, device.id is always defined at this point. + if (device?.id) { + dispatch(deviceActions.dismissFirmwareAuthenticityCheck(device.id)); + } + }; + + useEffect(() => { + const commonData = { revision, version, vendor }; + if (revisionCheckError) reportCheckFail('revision', { ...commonData, revisionCheckError }); + if (hashCheckError) reportCheckFail('hash', { ...commonData, hashCheckError }); + }, [revisionCheckError, hashCheckError, revision, vendor, version]); + + return ( + + + + + + ); +}; diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx deleted file mode 100644 index 1c18bf09f34..00000000000 --- a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedHashCheck.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { useEffect } from 'react'; - -import { isDeviceAcquired } from '@suite-common/suite-utils'; -import { deviceActions } from '@suite-common/wallet-core'; -import { Card } from '@trezor/components'; -import { getFirmwareVersion } from '@trezor/device-utils'; -import { TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL } from '@trezor/urls'; - -import { WelcomeLayout } from 'src/components/suite'; -import { useDevice, useDispatch } from 'src/hooks/suite'; -import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; -import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; - -export const DeviceCompromisedHashCheck = () => { - const dispatch = useDispatch(); - const { device } = useDevice(); - - const revision = device?.features?.revision; - const version = getFirmwareVersion(device); - const vendor = device?.features?.fw_vendor; - const authenticityError = - isDeviceAcquired(device) && device.authenticityChecks?.firmwareHash?.success === false - ? device.authenticityChecks.firmwareHash?.error - : undefined; - - const goToSuite = () => { - // Condition to satisfy TypeScript, device.id is always defined at this point. - if (device?.id) { - dispatch(deviceActions.dismissFirmwareHashCheck(device.id)); - } - }; - - useEffect(() => { - const contextData = { revision, version, vendor, authenticityError }; - - withSentryScope(scope => { - scope.setLevel('error'); - scope.setTag('deviceAuthenticityError', 'firmware hash check failed'); - captureSentryMessage( - `Firmware hash check failed! ${JSON.stringify(contextData)}`, - scope, - ); - }); - }, [authenticityError, revision, vendor, version]); - - return ( - - - {/* TODO #14766 REMOVE ME ! */} - (THIS IS HASH CHECK..) - - - - ); -}; diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx deleted file mode 100644 index e7e79cf1647..00000000000 --- a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromisedRevisionCheck.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useEffect } from 'react'; - -import { isDeviceAcquired } from '@suite-common/suite-utils'; -import { deviceActions } from '@suite-common/wallet-core'; -import { Card } from '@trezor/components'; -import { getFirmwareVersion } from '@trezor/device-utils'; -import { TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL } from '@trezor/urls'; - -import { WelcomeLayout } from 'src/components/suite'; -import { useDevice, useDispatch } from 'src/hooks/suite'; -import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; -import { SecurityCheckFail } from 'src/components/suite/SecurityCheck/SecurityCheckFail'; - -export const DeviceCompromisedRevisionCheck = () => { - const dispatch = useDispatch(); - const { device } = useDevice(); - - const revision = device?.features?.revision; - const version = getFirmwareVersion(device); - const vendor = device?.features?.fw_vendor; - const authenticityError = - isDeviceAcquired(device) && device.authenticityChecks?.firmwareRevision?.success === false - ? device.authenticityChecks.firmwareRevision?.error - : undefined; - - const goToSuite = () => { - // Condition to satisfy TypeScript, device.id is always defined at this point. - if (device?.id) { - dispatch(deviceActions.dismissFirmwareRevisionCheck(device.id)); - } - }; - - useEffect(() => { - const contextData = { revision, version, vendor, authenticityError }; - - withSentryScope(scope => { - scope.setLevel('error'); - scope.setTag('deviceAuthenticityError', 'firmware revision check failed'); - captureSentryMessage( - `Firmware revision check failed! ${JSON.stringify(contextData)}`, - scope, - ); - }); - }, [authenticityError, revision, vendor, version]); - - return ( - - - - - - ); -}; diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareHashCheckBanner.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareHashCheckBanner.tsx deleted file mode 100644 index 36dc22ef721..00000000000 --- a/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareHashCheckBanner.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { TranslationKey } from '@suite-common/intl-types'; -import { isDeviceAcquired } from '@suite-common/suite-utils'; -import { selectDevice } from '@suite-common/wallet-core'; -import { Banner } from '@trezor/components'; -import { FirmwareHashCheckError } from '@trezor/connect'; -import { HELP_CENTER_FIRMWARE_REVISION_CHECK } from '@trezor/urls'; - -import { Translation, TrezorLink } from 'src/components/suite'; -import { useSelector } from 'src/hooks/suite'; - -const messages: Record< - Exclude, - TranslationKey | string -> = { - // TODO #14766 use actual translation ids, remove the `string` type and use it in the component - 'hash-mismatch': 'Compromised FW (hash mismatch)', - 'check-unsupported': 'Update STRONGLY recommended to get security...', - 'unknown-release': 'Compromised FW (unrecognized version)', - 'other-error': 'Compromised FW (unexpected device behavior)', -}; - -export const FirmwareHashCheckBanner = () => { - const device = useSelector(selectDevice); - - if ( - !isDeviceAcquired(device) || - device.authenticityChecks?.firmwareHash?.success !== false || - device.authenticityChecks?.firmwareHash?.error === 'check-skipped' - ) { - return null; - } - - return ( - - - - - - } - > - {/*TODO #14766 see above*/} - {messages[device.authenticityChecks.firmwareHash.error]} - {/**/} - - ); -}; diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx index 35cc6efd521..aaeac2ecbac 100644 --- a/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx +++ b/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx @@ -1,32 +1,52 @@ import { TranslationKey } from '@suite-common/intl-types'; -import { isDeviceAcquired } from '@suite-common/suite-utils'; -import { selectDevice } from '@suite-common/wallet-core'; import { Banner } from '@trezor/components'; -import { FirmwareRevisionCheckError } from '@trezor/connect'; +import { FirmwareHashCheckError, FirmwareRevisionCheckError } from '@trezor/connect'; import { HELP_CENTER_FIRMWARE_REVISION_CHECK } from '@trezor/urls'; import { Translation, TrezorLink } from 'src/components/suite'; import { useSelector } from 'src/hooks/suite'; +import { + selectFirmwareHashCheckError, + selectFirmwareRevisionCheckError, +} from 'src/reducers/suite/suiteReducer'; -const messages: Record = { +const revisionCheckMessages: Record = { 'cannot-perform-check-offline': 'TR_DEVICE_FIRMWARE_REVISION_CHECK_UNABLE_TO_PERFORM', 'other-error': 'TR_FIRMWARE_REVISION_CHECK_OTHER_ERROR', 'revision-mismatch': 'TR_FIRMWARE_REVISION_CHECK_FAILED', 'firmware-version-unknown': 'TR_FIRMWARE_REVISION_CHECK_FAILED', }; -export const FirmwareRevisionCheckBanner = () => { - const device = useSelector(selectDevice); +const hashCheckMessages: Record< + Exclude, + TranslationKey +> = { + 'hash-mismatch': 'TR_DEVICE_FIRMWARE_HASH_CHECK_HASH_MISMATCH', + 'check-unsupported': 'TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED', + 'unknown-release': 'TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE', + 'other-error': 'TR_DEVICE_FIRMWARE_HASH_CHECK_OTHER_ERROR', +}; - if ( - !isDeviceAcquired(device) || - device.authenticityChecks?.firmwareRevision?.success !== false - ) { - return null; +const useAuthenticityCheckMessage = (): TranslationKey | null => { + const firmwareRevisionError = useSelector(selectFirmwareRevisionCheckError); + const firmwareHashError = useSelector(selectFirmwareHashCheckError); + + if (firmwareRevisionError) { + return revisionCheckMessages[firmwareRevisionError]; + } + if (firmwareHashError && firmwareHashError !== 'check-skipped') { + return hashCheckMessages[firmwareHashError]; } - const wasOffline = - device.authenticityChecks.firmwareRevision.error === 'cannot-perform-check-offline'; + return null; +}; + +export const FirmwareRevisionCheckBanner = () => { + const firmwareRevisionError = useSelector(selectFirmwareRevisionCheckError); + const wasOffline = firmwareRevisionError === 'cannot-perform-check-offline'; + + const message = useAuthenticityCheckMessage(); + if (message === null) return null; return ( { ) } > - + ); }; diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx index 056d7ee5657..2bd8d63da6c 100644 --- a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx +++ b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx @@ -10,6 +10,10 @@ import { spacingsPx } from '@trezor/theme'; import { isTranslationMode } from 'src/utils/suite/l10n'; import { useSelector } from 'src/hooks/suite'; import { MAX_CONTENT_WIDTH } from 'src/constants/suite/layout'; +import { + selectFirmwareHashCheckError, + selectFirmwareRevisionCheckError, +} from 'src/reducers/suite/suiteReducer'; import { MessageSystemBanner } from '../MessageSystemBanner'; import { NoConnectionBanner } from './NoConnectionBanner'; import { UpdateBridge } from './UpdateBridgeBanner'; @@ -20,7 +24,6 @@ import { SafetyChecksBanner } from './SafetyChecksBanner'; import { TranslationMode } from './TranslationModeBanner'; import { FirmwareHashMismatch } from './FirmwareHashMismatchBanner'; import { FirmwareRevisionCheckBanner } from './FirmwareRevisionCheckBanner'; -import { FirmwareHashCheckBanner } from './FirmwareHashCheckBanner'; const Container = styled.div<{ $isVisible?: boolean }>` width: 100%; @@ -37,9 +40,8 @@ export const SuiteBanners = () => { const isOnline = useSelector(state => state.suite.online); const firmwareHashInvalid = useSelector(state => state.firmware.firmwareHashInvalid); const bannerMessage = useSelector(selectBannerMessage); - const { isFirmwareRevisionCheckDisabled, isFirmwareHashCheckDisabled } = useSelector( - state => state.suite.settings, - ); + const firmwareRevisionError = useSelector(selectFirmwareRevisionCheckError); + const firmwareHashError = useSelector(selectFirmwareHashCheckError); // The dismissal doesn't need to outlive the session. Use local state. const [safetyChecksDismissed, setSafetyChecksDismissed] = useState(false); @@ -61,27 +63,15 @@ export const SuiteBanners = () => { let banner = null; let priority = 0; - // firmware hash invalid after a firmware update, not the regular check + // this handles firmware hash being invalid after a firmware update, not the regular firmware hash check if (device?.id && firmwareHashInvalid.includes(device.id)) { banner = ; priority = 92; } - // the regular firmware check + // the regular firmware hash check, and revision id check, either of them may fail else if ( - !isFirmwareHashCheckDisabled && - isDeviceAcquired(device) && - device.authenticityChecks !== undefined && - device.authenticityChecks.firmwareHash !== null && // only if check was performed - device.authenticityChecks.firmwareHash.success === false - ) { - banner = ; - priority = 91.1; - } else if ( - !isFirmwareRevisionCheckDisabled && - isDeviceAcquired(device) && - device.authenticityChecks !== undefined && - device.authenticityChecks.firmwareRevision !== null && // only if check was performed - device.authenticityChecks.firmwareRevision.success === false + firmwareRevisionError || + (firmwareHashError && firmwareHashError !== 'check-skipped') ) { banner = ; priority = 91; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx deleted file mode 100644 index 09e3b63179a..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareHashOptOutModal.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useState } from 'react'; - -import { Column, NewModal, Banner, Card, H3, Paragraph } from '@trezor/components'; -import { Translation, CheckItem } from 'src/components/suite'; -import { checkFirmwareHash } from 'src/actions/suite/suiteActions'; -import { useDispatch } from 'src/hooks/suite'; -import { spacings } from '@trezor/theme'; - -type DeviceAuthenticityOptOutModalProps = { - onCancel: () => void; -}; - -export const FirmwareHashOptOutModal = ({ onCancel }: DeviceAuthenticityOptOutModalProps) => { - const [isConfirmed, setIsConfirmed] = useState(false); - const dispatch = useDispatch(); - - const handleTurningOffHashCheck = () => { - dispatch(checkFirmwareHash({ isDisabled: true })); - onCancel(); - }; - - return ( - - - - - - - - - } - variant="warning" - > -

- - {/* TODO #14766 REMOVE ME ! */} - (HASH) -

- - - - - - - - - - - - - } - isChecked={isConfirmed} - onClick={() => setIsConfirmed(!isConfirmed)} - data-testid="@device-firmware-hash/checkbox" - /> - -
- ); -}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx index 1f39a613369..01dc67dc185 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/FirmwareRevisionOptOutModal.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import { Column, NewModal, Banner, Card, H3, Paragraph } from '@trezor/components'; import { Translation, CheckItem } from 'src/components/suite'; -import { checkFirmwareRevision } from 'src/actions/suite/suiteActions'; +import { toggleCheckFirmwareAuthenticity } from 'src/actions/suite/suiteActions'; import { useDispatch } from 'src/hooks/suite'; import { spacings } from '@trezor/theme'; @@ -15,7 +15,7 @@ export const FirmwareRevisionOptOutModal = ({ onCancel }: DeviceAuthenticityOptO const dispatch = useDispatch(); const handleTurningOffRevisionCheck = () => { - dispatch(checkFirmwareRevision({ isDisabled: true })); + dispatch(toggleCheckFirmwareAuthenticity({ isDisabled: true })); onCancel(); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx index 304881de9f8..4d757eb60bc 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UserContextModal.tsx @@ -47,7 +47,6 @@ import { CryptoId } from 'invity-api'; import { EverstakeModal } from './UnstakeModal/EverstakeModal'; import { PassphraseMismatchModal } from './PassphraseMismatchModal'; import { FirmwareRevisionOptOutModal } from './FirmwareRevisionOptOutModal'; -import { FirmwareHashOptOutModal } from './FirmwareHashOptOutModal'; /** Modals opened as a result of user action */ export const UserContextModal = ({ @@ -93,8 +92,6 @@ export const UserContextModal = ({ return ; case 'firmware-revision-opt-out': return ; - case 'firmware-hash-opt-out': - return ; case 'qr-reader': return ; case 'transaction-detail': diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts index d470fc5ecb9..b905cab3ab6 100644 --- a/packages/suite/src/reducers/suite/suiteReducer.ts +++ b/packages/suite/src/reducers/suite/suiteReducer.ts @@ -437,43 +437,64 @@ export const selectHasExperimentalFeature = (feature: ExperimentalFeature) => (state: SuiteRootState) => state.suite.settings.experimental?.includes(feature) ?? false; -export const selectIsFirmwareRevisionCheckEnabledAndFailed = ( - state: SuiteRootState & DeviceRootState & MessageSystemRootState, -) => { - const { isFirmwareRevisionCheckDisabled } = state.suite.settings; - const isDisabledByMessageSystem = selectIsFeatureDisabled(state, Feature.firmwareRevisionCheck); - if (isFirmwareRevisionCheckDisabled || isDisabledByMessageSystem) return false; +type StateForFirmwareChecks = SuiteRootState & DeviceRootState & MessageSystemRootState; +/** + * Get firmware revision check error, or null if check was successful / skipped. + */ +export const selectFirmwareRevisionCheckError = (state: StateForFirmwareChecks) => { const device = selectDevice(state); + if (!isDeviceAcquired(device) || !device.authenticityChecks) return null; + + const { isFirmwareRevisionCheckDisabled } = state.suite.settings; + const isDisabledByMessage = selectIsFeatureDisabled(state, Feature.firmwareRevisionCheck); + const isCheckEnabled = !isFirmwareRevisionCheckDisabled && !isDisabledByMessage; + const checkResult = device.authenticityChecks.firmwareRevision; // null means not performed, then don't consider it failed - return ( - isDeviceAcquired(device) && - // If `check` is null, it means that it was not performed yet. - device.authenticityChecks?.firmwareRevision?.success === false && - // If Suite is offline and cannot perform check or there is some unexpected error, an error banner is shown but Suite is otherwise unaffected. - !['cannot-perform-check-offline', 'other-error'].includes( - device.authenticityChecks.firmwareRevision.error, - ) - ); + return isCheckEnabled && checkResult?.success === false ? checkResult.error : null; }; -export const selectIsFirmwareHashCheckEnabledAndFailed = ( - state: SuiteRootState & DeviceRootState & MessageSystemRootState, -) => { - const { isFirmwareHashCheckDisabled } = state.suite.settings; - const isDisabledByMessageSystem = selectIsFeatureDisabled(state, Feature.firmwareHashCheck); - if (isFirmwareHashCheckDisabled || isDisabledByMessageSystem) return false; +/** + * Determine hard failure of firmware revision check - specific error types which are severe. + * If Suite is offline and cannot perform check or there is some unexpected error, a banner is shown but device is accessible. + */ +const selectIsFirmwareRevisionCheckEnabledAndFailed = (state: StateForFirmwareChecks): boolean => { + const error = selectFirmwareRevisionCheckError(state); + + return error ? !['cannot-perform-check-offline', 'other-error'].includes(error) : false; +}; +/** + * Get firmware hash check error, or null if check was successful / skipped. + */ +export const selectFirmwareHashCheckError = (state: StateForFirmwareChecks) => { const device = selectDevice(state); + if (!isDeviceAcquired(device) || !device.authenticityChecks) return false; - return ( - isDeviceAcquired(device) && - // If `check` is null, it means that it was not performed yet. - device.authenticityChecks?.firmwareHash?.success === false && - !['check-skipped', 'check-unsupported'].includes( - device.authenticityChecks.firmwareHash.error, - ) - ); + const { isFirmwareHashCheckDisabled } = state.suite.settings; + const isDisabledByMessage = selectIsFeatureDisabled(state, Feature.firmwareHashCheck); + const isCheckEnabled = !isFirmwareHashCheckDisabled && !isDisabledByMessage; + const checkResult = device.authenticityChecks.firmwareHash; // null means not performed, then don't consider it failed + + return isCheckEnabled && checkResult?.success === false ? checkResult.error : null; +}; + +/** + * Determine hard failure of firmware hash check - specific error types which are severe. + * If check was skipped, don't consider it failed. + * If check is unsupported by device, a banner is shown but device is accessible. + */ +const selectIsFirmwareHashCheckEnabledAndFailed = (state: StateForFirmwareChecks): boolean => { + const error = selectFirmwareHashCheckError(state); + + return error ? !['check-skipped', 'check-unsupported'].includes(error) : false; }; +/** + * Determine hard failure of either of firmware authenticity checks to block access to device. + */ +export const selectIsFirmwareAuthenticityCheckEnabledAndFailed = (state: StateForFirmwareChecks) => + selectIsFirmwareRevisionCheckEnabledAndFailed(state) || + selectIsFirmwareHashCheckEnabledAndFailed(state); + export default suiteReducer; diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index b893c2a948d..69da7796266 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -7022,6 +7022,24 @@ export default defineMessages({ id: 'TR_FIRMWARE_REVISION_CHECK_OTHER_ERROR', defaultMessage: "Couldn't perform firmware revision check.", }, + TR_DEVICE_FIRMWARE_HASH_CHECK_HASH_MISMATCH: { + id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_HASH_MISMATCH', + defaultMessage: 'Firmware hash check failed. Your Trezor may be counterfeit.', + }, + TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED: { + id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED', + defaultMessage: + 'New Trezor firmware is available! Update your device now to get latest security features.', + }, + TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE: { + id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE', + defaultMessage: 'Firmware unrecognized. Your Trezor may be counterfeit.', + }, + TR_DEVICE_FIRMWARE_HASH_CHECK_OTHER_ERROR: { + id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_OTHER_ERROR', + defaultMessage: + "Firmware hash check couldn't be performed. Your Trezor may be counterfeit.", + }, TR_ONBOARDING_COINS_STEP: { id: 'TR_ONBOARDING_COINS_STEP', defaultMessage: 'Activate coins', diff --git a/packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx b/packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx deleted file mode 100644 index 8bf4c894fe2..00000000000 --- a/packages/suite/src/views/settings/SettingsDevice/FirmwareHashCheck.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { - ActionButton, - ActionColumn, - SectionItem, - TextColumn, - Translation, -} from 'src/components/suite'; -import { useDispatch, useSelector } from 'src/hooks/suite'; -import { openModal } from 'src/actions/suite/modalActions'; -import { checkFirmwareHash } from 'src/actions/suite/suiteActions'; -import { HELP_CENTER_FIRMWARE_REVISION_CHECK } from '@trezor/urls'; - -export const FirmwareHashCheck = () => { - const dispatch = useDispatch(); - const isFirmwareHashCheckDisabled = useSelector( - state => state.suite.settings.isFirmwareHashCheckDisabled, - ); - - const handleClick = () => - dispatch( - isFirmwareHashCheckDisabled - ? checkFirmwareHash({ isDisabled: false }) - : openModal({ type: 'firmware-hash-opt-out' }), - ); - - return ( - - - } - description={ - - } - buttonLink={HELP_CENTER_FIRMWARE_REVISION_CHECK} - /> - - - - {/* TODO #14766 REMOVE ME ! */} - (HASH) - - - - ); -}; diff --git a/packages/suite/src/views/settings/SettingsDevice/FirmwareRevisionCheck.tsx b/packages/suite/src/views/settings/SettingsDevice/FirmwareRevisionCheck.tsx index 3262ebbedf8..f1a702a9f75 100644 --- a/packages/suite/src/views/settings/SettingsDevice/FirmwareRevisionCheck.tsx +++ b/packages/suite/src/views/settings/SettingsDevice/FirmwareRevisionCheck.tsx @@ -7,18 +7,23 @@ import { } from 'src/components/suite'; import { useDispatch, useSelector } from 'src/hooks/suite'; import { openModal } from 'src/actions/suite/modalActions'; -import { checkFirmwareRevision } from 'src/actions/suite/suiteActions'; +import { toggleCheckFirmwareAuthenticity } from 'src/actions/suite/suiteActions'; import { HELP_CENTER_FIRMWARE_REVISION_CHECK } from '@trezor/urls'; + export const FirmwareRevisionCheck = () => { const dispatch = useDispatch(); - const isFirmwareRevisionCheckDisabled = useSelector( - state => state.suite.settings.isFirmwareRevisionCheckDisabled, + const isFirmwareAuthenticityCheckDisabled = useSelector( + state => + // users can granularly turn off the partial checks in debug settings + // in that case, the toggle shall be considered off, inviting the user to turn it on. + state.suite.settings.isFirmwareRevisionCheckDisabled || + state.suite.settings.isFirmwareHashCheckDisabled, ); const handleClick = () => dispatch( - isFirmwareRevisionCheckDisabled - ? checkFirmwareRevision({ isDisabled: false }) + isFirmwareAuthenticityCheckDisabled + ? toggleCheckFirmwareAuthenticity({ isDisabled: false }) : openModal({ type: 'firmware-revision-opt-out' }), ); @@ -28,7 +33,7 @@ export const FirmwareRevisionCheck = () => { title={ { description={ { ) => { @@ -177,7 +176,6 @@ export const SettingsDevice = () => { {supportsDeviceAuthentication && } - ); diff --git a/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx b/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx index 31d9c8ea829..110549094a0 100644 --- a/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx +++ b/packages/suite/src/views/wallet/receive/components/FreshAddress.tsx @@ -11,10 +11,7 @@ import { AccountsRootState, selectIsAccountUtxoBased } from '@suite-common/walle import { networks } from '@suite-common/wallet-config'; import { EvmExplanationBox } from 'src/components/wallet/EvmExplanationBox'; import { spacingsPx, typography } from '@trezor/theme'; -import { - selectIsFirmwareHashCheckEnabledAndFailed, - selectIsFirmwareRevisionCheckEnabledAndFailed, -} from 'src/reducers/suite/suiteReducer'; +import { selectIsFirmwareAuthenticityCheckEnabledAndFailed } from 'src/reducers/suite/suiteReducer'; // eslint-disable-next-line local-rules/no-override-ds-component const StyledCard = styled(Card)` @@ -129,8 +126,9 @@ export const FreshAddress = ({ const isAccountUtxoBased = useSelector((state: AccountsRootState) => selectIsAccountUtxoBased(state, account?.key ?? ''), ); - const isRevisionCheckFailed = useSelector(selectIsFirmwareRevisionCheckEnabledAndFailed); - const isFwHashCheckFailed = useSelector(selectIsFirmwareHashCheckEnabledAndFailed); + const isAuthenticityCheckFailed = useSelector( + selectIsFirmwareAuthenticityCheckEnabledAndFailed, + ); const dispatch = useDispatch(); const firstFreshAddress = useMemo(() => { @@ -162,7 +160,7 @@ export const FreshAddress = ({ if (!firstFreshAddress) { return ; } - if (isRevisionCheckFailed || isFwHashCheckFailed) { + if (isAuthenticityCheckFailed) { return ; } @@ -177,8 +175,7 @@ export const FreshAddress = ({ locked || coinjoinDisallowReveal || !firstFreshAddress || - isRevisionCheckFailed || - isFwHashCheckFailed, + isAuthenticityCheckFailed, isLoading: locked, }; diff --git a/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx b/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx index e376a01ea2f..c867a653a17 100644 --- a/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx +++ b/packages/suite/src/views/wallet/receive/components/UsedAddresses.tsx @@ -22,10 +22,7 @@ import { MetadataAddPayload } from 'src/types/suite/metadata'; import { showAddress } from 'src/actions/wallet/receiveActions'; import { useDispatch, useSelector } from 'src/hooks/suite/'; import { selectLabelingDataForSelectedAccount } from 'src/reducers/suite/metadataReducer'; -import { - selectIsFirmwareHashCheckEnabledAndFailed, - selectIsFirmwareRevisionCheckEnabledAndFailed, -} from 'src/reducers/suite/suiteReducer'; +import { selectIsFirmwareAuthenticityCheckEnabledAndFailed } from 'src/reducers/suite/suiteReducer'; const AddressActions = styled.div<{ $isVisible?: boolean }>` opacity: ${({ $isVisible }) => ($isVisible ? '1' : '0')}; @@ -50,18 +47,18 @@ type ItemProps = { }; const Item = ({ addr, locked, symbol, onClick, metadataPayload, index }: ItemProps) => { - const isRevisionCheckFailed = useSelector(selectIsFirmwareRevisionCheckEnabledAndFailed); - const isFwHashCheckFailed = useSelector(selectIsFirmwareHashCheckEnabledAndFailed); + const isAuthenticityCheckFailed = useSelector( + selectIsFirmwareAuthenticityCheckEnabledAndFailed, + ); const [isHovered, setIsHovered] = useState(false); const amount = formatNetworkAmount(addr.received || '0', symbol); const fresh = !addr.transfers; const address = addr.address.substring(0, 20); - const isDisabled = locked || isRevisionCheckFailed || isFwHashCheckFailed; - const tooltipContent = - isRevisionCheckFailed || isFwHashCheckFailed ? ( - - ) : null; + const isDisabled = locked || isAuthenticityCheckFailed; + const tooltipContent = isAuthenticityCheckFailed ? ( + + ) : null; return ( diff --git a/suite-common/suite-types/src/modal.ts b/suite-common/suite-types/src/modal.ts index 33637e03f7a..5e0ff9e328f 100644 --- a/suite-common/suite-types/src/modal.ts +++ b/suite-common/suite-types/src/modal.ts @@ -101,9 +101,6 @@ export type UserContextPayload = | { type: 'firmware-revision-opt-out'; } - | { - type: 'firmware-hash-opt-out'; - } | { type: 'disconnect-device'; } diff --git a/suite-common/wallet-core/src/device/deviceActions.ts b/suite-common/wallet-core/src/device/deviceActions.ts index 078a4ad7d6c..cba75d57904 100644 --- a/suite-common/wallet-core/src/device/deviceActions.ts +++ b/suite-common/wallet-core/src/device/deviceActions.ts @@ -80,13 +80,8 @@ export const removeButtonRequests = createAction( }), ); -const dismissFirmwareRevisionCheck = createAction( - `${DEVICE_MODULE_PREFIX}/dismissFirmwareRevisionCheck`, - (payload: string) => ({ payload }), -); - -const dismissFirmwareHashCheck = createAction( - `${DEVICE_MODULE_PREFIX}/dismissFirmwareHashCheck`, +const dismissFirmwareAuthenticityCheck = createAction( + `${DEVICE_MODULE_PREFIX}/dismissFirmwareAuthenticityCheck`, (payload: string) => ({ payload }), ); @@ -95,8 +90,7 @@ export const deviceActions = { connectUnacquiredDevice, deviceChanged, deviceDisconnect, - dismissFirmwareRevisionCheck, - dismissFirmwareHashCheck, + dismissFirmwareAuthenticityCheck, updatePassphraseMode, receiveAuthConfirm, rememberDevice, diff --git a/suite-common/wallet-core/src/device/deviceReducer.ts b/suite-common/wallet-core/src/device/deviceReducer.ts index be11a22ec9b..c947fe221ef 100644 --- a/suite-common/wallet-core/src/device/deviceReducer.ts +++ b/suite-common/wallet-core/src/device/deviceReducer.ts @@ -33,8 +33,7 @@ export type State = { selectedDevice?: TrezorDevice; deviceAuthenticity?: Record; dismissedSecurityChecks?: { - firmwareRevision?: string[]; - firmwareHash?: string[]; + firmwareAuthenticity?: string[]; }; }; @@ -587,23 +586,14 @@ export const prepareDeviceReducer = createReducerWithExtraDeps(initialState, (bu .addCase(deviceAuthenticityActions.result, (state, { payload }) => { setDeviceAuthenticity(state, payload.device, payload.result); }) - .addCase(deviceActions.dismissFirmwareRevisionCheck, (state, { payload }) => { + .addCase(deviceActions.dismissFirmwareAuthenticityCheck, (state, { payload }) => { if (!state.dismissedSecurityChecks) { state.dismissedSecurityChecks = {}; } - if (!state.dismissedSecurityChecks.firmwareRevision) { - state.dismissedSecurityChecks.firmwareRevision = []; + if (!state.dismissedSecurityChecks.firmwareAuthenticity) { + state.dismissedSecurityChecks.firmwareAuthenticity = []; } - state.dismissedSecurityChecks.firmwareRevision.unshift(payload); - }) - .addCase(deviceActions.dismissFirmwareHashCheck, (state, { payload }) => { - if (!state.dismissedSecurityChecks) { - state.dismissedSecurityChecks = {}; - } - if (!state.dismissedSecurityChecks.firmwareHash) { - state.dismissedSecurityChecks.firmwareHash = []; - } - state.dismissedSecurityChecks.firmwareHash.unshift(payload); + state.dismissedSecurityChecks.firmwareAuthenticity.unshift(payload); }) .addCase(extra.actionTypes.setDeviceMetadata, extra.reducers.setDeviceMetadataReducer) .addCase( @@ -789,19 +779,12 @@ export const selectSelectedDeviceAuthenticity = (state: DeviceRootState) => { return device?.id ? deviceAuthenticity?.[device.id] : undefined; }; -export const selectIsFirmwareRevisionCheckDismissed = (state: DeviceRootState): boolean => { - const device = selectDevice(state); - - return !!( - device?.id && state.device.dismissedSecurityChecks?.firmwareRevision?.includes(device.id) - ); -}; - -export const selectIsFirmwareHashCheckDismissed = (state: DeviceRootState): boolean => { +export const selectIsFirmwareAuthenticityCheckDismissed = (state: DeviceRootState): boolean => { const device = selectDevice(state); return !!( - device?.id && state.device.dismissedSecurityChecks?.firmwareHash?.includes(device.id) + device?.id && + state.device.dismissedSecurityChecks?.firmwareAuthenticity?.includes(device.id) ); }; From 0ccd52b6e0a55375ce110949b16733cee7c20044 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Wed, 9 Oct 2024 18:52:33 +0200 Subject: [PATCH 104/624] test(suite): skip fw hash check in E2E --- packages/suite-web/e2e/support/commands.ts | 3 +++ .../suite-web/e2e/support/utils/shortcuts.ts | 18 +++++++++++++++++- .../onboarding/t1b1-create-wallet.test.ts | 3 ++- .../onboarding/t1b1-recovery-advanced.test.ts | 1 + .../onboarding/t1b1-recovery-basic.test.ts | 4 ++-- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/suite-web/e2e/support/commands.ts b/packages/suite-web/e2e/support/commands.ts index 41106db2a1c..911447f406b 100644 --- a/packages/suite-web/e2e/support/commands.ts +++ b/packages/suite-web/e2e/support/commands.ts @@ -12,6 +12,7 @@ import { resetDb } from './utils/test-env'; import { toggleDeviceMenu, enableDebugMode, + disableFirmwareHashCheck, toggleDebugModeInSettings, passThroughInitialRun, passThroughAuthenticityCheck, @@ -113,6 +114,7 @@ declare global { discoveryMightAppearAndShouldFinish: () => Chainable; toggleDeviceMenu: () => Chainable; enableDebugMode: () => Chainable; + disableFirmwareHashCheck: () => Chainable; toggleDebugModeInSettings: () => Chainable; text: () => Chainable; passThroughInitialRun: ( @@ -174,6 +176,7 @@ Cypress.Commands.add('hoverTestElement', hoverTestElement); // various shortcuts Cypress.Commands.add('toggleDeviceMenu', toggleDeviceMenu); Cypress.Commands.add('enableDebugMode', enableDebugMode); +Cypress.Commands.add('disableFirmwareHashCheck', disableFirmwareHashCheck); Cypress.Commands.add('toggleDebugModeInSettings', toggleDebugModeInSettings); Cypress.Commands.add('passThroughInitialRun', passThroughInitialRun); Cypress.Commands.add('passThroughAuthenticityCheck', passThroughAuthenticityCheck); diff --git a/packages/suite-web/e2e/support/utils/shortcuts.ts b/packages/suite-web/e2e/support/utils/shortcuts.ts index 559584f282b..2146d216958 100644 --- a/packages/suite-web/e2e/support/utils/shortcuts.ts +++ b/packages/suite-web/e2e/support/utils/shortcuts.ts @@ -1,5 +1,6 @@ import { SuiteAnalyticsEvent } from '@trezor/suite-analytics'; import { urlSearchParams } from '@trezor/suite/src/utils/suite/metadata'; +import { SUITE as SuiteActions } from '@trezor/suite/src/actions/suite/constants'; import { EventPayload, Requests } from '../types'; import { onNavBar } from '../pageObjects/topBarObject'; @@ -9,6 +10,7 @@ import { onNavBar } from '../pageObjects/topBarObject'; export const toggleDeviceMenu = () => cy.getTestElement('@menu/switch-device').click(); export const passThroughInitialRun = ({ viewOnly = true } = {}) => { + cy.disableFirmwareHashCheck(); cy.getTestElement('@analytics/continue-button', { timeout: 30_000 }) .click() .getTestElement('@onboarding/exit-app-button') @@ -84,7 +86,21 @@ export const passThroughSetPin = () => { export const enableDebugMode = () => { cy.window().then(window => { - window.store.dispatch({ type: '@suite/set-debug-mode', payload: { showDebugMenu: true } }); + window.store.dispatch({ + type: SuiteActions.SET_DEBUG_MODE, + payload: { showDebugMenu: true }, + }); + }); +}; + +export const disableFirmwareHashCheck = () => { + // window.store may not be ready at this point, we need to wait for app to load + cy.getTestElement('@welcome-layout/body'); + cy.window().then(window => { + window.store.dispatch({ + type: SuiteActions.DEVICE_FIRMWARE_HASH_CHECK, + payload: { isDisabled: true }, + }); }); }; diff --git a/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts b/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts index d9ca51ba5c3..fc65fe82815 100644 --- a/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts @@ -3,15 +3,16 @@ describe('Onboarding - create wallet', () => { beforeEach(() => { + cy.task('startEmu', { model: 'T1B1', version: '1-latest', wipe: true }); cy.task('startBridge'); cy.viewport(1440, 2560).resetDb(); cy.prefixedVisit('/'); + cy.disableFirmwareHashCheck(); }); // todo: skipping for it is too flaky.. // after calling "resetDevice" we almost always receive "device disconnected during action" which is error sent by bridge. it.skip('Success (basic)', () => { - cy.task('startEmu', { model: 'T1B1', version: '1-latest', wipe: true }); cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@firmware/continue-button').click(); diff --git a/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts b/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts index fd259a4f132..09336323726 100644 --- a/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts @@ -8,6 +8,7 @@ describe('Onboarding - recover wallet T1B1', () => { cy.viewport(1440, 2560).resetDb(); cy.prefixedVisit('/'); + cy.disableFirmwareHashCheck(); }); it('Incomplete run of advanced recovery', () => { diff --git a/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-basic.test.ts b/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-basic.test.ts index b47b095d54c..85dba24c371 100644 --- a/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-basic.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-basic.test.ts @@ -3,13 +3,13 @@ // todo: this started to fail mysteriously after merging new base image. Skipping it for now and will investigate. describe.skip('Onboarding - recover wallet T1B1', () => { - before(() => { + beforeEach(() => { cy.task('startEmu', { model: 'T1B1', version: '1-latest', wipe: true }); cy.task('startBridge'); cy.viewport(1440, 2560).resetDb(); cy.prefixedVisit('/'); - cy.task('startEmu', { wipe: true }); + cy.disableFirmwareHashCheck(); cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@analytics/continue-button').click(); cy.onboardingShouldLoad(); From 98eccb8dda1194a73ec8daf5fd433a583d623581 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Thu, 10 Oct 2024 15:48:48 +0200 Subject: [PATCH 105/624] feat(suite): add granular controls to debug settings --- .../CheckFirmwareAuthenticity.tsx | 75 ++++++++++++++----- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx b/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx index e2a1867ad16..b82de1a0bf5 100644 --- a/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx +++ b/packages/suite/src/views/settings/SettingsDebug/CheckFirmwareAuthenticity.tsx @@ -1,15 +1,19 @@ import { useState } from 'react'; -import { Button } from '@trezor/components'; +import { Button, Switch } from '@trezor/components'; import { ActionColumn, SectionItem, TextColumn } from 'src/components/suite'; -import { useDispatch } from 'src/hooks/suite'; +import { useDispatch, useSelector } from 'src/hooks/suite'; import { manualFirmwareHashCheckThunk } from '@suite-common/wallet-core'; +import { SUITE } from 'src/actions/suite/constants'; export const CheckFirmwareAuthenticity = () => { const [inProgress, setInProgress] = useState(false); const dispatch = useDispatch(); + const { isFirmwareHashCheckDisabled, isFirmwareRevisionCheckDisabled } = useSelector( + state => state.suite.settings, + ); const onCheckFirmwareAuthenticity = async () => { setInProgress(true); @@ -17,21 +21,58 @@ export const CheckFirmwareAuthenticity = () => { setInProgress(false); }; + const onToggleFirmwareRevisionCheck = (newEnabledState?: boolean) => + dispatch({ + type: SUITE.DEVICE_FIRMWARE_REVISION_CHECK, + payload: { isDisabled: !newEnabledState }, + }); + const onToggleFirmwareHashCheck = (newEnabledState?: boolean) => + dispatch({ + type: SUITE.DEVICE_FIRMWARE_HASH_CHECK, + payload: { isDisabled: !newEnabledState }, + }); + return ( - - - - - - + <> + + + + + + + + + + + + + + + + + + + ); }; From 17ea510cd2a475a3c996cc9b700b4979fa39e3c9 Mon Sep 17 00:00:00 2001 From: Albina Nikiforova Date: Thu, 10 Oct 2024 11:44:21 +0200 Subject: [PATCH 106/624] feat(product-components): TokenIconSet --- .../TokenIconSet/TokenIconSet.stories.tsx | 46 +++++++++++++ .../components/TokenIconSet/TokenIconSet.tsx | 64 +++++++++++++++++++ packages/product-components/src/index.ts | 1 + 3 files changed, 111 insertions(+) create mode 100644 packages/product-components/src/components/TokenIconSet/TokenIconSet.stories.tsx create mode 100644 packages/product-components/src/components/TokenIconSet/TokenIconSet.tsx diff --git a/packages/product-components/src/components/TokenIconSet/TokenIconSet.stories.tsx b/packages/product-components/src/components/TokenIconSet/TokenIconSet.stories.tsx new file mode 100644 index 00000000000..0b8705b9356 --- /dev/null +++ b/packages/product-components/src/components/TokenIconSet/TokenIconSet.stories.tsx @@ -0,0 +1,46 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { TokenIconSet as TokenIconSetComponent, TokenIconSetProps } from './TokenIconSet'; + +const getToken = (contract: string, symbol: string, decimals: number) => ({ + contract, + symbol, + decimals, + type: 'ERC20', +}); + +const TOKEN_1 = getToken('0xaea46a60368a7bd060eec7df8cba43b7ef41ad85', 'FET', 6); +const TOKEN_2 = getToken('0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', 'AAVE', 6); +const TOKEN_3 = getToken('0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce', 'SHIB', 18); +const TOKEN_4 = getToken('0xdAC17F958D2ee523a2206206994597C13D831ec7', 'usdt', 6); + +const meta: Meta = { + title: 'TokenIconSet', +} as Meta; +export default meta; +export const TokenIconSet: StoryObj = { + render: (props: TokenIconSetProps) => , + args: { + network: 'eth', + tokens: [TOKEN_1, TOKEN_2, TOKEN_3, TOKEN_4], + }, + argTypes: { + tokens: { + options: ['1', '2', '3', '4'], + mapping: { + '1': [TOKEN_1], + '2': [TOKEN_1, TOKEN_2], + '3': [TOKEN_1, TOKEN_2, TOKEN_3], + '4': [TOKEN_1, TOKEN_2, TOKEN_3, TOKEN_4], + }, + control: { + type: 'select', + labels: { + 1: '1 token', + 2: '2 tokens', + 3: '3 tokens', + 4: '4+ tokens', + }, + }, + }, + }, +}; diff --git a/packages/product-components/src/components/TokenIconSet/TokenIconSet.tsx b/packages/product-components/src/components/TokenIconSet/TokenIconSet.tsx new file mode 100644 index 00000000000..4c7081deeff --- /dev/null +++ b/packages/product-components/src/components/TokenIconSet/TokenIconSet.tsx @@ -0,0 +1,64 @@ +import { AssetLogo, useElevation } from '@trezor/components'; +import { getCoingeckoId } from '@suite-common/wallet-config'; +import { NetworkSymbol } from '@suite-common/wallet-config'; +import { TokenInfo } from '@trezor/connect'; +import { getContractAddressForNetwork } from '@suite-common/wallet-utils'; + +import styled, { css } from 'styled-components'; +import { borders, Elevation, mapElevationToBackground, mapElevationToBorder } from '@trezor/theme'; + +export type TokenIconSetProps = { + network: NetworkSymbol; + tokens: TokenInfo[]; +}; + +const IconContainer = styled.div<{ $length: number }>` + width: 24px; + justify-content: center; + display: flex; + align-items: center; + ${({ $length }) => + $length > 1 && + css` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(${$length > 1 ? '1px' : '6px'}, 6px)); + direction: rtl; + justify-items: center; + `} +`; + +const TokenIconPlaceholder = styled.div<{ $elevation: Elevation }>` + width: 20px; + height: 20px; + border-radius: ${borders.radii.full}; + border: 1px solid ${mapElevationToBorder}; + background: ${mapElevationToBackground}; +`; + +export const TokenIconSet = ({ network, tokens }: TokenIconSetProps) => { + const { elevation } = useElevation(); + const { length } = tokens; + + if (length === 0) { + return null; + } + + const visibleTokens = tokens.slice(0, 3).reverse(); + + const coingeckoId = getCoingeckoId(network); + + return ( + + {length > 3 && } + {visibleTokens.map(token => ( + 1 ? 20 : 24} + coingeckoId={coingeckoId ?? ''} + contractAddress={getContractAddressForNetwork(network, token.contract)} + placeholder={token.symbol?.toUpperCase() ?? ''} + /> + ))} + + ); +}; diff --git a/packages/product-components/src/index.ts b/packages/product-components/src/index.ts index e4dbd2cfce1..dbc1071338b 100644 --- a/packages/product-components/src/index.ts +++ b/packages/product-components/src/index.ts @@ -15,3 +15,4 @@ export { TrezorLogo } from './components/TrezorLogo/TrezorLogo'; export { PasswordStrengthIndicator } from './components/PasswordStrengthIndicator/PasswordStrengthIndicator'; export { CoinLogo } from './components/CoinLogo/CoinLogo'; export { AssetShareIndicator } from './components/AssetShareIndicator/AssetShareIndicator'; +export * from './components/TokenIconSet/TokenIconSet'; From 50d8e40cd21379175086bff5880c7f027dcfe6de Mon Sep 17 00:00:00 2001 From: Albina Nikiforova Date: Thu, 10 Oct 2024 11:45:04 +0200 Subject: [PATCH 107/624] feat(suite): use TokenIconSet in AccountItem --- .../components/wallet/TokenIconSetWrapper.tsx | 32 +++++++++++++++++++ .../WalletLayout/AccountsMenu/AccountItem.tsx | 18 ++--------- 2 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 packages/suite/src/components/wallet/TokenIconSetWrapper.tsx diff --git a/packages/suite/src/components/wallet/TokenIconSetWrapper.tsx b/packages/suite/src/components/wallet/TokenIconSetWrapper.tsx new file mode 100644 index 00000000000..af02f411f39 --- /dev/null +++ b/packages/suite/src/components/wallet/TokenIconSetWrapper.tsx @@ -0,0 +1,32 @@ +import { selectCoinDefinitions } from '@suite-common/token-definitions'; +import { + enhanceTokensWithRates, + getTokens, + sortTokensWithRates, +} from 'src/utils/wallet/tokenUtils'; +import { TokenIconSet } from '@trezor/product-components'; +import { useSelector } from 'src/hooks/suite'; +import { selectLocalCurrency } from 'src/reducers/wallet/settingsReducer'; +import { selectCurrentFiatRates } from '@suite-common/wallet-core'; +import { Account } from '@suite-common/wallet-types'; + +type TokenIconSetWrapperProps = { + account: Account; +}; + +export const TokenIconSetWrapper = ({ account }: TokenIconSetWrapperProps) => { + const { tokens: accountTokens, symbol: network } = account; + const fiatRates = useSelector(selectCurrentFiatRates); + const coinDefinitions = useSelector(state => selectCoinDefinitions(state, network)); + const localCurrency = useSelector(selectLocalCurrency); + const tokensWithRates = enhanceTokensWithRates( + accountTokens, + localCurrency, + network, + fiatRates, + ); + const sortedTokens = tokensWithRates.sort(sortTokensWithRates); + const tokens = getTokens(sortedTokens, network, coinDefinitions); + + return ; +}; diff --git a/packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem.tsx b/packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem.tsx index 2cac32210af..755d00f766b 100644 --- a/packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem.tsx +++ b/packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem.tsx @@ -2,7 +2,7 @@ import { forwardRef, Ref } from 'react'; import styled from 'styled-components'; import { isTestnet } from '@suite-common/wallet-utils'; -import { borders, spacings, spacingsPx, typography } from '@trezor/theme'; +import { spacings, spacingsPx, typography } from '@trezor/theme'; import { Icon, Column, @@ -26,6 +26,7 @@ import { NavigationItemBase } from 'src/components/suite/layouts/SuiteLayout/Sid import { useFormatters } from '@suite-common/formatters'; import { selectLocalCurrency } from 'src/reducers/wallet/settingsReducer'; import { CoinLogo } from '@trezor/product-components'; +import { TokenIconSetWrapper } from 'src/components/wallet/TokenIconSetWrapper'; const ICON_SIZE = 24; @@ -51,18 +52,6 @@ export const Left = styled.div` position: relative; `; -const TokensBadge = styled.div` - ${typography.label}; - display: flex; - align-items: center; - justify-content: center; - padding: 0 ${spacingsPx.xxs}; - min-width: ${ICON_SIZE}px; - height: ${ICON_SIZE}px; - border-radius: ${borders.radii.full}; - background: ${({ theme }) => theme.borderDashed}; -`; - const AccountLabelContainer = styled.div` flex: 1; min-width: 60px; @@ -98,7 +87,6 @@ export const AccountItem = forwardRef( formattedBalance, customFiatValue, isGroup, - tokens, dataTestKey, onClick, }: AccountItemProps, @@ -140,7 +128,7 @@ export const AccountItem = forwardRef( case 'staking': return ; case 'tokens': - return {tokens?.length}; + return ; } }; From a94c0b8ee59c5a0a80e53ecd7d23e366ed159696 Mon Sep 17 00:00:00 2001 From: Albina Nikiforova Date: Fri, 11 Oct 2024 12:02:47 +0200 Subject: [PATCH 108/624] refactor(packages): getContractAddressforNetwork --- packages/product-components/package.json | 1 + .../wallet/coinmarket/coinmarketUtils.ts | 7 +--- .../tokens/common/TokensTable/TokenRow.tsx | 2 +- suite-common/token-definitions/package.json | 1 + .../src/__fixtures__/utils.ts | 39 ------------------ .../src/__tests__/utils.test.ts | 13 ------ .../src/tokenDefinitionsUtils.ts | 23 +---------- .../src/__fixtures__/tokenUtils.ts | 40 +++++++++++++++++++ .../src/__tests__/tokenUtils.test.ts | 13 ++++++ suite-common/wallet-utils/src/index.ts | 1 + suite-common/wallet-utils/src/tokenUtils.ts | 23 +++++++++++ yarn.lock | 2 + 12 files changed, 85 insertions(+), 80 deletions(-) create mode 100644 suite-common/wallet-utils/src/__fixtures__/tokenUtils.ts create mode 100644 suite-common/wallet-utils/src/__tests__/tokenUtils.test.ts create mode 100644 suite-common/wallet-utils/src/tokenUtils.ts diff --git a/packages/product-components/package.json b/packages/product-components/package.json index aef8aa6dc87..6e40de59180 100644 --- a/packages/product-components/package.json +++ b/packages/product-components/package.json @@ -19,6 +19,7 @@ "dependencies": { "@suite-common/validators": "workspace:*", "@suite-common/wallet-config": "workspace:*", + "@suite-common/wallet-utils": "workspace:*", "@trezor/components": "workspace:*", "@trezor/connect": "workspace:*", "@trezor/dom-utils": "workspace:*", diff --git a/packages/suite/src/utils/wallet/coinmarket/coinmarketUtils.ts b/packages/suite/src/utils/wallet/coinmarket/coinmarketUtils.ts index 46c00bad02a..45455c45d18 100644 --- a/packages/suite/src/utils/wallet/coinmarket/coinmarketUtils.ts +++ b/packages/suite/src/utils/wallet/coinmarket/coinmarketUtils.ts @@ -12,11 +12,8 @@ import TrezorConnect from '@trezor/connect'; import regional from 'src/constants/wallet/coinmarket/regional'; import { ExtendedMessageDescriptor, TrezorDevice } from 'src/types/suite'; import { BuyTrade, SellFiatTrade, CryptoId } from 'invity-api'; -import { - DefinitionType, - getContractAddressForNetwork, - isTokenDefinitionKnown, -} from '@suite-common/token-definitions'; +import { DefinitionType, isTokenDefinitionKnown } from '@suite-common/token-definitions'; +import { getContractAddressForNetwork } from '@suite-common/wallet-utils'; import { CoinmarketAccountOptionsGroupOptionProps, CoinmarketAccountsOptionsGroupProps, diff --git a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx index 90c570e5eb3..4301ceb4a9f 100644 --- a/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx +++ b/packages/suite/src/views/wallet/tokens/common/TokensTable/TokenRow.tsx @@ -7,10 +7,10 @@ import { DefinitionType, EnhancedTokenInfo, TokenManagementAction, - getContractAddressForNetwork, selectIsSpecificCoinDefinitionKnown, tokenDefinitionsActions, } from '@suite-common/token-definitions'; +import { getContractAddressForNetwork } from '@suite-common/wallet-utils'; import { notificationsActions } from '@suite-common/toast-notifications'; import { copyToClipboard } from '@trezor/dom-utils'; import { diff --git a/suite-common/token-definitions/package.json b/suite-common/token-definitions/package.json index b2cb5f8e3a5..033c24b8114 100644 --- a/suite-common/token-definitions/package.json +++ b/suite-common/token-definitions/package.json @@ -19,6 +19,7 @@ "@suite-common/redux-utils": "workspace:*", "@suite-common/wallet-config": "workspace:*", "@suite-common/wallet-types": "workspace:*", + "@suite-common/wallet-utils": "workspace:*", "@trezor/blockchain-link-types": "workspace:^", "@trezor/blockchain-link-utils": "workspace:*", "@trezor/connect": "workspace:*", diff --git a/suite-common/token-definitions/src/__fixtures__/utils.ts b/suite-common/token-definitions/src/__fixtures__/utils.ts index 7e4605fbf1d..f458fcd2297 100644 --- a/suite-common/token-definitions/src/__fixtures__/utils.ts +++ b/suite-common/token-definitions/src/__fixtures__/utils.ts @@ -2,45 +2,6 @@ import { NetworkSymbol } from '@suite-common/wallet-config'; import { DefinitionType } from '../tokenDefinitionsTypes'; -export const getContractAddressForNetworkFixtures = [ - { - testName: 'Converts to lowercase for non-sol networks', - networkSymbol: 'eth' as NetworkSymbol, - contractAddress: '0xABCD', - expected: '0xabcd', - }, - { - testName: 'Preserves case for sol network', - networkSymbol: 'sol' as NetworkSymbol, - contractAddress: 'SolContractAddress', - expected: 'SolContractAddress', - }, - { - testName: 'Converts to lowercase for eth network', - networkSymbol: 'eth' as NetworkSymbol, - contractAddress: '0XABCDE', - expected: '0xabcde', - }, - { - testName: 'Handles empty contract address for non-sol network', - networkSymbol: 'btc' as NetworkSymbol, - contractAddress: '', - expected: '', - }, - { - testName: 'Handles empty contract address for sol network', - networkSymbol: 'sol' as NetworkSymbol, - contractAddress: '', - expected: '', - }, - { - testName: 'Returns policy id for cardano', - networkSymbol: 'ada' as NetworkSymbol, - contractAddress: 'f43a62fdc3965df486de8a0d32fe800963589c41b38946602a0dc53541474958', - expected: 'f43a62fdc3965df486de8a0d32fe800963589c41b38946602a0dc535', - }, -]; - export const isTokenDefinitionKnownFixtures = [ { testName: 'Token definition known, case-insensitive network', diff --git a/suite-common/token-definitions/src/__tests__/utils.test.ts b/suite-common/token-definitions/src/__tests__/utils.test.ts index 106c31a0a40..1109125aaad 100644 --- a/suite-common/token-definitions/src/__tests__/utils.test.ts +++ b/suite-common/token-definitions/src/__tests__/utils.test.ts @@ -1,27 +1,14 @@ import { - getContractAddressForNetworkFixtures, getSupportedDefinitionTypesFixtures, isTokenDefinitionKnownFixtures, buildTokenDefinitionsFromStorageFixtures, } from '../__fixtures__/utils'; import { buildTokenDefinitionsFromStorage, - getContractAddressForNetwork, getSupportedDefinitionTypes, isTokenDefinitionKnown, } from '../tokenDefinitionsUtils'; -describe('getContractAddressForNetwork', () => { - getContractAddressForNetworkFixtures.forEach( - ({ testName, networkSymbol, contractAddress, expected }) => { - test(testName, () => { - const result = getContractAddressForNetwork(networkSymbol, contractAddress); - expect(result).toBe(expected); - }); - }, - ); -}); - describe('isTokenDefinitionKnown', () => { isTokenDefinitionKnownFixtures.forEach( ({ testName, tokenDefinitions, networkSymbol, contractAddress, result }) => { diff --git a/suite-common/token-definitions/src/tokenDefinitionsUtils.ts b/suite-common/token-definitions/src/tokenDefinitionsUtils.ts index 32acbf8d557..993ccaa9ca5 100644 --- a/suite-common/token-definitions/src/tokenDefinitionsUtils.ts +++ b/suite-common/token-definitions/src/tokenDefinitionsUtils.ts @@ -1,5 +1,5 @@ import { NetworkSymbol, getNetworkFeatures } from '@suite-common/wallet-config'; -import { parseAsset } from '@trezor/blockchain-link-utils/src/blockfrost'; +import { getContractAddressForNetwork } from '@suite-common/wallet-utils'; import { DefinitionType, @@ -9,27 +9,6 @@ import { TokenManagementStorage, } from './tokenDefinitionsTypes'; -export const getContractAddressForNetwork = ( - networkSymbol: NetworkSymbol, - contractAddress: string, -) => { - switch (networkSymbol) { - case 'eth': - // Specyfing most common network as first case improves performance little bit - return contractAddress.toLowerCase(); - case 'sol': - case 'dsol': - return contractAddress; - case 'ada': - case 'tada': - const { policyId } = parseAsset(contractAddress); - - return policyId.toLowerCase(); - default: - return contractAddress.toLowerCase(); - } -}; - // Using Set greatly improves performance of this function because of O(1) complexity instead of O(n) for Array.includes const tokenDefinitionsMap = new WeakMap>(); export const isTokenDefinitionKnown = ( diff --git a/suite-common/wallet-utils/src/__fixtures__/tokenUtils.ts b/suite-common/wallet-utils/src/__fixtures__/tokenUtils.ts new file mode 100644 index 00000000000..8b85e8a8e45 --- /dev/null +++ b/suite-common/wallet-utils/src/__fixtures__/tokenUtils.ts @@ -0,0 +1,40 @@ +import { NetworkSymbol } from '@suite-common/wallet-config'; + +export const getContractAddressForNetworkFixtures = [ + { + testName: 'Converts to lowercase for non-sol networks', + networkSymbol: 'eth' as NetworkSymbol, + contractAddress: '0xABCD', + expected: '0xabcd', + }, + { + testName: 'Preserves case for sol network', + networkSymbol: 'sol' as NetworkSymbol, + contractAddress: 'SolContractAddress', + expected: 'SolContractAddress', + }, + { + testName: 'Converts to lowercase for eth network', + networkSymbol: 'eth' as NetworkSymbol, + contractAddress: '0XABCDE', + expected: '0xabcde', + }, + { + testName: 'Handles empty contract address for non-sol network', + networkSymbol: 'btc' as NetworkSymbol, + contractAddress: '', + expected: '', + }, + { + testName: 'Handles empty contract address for sol network', + networkSymbol: 'sol' as NetworkSymbol, + contractAddress: '', + expected: '', + }, + { + testName: 'Returns policy id for cardano', + networkSymbol: 'ada' as NetworkSymbol, + contractAddress: 'f43a62fdc3965df486de8a0d32fe800963589c41b38946602a0dc53541474958', + expected: 'f43a62fdc3965df486de8a0d32fe800963589c41b38946602a0dc535', + }, +]; diff --git a/suite-common/wallet-utils/src/__tests__/tokenUtils.test.ts b/suite-common/wallet-utils/src/__tests__/tokenUtils.test.ts new file mode 100644 index 00000000000..4ee11ce96ba --- /dev/null +++ b/suite-common/wallet-utils/src/__tests__/tokenUtils.test.ts @@ -0,0 +1,13 @@ +import { getContractAddressForNetworkFixtures } from '../__fixtures__/tokenUtils'; +import { getContractAddressForNetwork } from '../tokenUtils'; + +describe('getContractAddressForNetwork', () => { + getContractAddressForNetworkFixtures.forEach( + ({ testName, networkSymbol, contractAddress, expected }) => { + test(testName, () => { + const result = getContractAddressForNetwork(networkSymbol, contractAddress); + expect(result).toBe(expected); + }); + }, + ); +}); diff --git a/suite-common/wallet-utils/src/index.ts b/suite-common/wallet-utils/src/index.ts index 699e388498b..fd634a823e3 100644 --- a/suite-common/wallet-utils/src/index.ts +++ b/suite-common/wallet-utils/src/index.ts @@ -20,5 +20,6 @@ export * from './antiFraud'; export * from './stakingUtils'; export * from './reviewTransactionUtils'; export * from './filterReceiveAccounts'; +export * from './tokenUtils'; export { analyzeTransactions as analyzeTransactionsFixtures } from './__fixtures__/transactionUtils'; diff --git a/suite-common/wallet-utils/src/tokenUtils.ts b/suite-common/wallet-utils/src/tokenUtils.ts new file mode 100644 index 00000000000..e0f36d32c80 --- /dev/null +++ b/suite-common/wallet-utils/src/tokenUtils.ts @@ -0,0 +1,23 @@ +import { NetworkSymbol } from '@suite-common/wallet-config'; +import { parseAsset } from '@trezor/blockchain-link-utils/src/blockfrost'; + +export const getContractAddressForNetwork = ( + networkSymbol: NetworkSymbol, + contractAddress: string, +) => { + switch (networkSymbol) { + case 'eth': + // Specyfing most common network as first case improves performance little bit + return contractAddress.toLowerCase(); + case 'sol': + case 'dsol': + return contractAddress; + case 'ada': + case 'tada': + const { policyId } = parseAsset(contractAddress); + + return policyId.toLowerCase(); + default: + return contractAddress.toLowerCase(); + } +}; diff --git a/yarn.lock b/yarn.lock index e7145504d3a..a60568ce0a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9346,6 +9346,7 @@ __metadata: "@suite-common/redux-utils": "workspace:*" "@suite-common/wallet-config": "workspace:*" "@suite-common/wallet-types": "workspace:*" + "@suite-common/wallet-utils": "workspace:*" "@trezor/blockchain-link-types": "workspace:^" "@trezor/blockchain-link-utils": "workspace:*" "@trezor/connect": "workspace:*" @@ -11650,6 +11651,7 @@ __metadata: "@storybook/react-webpack5": "npm:^7.6.13" "@suite-common/validators": "workspace:*" "@suite-common/wallet-config": "workspace:*" + "@suite-common/wallet-utils": "workspace:*" "@trezor/components": "workspace:*" "@trezor/connect": "workspace:*" "@trezor/dom-utils": "workspace:*" From b102229c036adc7e6a471b4f886493ce3400d9e3 Mon Sep 17 00:00:00 2001 From: Albina Nikiforova Date: Fri, 11 Oct 2024 12:53:07 +0200 Subject: [PATCH 109/624] refactor(packages): move antiFraud --- packages/product-components/tsconfig.json | 3 +++ packages/suite/src/utils/wallet/exportTransactionsUtils.ts | 3 ++- suite-common/token-definitions/package.json | 2 ++ .../src/__fixtures__/antiFraud.ts | 2 +- .../src/__tests__/antiFraud.test.ts | 0 .../{wallet-utils => token-definitions}/src/antiFraud.ts | 5 +++-- suite-common/token-definitions/src/index.ts | 1 + suite-common/token-definitions/tsconfig.json | 7 ++++++- .../wallet-core/src/transactions/transactionsReducer.ts | 2 +- suite-common/wallet-utils/package.json | 2 -- suite-common/wallet-utils/src/index.ts | 1 - suite-common/wallet-utils/tsconfig.json | 4 ---- yarn.lock | 4 ++-- 13 files changed, 21 insertions(+), 15 deletions(-) rename suite-common/{wallet-utils => token-definitions}/src/__fixtures__/antiFraud.ts (99%) rename suite-common/{wallet-utils => token-definitions}/src/__tests__/antiFraud.test.ts (100%) rename suite-common/{wallet-utils => token-definitions}/src/antiFraud.ts (90%) diff --git a/packages/product-components/tsconfig.json b/packages/product-components/tsconfig.json index 64b47d80c4c..72bcdda32bc 100644 --- a/packages/product-components/tsconfig.json +++ b/packages/product-components/tsconfig.json @@ -19,6 +19,9 @@ { "path": "../../suite-common/wallet-config" }, + { + "path": "../../suite-common/wallet-utils" + }, { "path": "../components" }, { "path": "../connect" }, { "path": "../dom-utils" }, diff --git a/packages/suite/src/utils/wallet/exportTransactionsUtils.ts b/packages/suite/src/utils/wallet/exportTransactionsUtils.ts index 980fc2d05fa..3e05d5bed06 100644 --- a/packages/suite/src/utils/wallet/exportTransactionsUtils.ts +++ b/packages/suite/src/utils/wallet/exportTransactionsUtils.ts @@ -20,13 +20,14 @@ import { formatAmount, formatNetworkAmount, getFiatRateKey, - getIsPhishingTransaction, getNftTokenId, isNftTokenTransfer, localizeNumber, roundTimestampToNearestPastHour, } from '@suite-common/wallet-utils'; +import { getIsPhishingTransaction } from '@suite-common/token-definitions'; + type AccountTransactionForExports = Omit & { targets: (TransactionTarget & { metadataLabel?: string })[]; }; diff --git a/suite-common/token-definitions/package.json b/suite-common/token-definitions/package.json index 033c24b8114..2265671cb91 100644 --- a/suite-common/token-definitions/package.json +++ b/suite-common/token-definitions/package.json @@ -20,11 +20,13 @@ "@suite-common/wallet-config": "workspace:*", "@suite-common/wallet-types": "workspace:*", "@suite-common/wallet-utils": "workspace:*", + "@trezor/blockchain-link": "workspace:*", "@trezor/blockchain-link-types": "workspace:^", "@trezor/blockchain-link-utils": "workspace:*", "@trezor/connect": "workspace:*", "@trezor/env-utils": "workspace:*", "@trezor/type-utils": "workspace:*", + "@trezor/utils": "workspace:*", "jws": "^4.0.0", "proxy-memoize": "2.0.2" }, diff --git a/suite-common/wallet-utils/src/__fixtures__/antiFraud.ts b/suite-common/token-definitions/src/__fixtures__/antiFraud.ts similarity index 99% rename from suite-common/wallet-utils/src/__fixtures__/antiFraud.ts rename to suite-common/token-definitions/src/__fixtures__/antiFraud.ts index fae001f138c..fbd98f51da8 100644 --- a/suite-common/wallet-utils/src/__fixtures__/antiFraud.ts +++ b/suite-common/token-definitions/src/__fixtures__/antiFraud.ts @@ -1,7 +1,7 @@ import type { TokenTransfer } from '@trezor/blockchain-link'; import type { WalletAccountTransaction } from '@suite-common/wallet-types'; -import { TokenDefinitions } from '@suite-common/token-definitions'; +import type { TokenDefinitions } from '../tokenDefinitionsTypes'; export const getIsZeroValuePhishingFixtures = [ { testName: 'detects potential zero-value phishing transactions', diff --git a/suite-common/wallet-utils/src/__tests__/antiFraud.test.ts b/suite-common/token-definitions/src/__tests__/antiFraud.test.ts similarity index 100% rename from suite-common/wallet-utils/src/__tests__/antiFraud.test.ts rename to suite-common/token-definitions/src/__tests__/antiFraud.test.ts diff --git a/suite-common/wallet-utils/src/antiFraud.ts b/suite-common/token-definitions/src/antiFraud.ts similarity index 90% rename from suite-common/wallet-utils/src/antiFraud.ts rename to suite-common/token-definitions/src/antiFraud.ts index 793cf2092ee..9639c6ba06f 100644 --- a/suite-common/wallet-utils/src/antiFraud.ts +++ b/suite-common/token-definitions/src/antiFraud.ts @@ -2,10 +2,11 @@ import { D } from '@mobily/ts-belt'; import { BigNumber } from '@trezor/utils/src/bigNumber'; import type { WalletAccountTransaction } from '@suite-common/wallet-types'; -import { TokenDefinitions, isTokenDefinitionKnown } from '@suite-common/token-definitions'; import { getNetworkType } from '@suite-common/wallet-config'; +import { isNftTokenTransfer } from '@suite-common/wallet-utils'; -import { isNftTokenTransfer } from './transactionUtils'; +import type { TokenDefinitions } from './tokenDefinitionsTypes'; +import { isTokenDefinitionKnown } from './tokenDefinitionsUtils'; export const getIsZeroValuePhishing = (transaction: WalletAccountTransaction) => new BigNumber(transaction.amount).isEqualTo(0) && diff --git a/suite-common/token-definitions/src/index.ts b/suite-common/token-definitions/src/index.ts index cb90e09f3b7..ed02e445967 100644 --- a/suite-common/token-definitions/src/index.ts +++ b/suite-common/token-definitions/src/index.ts @@ -6,3 +6,4 @@ export * from './tokenDefinitionsThunks'; export * from './tokenDefinitionsMiddleware'; export * from './tokenDefinitionsTypes'; export * from './tokenDefinitionsUtils'; +export * from './antiFraud'; diff --git a/suite-common/token-definitions/tsconfig.json b/suite-common/token-definitions/tsconfig.json index 338257e048c..5490d9033fc 100644 --- a/suite-common/token-definitions/tsconfig.json +++ b/suite-common/token-definitions/tsconfig.json @@ -5,6 +5,10 @@ { "path": "../redux-utils" }, { "path": "../wallet-config" }, { "path": "../wallet-types" }, + { "path": "../wallet-utils" }, + { + "path": "../../packages/blockchain-link" + }, { "path": "../../packages/blockchain-link-types" }, @@ -13,6 +17,7 @@ }, { "path": "../../packages/connect" }, { "path": "../../packages/env-utils" }, - { "path": "../../packages/type-utils" } + { "path": "../../packages/type-utils" }, + { "path": "../../packages/utils" } ] } diff --git a/suite-common/wallet-core/src/transactions/transactionsReducer.ts b/suite-common/wallet-core/src/transactions/transactionsReducer.ts index facc5c2d248..788e04868f2 100644 --- a/suite-common/wallet-core/src/transactions/transactionsReducer.ts +++ b/suite-common/wallet-core/src/transactions/transactionsReducer.ts @@ -6,9 +6,9 @@ import { findTransaction, getConfirmations, isPending, - getIsPhishingTransaction, getEverstakePool, } from '@suite-common/wallet-utils'; +import { getIsPhishingTransaction } from '@suite-common/token-definitions'; import { isClaimTx, isStakeTx, isStakeTypeTx, isUnstakeTx } from '@suite-common/suite-utils'; import { createReducerWithExtraDeps } from '@suite-common/redux-utils'; import { selectNetworkTokenDefinitions } from '@suite-common/token-definitions/src/tokenDefinitionsSelectors'; diff --git a/suite-common/wallet-utils/package.json b/suite-common/wallet-utils/package.json index ce3922f1f3e..965791874fe 100644 --- a/suite-common/wallet-utils/package.json +++ b/suite-common/wallet-utils/package.json @@ -21,12 +21,10 @@ "@suite-common/suite-config": "workspace:*", "@suite-common/suite-types": "workspace:*", "@suite-common/test-utils": "workspace:*", - "@suite-common/token-definitions": "workspace:*", "@suite-common/wallet-config": "workspace:*", "@suite-common/wallet-constants": "workspace:*", "@suite-common/wallet-types": "workspace:*", "@trezor/address-validator": "workspace:*", - "@trezor/blockchain-link": "workspace:*", "@trezor/blockchain-link-types": "workspace:*", "@trezor/blockchain-link-utils": "workspace:*", "@trezor/connect": "workspace:*", diff --git a/suite-common/wallet-utils/src/index.ts b/suite-common/wallet-utils/src/index.ts index fd634a823e3..543272e299f 100644 --- a/suite-common/wallet-utils/src/index.ts +++ b/suite-common/wallet-utils/src/index.ts @@ -16,7 +16,6 @@ export * from './settingsUtils'; export * from './solanaUtils'; export * from './transactionUtils'; export * from './validationUtils'; -export * from './antiFraud'; export * from './stakingUtils'; export * from './reviewTransactionUtils'; export * from './filterReceiveAccounts'; diff --git a/suite-common/wallet-utils/tsconfig.json b/suite-common/wallet-utils/tsconfig.json index c6052644963..687b3f70d72 100644 --- a/suite-common/wallet-utils/tsconfig.json +++ b/suite-common/wallet-utils/tsconfig.json @@ -8,16 +8,12 @@ { "path": "../suite-config" }, { "path": "../suite-types" }, { "path": "../test-utils" }, - { "path": "../token-definitions" }, { "path": "../wallet-config" }, { "path": "../wallet-constants" }, { "path": "../wallet-types" }, { "path": "../../packages/address-validator" }, - { - "path": "../../packages/blockchain-link" - }, { "path": "../../packages/blockchain-link-types" }, diff --git a/yarn.lock b/yarn.lock index a60568ce0a9..f11d1fc27d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9347,11 +9347,13 @@ __metadata: "@suite-common/wallet-config": "workspace:*" "@suite-common/wallet-types": "workspace:*" "@suite-common/wallet-utils": "workspace:*" + "@trezor/blockchain-link": "workspace:*" "@trezor/blockchain-link-types": "workspace:^" "@trezor/blockchain-link-utils": "workspace:*" "@trezor/connect": "workspace:*" "@trezor/env-utils": "workspace:*" "@trezor/type-utils": "workspace:*" + "@trezor/utils": "workspace:*" ajv: "npm:^8.17.1" jws: "npm:^4.0.0" proxy-memoize: "npm:2.0.2" @@ -9448,12 +9450,10 @@ __metadata: "@suite-common/suite-config": "workspace:*" "@suite-common/suite-types": "workspace:*" "@suite-common/test-utils": "workspace:*" - "@suite-common/token-definitions": "workspace:*" "@suite-common/wallet-config": "workspace:*" "@suite-common/wallet-constants": "workspace:*" "@suite-common/wallet-types": "workspace:*" "@trezor/address-validator": "workspace:*" - "@trezor/blockchain-link": "workspace:*" "@trezor/blockchain-link-types": "workspace:*" "@trezor/blockchain-link-utils": "workspace:*" "@trezor/connect": "workspace:*" From f23d14a14b5571c4eafb061ed5da6d7f35b79a69 Mon Sep 17 00:00:00 2001 From: Albina Nikiforova Date: Fri, 11 Oct 2024 13:58:27 +0200 Subject: [PATCH 110/624] feat(components): optional Tooltip on AssetLogo --- .../src/components/AssetLogo/AssetInitials.tsx | 14 ++++++++++---- .../src/components/AssetLogo/AssetLogo.tsx | 8 +++++++- .../src/components/TokenIconSet/TokenIconSet.tsx | 3 ++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/components/src/components/AssetLogo/AssetInitials.tsx b/packages/components/src/components/AssetLogo/AssetInitials.tsx index e22a3fede70..6f5ebdb48d5 100644 --- a/packages/components/src/components/AssetLogo/AssetInitials.tsx +++ b/packages/components/src/components/AssetLogo/AssetInitials.tsx @@ -27,18 +27,24 @@ const Circle = styled.div<{ $size: number; $elevation: Elevation }>` `; type AssetInitialsProps = { children: string; + withTooltip?: boolean; size: number; }; -const AssetInitialsInner = ({ children, size }: AssetInitialsProps) => { +const AssetInitialsInner = ({ children, size, withTooltip = true }: AssetInitialsProps) => { const { elevation } = useElevation(); + const firstChar = children[0]; return ( - - {children[0]} - + {withTooltip ? ( + + {firstChar} + + ) : ( + {firstChar} + )} ); diff --git a/packages/components/src/components/AssetLogo/AssetLogo.tsx b/packages/components/src/components/AssetLogo/AssetLogo.tsx index b4af7cf5100..4afbcb75632 100644 --- a/packages/components/src/components/AssetLogo/AssetLogo.tsx +++ b/packages/components/src/components/AssetLogo/AssetLogo.tsx @@ -24,6 +24,7 @@ export type AssetLogoProps = AllowedFrameProps & { coingeckoId: string; contractAddress?: string; shouldTryToFetch?: boolean; + placeholderWithTooltip?: boolean; placeholder: string; 'data-testid'?: string; }; @@ -54,6 +55,7 @@ export const AssetLogo = ({ contractAddress, shouldTryToFetch = true, placeholder, + placeholderWithTooltip = true, 'data-testid': dataTest, ...rest }: AssetLogoProps) => { @@ -76,7 +78,11 @@ export const AssetLogo = ({ return ( - {isPlaceholder && {placeholder}} + {isPlaceholder && ( + + {placeholder} + + )} {!isPlaceholder && ( { {visibleTokens.map(token => ( 1 ? 20 : 24} + size={20} coingeckoId={coingeckoId ?? ''} contractAddress={getContractAddressForNetwork(network, token.contract)} placeholder={token.symbol?.toUpperCase() ?? ''} + placeholderWithTooltip={false} /> ))} From 369d25721618bde90a490f20e9cc323e801cdf40 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Tue, 8 Oct 2024 12:06:21 +0200 Subject: [PATCH 111/624] chore(suite-native): send feature flag used for btc like coins --- .../feature-flags/src/featureFlagsSlice.ts | 6 ++--- .../src/components/TransactionListHeader.tsx | 15 +++++------ .../src/selectors.ts | 27 +++++++++++++++++++ .../src/components/FeatureFlags.tsx | 2 +- 4 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 suite-native/module-accounts-management/src/selectors.ts diff --git a/suite-native/feature-flags/src/featureFlagsSlice.ts b/suite-native/feature-flags/src/featureFlagsSlice.ts index fd592f4976a..18e747db1c0 100644 --- a/suite-native/feature-flags/src/featureFlagsSlice.ts +++ b/suite-native/feature-flags/src/featureFlagsSlice.ts @@ -5,7 +5,7 @@ import { isDebugEnv, isDetoxTestBuild, isDevelopOrDebugEnv } from '@suite-native export const FeatureFlag = { IsDeviceConnectEnabled: 'isDeviceConnectEnabled', - IsSendEnabled: 'isSendEnabled', + IsBitcoinLikeSendEnabled: 'isBitcoinLikeSendEnabled', IsRegtestEnabled: 'isRegtestEnabled', IsPolygonEnabled: 'IsPolygonEnabled', IsBscEnabled: 'IsBscEnabled', @@ -20,7 +20,7 @@ export type FeatureFlagsRootState = { export const featureFlagsInitialState: FeatureFlagsState = { [FeatureFlag.IsDeviceConnectEnabled]: isAndroid() || isDebugEnv(), - [FeatureFlag.IsSendEnabled]: isAndroid() && isDevelopOrDebugEnv(), + [FeatureFlag.IsBitcoinLikeSendEnabled]: isAndroid() && isDevelopOrDebugEnv(), [FeatureFlag.IsRegtestEnabled]: isDebugEnv() || isDetoxTestBuild(), [FeatureFlag.IsPolygonEnabled]: false, [FeatureFlag.IsBscEnabled]: false, @@ -28,7 +28,7 @@ export const featureFlagsInitialState: FeatureFlagsState = { export const featureFlagsPersistedKeys: Array = [ FeatureFlag.IsDeviceConnectEnabled, - FeatureFlag.IsSendEnabled, + FeatureFlag.IsBitcoinLikeSendEnabled, FeatureFlag.IsRegtestEnabled, FeatureFlag.IsPolygonEnabled, FeatureFlag.IsBscEnabled, diff --git a/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx b/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx index 393b9d7616c..c6871099bca 100644 --- a/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx +++ b/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx @@ -20,14 +20,14 @@ import { TabToStackCompositeNavigationProp, } from '@suite-native/navigation'; import { Translation } from '@suite-native/intl'; -import { FeatureFlag, useFeatureFlag } from '@suite-native/feature-flags'; -import { NetworkSymbol } from '@suite-common/wallet-config'; +import { FeatureFlag, FeatureFlagsRootState, useFeatureFlag } from '@suite-native/feature-flags'; import { isCoinWithTokens } from '@suite-native/tokens'; import { AccountDetailGraph } from './AccountDetailGraph'; import { AccountDetailCryptoValue } from './AccountDetailCryptoValue'; import { IncludeTokensToggle } from './IncludeTokensToggle'; import { CoinPriceCard } from './CoinPriceCard'; +import { selectIsNetworkSendFlowEnabled } from '../selectors'; type AccountDetailHeaderProps = { accountKey: AccountKey; @@ -47,8 +47,6 @@ type AccountsNavigationProps = TabToStackCompositeNavigationProp< RootStackParamList >; -const SEND_NETWORK_WHITELIST: Readonly = ['btc', 'test', 'regtest']; - const TransactionListHeaderContent = ({ accountKey, tokenContract, @@ -99,7 +97,7 @@ export const TransactionListHeader = memo( tokenContract, }: AccountDetailHeaderProps) => { const navigation = useNavigation(); - const [isSendEnabled] = useFeatureFlag(FeatureFlag.IsSendEnabled); + const [isDeviceConnectEnabled] = useFeatureFlag(FeatureFlag.IsDeviceConnectEnabled); const account = useSelector((state: AccountsRootState) => selectAccountByKey(state, accountKey), @@ -110,6 +108,9 @@ export const TransactionListHeader = memo( const isTestnetAccount = useSelector((state: AccountsRootState) => selectIsTestnetAccount(state, accountKey), ); + const isNetworkSendFlowEnabled = useSelector((state: FeatureFlagsRootState) => + selectIsNetworkSendFlowEnabled(state, account?.symbol), + ); const isPortfolioTrackerDevice = useSelector(selectIsPortfolioTrackerDevice); if (!account) return null; @@ -136,9 +137,7 @@ export const TransactionListHeader = memo( const isPriceCardDisplayed = !isTestnetAccount && !isTokenDetail; const isSendButtonDisplayed = - isSendEnabled && - SEND_NETWORK_WHITELIST.includes(account.symbol) && - !isPortfolioTrackerDevice; + isDeviceConnectEnabled && isNetworkSendFlowEnabled && !isPortfolioTrackerDevice; return ( diff --git a/suite-native/module-accounts-management/src/selectors.ts b/suite-native/module-accounts-management/src/selectors.ts new file mode 100644 index 00000000000..ab4d48ad7b6 --- /dev/null +++ b/suite-native/module-accounts-management/src/selectors.ts @@ -0,0 +1,27 @@ +import { NetworkSymbol, getNetworkType } from '@suite-common/wallet-config'; +import { + FeatureFlagsRootState, + selectIsFeatureFlagEnabled, + FeatureFlag, +} from '@suite-native/feature-flags'; + +const SEND_COINS_WHITELIST: NetworkSymbol[] = ['btc', 'test', 'regtest']; + +export const selectIsNetworkSendFlowEnabled = ( + state: FeatureFlagsRootState, + networkSymbol?: NetworkSymbol, +) => { + if (!networkSymbol) return false; + + if (SEND_COINS_WHITELIST.includes(networkSymbol)) return true; + + const isBitcoinLikeSendEnabled = selectIsFeatureFlagEnabled( + state, + FeatureFlag.IsBitcoinLikeSendEnabled, + ); + + const networkType = getNetworkType(networkSymbol); + if (isBitcoinLikeSendEnabled && networkType === 'bitcoin') return true; + + return false; +}; diff --git a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx index f1699adc697..84cc34d4df4 100644 --- a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx +++ b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx @@ -3,7 +3,7 @@ import { FeatureFlag as FeatureFlagEnum, useFeatureFlag } from '@suite-native/fe const featureFlagsTitleMap = { [FeatureFlagEnum.IsDeviceConnectEnabled]: 'Connect device', - [FeatureFlagEnum.IsSendEnabled]: 'Send', + [FeatureFlagEnum.IsBitcoinLikeSendEnabled]: 'Bitcoin-like coins send', [FeatureFlagEnum.IsRegtestEnabled]: 'Regtest', [FeatureFlagEnum.IsPolygonEnabled]: 'Polygon', [FeatureFlagEnum.IsBscEnabled]: 'BNB Smart Chain', From 151b65d2495722a7c5dcbc1cad8ffe93984aea4c Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Fri, 11 Oct 2024 14:03:03 +0000 Subject: [PATCH 112/624] chore: crowdin translation update --- .../suite-data/files/translations/cs.json | 6 --- .../suite-data/files/translations/de.json | 8 +--- .../suite-data/files/translations/en.json | 21 ++++++----- .../suite-data/files/translations/es.json | 6 --- .../suite-data/files/translations/fr.json | 8 +--- .../suite-data/files/translations/hu.json | 12 ++---- .../suite-data/files/translations/it.json | 6 --- .../suite-data/files/translations/ja.json | 35 ++++++++++-------- .../suite-data/files/translations/lol.json | 37 +++++++++++++++---- .../suite-data/files/translations/nl.json | 2 - .../suite-data/files/translations/pt.json | 6 --- .../suite-data/files/translations/ro.json | 1 - .../suite-data/files/translations/ru.json | 4 -- .../suite-data/files/translations/sk.json | 4 -- .../suite-data/files/translations/tr.json | 6 --- .../suite-data/files/translations/uk.json | 4 -- .../suite-data/files/translations/zh.json | 31 +++++++++------- packages/suite/src/support/messages.ts | 25 +++++-------- 18 files changed, 93 insertions(+), 129 deletions(-) diff --git a/packages/suite-data/files/translations/cs.json b/packages/suite-data/files/translations/cs.json index 6979a963dc7..87e8fca39c5 100644 --- a/packages/suite-data/files/translations/cs.json +++ b/packages/suite-data/files/translations/cs.json @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Částka v Trezoru", "TR_CHAINED_TXS": "Řetězové transakce", "TR_CHANGELOG": "Changelog", - "TR_CHANGELOG_ON_GITHUB": "Changelog na GitHubu", "TR_CHANGE_ADDRESS_TOOLTIP": "Tato adresa vznikla při předchozí transakci jako adresa zpět na peněženku.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Typ firmwaru můžete kdykoli změnit v nastavení.", "TR_CHANGE_HOMESCREEN": "Změnit domovskou obrazovku", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Zobrazit podrobnosti", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Automatické aktualizace aplikace Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Aplikace Trezor Suite automaticky stáhne nejnovější verzi na pozadí a nainstaluje ji při restartování aplikace. Díky tomu budete mít vždy aktuální verzi s nejnovějšími funkcemi a bezpečnostními opravami. Aktualizace probíhají bez vašeho zásahu.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Povolí síť BNB Smart Chain, ale bez historie dat interních transakcí.", "TR_EXPERIMENTAL_FEATURES": "Experimentální", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Experimentální funkce", "TR_EXPERIMENTAL_FEATURES_WARNING": "Pouze pro zkušené uživatele. Používejte na vlastní riziko. Tyto funkce jsou ve fázi testování, mohou být nestabilní a nemusí mít dlouhodobou podporu.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "Na BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Chcete-li, aby vaše popisky byly konzistentní a dostupné na všech zařízeních, připojte se ke cloudovému úložišti.", "TR_TO_SATOSHIS": "Na satoshi", - "TR_TRADE_BUYS": "kupuje", - "TR_TRADE_EXCHANGES": "směňuje", "TR_TRADE_REDIRECTING": "Přesměrování…", - "TR_TRADE_SELLS": "prodává", "TR_TRANSACTIONS_NOT_AVAILABLE": "Historie transakcí není k dispozici", "TR_TRANSACTIONS_SEARCH_TIP_1": "Tip: Můžete vyhledávat ID transakcí, adresy, tokeny, popisky, částky a data.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Tip: Kombinací operátorů AND (&) a OR (|) můžete získat podrobnější výsledky. Například > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 zobrazí všechny transakce z ledna nebo prosince {lastYear}.", diff --git a/packages/suite-data/files/translations/de.json b/packages/suite-data/files/translations/de.json index d73091df147..ba0daa79e81 100644 --- a/packages/suite-data/files/translations/de.json +++ b/packages/suite-data/files/translations/de.json @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor Betrag", "TR_CHAINED_TXS": "Verkettete Transaktionen", "TR_CHANGELOG": "Änderungsprotokoll", - "TR_CHANGELOG_ON_GITHUB": "Änderungsprotokoll auf GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Dies ist eine Wechselgeldadresse, die aus einer früheren Sendung stammt.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Du kannst deinen Firmware-Typ jederzeit in den Einstellungen ändern.", "TR_CHANGE_HOMESCREEN": "Startbildschirm ändern", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Details anzeigen", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Automatische Updates für Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite lädt im Hintergrund automatisch die neueste Version herunter. Beim Neustart der App wird diese installiert. So bleibst du bei den neuesten Funktionen und Sicherheits-Patches immer auf dem Laufenden. Updates werden ausgeführt, ohne dass du deine Zustimmung erteilen musst.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Aktiviert das Netzwerk der BNB Smart Chain, jedoch ohne internen Transaktionsdatenverlauf.", "TR_EXPERIMENTAL_FEATURES": "Experimentell", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Experimentelle Funktionen", "TR_EXPERIMENTAL_FEATURES_WARNING": "Der langfristige Support dieser Funktionen ist von der Garantie ausgeschlossen.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "In BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Um deine Labels konsistent und auf verschiedenen Geräten verfügbar zu machen, stelle eine Verbindung zu einem Cloud-Speicher-Provider her.", "TR_TO_SATOSHIS": "Zu Sats", - "TR_TRADE_BUYS": "kauft", - "TR_TRADE_EXCHANGES": "tauscht", "TR_TRADE_REDIRECTING": "Wird umgeleitet ...", - "TR_TRADE_SELLS": "verkauft", "TR_TRANSACTIONS_NOT_AVAILABLE": "Transaktionsverlauf nicht verfügbar", "TR_TRANSACTIONS_SEARCH_TIP_1": "Tipp: Du kannst nach Transaktions-IDs, Adressen, Tokens, Labels, Beträgen und Datumsangaben suchen.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Tipp: Für komplexeres Suchen kannst du die Operatoren AND (&) und OR (|) kombinieren. > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 zeigt zum Beispiel alle Transaktionen im Januar oder Dezember {lastYear} an.", @@ -2010,7 +2004,7 @@ "TR_VERIFY_TREZOR_OWNERSHIP_CARD_2": "Keine Fotos und keine digitalen Kopien deines Wallet-Backups", "TR_VERIFY_TREZOR_OWNERSHIP_EXPLANATION": "Gib dein aktuelles Wallet-Backup auf deinem Trezor ein und bestätige damit, dass du der Eigentümer dieses Wallets bist.", "TR_VERSION": "Version {version}", - "TR_VERSION_HAS_BEEN_RELEASED": "Version {version} wurde veröffentlicht.", + "TR_VERSION_HAS_BEEN_RELEASED": "Version {version} wurde veröffentlicht!", "TR_VIEW": "Anzeigen", "TR_VIEW_ACCOUNT": "Konto anzeigen", "TR_VIEW_ALL": "Alle anzeigen", diff --git a/packages/suite-data/files/translations/en.json b/packages/suite-data/files/translations/en.json index 682353c471a..9210ee32528 100644 --- a/packages/suite-data/files/translations/en.json +++ b/packages/suite-data/files/translations/en.json @@ -129,7 +129,7 @@ "RECIPIENT_SCAN": "Scan", "REFRESH": "Refresh", "REMAINING_BALANCE_LESS_THAN_RENT": "After sending this amount, your account will have {remainingSolBalance} SOL remaining. A non-empty account must maintain a balance of more than {rent} SOL.", - "REVIEW_AND_SEND_TRANSACTION": "Review & Send", + "REVIEW_AND_SEND_TRANSACTION": "Review & send", "SEND_RAW": "Send raw", "SEND_RAW_TRANSACTION_TOOLTIP": "You can provide all the raw data for your transaction by yourself.", "SEND_TRANSACTION": "Send", @@ -297,6 +297,8 @@ "TR_ALLOW_ANALYTICS_DESCRIPTION": "All data is kept strictly anonymous. It's only used to improve the Trezor ecosystem.", "TR_ALLOW_AUTOMATIC_SUITE_UPDATES": "Automatic Trezor Suite updates", "TR_ALLOW_AUTOMATIC_SUITE_UPDATES_DESCRIPTION": "Trezor Suite automatically downloads the latest version in the background and installs it when restarting the app. This ensures you're always up-to-date with the latest features and security patches. Updates occur without requiring your permission.", + "TR_ALL_NETWORKS": "All networks ({networkCount})", + "TR_ALL_NETWORKS_TOOLTIP": "View tokens from all {networkCount} networks. Filter by the most popular networks on the right.", "TR_ALL_TRANSACTIONS": "Transactions", "TR_AMOUNT_SENT": "Amount sent", "TR_AMOUNT_TOO_BIG_FOR_COINJOIN": "Not suitable for coinjoin - amount too high", @@ -387,7 +389,7 @@ "TR_BUY_DETAIL_WAITING_FOR_USER_TEXT": "{providerName} needs some final details to finish this transaction. Visit their site to proceed.", "TR_BUY_DETAIL_WAITING_FOR_USER_TITLE": "Complete your transaction", "TR_BUY_FOOTER_TEXT_1": "Invity is a comparison tool that connects you to the best exchange providers. They only use location in order to show the most relevant offers.", - "TR_BUY_FOOTER_TEXT_2": "Invity does not see any of your payment or KYC information; you share this only with the exchange provider if you choose to finish the transaction.", + "TR_BUY_FOOTER_TEXT_2": "Invity doesn't see any of your payment or KYC information; you share this only with the exchange provider if you choose to finish the transaction.", "TR_BUY_GO_TO_PAYMENT": "Finish transaction", "TR_BUY_LEARN_MORE": "Learn more", "TR_BUY_MODAL_CONFIRM": "I’m ready to buy", @@ -438,7 +440,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor amount", "TR_CHAINED_TXS": "Chained transactions", "TR_CHANGELOG": "Changelog", - "TR_CHANGELOG_ON_GITHUB": "Changelog on GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "This is a change address created from a previous send.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "You can change your firmware type in Settings anytime.", "TR_CHANGE_HOMESCREEN": "Change homescreen", @@ -988,8 +989,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "View details", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Automatic Trezor Suite updates", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite automatically downloads the latest version in the background and installs it when restarting the app. This ensures you're always up-to-date with the latest features and security patches. Updates occur without requiring your permission.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Enables the BNB Smart Chain network but without internal transaction data history.", "TR_EXPERIMENTAL_FEATURES": "Experimental", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Experimental features", "TR_EXPERIMENTAL_FEATURES_WARNING": "For experienced users only. Use at your own risk. These features are in testing, may be unstable, and might not have long-term support.", @@ -1532,7 +1531,7 @@ "TR_SAFETY_CHECKS_MODAL_TITLE": "Safety checks", "TR_SAFETY_CHECKS_PROMPT_LEVEL": "Prompt", "TR_SAFETY_CHECKS_PROMPT_LEVEL_DESC": "Allow potentially unsafe actions, such as mismatching keys or allowing extreme fees, by manually approving them on your Trezor.", - "TR_SAFETY_CHECKS_PROMPT_LEVEL_WARNING": "Do not change this unless you know what you're doing!", + "TR_SAFETY_CHECKS_PROMPT_LEVEL_WARNING": "Only change this if you know what you're doing!", "TR_SAFETY_CHECKS_STRICT_LEVEL": "Strict", "TR_SAFETY_CHECKS_STRICT_LEVEL_DESC": "Full Trezor security.", "TR_SCAN_QR_CODE": "Scan QR code", @@ -1558,9 +1557,11 @@ "TR_SELECTED": "{amount} selected", "TR_SELECT_COIN_FOR_SETTINGS": "Select active coin to change settings", "TR_SELECT_DEVICE": "Select device", + "TR_SELECT_NAME_OR_ADDRESS": "Search by name, symbol, network, or contract address", "TR_SELECT_NUMBER_OF_WORDS": "Select the number of words in your wallet backup", "TR_SELECT_PASSPHRASE_SOURCE": "Select where to enter passphrase on \"{deviceLabel}\" .", "TR_SELECT_RECOVERY_METHOD": "Select recovery method", + "TR_SELECT_TOKEN": "Select a token", "TR_SELECT_TREZOR": "Select Trezor", "TR_SELECT_TREZOR_TO_CONTINUE": "Select your Trezor to continue.", "TR_SELECT_TYPE": "Select type", @@ -1794,6 +1795,7 @@ "TR_START_COINJOIN": "Start coinjoin", "TR_START_RECOVERY": "Start recovery", "TR_STEP": "Step {number}", + "TR_STEP_OF_TOTAL": "Select a token", "TR_STILL_DONT_SEE_YOUR_TREZOR": "Still don’t see your Trezor?", "TR_STOP": "Stop", "TR_STOPPING": "Stopping", @@ -1845,7 +1847,11 @@ "TR_TOKENS_EMPTY": "No tokens... yet.", "TR_TOKENS_EMPTY_CHECK_HIDDEN": "No tokens. They may be hidden.", "TR_TOKENS_SEARCH_TOOLTIP": "Search by token, symbol, or contract address.", + "TR_TOKEN_NOT_FOUND": "Token not found", + "TR_TOKEN_NOT_FOUND_ON_NETWORK": "Token not found on the {networkName} network.", "TR_TOKEN_TRANSFERS": "{standard} Token Transfers", + "TR_TOKEN_TRY_DIFFERENT_SEARCH": "Try a different search.", + "TR_TOKEN_TRY_DIFFERENT_SEARCH_OR_SWITCH": "Try a different search or switch to another network.", "TR_TOKEN_UNRECOGNIZED_BY_TREZOR": "Unrecognized tokens", "TR_TOKEN_UNRECOGNIZED_BY_TREZOR_TOOLTIP": "Unrecognized tokens pose potential risks. Use caution.", "TR_TOO_LONG": "Message is too long", @@ -1889,10 +1895,7 @@ "TR_TO_BTC": "To BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "To make your labels consistent and available on different devices, connect to a cloud storage provider.", "TR_TO_SATOSHIS": "To sats", - "TR_TRADE_BUYS": "buys", - "TR_TRADE_EXCHANGES": "exchanges", "TR_TRADE_REDIRECTING": "Redirecting ...", - "TR_TRADE_SELLS": "sells", "TR_TRANSACTIONS_NOT_AVAILABLE": "Transaction history not available", "TR_TRANSACTIONS_SEARCH_TIP_1": "Tip: You can search for transaction IDs, addresses, tokens, labels, amounts, and dates.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Tip: Combine AND (&) and OR (|) operators for more complex searches. For example > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 will show all transactions in January or December {lastYear}.", diff --git a/packages/suite-data/files/translations/es.json b/packages/suite-data/files/translations/es.json index 0b6bd27f889..8181fd4eb36 100644 --- a/packages/suite-data/files/translations/es.json +++ b/packages/suite-data/files/translations/es.json @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Importe de Trezor", "TR_CHAINED_TXS": "Transacciones encadenadas", "TR_CHANGELOG": "Registro de cambios", - "TR_CHANGELOG_ON_GITHUB": "Registro de cambios en GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Se trata de una dirección de cambio creada a partir de un envío anterior.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Puedes cambiar el tipo de firmware en Configuración en cualquier momento.", "TR_CHANGE_HOMESCREEN": "Cambiar pantalla de inicio", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Ver detalles", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Actualizaciones automáticas de Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite descarga automáticamente la versión más reciente en segundo plano y la instala al reiniciar la aplicación. De este modo, siempre estarás al día de las últimas funciones y medidas de seguridad. Las actualizaciones se producen sin solicitar tu permiso.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Permite utilizar la red de BNB Smart Chain sin que haya un historial interno con información sobre las transacciones.", "TR_EXPERIMENTAL_FEATURES": "Experimental", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Funciones experimentales", "TR_EXPERIMENTAL_FEATURES_WARNING": "Solo para usuarios con experiencia. Utilízala bajo tu propia responsabilidad. Estas funciones están en fase de prueba, pueden ser inestables y podrían dejar de recibir soporte a largo plazo.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "A BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Para que tus etiquetas se mantengan y estén disponibles en diferentes dispositivos, conéctate al proveedor de almacenamiento en la nube.", "TR_TO_SATOSHIS": "A sats", - "TR_TRADE_BUYS": "compras", - "TR_TRADE_EXCHANGES": "intercambios", "TR_TRADE_REDIRECTING": "Redirigiendo...", - "TR_TRADE_SELLS": "ventas", "TR_TRANSACTIONS_NOT_AVAILABLE": "El historial de transacciones no está disponible.", "TR_TRANSACTIONS_SEARCH_TIP_1": "Sugerencia: Puedes buscar ID de transacción, direcciones, tokens, etiquetas, importes y fechas.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Sugerencia: Combina los operadores AND (&) y OR (|) para hacer búsquedas más complejas. Por ejemplo, con > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 verás todas las transacciones en enero o diciembre de {lastYear}.", diff --git a/packages/suite-data/files/translations/fr.json b/packages/suite-data/files/translations/fr.json index 906be276d49..ccc9f84b9ee 100644 --- a/packages/suite-data/files/translations/fr.json +++ b/packages/suite-data/files/translations/fr.json @@ -387,7 +387,7 @@ "TR_BUY_DETAIL_WAITING_FOR_USER_TEXT": "{providerName} a besoin de quelques informations supplémentaires pour finaliser cette transaction. Consultez le site pertinent pour continuer.", "TR_BUY_DETAIL_WAITING_FOR_USER_TITLE": "Terminez votre transaction", "TR_BUY_FOOTER_TEXT_1": "Invity est un outil de comparaison qui vous met en relation avec les meilleurs fournisseurs de plateforme d’échange. Il n’utilise que la localisation pour présenter les offres les plus pertinentes.", - "TR_BUY_FOOTER_TEXT_2": "Invity ne voit aucune de vos informations de paiement ou de KYC ; vous ne les partagez qu’avec le fournisseur de plateforme d’échange si vous choisissez de clôturer la transaction.", + "TR_BUY_FOOTER_TEXT_2": "Invity ne voit aucune de vos informations de paiement ou de KYC ;\n vous ne les partagez qu’avec le fournisseur de plateforme d’échange si vous choisissez de\n clôturer la transaction.", "TR_BUY_GO_TO_PAYMENT": "Terminer la transaction", "TR_BUY_LEARN_MORE": "En savoir plus", "TR_BUY_MODAL_CONFIRM": "Je suis prêt à acheter", @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Montant du Trezor", "TR_CHAINED_TXS": "Transactions enchaînées", "TR_CHANGELOG": "Changelog", - "TR_CHANGELOG_ON_GITHUB": "Changelog sur GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Il s’agit d’une adresse de modification créée à partir d’un envoi précédent.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Vous pouvez modifier votre type de micrologiciel à tout moment dans les paramètres.", "TR_CHANGE_HOMESCREEN": "Changer l’écran d’accueil", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Afficher les détails", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Mises à jour automatiques pour Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite télécharge automatiquement la dernière version en arrière-plan et l’installe lors du redémarrage de l’application. Vous bénéficiez ainsi en permanence de la mise à jour des dernières fonctionnalités et des correctifs de sécurité. Les mises à jour ont lieu sans nécessiter votre autorisation.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Permet d’utiliser le réseau BNB Smart Chain mais sans l’historique des données de transaction internes.", "TR_EXPERIMENTAL_FEATURES": "Expérimental", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Fonctionnalités expérimentales", "TR_EXPERIMENTAL_FEATURES_WARNING": "Destiné uniquement aux utilisateurs expérimentés. Cette utilisation se fait à vos risques et périls. Ces fonctionnalités sont en cours de test, peuvent être instables et ne pas être prises en charge à long terme.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "En BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Pour rendre vos étiquettes cohérentes et disponibles sur différents dispositifs, connectez-vous au fournisseur de services de stockage cloud.", "TR_TO_SATOSHIS": "En sats", - "TR_TRADE_BUYS": "achète", - "TR_TRADE_EXCHANGES": "échange", "TR_TRADE_REDIRECTING": "Redirection...", - "TR_TRADE_SELLS": "vend", "TR_TRANSACTIONS_NOT_AVAILABLE": "L’historique des transactions n’est pas disponible", "TR_TRANSACTIONS_SEARCH_TIP_1": "Astuce : vous pouvez rechercher des ID de transaction, des adresses, des jetons, des étiquettes, des montants et des dates.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Astuce : combinez les opérateurs AND (&) et OR (|) pour des recherches plus complexes. Par exemple, > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 afficheront toutes les transactions effectuées en janvier ou décembre {lastYear}.", diff --git a/packages/suite-data/files/translations/hu.json b/packages/suite-data/files/translations/hu.json index f51ddee3dd3..d1e23b3fac7 100644 --- a/packages/suite-data/files/translations/hu.json +++ b/packages/suite-data/files/translations/hu.json @@ -437,7 +437,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor Összeg", "TR_CHAINED_TXS": "Kapcsolt tranzakciók", "TR_CHANGELOG": "Változások naplója", - "TR_CHANGELOG_ON_GITHUB": "Változások naplója a GitHub-on", "TR_CHANGE_ADDRESS_TOOLTIP": "Ez egy korábbi küldésnél létrehozott visszajáró-cím.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "A firmware típusa bármikor megváltoztatható a Beállításokban.", "TR_CHANGE_HOMESCREEN": "Kezdőképernyő módosítása", @@ -970,8 +969,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Részletek megtekintése", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Automatikus Trezor Suite frissítések", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "A Trezor Suite automatikusan letölti a legújabb verziót a háttérben, és az alkalmazás újraindításakor telepíti azt. Ez biztosítja, hogy mindig naprakész legyél a legújabb funkciókkal és biztonsági javításokkal. A frissítések az engedélyed nélkül történnek.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Okoslánc", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "A BNB okoslánc engedélyezése korábbi belső tranzakciók nélkül.", "TR_EXPERIMENTAL_FEATURES": "Kísérleti funkciók", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Kísérleti funkciók", "TR_EXPERIMENTAL_FEATURES_WARNING": "Csak tapasztalt felhasználóknak. Használat saját felelősségre. Ezek a funkciók tesztelés alatt állnak, instabilak lehetnek, és nem biztos, hogy hosszú távú támogatásban részesülnek.", @@ -1264,7 +1261,7 @@ "TR_NAV_SIGN_AND_VERIFY": "Aláír & Hitelesít", "TR_NAV_SIGN_VERIFY": "Üzenet aláírása és hitelesítése", "TR_NAV_SOON_BADGE": "Hamarosan", - "TR_NAV_STAKING": "Letétbe helyezés", + "TR_NAV_STAKING": "Stake-elés", "TR_NAV_TOKENS": "Tokenek", "TR_NAV_TRADE": "Kereskedés", "TR_NAV_TRANSACTIONS": "Áttekintés", @@ -1724,7 +1721,7 @@ "TR_STAKE_STAKED_ETH_AMOUNT_LOCKED": "A(z) {symbol} stake-elt összege zárolva van és nem lehet kereskedni, vagy elküldeni.", "TR_STAKE_STAKE_MORE": "Több stake-elése", "TR_STAKE_STAKING_IN_A_NUTSHELL": "Stake-elés dióhéjban", - "TR_STAKE_STAKING_IS": "A stake-elés olyan, mint egy baráti gesztus, amikor ideiglenesen zárolod az Ethereum-jaid, hogy támogasd a blokklánc működését. Cserébe jutalomként {symbol} -t fogsz keresni!", + "TR_STAKE_STAKING_IS": "A stake-elés során ideiglenesen zárolod az Ethereum-jaid, hogy támogasd a blokklánc működését. Cserébe jutalomként {symbol} -t fogsz keresni!", "TR_STAKE_START_STAKING": "Stake-elés megkezdése", "TR_STAKE_TIME_TO_CLAIM": "Idő az igénylésre", "TR_STAKE_TOTAL_PENDING": "Teljes stake függőben:", @@ -1742,7 +1739,7 @@ "TR_STAKING_DEPOSIT_FEE_DECRIPTION": "A letéti díj {feeAmount} ADA, amely a címed stake-eléshez való regisztrációjához szükséges. Amikor úgy döntesz, hogy a Cardano stake-et feloldod, a letéti díjat visszakapod.", "TR_STAKING_FEE": "Tranzakciós díj", "TR_STAKING_INSTANTLY_STAKED": "Azonnal stake-elve lett {amount} {symbol}. {days, plural, =0 {} one {A maradék {symbol} # napon belül stake-elve lesz.} other {A maradék {symbol} # napon belül stake-elve lesz.}}", - "TR_STAKING_IS_NOT_SUPPORTED": "A letétbe helyezés ezen a hálózaton nem támogatott.", + "TR_STAKING_IS_NOT_SUPPORTED": "A stake-elés ezen a hálózaton nem támogatott.", "TR_STAKING_NOT_ENOUGH_FUNDS": "Nincs elég pénzeszköz a számlán.", "TR_STAKING_ON_3RD_PARTY_DESCRIPTION": "A Trezor stake pooljában való stake-eléssel közvetlenül támogatod a Trezort és a Cardano ökoszisztémát a Trezor Suite-ból.", "TR_STAKING_ON_3RD_PARTY_TITLE": "Egy harmadik fél stake pooljára delegálsz", @@ -1861,10 +1858,7 @@ "TR_TO_BTC": "BTC-ben", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Annak érdekében, hogy a címkék állandóak és elérhetőek legyenek különböző eszközökön, csatlakozz egy felhőalapú tárhelyszolgáltatóhoz.", "TR_TO_SATOSHIS": "sat-ban", - "TR_TRADE_BUYS": "vásárlás", - "TR_TRADE_EXCHANGES": "átváltás", "TR_TRADE_REDIRECTING": "Átirányítás...", - "TR_TRADE_SELLS": "eladás", "TR_TRANSACTIONS_NOT_AVAILABLE": "Tranzakciós történek nem érhető el", "TR_TRANSACTIONS_SEARCH_TIP_1": "Tipp: Kereshetsz tranzakció azonosítókat, címeket, címkéket, összegeket és dátumokat.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Tipp: Kombinálhatod az ÉS (&) és a VAGY (|) operátorokat bonyolultabb keresésekhez. Például 2022-01-01 & < 2022-01-31 | > 2022-12-01 & < 2022-12-31 kulcsszó minden 2022 januári és 2022 decemberi tranzakciót eredményül hoz.", diff --git a/packages/suite-data/files/translations/it.json b/packages/suite-data/files/translations/it.json index f18bd5e1f1e..7d460c7c781 100644 --- a/packages/suite-data/files/translations/it.json +++ b/packages/suite-data/files/translations/it.json @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Importo Trezor", "TR_CHAINED_TXS": "Transazioni concatenate", "TR_CHANGELOG": "Changelog", - "TR_CHANGELOG_ON_GITHUB": "Changelog su GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Questo è un indirizzo modificato creato da un invio precedente.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Puoi modificare il tipo di firmware nelle impostazioni in qualsiasi momento.", "TR_CHANGE_HOMESCREEN": "Modifica homescreen", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Visualizza dettagli", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Aggiornamenti automatici di Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite scarica automaticamente l'ultima versione in background e la installa al riavvio dell'applicazione. In questo modo si garantisce che le funzionalità e i patch di sicurezza siano sempre aggiornati. Gli aggiornamenti vengono installati senza richiedere l'autorizzazione dell'utente.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "Smart Chain BNB", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Abilita il network BNB Smart Chain ma senza la cronologia dei dati delle transazioni interne.", "TR_EXPERIMENTAL_FEATURES": "Sperimentale", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Funzionalità sperimentali", "TR_EXPERIMENTAL_FEATURES_WARNING": "Solo per utenti esperti. L'utilizzo del presente servizio avviene a proprio rischio e pericolo. Queste funzioni sono in fase di test. Di conseguenza potrebbero risultare instabili e non essere supportate a lungo termine.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "A BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Per rendere le etichette compatibili e disponibili su diversi dispositivi, effettua la connessione a un provider di archiviazione nel cloud.", "TR_TO_SATOSHIS": "A sat", - "TR_TRADE_BUYS": "acquisti", - "TR_TRADE_EXCHANGES": "exchange", "TR_TRADE_REDIRECTING": "Reindirizzamento in corso...", - "TR_TRADE_SELLS": "vendite", "TR_TRANSACTIONS_NOT_AVAILABLE": "Cronologia transazioni non disponibile", "TR_TRANSACTIONS_SEARCH_TIP_1": "Suggerimento: puoi cercare le transazioni per ID, indirizzi, token, etichette, importi e date.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Suggerimento: per eseguire ricerche più complesse, combina gli operatori AND (&) e OR (|). Ad esempio, utilizzando > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 verranno visualizzate tutte le transazioni di gennaio o dicembre {lastYear}.", diff --git a/packages/suite-data/files/translations/ja.json b/packages/suite-data/files/translations/ja.json index 6cb38a78e9b..8a9d2c9bb79 100644 --- a/packages/suite-data/files/translations/ja.json +++ b/packages/suite-data/files/translations/ja.json @@ -297,6 +297,8 @@ "TR_ALLOW_ANALYTICS_DESCRIPTION": "すべてのデータは厳密に匿名のままです。Trezorエコシステムを改善するためにのみ使されます。", "TR_ALLOW_AUTOMATIC_SUITE_UPDATES": "Trezor Suiteの自動アップデート", "TR_ALLOW_AUTOMATIC_SUITE_UPDATES_DESCRIPTION": "Trezor Suiteはバックグラウンドで最新バージョンを自動的にダウンロードし、アプリの再起動時にインストールします。 これにより、最新の機能とセキュリティパッチで常に最新の状態に保つことができます。アップデートは許可を必要とせずに行われます。", + "TR_ALL_NETWORKS": "全ネットワーク ({networkCount})", + "TR_ALL_NETWORKS_TOOLTIP": "全部で {networkCount} のネットワークからトークンを表示します。上位ネットワークでフィルタリングするには、右側のボタンを使用します。", "TR_ALL_TRANSACTIONS": "取引", "TR_AMOUNT_SENT": "送金額", "TR_AMOUNT_TOO_BIG_FOR_COINJOIN": "Coinjoin の利用は不適当です ー 金額が多すぎます", @@ -438,7 +440,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezorの金額", "TR_CHAINED_TXS": "連鎖取引", "TR_CHANGELOG": "変更履歴", - "TR_CHANGELOG_ON_GITHUB": "GitHubの変更履歴", "TR_CHANGE_ADDRESS_TOOLTIP": "これは以前の送金取引におけるお釣りのアドレスです。", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "ファームウェアの種類はいつでも設定で変更できます。", "TR_CHANGE_HOMESCREEN": "ホーム画面を変更", @@ -652,7 +653,7 @@ "TR_CONNECT_DEVICE_SEND_PROMO_TITLE": "Trezorが接続されていません", "TR_CONNECT_TREZOR_TO_SEND_BUTTON": "送信するにはTrezorを接続してください", "TR_CONNECT_YOUR_DEVICE": "Trezorを接続してロックを解除する", - "TR_CONTACT_SUPPORT": "サポートに問い合わせる", + "TR_CONTACT_SUPPORT": "Trezorサポートに問い合わせ", "TR_CONTACT_TREZOR_SUPPORT": "Trezorサポートに連絡する", "TR_CONTINUE": "続ける", "TR_CONTINUE_ANYWAY": "とにかく続行する", @@ -988,8 +989,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "詳細を表示", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Trezor Suiteの自動アップデート", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suiteはバックグラウンドで最新バージョンを自動的にダウンロードし、アプリの再起動時にインストールします。 これにより、最新の機能とセキュリティパッチで常に最新の状態に保つことができます。アップデートは許可を必要とせずに行われます。", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNBスマートチェーン", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "BNBスマートチェーンのネットワークを有効にしまが、内部取引の履歴はありません。", "TR_EXPERIMENTAL_FEATURES": "実験的な機能", "TR_EXPERIMENTAL_FEATURES_ALLOW": "実験的な機能", "TR_EXPERIMENTAL_FEATURES_WARNING": "上級者向けです。自己責任で使用してください。これらの機能はテスト中であり、不安定な場合があり、長期的なサポートがない可能性があります。", @@ -1091,7 +1090,7 @@ "TR_GUIDE_FORUM": "Trezor フォーラム", "TR_GUIDE_FORUM_LABEL": "Trezorコミュニティと繋がる", "TR_GUIDE_SUGGESTION_LABEL": "このアプリはいかがですか?", - "TR_GUIDE_SUPPORT": "サポートに問い合わせる", + "TR_GUIDE_SUPPORT": "Trezorサポートに問い合わせ", "TR_GUIDE_SUPPORT_AND_FEEDBACK": "サポートとフィードバック", "TR_GUIDE_VIEW_HEADLINES_SUPPORT_FEEDBACK_SELECTION": "サポートとフィードバック", "TR_GUIDE_VIEW_HEADLINE_HELP_US_IMPROVE": "改善にご協力ください", @@ -1223,7 +1222,7 @@ "TR_LOCAL_FILE_SYSTEM": "ローカルファイル システム", "TR_LOG": "アプリケーションのログ", "TR_LOGIN_PROCEED": "続行する", - "TR_LOG_DESCRIPTION": "ログには、Trezor Suite に関するすべての必要な技術情報が含まれています。Trezorサポートにコンタクトする際に必要となる場合があります。", + "TR_LOG_DESCRIPTION": "このログには、Trezor Suite に関する重要な技術情報が含まれており、Trezor サポートに連絡する際に必要となる場合があります。", "TR_LOOKING_FOR_COINJOIN_ROUND": "ラウンドを待っています", "TR_LOW_ANONYMITY_WARNING": "匿名性が低すぎます。 1 in 5 未満は匿名とはいえないので、それ以上を推奨します。", "TR_LTC_ADDRESS_INFO": "Litecoinはアドレスのフォーマットを変更しました。私たちのブログであなたのアドレスを変換する方法についての詳細をご覧ください。 {TR_LEARN_MORE}", @@ -1348,7 +1347,7 @@ "TR_NO_PASSPHRASE_WALLET": "標準ウォレット", "TR_NO_SEARCH_RESULTS": "検索条件に該当する結果はありません", "TR_NO_SPENDABLE_UTXOS": "あなたのアカウントには、使用可能なUTXOがありません。", - "TR_NO_TRANSPORT": "ブラウザがデバイスと通信できません", + "TR_NO_TRANSPORT": "お使いのブラウザはデバイスと通信できません", "TR_NO_TRANSPORT_DESKTOP": "アプリがデバイスと通信できません", "TR_NUM_ACCOUNTS_FIAT_VALUE": "{accountsCount} アカウント: {fiatValue}", "TR_N_MIN": "{n} 分", @@ -1558,9 +1557,11 @@ "TR_SELECTED": "{amount} を選択済", "TR_SELECT_COIN_FOR_SETTINGS": "設定を変更するコインを選択", "TR_SELECT_DEVICE": "デバイスを選択", + "TR_SELECT_NAME_OR_ADDRESS": "名前、シンボル、ネットワークまたはコントラクトアドレスで検索", "TR_SELECT_NUMBER_OF_WORDS": "ウォレットのバックアップの単語数を選択してください", "TR_SELECT_PASSPHRASE_SOURCE": "\"{deviceLabel}\" のパスフレーズを入力する場所を選択します。", "TR_SELECT_RECOVERY_METHOD": "復元方法を選択", + "TR_SELECT_TOKEN": "トークンを選択", "TR_SELECT_TREZOR": "Trezorを選択", "TR_SELECT_TREZOR_TO_CONTINUE": "続けるにはTrezorを選択してください。", "TR_SELECT_TYPE": "タイプを選択", @@ -1591,7 +1592,7 @@ "TR_SELL_MODAL_FOR_YOUR_SAFETY": "{provider} で {cryptocurrency} を売却する", "TR_SELL_MODAL_LEGAL_HEADER": "法的通知", "TR_SELL_MODAL_SECURITY_HEADER": "Trezorでセキュリティを確保", - "TR_SELL_MODAL_TERMS_1": "あなたは仮想通貨を売却するためにここにいます。他の理由でこのサイトに誘導された場合は、続行する前にサポートにお問い合わせください。", + "TR_SELL_MODAL_TERMS_1": "あなたは仮想通貨を売却するためにここにいます。他の理由でこのサイトに誘導された場合は、続行する前にTrezorのサポートに問い合わせてください。", "TR_SELL_MODAL_TERMS_2": "あなたは自分のアカウントのために仮想通貨を売却しています。プロバイダのポリシーにより本人確認が必要な場合があることを認めます。", "TR_SELL_MODAL_TERMS_3": "仮想通貨取引は元に戻すことができず、返金できない場合があることを理解してください。 ですから、不正または偶発的な損失は回復できない場合があります。", "TR_SELL_MODAL_TERMS_4": "Invityがこのサービスを提供していないことを理解してください。 {provider} の規約がサービスに適用されます。", @@ -1794,6 +1795,7 @@ "TR_START_COINJOIN": "Coinjoinを開始", "TR_START_RECOVERY": "復元を開始", "TR_STEP": "ステップ {number}", + "TR_STEP_OF_TOTAL": "ステップ {index} / {total}", "TR_STILL_DONT_SEE_YOUR_TREZOR": "まだTrezorが表示されていませんか?", "TR_STOP": "停止", "TR_STOPPING": "停止中", @@ -1845,7 +1847,11 @@ "TR_TOKENS_EMPTY": "まだトークンがありません...", "TR_TOKENS_EMPTY_CHECK_HIDDEN": "トークンはありません。トークンは隠されている可能性があります。", "TR_TOKENS_SEARCH_TOOLTIP": "トークン、シンボルまたはコントラクトアドレスで検索します。", + "TR_TOKEN_NOT_FOUND": "トークンが見つかりません", + "TR_TOKEN_NOT_FOUND_ON_NETWORK": "{networkName} ネットワーク上にトークンが見つかりません", "TR_TOKEN_TRANSFERS": "{standard} トークン転送", + "TR_TOKEN_TRY_DIFFERENT_SEARCH": "別の検索を試してください。", + "TR_TOKEN_TRY_DIFFERENT_SEARCH_OR_SWITCH": "別の検索を試すか、別のネットワークに切り替えてください。", "TR_TOKEN_UNRECOGNIZED_BY_TREZOR": "認識できないトークン", "TR_TOKEN_UNRECOGNIZED_BY_TREZOR_TOOLTIP": "認識できないトークンは潜在的なリスクをもたらす可能性があります。注意してください。", "TR_TOO_LONG": "メッセージが長すぎます", @@ -1889,10 +1895,7 @@ "TR_TO_BTC": "BTCに", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "ラベルを永続化し、異なるデバイスで利用できるようにするには、クラウドストレージプロバイダに接続します。", "TR_TO_SATOSHIS": "satsに", - "TR_TRADE_BUYS": "購入", - "TR_TRADE_EXCHANGES": "取引所", "TR_TRADE_REDIRECTING": "リダイレクト中...", - "TR_TRADE_SELLS": "売却", "TR_TRANSACTIONS_NOT_AVAILABLE": "取引履歴が利用できません", "TR_TRANSACTIONS_SEARCH_TIP_1": "ヒント: 取引ID、アドレス、トークン、ラベル、金額、日付を検索できます。", "TR_TRANSACTIONS_SEARCH_TIP_10": "ヒント: AND (&) と OR (|) 演算子を組み合わせることで、より複雑な検索を行うことができます。 例えば、 > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 は{lastYear}年1月または{lastYear}年12月のすべての取引を表示します。", @@ -1914,17 +1917,17 @@ "TR_TROUBLESHOOTING_CLOSE_TABS": "Trezorを使用している可能性のある他のタブやウィンドウを閉じる", "TR_TROUBLESHOOTING_CLOSE_TABS_DESCRIPTION": "他のタブやウィンドウを閉じたら、このページをリフレッシュしてみてください。", "TR_TROUBLESHOOTING_CLOSE_TABS_DESCRIPTION_DESKTOP": "他のブラウザのタブとウィンドウを閉じた後、Trezor Suiteを終了して再度開いてみてください。", - "TR_TROUBLESHOOTING_DEVICE_NOT_DETECTED": "通信を可能にするために必要なステップ", + "TR_TROUBLESHOOTING_DEVICE_NOT_DETECTED": "この問題を解決するには、以下の手順を試しください。", "TR_TROUBLESHOOTING_TIP_BRIDGE_STATUS_DESCRIPTION": "Trezor Bridgeのステータスページ を確認してください", "TR_TROUBLESHOOTING_TIP_BRIDGE_STATUS_TITLE": "Trezor Bridgeのプロセスが起動していることを確認してください", - "TR_TROUBLESHOOTING_TIP_BROWSER_WEBUSB_DESCRIPTION": "現在、クロームベースのブラウザだけがUSBデバイスとの直接通信を許可しています", + "TR_TROUBLESHOOTING_TIP_BROWSER_WEBUSB_DESCRIPTION": "現在、クロームベースのブラウザだけがUSBデバイスとの直接通信を許可しています。", "TR_TROUBLESHOOTING_TIP_BROWSER_WEBUSB_TITLE": "クロームベースのブラウザを使用してください", "TR_TROUBLESHOOTING_TIP_CABLE_DESCRIPTION": "ケーブルは完全に挿入する必要があります。 USB-Cで接続するデバイスの場合、ケーブルは適切に \"クリック\" する必要があります。", "TR_TROUBLESHOOTING_TIP_CABLE_TITLE": "別のケーブルをお試しください", "TR_TROUBLESHOOTING_TIP_COMPUTER_DESCRIPTION": "Trezor Bridgeがインストールされている必要があります。", "TR_TROUBLESHOOTING_TIP_COMPUTER_TITLE": "可能であれば、別のコンピュータを使用してみてください", - "TR_TROUBLESHOOTING_TIP_RESTART_COMPUTER_DESCRIPTION": "念のために", - "TR_TROUBLESHOOTING_TIP_RESTART_COMPUTER_TITLE": "コンピューターを再起動してみてください", + "TR_TROUBLESHOOTING_TIP_RESTART_COMPUTER_DESCRIPTION": "コンピュータを再起動すると、ブラウザとデバイス間の通信の問題が解決する場合があります。", + "TR_TROUBLESHOOTING_TIP_RESTART_COMPUTER_TITLE": "コンピューターを再起動してください", "TR_TROUBLESHOOTING_TIP_SUITE_DESKTOP_DESCRIPTION": "Trezor Suite デスクトップアプリを実行", "TR_TROUBLESHOOTING_TIP_SUITE_DESKTOP_TITLE": "Trezor Suiteデスクトップアプリを使用する", "TR_TROUBLESHOOTING_TIP_UDEV_INSTALL_DESCRIPTION": "udev rulesをインストールしてみてください。開く前にそれらをデスクトップに保存してください。", @@ -1986,7 +1989,7 @@ "TR_UPDATE_MODAL_START_DOWNLOAD": "ダウンロード", "TR_UPDATE_MODAL_UPDATE_DOWNLOADED": "アップデートをダウンロードしました", "TR_UPDATE_MODAL_UPDATE_ON_QUIT": "終了時に更新する", - "TR_UPGRADE_FIRMWARE_TO_DISCOVER_ACCOUNT_ERROR": "このアカウントを見つけるには、ファームウェアをアップグレードしてください。(上の青いバナーを参照してください)", + "TR_UPGRADE_FIRMWARE_TO_DISCOVER_ACCOUNT_ERROR": "このアカウントにアクセスするにはファームウェアをアップグレードしてください。上の青いバナーを参照してください。", "TR_UP_TO": "最大", "TR_UP_TO_DATE": "最新です", "TR_UP_TO_DAYS": "最大 {count, plural, other {# 日}}", diff --git a/packages/suite-data/files/translations/lol.json b/packages/suite-data/files/translations/lol.json index 8d45f5c2a6c..9836b8546e5 100644 --- a/packages/suite-data/files/translations/lol.json +++ b/packages/suite-data/files/translations/lol.json @@ -440,7 +440,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "crwdns28930:0crwdne28930:0", "TR_CHAINED_TXS": "crwdns23083:0crwdne23083:0", "TR_CHANGELOG": "crwdns23087:0crwdne23087:0", - "TR_CHANGELOG_ON_GITHUB": "crwdns23089:0crwdne23089:0", "TR_CHANGE_ADDRESS_TOOLTIP": "crwdns32344:0crwdne32344:0", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "crwdns29092:0crwdne29092:0", "TR_CHANGE_HOMESCREEN": "crwdns23091:0crwdne23091:0", @@ -600,6 +599,7 @@ "TR_COINMARKET_SWAP_MODAL_VERIFIED_PARTNERS_HEADER": "crwdns36604:0crwdne36604:0", "TR_COINMARKET_TOKEN_NETWORK": "crwdns36102:0{tokenName}crwdnd36102:0{networkName}crwdne36102:0", "TR_COINMARKET_TRADE_FEE": "crwdns36104:0crwdne36104:0", + "TR_COINMARKET_TRANSACTION_COUNTER": "crwdns36682:0{totalBuys}crwdnd36682:0{totalSells}crwdnd36682:0{totalSwaps}crwdne36682:0", "TR_COINMARKET_UNKNOWN_PROVIDER": "crwdns36162:0crwdne36162:0", "TR_COINMARKET_YOUR_BEST_OFFER": "crwdns36106:0crwdne36106:0", "TR_COINMARKET_YOU_BUY": "crwdns36108:0crwdne36108:0", @@ -708,6 +708,7 @@ "TR_DASHBOARD_ASSET_FAILED": "crwdns23261:0crwdne23261:0", "TR_DASHBOARD_DISCOVERY_ERROR": "crwdns23263:0crwdne23263:0", "TR_DASHBOARD_DISCOVERY_ERROR_PARTIAL_DESC": "crwdns23267:0{details}crwdne23267:0", + "TR_DATA": "crwdns36684:0crwdne36684:0", "TR_DATABASE_UPGRADE_BLOCKED": "crwdns23271:0crwdne23271:0", "TR_DATA_ANALYTICS_CATEGORY_1": "crwdns23273:0crwdne23273:0", "TR_DATA_ANALYTICS_CATEGORY_1_ITEM_1": "crwdns23275:0crwdne23275:0", @@ -763,6 +764,10 @@ "TR_DEVICE_CONNECTED_BOOTLOADER_RECONNECT_IN_NORMAL_NO_TOUCH": "crwdns28621:0crwdne28621:0", "TR_DEVICE_CONNECTED_WRONG_STATE": "crwdns23305:0crwdne23305:0", "TR_DEVICE_DISCONNECTED_DURING_ACTION_DESCRIPTION": "crwdns23309:0crwdne23309:0", + "TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED": "crwdns36686:0crwdne36686:0", + "TR_DEVICE_FIRMWARE_HASH_CHECK_HASH_MISMATCH": "crwdns36688:0crwdne36688:0", + "TR_DEVICE_FIRMWARE_HASH_CHECK_OTHER_ERROR": "crwdns36690:0crwdne36690:0", + "TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE": "crwdns36692:0crwdne36692:0", "TR_DEVICE_FIRMWARE_REVISION_CHECK_BUTTON": "crwdns36122:0crwdne36122:0", "TR_DEVICE_FIRMWARE_REVISION_CHECK_BUTTON_DISABLED": "crwdns36124:0crwdne36124:0", "TR_DEVICE_FIRMWARE_REVISION_CHECK_DESCRIPTION": "crwdns36126:0crwdne36126:0", @@ -990,11 +995,11 @@ "TR_EXCHANGE_VIEW_DETAILS": "crwdns23649:0crwdne23649:0", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "crwdns36478:0crwdne36478:0", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "crwdns36480:0crwdne36480:0", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "crwdns36148:0crwdne36148:0", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "crwdns36150:0crwdne36150:0", "TR_EXPERIMENTAL_FEATURES": "crwdns28675:0crwdne28675:0", "TR_EXPERIMENTAL_FEATURES_ALLOW": "crwdns35842:0crwdne35842:0", "TR_EXPERIMENTAL_FEATURES_WARNING": "crwdns35846:0crwdne35846:0", + "TR_EXPERIMENTAL_OP_ETHEREUM": "crwdns36694:0crwdne36694:0", + "TR_EXPERIMENTAL_OP_ETHEREUM_DESCRIPTION": "crwdns36696:0crwdne36696:0", "TR_EXPERIMENTAL_PASSWORD_MANAGER": "crwdns35848:0crwdne35848:0", "TR_EXPERIMENTAL_PASSWORD_MANAGER_DESCRIPTION": "crwdns35850:0crwdne35850:0", "TR_EXPERIMENTAL_TOR_SNOWFLAKE": "crwdns36014:0crwdne36014:0", @@ -1318,6 +1323,7 @@ "TR_NETWORK_LITECOIN": "crwdns24119:0crwdne24119:0", "TR_NETWORK_NAMECOIN": "crwdns24121:0crwdne24121:0", "TR_NETWORK_NEM": "crwdns24123:0crwdne24123:0", + "TR_NETWORK_OP": "crwdns36698:0crwdne36698:0", "TR_NETWORK_POLYGON": "crwdns35268:0crwdne35268:0", "TR_NETWORK_SOLANA_DEVNET": "crwdns35174:0crwdne35174:0", "TR_NETWORK_SOLANA_MAINNET": "crwdns35176:0crwdne35176:0", @@ -1483,8 +1489,16 @@ "TR_QUICK_ACTION_TOOLTIP_TREZOR_SUITE": "crwdns36534:0crwdne36534:0", "TR_QUICK_ACTION_TOOLTIP_UPDATE_AVAILABLE": "crwdns36536:0{newVersion}crwdne36536:0", "TR_QUICK_ACTION_TOOLTIP_UP_TO_DATE": "crwdns36538:0{currentVersion}crwdne36538:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_APP_DOWNLOADED": "crwdns36700:0crwdne36700:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_APP_HAS_BEEN_UPDATED": "crwdns36702:0crwdne36702:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_APP_UPDATE_AVAILABLE": "crwdns36704:0crwdne36704:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_RESTART_AND_UPDATE": "crwdns36706:0crwdne36706:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE": "crwdns36708:0crwdne36708:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_TREZOR_UPDATE_AVAILABLE": "crwdns36710:0crwdne36710:0", + "TR_QUICK_ACTION_UPDATE_POPOVER_WHATS_NEW": "crwdns36712:0crwdne36712:0", "TR_RANDOM_SEED_WORDS_DISCLAIMER": "crwdns24395:0crwdne24395:0", "TR_RANGE": "crwdns24397:0crwdne24397:0", + "TR_READ_ALL_ON_GITHUB": "crwdns36714:0crwdne36714:0", "TR_READ_AND_UNDERSTOOD": "crwdns33446:0crwdne33446:0", "TR_REBOOT_INTO_BOOTLOADER": "crwdns24411:0crwdne24411:0", "TR_RECEIVE": "crwdns24413:0crwdne24413:0", @@ -1676,7 +1690,9 @@ "TR_SIZE": "crwdns24735:0crwdne24735:0", "TR_SKIP": "crwdns24737:0crwdne24737:0", "TR_SKIP_BACKUP": "crwdns24741:0crwdne24741:0", + "TR_SKIP_BACKUP_DESCRIPTION": "crwdns36716:0crwdne36716:0", "TR_SKIP_PIN": "crwdns24749:0crwdne24749:0", + "TR_SKIP_PIN_DESCRIPTION": "crwdns36718:0crwdne36718:0", "TR_SKIP_ROUNDS": "crwdns32536:0crwdne32536:0", "TR_SKIP_ROUNDS_DESCRIPTION": "crwdns32538:0crwdne32538:0", "TR_SKIP_ROUNDS_HEADING": "crwdns32540:0crwdne32540:0", @@ -1798,7 +1814,7 @@ "TR_START_COINJOIN": "crwdns32953:0crwdne32953:0", "TR_START_RECOVERY": "crwdns24795:0crwdne24795:0", "TR_STEP": "crwdns32955:0{number}crwdne32955:0", - "TR_STEP_OF_TOTAL": "crwdns36672:0{index}crwdnd36672:0{total}crwdne36672:0", + "TR_STEP_OF_TOTAL": "crwdns36672:0crwdne36672:0", "TR_STILL_DONT_SEE_YOUR_TREZOR": "crwdns24801:0crwdne24801:0", "TR_STOP": "crwdns33249:0crwdne33249:0", "TR_STOPPING": "crwdns33267:0crwdne33267:0", @@ -1898,10 +1914,7 @@ "TR_TO_BTC": "crwdns29088:0crwdne29088:0", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "crwdns24975:0crwdne24975:0", "TR_TO_SATOSHIS": "crwdns29090:0crwdne29090:0", - "TR_TRADE_BUYS": "crwdns24979:0crwdne24979:0", - "TR_TRADE_EXCHANGES": "crwdns24981:0crwdne24981:0", "TR_TRADE_REDIRECTING": "crwdns24985:0crwdne24985:0", - "TR_TRADE_SELLS": "crwdns24989:0crwdne24989:0", "TR_TRANSACTIONS_NOT_AVAILABLE": "crwdns24995:0crwdne24995:0", "TR_TRANSACTIONS_SEARCH_TIP_1": "crwdns24997:0crwdne24997:0", "TR_TRANSACTIONS_SEARCH_TIP_10": "crwdns24999:0{lastYear}crwdnd24999:0{lastYear}crwdnd24999:0{lastYear}crwdnd24999:0{lastYear}crwdnd24999:0{lastYear}crwdne24999:0", @@ -1949,6 +1962,11 @@ "TR_TX_CONFIRMATIONS": "crwdns25081:0{confirmationsCount}crwdne25081:0", "TR_TX_CONFIRMED": "crwdns35430:0crwdne35430:0", "TR_TX_CONFIRMING": "crwdns35446:0crwdne35446:0", + "TR_TX_DATA_FUNCTION": "crwdns36720:0crwdne36720:0", + "TR_TX_DATA_INPUT_DATA": "crwdns36722:0crwdne36722:0", + "TR_TX_DATA_METHOD": "crwdns36724:0crwdne36724:0", + "TR_TX_DATA_METHOD_NAME": "crwdns36726:0crwdne36726:0", + "TR_TX_DATA_PARAMS": "crwdns36728:0crwdne36728:0", "TR_TX_DEPOSIT": "crwdns29068:0crwdne29068:0", "TR_TX_FEE": "crwdns25085:0crwdne25085:0", "TR_TX_TAB_AMOUNT": "crwdns25089:0crwdne25089:0", @@ -1988,6 +2006,8 @@ "TR_UPDATE_FIRMWARE_HOMESCREEN_LATER_TOOLTIP": "crwdns33191:0crwdne33191:0", "TR_UPDATE_FIRMWARE_HOMESCREEN_TOOLTIP": "crwdns33167:0crwdne33167:0", "TR_UPDATE_MODAL_AVAILABLE_HEADING": "crwdns25133:0crwdne25133:0", + "TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES": "crwdns36730:0crwdne36730:0", + "TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES_NEW_TAG": "crwdns36732:0crwdne36732:0", "TR_UPDATE_MODAL_INSTALL_AND_RESTART": "crwdns25137:0crwdne25137:0", "TR_UPDATE_MODAL_INSTALL_NOW_OR_LATER": "crwdns25141:0crwdne25141:0", "TR_UPDATE_MODAL_NOT_NOW": "crwdns28445:0crwdne28445:0", @@ -1995,6 +2015,8 @@ "TR_UPDATE_MODAL_START_DOWNLOAD": "crwdns25147:0crwdne25147:0", "TR_UPDATE_MODAL_UPDATE_DOWNLOADED": "crwdns25149:0crwdne25149:0", "TR_UPDATE_MODAL_UPDATE_ON_QUIT": "crwdns32316:0crwdne32316:0", + "TR_UPDATE_MODAL_WHATS_NEW": "crwdns36734:0crwdne36734:0", + "TR_UPDATE_MODAL_YOUR_VERSION": "crwdns36736:0{version}crwdne36736:0", "TR_UPGRADE_FIRMWARE_TO_DISCOVER_ACCOUNT_ERROR": "crwdns36662:0crwdne36662:0", "TR_UP_TO": "crwdns35432:0crwdne35432:0", "TR_UP_TO_DATE": "crwdns25153:0crwdne25153:0", @@ -2049,6 +2071,7 @@ "TR_WALLET_SELECTION_ACCESS_HIDDEN_WALLET": "crwdns25205:0crwdne25205:0", "TR_WALLET_SELECTION_HIDDEN_WALLET": "crwdns25209:0crwdne25209:0", "TR_WELCOME_TO_TREZOR_TEXT_WALLET_CREATION": "crwdns25221:0crwdne25221:0", + "TR_WERE_CONSTANTLY_WORKING_TO_IMPROVE": "crwdns36738:0crwdne36738:0", "TR_WEST": "crwdns25223:0crwdne25223:0", "TR_WHAT_DATA_WE_COLLECT": "crwdns25229:0crwdne25229:0", "TR_WHAT_IS_PASSPHRASE": "crwdns25233:0crwdne25233:0", diff --git a/packages/suite-data/files/translations/nl.json b/packages/suite-data/files/translations/nl.json index 6a0dca0d88a..0f3347a398d 100644 --- a/packages/suite-data/files/translations/nl.json +++ b/packages/suite-data/files/translations/nl.json @@ -380,7 +380,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor-bedrag", "TR_CHAINED_TXS": "Ketting transacties", "TR_CHANGELOG": "Log van wijzigingen", - "TR_CHANGELOG_ON_GITHUB": "Overzicht aanpassingen op GitHub", "TR_CHANGE_HOMESCREEN": "Overzicht-scherm wijzigen", "TR_CHANGE_PIN": "Wijzigen", "TR_CHANGE_WIPE_CODE": "Wijzig wiscode", @@ -891,7 +890,6 @@ "TR_TOR_DISABLE": "Schakel Tor uit", "TR_TO_BTC": "Naar BTC", "TR_TO_SATOSHIS": "Naar sat", - "TR_TRADE_EXCHANGES": "exchanges", "TR_TRANSACTION_DETAILS": "Details", "TR_TROUBLESHOOTING_TIP_CABLE_TITLE": "Probeer een andere kabel", "TR_TROUBLESHOOTING_TIP_COMPUTER_DESCRIPTION": "Met Trezor Bridge geïnstalleerd.", diff --git a/packages/suite-data/files/translations/pt.json b/packages/suite-data/files/translations/pt.json index 25983d0c572..dab2d4f521c 100644 --- a/packages/suite-data/files/translations/pt.json +++ b/packages/suite-data/files/translations/pt.json @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Valor na Trezor", "TR_CHAINED_TXS": "Transações em chain", "TR_CHANGELOG": "Changelog", - "TR_CHANGELOG_ON_GITHUB": "Changelog no GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Este é um endereço de alteração criado a partir de um envio anterior.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Você pode alterar seu tipo de firmware em Configurações a qualquer momento.", "TR_CHANGE_HOMESCREEN": "Alterar tela inicial", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Ver detalhes", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Atualizações automáticas do Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "O Trezor Suite baixa automaticamente a nova versão em segundo plano e a instala ao reiniciar o aplicativo. Isso garante que você esteja sempre atualizado com os recursos e patches de segurança mais recentes. As atualizações são feitas sem exigir sua permissão.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Habilita a rede BNB Smart Chain, mas sem histórico de dados de transações internas.", "TR_EXPERIMENTAL_FEATURES": "Experimental", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Recursos experimentais", "TR_EXPERIMENTAL_FEATURES_WARNING": "Apenas para usuários experientes. Use por sua conta e risco. Estes recursos estão em teste, talvez estejam instáveis e podem não ter suporte a longo prazo.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "Para BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Para tornar seus rótulos persistentes e disponíveis em diferentes dispositivos, conecte-se ao provedor de armazenamento em nuvem.", "TR_TO_SATOSHIS": "Para sat", - "TR_TRADE_BUYS": "compras", - "TR_TRADE_EXCHANGES": "trocas", "TR_TRADE_REDIRECTING": "Redirecionando...", - "TR_TRADE_SELLS": "vendas", "TR_TRANSACTIONS_NOT_AVAILABLE": "Histórico de transações não disponível", "TR_TRANSACTIONS_SEARCH_TIP_1": "Dica: Você pode buscar IDs de transação, endereços, tokens, rótulos, valores e datas.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Dica: Você pode combinar operadores E (&) e OU (|) para pesquisas mais complexas. Por exemplo, > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 exibirá todas as transações em janeiro ou dezembro de {lastYear}.", diff --git a/packages/suite-data/files/translations/ro.json b/packages/suite-data/files/translations/ro.json index f83bf53b3ad..16eed84a069 100644 --- a/packages/suite-data/files/translations/ro.json +++ b/packages/suite-data/files/translations/ro.json @@ -336,7 +336,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Valoare Trezor", "TR_CHAINED_TXS": "Tranzacții înlănțuite", "TR_CHANGELOG": "Jurnal de modificări", - "TR_CHANGELOG_ON_GITHUB": "Jurnal de modificări pe GitHub", "TR_CHANGE_HOMESCREEN": "Schimbați ecranul de pornire", "TR_CHANGE_PIN": "Schimbare PIN", "TR_CHECK_FINGERPRINT": "Verificați amprenta digitală", diff --git a/packages/suite-data/files/translations/ru.json b/packages/suite-data/files/translations/ru.json index 788e875ba0e..08ac2c48809 100644 --- a/packages/suite-data/files/translations/ru.json +++ b/packages/suite-data/files/translations/ru.json @@ -409,7 +409,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Сумма Трезор", "TR_CHAINED_TXS": "Цепные транзакции", "TR_CHANGELOG": "Список изменений", - "TR_CHANGELOG_ON_GITHUB": "Список изменений на GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Этот адрес был создан как неизрасходованный остаток (\"change\") предыдущей транзакции.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Тип прошивки в любое время можно изменить в Настройках.", "TR_CHANGE_HOMESCREEN": "Поменять заставку", @@ -1475,10 +1474,7 @@ "TR_TO_BTC": "В BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Чтобы Ваши метки синхронизировались и были доступны на разных устройствах, подключитесь к сервису облачного хранилища.", "TR_TO_SATOSHIS": "В sat", - "TR_TRADE_BUYS": "покупки", - "TR_TRADE_EXCHANGES": "обмены", "TR_TRADE_REDIRECTING": "Перенаправление ...", - "TR_TRADE_SELLS": "продажи", "TR_TRANSACTIONS_NOT_AVAILABLE": "История транзакций недоступна", "TR_TRANSACTIONS_SEARCH_TIP_1": "Совет: Вы можете искать среди ID транзакций, адресов, меток, сумм и дат.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Совет: Для более сложного поиска можно комбинировать операторы AND (&) и OR (|). Например, >> 2020-01-01 & < 2020-01-31 | > 2020-12-01 & < 2020-12-31 покажет все транзакции за январь 2020 года или декабрь 2020 года.", diff --git a/packages/suite-data/files/translations/sk.json b/packages/suite-data/files/translations/sk.json index 4e556188d2c..2939ba96ec6 100644 --- a/packages/suite-data/files/translations/sk.json +++ b/packages/suite-data/files/translations/sk.json @@ -414,7 +414,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor amount", "TR_CHAINED_TXS": "Chained transactions", "TR_CHANGELOG": "Changelog", - "TR_CHANGELOG_ON_GITHUB": "Changelog on GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "This is a change address created from a previous send.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "You can change your firmware type in Settings anytime.", "TR_CHANGE_HOMESCREEN": "Change homescreen", @@ -1693,10 +1692,7 @@ "TR_TO_BTC": "To BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "To make your labels consistent and available on different devices, connect to a cloud storage provider.", "TR_TO_SATOSHIS": "To sats", - "TR_TRADE_BUYS": "buys", - "TR_TRADE_EXCHANGES": "exchanges", "TR_TRADE_REDIRECTING": "Presmerovanie ...", - "TR_TRADE_SELLS": "predáva", "TR_TRANSACTIONS_NOT_AVAILABLE": "História transakcií nie je k dispozícii", "TR_TRANSACTIONS_SEARCH_TIP_1": "Tip: Môžete vyhľadávať ID transakcií, adresy, štítky, sumy a dátumy.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Tip: Combine AND (&) and OR (|) operators for more complex searches. For example > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 will show all transactions in January or December {lastYear}.", diff --git a/packages/suite-data/files/translations/tr.json b/packages/suite-data/files/translations/tr.json index 78f1449fff0..d13be5d964b 100644 --- a/packages/suite-data/files/translations/tr.json +++ b/packages/suite-data/files/translations/tr.json @@ -438,7 +438,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor tutarı", "TR_CHAINED_TXS": "Zincir işlemler", "TR_CHANGELOG": "Değişiklik Günlüğü", - "TR_CHANGELOG_ON_GITHUB": "GitHub'da Değişiklik Günlüğü", "TR_CHANGE_ADDRESS_TOOLTIP": "Bu, önceki bir gönderimden oluşturulan bir değişiklik adresidir.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Bellenim türünüzü istediğiniz zaman Ayarlar'dan değiştirebilirsiniz.", "TR_CHANGE_HOMESCREEN": "Ana ekranı değiştir", @@ -988,8 +987,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "Ayrıntıları görüntüle", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "Otomatik Trezor Suite güncellemeleri", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite, en son sürümü arka planda otomatik olarak indirir ve uygulama yeniden başlatılırken yükler. Bu sayede en son özellikler ve güvenlik yamalarıyla her zaman güncel kalırsınız. Güncellemeler izniniz istenmeden gerçekleşir.", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "BNB Smart Chain", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "Geçmiş dahili işlemler olmadan BNB Smart Chain'i etkinleştirin.", "TR_EXPERIMENTAL_FEATURES": "Deneysel", "TR_EXPERIMENTAL_FEATURES_ALLOW": "Deneysel özellikler", "TR_EXPERIMENTAL_FEATURES_WARNING": "Yalnızca deneyimli kullanıcılara yöneliktir. Riski üstlenerek kullanın. Bu özellikler test aşamasında olup istikrarsız olabilir ve bunlar için uzun vadede destek sunulmayabilir.", @@ -1889,10 +1886,7 @@ "TR_TO_BTC": "BTC'ye", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Etiketlerinizi tutarlı ve farklı cihazlarda kullanılabilir hale getirmek için bir bulut depolama sağlayıcısına bağlanın.", "TR_TO_SATOSHIS": "Sat'a", - "TR_TRADE_BUYS": "satın alır", - "TR_TRADE_EXCHANGES": "takas işlemi yapar", "TR_TRADE_REDIRECTING": "Yeniden yönlendiriliyor...", - "TR_TRADE_SELLS": "satar", "TR_TRANSACTIONS_NOT_AVAILABLE": "İşlem geçmişi mevcut değil", "TR_TRANSACTIONS_SEARCH_TIP_1": "İpucu: İşlem kimliklerini, adresleri, token'ları, etiketleri, tutarları ve tarihleri arayabilirsiniz.", "TR_TRANSACTIONS_SEARCH_TIP_10": "İpucu: Daha karmaşık aramalar için AND (&) ve OR (|) işleçlerini birleştirin. Örneğin, > {lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31, {lastYear} Ocak veya Aralık ayındaki tüm işlemleri gösterecektir.", diff --git a/packages/suite-data/files/translations/uk.json b/packages/suite-data/files/translations/uk.json index 60b8ceffe01..eba6a74878f 100644 --- a/packages/suite-data/files/translations/uk.json +++ b/packages/suite-data/files/translations/uk.json @@ -414,7 +414,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Сума Trezor", "TR_CHAINED_TXS": "Ланцюгові транзакції", "TR_CHANGELOG": "Список змін", - "TR_CHANGELOG_ON_GITHUB": "Список змін на GitHub", "TR_CHANGE_ADDRESS_TOOLTIP": "Ця адреса була створена як невитрачений залишок (\"change\") попередньої транзакції.", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "Ви можете змінити тип прошивки в налаштуваннях в будь-який час.", "TR_CHANGE_HOMESCREEN": "Змінити заставку", @@ -1693,10 +1692,7 @@ "TR_TO_BTC": "В BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "Щоб зробити ваші мітки узгодженими та доступними на різних пристроях, під’єднайтеся до постачальника хмарного сховища.", "TR_TO_SATOSHIS": "В sat", - "TR_TRADE_BUYS": "покупки", - "TR_TRADE_EXCHANGES": "обміни", "TR_TRADE_REDIRECTING": "Перенаправлення...", - "TR_TRADE_SELLS": "продажі", "TR_TRANSACTIONS_NOT_AVAILABLE": "Історія транзакцій недоступна", "TR_TRANSACTIONS_SEARCH_TIP_1": "Порада: Ви можете шукати ID транзакцій, адрес, мітки, суми та дат.", "TR_TRANSACTIONS_SEARCH_TIP_10": "Порада: Для складнішого пошуку можна комбінувати оператори AND (&) та OR (|). Наприклад, >> 2020-01-01 & < 2020-01-31 | > 2020-12-01 & < 2020-12-31 покаже всі транзакції за січень 2020 року або грудень 2020 року.", diff --git a/packages/suite-data/files/translations/zh.json b/packages/suite-data/files/translations/zh.json index 980bf59b4ad..a2c5f71773a 100644 --- a/packages/suite-data/files/translations/zh.json +++ b/packages/suite-data/files/translations/zh.json @@ -16,7 +16,7 @@ "BACKUP_BACKUP_ALREADY_FINISHED_HEADING": "备份已完成", "BROADCAST": "广播", "BROADCAST_TOOLTIP": "向网络广播此交易。", - "BROADCAST_TOOLTIP_DISABLED_LOCKTIME": "锁定时间设置超过当前区块或时间戳的交易将被网络拒绝。", + "BROADCAST_TOOLTIP_DISABLED_LOCKTIME": "时间锁设置超过当前区块或时间戳的交易将被网络拒绝。", "COPY_TRANSACTION_TO_CLIPBOARD": "复制原始交易", "CUSTOM_FEE_IS_NOT_INTEGER": "输入一个整数", "CUSTOM_FEE_IS_NOT_SET": "输入您愿意使用的费率来完整此交易", @@ -47,14 +47,14 @@ "FEE_LEVEL_CUSTOM": "自定义", "FEE_LEVEL_HIGH": "高", "FEE_LEVEL_LOW": "低", - "FEE_LEVEL_NORMAL": "正常", + "FEE_LEVEL_NORMAL": "普通", "FIRMWARE_CONNECT_IN_NORMAL_MODEL_NO_BUTTON": "连接USB数据线时请不要按住任何按钮。", "FIRMWARE_USER_HAS_SEED_CHECKBOX_DESC": "是的、我已有备份!", "FIRMWARE_USER_TAKES_RESPONSIBILITY_CHECKBOX_DESC": "我愿意承担这些风险", "FW_CAPABILITY_CONNECT_OUTDATED": "需要更新应用程序", "FW_CAPABILITY_UPDATE_REQUIRED": "需要更新设备固件", "IMAGE_VALIDATION_ERROR_INVALID_COLOR_COMBINATION": "无效的图像颜色。图像只能包含黑白 (而不是灰度)。", - "IMAGE_VALIDATION_ERROR_INVALID_DIMENSIONS": "无效的尺寸 (图像必须是 {width} x {height}px)。", + "IMAGE_VALIDATION_ERROR_INVALID_DIMENSIONS": "无效的尺寸 (图像必须是 {width} x {height} px)。", "IMAGE_VALIDATION_ERROR_INVALID_FORMAT_ONLY_JPG": "选择的文件是无效的。必须是 .jpg", "IMAGE_VALIDATION_ERROR_INVALID_FORMAT_ONLY_PNG_JPG": "选择的文件是无效的。必须是 .jpg 或 .png", "IMAGE_VALIDATION_ERROR_INVALID_SIZE_JPG": "无效的尺寸 (图像必须小于16KB)。", @@ -108,7 +108,7 @@ "RBF": "费用替代", "RECEIVE_ADDRESS": "地址", "RECEIVE_ADDRESS_COINJOIN_DISALLOW": "要为混币器账户创建其他地址、您必须确保已在初始地址收到比特币。", - "RECEIVE_ADDRESS_FRESH": "新地址", + "RECEIVE_ADDRESS_FRESH": "新的地址", "RECEIVE_ADDRESS_LIMIT_REACHED": "您已经达到21个未使用过的地址上限", "RECEIVE_ADDRESS_REVEAL": "显示完整地址", "RECEIVE_ADDRESS_UNAVAILABLE": "无法提供", @@ -297,6 +297,8 @@ "TR_ALLOW_ANALYTICS_DESCRIPTION": "所有用户使用数据都是严格匿名的; 我们只用它来改善Trezor的生态系统。", "TR_ALLOW_AUTOMATIC_SUITE_UPDATES": "自动更新Trezor Suite", "TR_ALLOW_AUTOMATIC_SUITE_UPDATES_DESCRIPTION": "Trezor Suite会在后台自动下载最新版本、并在重启应用程序时安装。这可确保您始终使用最新功能和安全补丁。更新无需经过您的许可。", + "TR_ALL_NETWORKS": "所有网络", + "TR_ALL_NETWORKS_TOOLTIP": "查看所有 {networkCount} 网络上的代币。使用右侧的按钮按照热门网络进行筛选。", "TR_ALL_TRANSACTIONS": "所有交易", "TR_AMOUNT_SENT": "已发送的金额", "TR_AMOUNT_TOO_BIG_FOR_COINJOIN": "无法用于混币 — 金额太大", @@ -306,7 +308,7 @@ "TR_ANALYZE_IN_BLOCKBOOK_OPEN": "打开", "TR_ANONYMITY_SET_ERROR": "计算匿名性时发生错误。 请稍后再试", "TR_ANONYMIZATION_OPTION_1": "加强比特币的隐私性", - "TR_ANONYMIZATION_OPTION_2": "在中选择“未消费交易输出”", + "TR_ANONYMIZATION_OPTION_2": "在中选择“未消费交易输出”", "TR_ANONYMIZATION_OPTION_3": "减少匿名程度", "TR_ANONYMIZATION_PAUSED": "混币器已暂停", "TR_ANONYMIZING": "运行中", @@ -438,7 +440,6 @@ "TR_CARDANO_TREZOR_AMOUNT_HEADLINE": "Trezor金额", "TR_CHAINED_TXS": "链式交易", "TR_CHANGELOG": "更新日志", - "TR_CHANGELOG_ON_GITHUB": "GitHub上的更新日志", "TR_CHANGE_ADDRESS_TOOLTIP": "这是从上次发送创建的找零地址。", "TR_CHANGE_FIRMWARE_TYPE_ANYTIME": "您可以随时在设置中更改您的固件类型。", "TR_CHANGE_HOMESCREEN": "更改主屏幕图片", @@ -608,8 +609,8 @@ "TR_COINMARKET_YOU_WILL_GET": "您将获得", "TR_COINMARKET_YOU_WILL_PAY": "您将支付", "TR_COINS": "加密货币", - "TR_COIN_CONTROL": "货币控制", - "TR_COIN_CONTROL_TOOLTIP": "货币控制使得手动选择“未消费交易输出”可以用作交易的输入。", + "TR_COIN_CONTROL": "币控制", + "TR_COIN_CONTROL_TOOLTIP": "币控制使得手动选择“未消费交易输出”可以用作交易的输入。", "TR_COIN_DISCOVERY_LOADER_DESCRIPTION": "检查隐藏钱包的余额和交易情况", "TR_COIN_SETTINGS": "货币设置", "TR_COLOR_SCHEME": "配色方案", @@ -988,8 +989,6 @@ "TR_EXCHANGE_VIEW_DETAILS": "查看详情", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE": "自动更新Trezor Suite", "TR_EXPERIMENTAL_AUTOMATIC_UPDATE_DESCRIPTION": "Trezor Suite会在后台自动下载最新版本、并在重启应用程序时安装。这可确保您始终使用最新功能和安全补丁。更新无需经过您的许可。", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN": "币安智能链", - "TR_EXPERIMENTAL_BNB_SMART_CHAIN_DESCRIPTON": "启用币安智能链网络、但无内部交易数据历史记录。", "TR_EXPERIMENTAL_FEATURES": "实验性", "TR_EXPERIMENTAL_FEATURES_ALLOW": "实验功能", "TR_EXPERIMENTAL_FEATURES_WARNING": "仅供有经验的用户使用。使用风险自负。这些功能正在测试中、可能不稳定、也可能得不到长期支持。", @@ -1338,7 +1337,7 @@ "TR_NOT_ENOUGH_ANONYMIZED_FUNDS": "没有足够具有隐私性的资产", "TR_NOT_ENOUGH_ANONYMIZED_FUNDS_RBF_WARNING": "具有隐私性的比特币不足。您可以提高您的比特币隐私性或者降低隐私级别。", "TR_NOT_ENOUGH_ANONYMIZED_FUNDS_TOOLTIP": "您可以: ", - "TR_NOT_ENOUGH_ANONYMIZED_FUNDS_WARNING": "具有隐私性的比特币不足。您可以提高您的比特币隐私性、在“货币控制”中手动选择“消费的交易输出”、或者降低隐私级别。", + "TR_NOT_ENOUGH_ANONYMIZED_FUNDS_WARNING": "具有隐私性的比特币不足。您可以提高您的比特币隐私性、在“币控制”中手动选择“未消费交易输出”、或者降低隐私级别。", "TR_NOT_ENOUGH_SELECTED": "没有选择足够的资金", "TR_NOT_PRIVATE": "不具有隐私性的", "TR_NOT_PRIVATE_DESCRIPTION": "匿名性低于 {targetAnonymity}", @@ -1558,9 +1557,11 @@ "TR_SELECTED": " 已选择 {amount} ", "TR_SELECT_COIN_FOR_SETTINGS": "选择活跃的加密货币来更改设置", "TR_SELECT_DEVICE": "选择设备", + "TR_SELECT_NAME_OR_ADDRESS": "通过名称、符号、网络或合约地址进行搜索", "TR_SELECT_NUMBER_OF_WORDS": "选择您钱包助记词备份中的单词数", "TR_SELECT_PASSPHRASE_SOURCE": "在 “{deviceLabel}” 里选择输入密码短语的地方。", "TR_SELECT_RECOVERY_METHOD": "选择恢复钱包的方式", + "TR_SELECT_TOKEN": "选择一个代币", "TR_SELECT_TREZOR": "选择Trezor设备", "TR_SELECT_TREZOR_TO_CONTINUE": "选择您的Trezor设备以继续。", "TR_SELECT_TYPE": "选择类型", @@ -1794,6 +1795,7 @@ "TR_START_COINJOIN": "开始混币器\n", "TR_START_RECOVERY": "开始恢复", "TR_STEP": "步骤 {number}", + "TR_STEP_OF_TOTAL": "步骤: {index} / {total} ", "TR_STILL_DONT_SEE_YOUR_TREZOR": "仍然看不到您的Trezor设备?", "TR_STOP": "停止", "TR_STOPPING": "正在停止", @@ -1845,7 +1847,11 @@ "TR_TOKENS_EMPTY": "还没有代币...", "TR_TOKENS_EMPTY_CHECK_HIDDEN": "没有代币。它们可以已被隐藏。", "TR_TOKENS_SEARCH_TOOLTIP": "按代币、符号或合约地址搜索。", + "TR_TOKEN_NOT_FOUND": "未能找到此代币", + "TR_TOKEN_NOT_FOUND_ON_NETWORK": "未能在 {networkName} 网络上找到此代币", "TR_TOKEN_TRANSFERS": "{standard} 代币转让", + "TR_TOKEN_TRY_DIFFERENT_SEARCH": "请尝试不同的搜索。", + "TR_TOKEN_TRY_DIFFERENT_SEARCH_OR_SWITCH": "请尝试不同的搜索或切换到另一个网络。", "TR_TOKEN_UNRECOGNIZED_BY_TREZOR": "未识别的代币", "TR_TOKEN_UNRECOGNIZED_BY_TREZOR_TOOLTIP": "未识别的代币会带来潜在的风险。谨慎使用。", "TR_TOO_LONG": "留言太长", @@ -1889,10 +1895,7 @@ "TR_TO_BTC": "到BTC", "TR_TO_MAKE_YOUR_LABELS_PERSISTENT": "要使您的标签在不同的设备上持久可用、请连接到云存储提供商。", "TR_TO_SATOSHIS": "到聪", - "TR_TRADE_BUYS": "购买", - "TR_TRADE_EXCHANGES": "交易", "TR_TRADE_REDIRECTING": "重定向...", - "TR_TRADE_SELLS": "卖出", "TR_TRANSACTIONS_NOT_AVAILABLE": "交易记录不可用", "TR_TRANSACTIONS_SEARCH_TIP_1": "提示:您可以搜索交易ID、地址、标签、数量和日期。", "TR_TRANSACTIONS_SEARCH_TIP_10": "提示:您可以合并AND(&)和 OR(|)操作符号来进行更复杂的搜索。 例如,>{lastYear}-01-01 & < {lastYear}-01-31 | > {lastYear}-12-01 & < {lastYear}-12-31 将显示{lastYear}年所有1月或12月的交易。", diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 69da7796266..cdbae34906a 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -336,7 +336,7 @@ export default defineMessages({ }, TR_ALL_NETWORKS_TOOLTIP: { defaultMessage: - 'View tokens from all {networkCount} networks. Use the buttons on the right to filter by top networks.', + 'View tokens from all {networkCount} networks. Filter by the most popular networks on the right.', id: 'TR_ALL_NETWORKS_TOOLTIP', }, TR_SELECT_TOKEN: { @@ -344,7 +344,7 @@ export default defineMessages({ id: 'TR_SELECT_TOKEN', }, TR_SELECT_NAME_OR_ADDRESS: { - defaultMessage: 'Search by name, symbol, network or contract address', + defaultMessage: 'Search by name, symbol, network, or contract address', id: 'TR_SELECT_NAME_OR_ADDRESS', }, TR_TOKEN_NOT_FOUND: { @@ -352,15 +352,15 @@ export default defineMessages({ id: 'TR_TOKEN_NOT_FOUND', }, TR_TOKEN_NOT_FOUND_ON_NETWORK: { - defaultMessage: 'Token not found on the {networkName} network', + defaultMessage: 'Token not found on the {networkName} network.', id: 'TR_TOKEN_NOT_FOUND_ON_NETWORK', }, TR_TOKEN_TRY_DIFFERENT_SEARCH: { - defaultMessage: 'Please try a different search.', + defaultMessage: 'Try a different search.', id: 'TR_TOKEN_TRY_DIFFERENT_SEARCH', }, TR_TOKEN_TRY_DIFFERENT_SEARCH_OR_SWITCH: { - defaultMessage: 'Please try a different search or switch to another network.', + defaultMessage: 'Try a different search or switch to another network.', id: 'TR_TOKEN_TRY_DIFFERENT_SEARCH_OR_SWITCH', }, TR_EXCHANGE_STATUS_ERROR: { @@ -923,7 +923,7 @@ export default defineMessages({ }, TR_BUY_FOOTER_TEXT_2: { defaultMessage: - 'Invity does not see any of your payment or KYC information; you share this only with the exchange provider if you choose to finish the transaction.', + "Invity doesn't see any of your payment or KYC information; you share this only with the exchange provider if you choose to finish the transaction.", id: 'TR_BUY_FOOTER_TEXT_2', }, TR_BUY_MODAL_FOR_YOUR_SAFETY: { @@ -1423,7 +1423,6 @@ export default defineMessages({ defaultMessage: 'Swap', id: 'TR_COINMARKET_SWAP', }, - TR_ADDRESS_MODAL_CLIPBOARD: { defaultMessage: 'Copy address', id: 'TR_ADDRESS_MODAL_CLIPBOARD', @@ -2169,7 +2168,7 @@ export default defineMessages({ id: 'TR_SAFETY_CHECKS_PROMPT_LEVEL', }, TR_SAFETY_CHECKS_PROMPT_LEVEL_WARNING: { - defaultMessage: "Do not change this unless you know what you're doing!", + defaultMessage: "Only change this if you know what you're doing!", id: 'TR_SAFETY_CHECKS_PROMPT_LEVEL_WARNING', }, TR_SAFETY_CHECKS_PROMPT_LEVEL_DESC: { @@ -2472,7 +2471,7 @@ export default defineMessages({ id: 'TR_SKIP_PIN_DESCRIPTION', }, TR_SKIP_BACKUP: { - defaultMessage: 'Skip backup', + defaultMessage: 'Skip Backup', id: 'TR_SKIP_BACKUP', }, TR_SKIP_BACKUP_DESCRIPTION: { @@ -3875,7 +3874,6 @@ export default defineMessages({ id: 'TR_QUICK_ACTION_TOOLTIP_JUST_UPDATED', defaultMessage: 'Just updated ({currentVersion})', }, - TR_QUICK_ACTION_UPDATE_POPOVER_APP_UPDATE_AVAILABLE: { id: 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_UPDATE_AVAILABLE', defaultMessage: 'App update available', @@ -3888,12 +3886,10 @@ export default defineMessages({ id: 'TR_QUICK_ACTION_UPDATE_POPOVER_APP_DOWNLOADED', defaultMessage: 'Suite downloaded a new Trezor update!', }, - TR_QUICK_ACTION_UPDATE_POPOVER_TREZOR_UPDATE_AVAILABLE: { id: 'TR_QUICK_ACTION_UPDATE_POPOVER_TREZOR_UPDATE_AVAILABLE', defaultMessage: 'Trezor update available', }, - TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE: { id: 'TR_QUICK_ACTION_UPDATE_POPOVER_CLICK_TO_START_UPDATE', defaultMessage: 'Click to start update', @@ -3906,7 +3902,6 @@ export default defineMessages({ id: 'TR_QUICK_ACTION_UPDATE_POPOVER_WHATS_NEW', defaultMessage: 'What’s new?', }, - TR_QUICK_ACTION_DEBUG_EAP_EXPERIMENTAL_ENABLED: { id: 'TR_QUICK_ACTION_DEBUG_EAP_EXPERIMENTAL_ENABLED', defaultMessage: 'Enabled', @@ -5563,7 +5558,7 @@ export default defineMessages({ REVIEW_AND_SEND_TRANSACTION: { id: 'REVIEW_AND_SEND_TRANSACTION', description: 'Sign and send button used in send form', - defaultMessage: 'Review & Send', + defaultMessage: 'Review & send', }, TR_CONNECT_TREZOR_TO_SEND_BUTTON: { id: 'TR_CONNECT_TREZOR_TO_SEND_BUTTON', @@ -8223,7 +8218,7 @@ export default defineMessages({ }, TR_STEP_OF_TOTAL: { id: 'TR_STEP_OF_TOTAL', - defaultMessage: 'Step {index} of {total}', + defaultMessage: 'Select a token', }, TR_COINJOIN_STEP_1_TITLE: { id: 'TR_COINJOIN_STEP_1_TITLE', From f53d31e47fc68e1ce17248b6591d865088781ed1 Mon Sep 17 00:00:00 2001 From: PeterBenc Date: Thu, 10 Oct 2024 11:07:57 +0200 Subject: [PATCH 113/624] fix(blockchain-link-utils): fix solana self txs info in history --- packages/blockchain-link-utils/src/solana.ts | 17 ++++++++++------- .../src/tests/fixtures/solana.ts | 12 ++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/blockchain-link-utils/src/solana.ts b/packages/blockchain-link-utils/src/solana.ts index 918b212c122..e9682634953 100644 --- a/packages/blockchain-link-utils/src/solana.ts +++ b/packages/blockchain-link-utils/src/solana.ts @@ -242,9 +242,9 @@ export const getTargets = ( ): Transaction['targets'] => effects .filter(effect => { - // for 'self` transaction there is only one effect + // exclude target for 'self` transaction because it is redundant with fee if (txType === 'self') { - return true; + return false; } // ignore all targets for unknown transactions if (txType === 'unknown') { @@ -365,10 +365,12 @@ export const getDetails = ( // include positive effects only on accountAddress for tx types other then sent, otherwise it // leads to foreign address being displayed next to users own address which might lead to confusion - const receivers = effects.filter( - ({ amount, address }) => - amount.isPositive() && (txType !== 'sent' ? address === accountAddress : true), - ); + const receivers = effects + .filter( + ({ amount, address }) => + amount.isPositive() && (txType !== 'sent' ? address === accountAddress : true), + ) + .filter(({ address }) => !(txType === 'self' && address === accountAddress)); const getVin = ({ address, amount }: { address: string; amount?: BigNumber }, i: number) => ({ txid: transaction.transaction.signatures[0].toString(), @@ -409,7 +411,8 @@ export const getAmount = ( return '0'; } if (txType === 'self') { - return accountEffect.amount?.abs().toString(); + // we do not want to show amount because its redundant with fee + return '0'; } return accountEffect.amount.toString(); diff --git a/packages/blockchain-link-utils/src/tests/fixtures/solana.ts b/packages/blockchain-link-utils/src/tests/fixtures/solana.ts index daa33a96501..a00f2e06647 100644 --- a/packages/blockchain-link-utils/src/tests/fixtures/solana.ts +++ b/packages/blockchain-link-utils/src/tests/fixtures/solana.ts @@ -554,15 +554,7 @@ export const fixtures = { txType: 'self', accountAddress: effects.negative.address, }, - expectedOutput: [ - { - n: 0, - addresses: [effects.negative.address], - isAddress: true, - amount: effects.negative.amount.abs().toString(), - isAccountTarget: true, - }, - ], + expectedOutput: [], }, { description: 'should return an array with a target for "sent" transaction type', @@ -641,7 +633,7 @@ export const fixtures = { accountEffect: effects.negative, txType: 'self', }, - expectedOutput: effects.negative.amount.abs().toString(), + expectedOutput: '0', }, { description: 'should return the amount as a string for other transaction types', From 9dee606f43daba33f25f030d74d6f600915581fc Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Mon, 14 Oct 2024 09:43:56 +0200 Subject: [PATCH 114/624] test(connect-popup): fix log going to --- packages/connect-popup/e2e/tests/transport.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/connect-popup/e2e/tests/transport.test.ts b/packages/connect-popup/e2e/tests/transport.test.ts index d977fa15c4a..f4297de5c29 100644 --- a/packages/connect-popup/e2e/tests/transport.test.ts +++ b/packages/connect-popup/e2e/tests/transport.test.ts @@ -129,8 +129,9 @@ fixtures.forEach(f => { const afterCleanup = await f.setup?.(context); - log(`going to: ${url}${f.queryString}#/method/verifyMessage`); - await page.goto(formatUrl(url, `methods/bitcoin/verifyMessage/${f.queryString}`)); + const formattedUrl = formatUrl(url, `methods/bitcoin/verifyMessage/${f.queryString}`); + log(`going to: ${formattedUrl}`); + await page.goto(formattedUrl); log('waiting for explorer to load'); await waitAndClick(page, ['@api-playground/collapsible-box']); await page.waitForSelector("button[data-testid='@submit-button']", { From c521c80b1912f9aae0cc2696cd53ab7ec0c8de08 Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Thu, 10 Oct 2024 09:45:15 +0200 Subject: [PATCH 115/624] feat(module-connect-popup): handling for dev and prod deeplink URLs --- suite-native/app/app.config.ts | 32 ++++++++++++------- .../src/hooks/useConnectPopupNavigation.ts | 12 ++++++- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/suite-native/app/app.config.ts b/suite-native/app/app.config.ts index 21822a214c1..7d54f91b9b1 100644 --- a/suite-native/app/app.config.ts +++ b/suite-native/app/app.config.ts @@ -183,14 +183,20 @@ export default ({ config }: ConfigContext): ExpoConfig => { monochromeImage: './assets/appIcon_android.png', ...appIconAndroid, }, - intentFilters: - buildType === 'production' - ? [] - : [ - { - action: 'VIEW', - autoVerify: true, - data: [ + intentFilters: [ + { + action: 'VIEW', + autoVerify: true, + data: + buildType === 'production' + ? [ + { + scheme: 'https', + host: 'connect.trezor.io', + pathPattern: '/9/deeplink/.*', + }, + ] + : [ { scheme: 'https', host: 'dev.suite.sldev.cz', @@ -203,9 +209,9 @@ export default ({ config }: ConfigContext): ExpoConfig => { pathPattern: '/connect/.*/.*/deeplink/.*', }, ], - category: ['BROWSABLE', 'DEFAULT'], - }, - ], + category: ['BROWSABLE', 'DEFAULT'], + }, + ], }, ios: { bundleIdentifier, @@ -232,6 +238,10 @@ export default ({ config }: ConfigContext): ExpoConfig => { }, UIRequiredDeviceCapabilities: ['armv7'], }, + associatedDomains: + buildType === 'production' + ? ['applinks:connect.trezor.io'] + : ['applinks:dev.suite.sldev.cz'], }, plugins: getPlugins(), extra: { diff --git a/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts b/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts index 9701404009b..d2e521c32c8 100644 --- a/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts +++ b/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts @@ -8,6 +8,7 @@ import { RootStackParamList, RootStackRoutes, } from '@suite-native/navigation'; +import { isDevelopOrDebugEnv } from '@suite-native/config'; type NavigationProp = StackToStackCompositeNavigationProps< RootStackParamList, @@ -15,7 +16,16 @@ type NavigationProp = StackToStackCompositeNavigationProps< RootStackParamList >; -const isConnectPopupUrl = (url: string): boolean => url.startsWith('trezorsuitelite://'); +const isConnectPopupUrl = (url: string): boolean => { + if (isDevelopOrDebugEnv()) { + if (url.startsWith('trezorsuitelite://connect')) return true; + if (/^https:\/\/dev\.suite\.sldev\.cz\/connect\/(.*)\/deeplink(.*)$/g.test(url)) + return true; + } + if (/^https:\/\/connect\.trezor\.io\/9\/deeplink(.*)$/g.test(url)) return true; + + return false; +}; // TODO: will be necessary to handle if device is not connected/unlocked so we probably want to wait until user unlock device // we already have some modals like biometrics or coin enabled which are waiting for device to be connected From 0f49b0fadd15e07a61d4fb88d47a4f7e2d5158db Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Thu, 10 Oct 2024 09:51:21 +0200 Subject: [PATCH 116/624] feat(mobile-connect-popup): add feature flag for popup --- suite-native/feature-flags/src/featureFlagsSlice.ts | 3 +++ suite-native/module-connect-popup/package.json | 1 + .../src/hooks/useConnectPopupNavigation.ts | 12 ++++++------ suite-native/module-connect-popup/tsconfig.json | 1 + .../module-dev-utils/src/components/FeatureFlags.tsx | 1 + yarn.lock | 3 ++- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/suite-native/feature-flags/src/featureFlagsSlice.ts b/suite-native/feature-flags/src/featureFlagsSlice.ts index 18e747db1c0..da5ecac14c8 100644 --- a/suite-native/feature-flags/src/featureFlagsSlice.ts +++ b/suite-native/feature-flags/src/featureFlagsSlice.ts @@ -9,6 +9,7 @@ export const FeatureFlag = { IsRegtestEnabled: 'isRegtestEnabled', IsPolygonEnabled: 'IsPolygonEnabled', IsBscEnabled: 'IsBscEnabled', + IsConnectPopupEnabled: 'IsConnectPopupEnabled', } as const; export type FeatureFlag = (typeof FeatureFlag)[keyof typeof FeatureFlag]; @@ -24,6 +25,7 @@ export const featureFlagsInitialState: FeatureFlagsState = { [FeatureFlag.IsRegtestEnabled]: isDebugEnv() || isDetoxTestBuild(), [FeatureFlag.IsPolygonEnabled]: false, [FeatureFlag.IsBscEnabled]: false, + [FeatureFlag.IsConnectPopupEnabled]: isDevelopOrDebugEnv(), }; export const featureFlagsPersistedKeys: Array = [ @@ -32,6 +34,7 @@ export const featureFlagsPersistedKeys: Array = [ FeatureFlag.IsRegtestEnabled, FeatureFlag.IsPolygonEnabled, FeatureFlag.IsBscEnabled, + FeatureFlag.IsConnectPopupEnabled, ]; export const featureFlagsSlice = createSlice({ diff --git a/suite-native/module-connect-popup/package.json b/suite-native/module-connect-popup/package.json index a77ea4a05d9..041789e62e7 100644 --- a/suite-native/module-connect-popup/package.json +++ b/suite-native/module-connect-popup/package.json @@ -18,6 +18,7 @@ "@suite-native/config": "workspace:*", "@suite-native/device": "workspace:*", "@suite-native/device-manager": "workspace:*", + "@suite-native/feature-flags": "workspace:^", "@suite-native/intl": "workspace:^", "@suite-native/navigation": "workspace:*", "@trezor/connect": "workspace:*", diff --git a/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts b/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts index d2e521c32c8..10f2aa17ee7 100644 --- a/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts +++ b/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts @@ -9,6 +9,7 @@ import { RootStackRoutes, } from '@suite-native/navigation'; import { isDevelopOrDebugEnv } from '@suite-native/config'; +import { FeatureFlag, useFeatureFlag } from '@suite-native/feature-flags'; type NavigationProp = StackToStackCompositeNavigationProps< RootStackParamList, @@ -30,22 +31,23 @@ const isConnectPopupUrl = (url: string): boolean => { // TODO: will be necessary to handle if device is not connected/unlocked so we probably want to wait until user unlock device // we already have some modals like biometrics or coin enabled which are waiting for device to be connected export const useConnectPopupNavigation = () => { + const [featureFlagEnabled] = useFeatureFlag(FeatureFlag.IsConnectPopupEnabled); const navigation = useNavigation(); const navigateToConnectPopup = useCallback( (url: string) => { + if (!featureFlagEnabled) return; + if (!isConnectPopupUrl(url)) return; const parsedUrl = Linking.parse(url); navigation.navigate(RootStackRoutes.ConnectPopup, { parsedUrl }); }, - [navigation], + [navigation, featureFlagEnabled], ); useEffect(() => { const navigateToInitalUrl = async () => { const currentUrl = await Linking.getInitialURL(); - if (currentUrl && isConnectPopupUrl(currentUrl)) { - // eslint-disable-next-line no-console - console.log('initial url', currentUrl); + if (currentUrl) { navigateToConnectPopup(currentUrl); } }; @@ -56,8 +58,6 @@ export const useConnectPopupNavigation = () => { // there could be when you open same deep link for second time and in that case it will be ignored // this could be probably handed by Linking.addEventListener const subscription = Linking.addEventListener('url', event => { - // eslint-disable-next-line no-console - console.log('url event received', event.url); navigateToConnectPopup(event.url); }); diff --git a/suite-native/module-connect-popup/tsconfig.json b/suite-native/module-connect-popup/tsconfig.json index 0914835035e..73d2d31066d 100644 --- a/suite-native/module-connect-popup/tsconfig.json +++ b/suite-native/module-connect-popup/tsconfig.json @@ -12,6 +12,7 @@ { "path": "../config" }, { "path": "../device" }, { "path": "../device-manager" }, + { "path": "../feature-flags" }, { "path": "../intl" }, { "path": "../navigation" }, { "path": "../../packages/connect" }, diff --git a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx index 84cc34d4df4..6504955833d 100644 --- a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx +++ b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx @@ -7,6 +7,7 @@ const featureFlagsTitleMap = { [FeatureFlagEnum.IsRegtestEnabled]: 'Regtest', [FeatureFlagEnum.IsPolygonEnabled]: 'Polygon', [FeatureFlagEnum.IsBscEnabled]: 'BNB Smart Chain', + [FeatureFlagEnum.IsConnectPopupEnabled]: 'Connect Popup', } as const satisfies Record; const FeatureFlag = ({ featureFlag }: { featureFlag: FeatureFlagEnum }) => { diff --git a/yarn.lock b/yarn.lock index f11d1fc27d4..edcce42cec7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9913,7 +9913,7 @@ __metadata: languageName: unknown linkType: soft -"@suite-native/feature-flags@workspace:*, @suite-native/feature-flags@workspace:suite-native/feature-flags": +"@suite-native/feature-flags@workspace:*, @suite-native/feature-flags@workspace:^, @suite-native/feature-flags@workspace:suite-native/feature-flags": version: 0.0.0-use.local resolution: "@suite-native/feature-flags@workspace:suite-native/feature-flags" dependencies: @@ -10219,6 +10219,7 @@ __metadata: "@suite-native/config": "workspace:*" "@suite-native/device": "workspace:*" "@suite-native/device-manager": "workspace:*" + "@suite-native/feature-flags": "workspace:^" "@suite-native/intl": "workspace:^" "@suite-native/navigation": "workspace:*" "@trezor/connect": "workspace:*" From a741e65bfdb64ec9ec7a37f7d4288c7d5ac57a86 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Fri, 11 Oct 2024 17:02:23 +0200 Subject: [PATCH 117/624] chore(suite): tweak suite fw hash selectors --- .../suite/src/reducers/suite/suiteReducer.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts index b905cab3ab6..0503697904d 100644 --- a/packages/suite/src/reducers/suite/suiteReducer.ts +++ b/packages/suite/src/reducers/suite/suiteReducer.ts @@ -10,7 +10,13 @@ import { isDeviceAcquired } from '@suite-common/suite-utils'; import { discoveryActions, DeviceRootState, selectDevice } from '@suite-common/wallet-core'; import { versionUtils } from '@trezor/utils'; import { isWeb } from '@trezor/env-utils'; -import { TRANSPORT, TransportInfo, ConnectSettings } from '@trezor/connect'; +import { + TRANSPORT, + TransportInfo, + ConnectSettings, + FirmwareHashCheckError, + FirmwareRevisionCheckError, +} from '@trezor/connect'; import { getIsTorEnabled, getIsTorLoading } from 'src/utils/suite/tor'; import type { OAuthServerEnvironment } from 'src/types/suite/metadata'; @@ -460,8 +466,12 @@ export const selectFirmwareRevisionCheckError = (state: StateForFirmwareChecks) */ const selectIsFirmwareRevisionCheckEnabledAndFailed = (state: StateForFirmwareChecks): boolean => { const error = selectFirmwareRevisionCheckError(state); + const softErrors: FirmwareRevisionCheckError[] = [ + 'cannot-perform-check-offline', + 'other-error', + ]; - return error ? !['cannot-perform-check-offline', 'other-error'].includes(error) : false; + return error !== null ? !softErrors.includes(error) : false; }; /** @@ -469,7 +479,7 @@ const selectIsFirmwareRevisionCheckEnabledAndFailed = (state: StateForFirmwareCh */ export const selectFirmwareHashCheckError = (state: StateForFirmwareChecks) => { const device = selectDevice(state); - if (!isDeviceAcquired(device) || !device.authenticityChecks) return false; + if (!isDeviceAcquired(device) || !device.authenticityChecks) return null; const { isFirmwareHashCheckDisabled } = state.suite.settings; const isDisabledByMessage = selectIsFeatureDisabled(state, Feature.firmwareHashCheck); @@ -486,8 +496,9 @@ export const selectFirmwareHashCheckError = (state: StateForFirmwareChecks) => { */ const selectIsFirmwareHashCheckEnabledAndFailed = (state: StateForFirmwareChecks): boolean => { const error = selectFirmwareHashCheckError(state); + const softErrors: FirmwareHashCheckError[] = ['check-skipped', 'check-unsupported']; - return error ? !['check-skipped', 'check-unsupported'].includes(error) : false; + return error !== null ? !softErrors.includes(error) : false; }; /** From e583e84c324cda6682499b7d6ef7987cec112b9a Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Mon, 14 Oct 2024 14:22:16 +0200 Subject: [PATCH 118/624] fix(connect): make getBinaryOptional async --- packages/connect/src/api/firmware/getBinary.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/connect/src/api/firmware/getBinary.ts b/packages/connect/src/api/firmware/getBinary.ts index b9ca25a33d3..55fbba3683b 100644 --- a/packages/connect/src/api/firmware/getBinary.ts +++ b/packages/connect/src/api/firmware/getBinary.ts @@ -14,9 +14,9 @@ export const getBinary = ({ baseUrl, btcOnly, release }: GetBinaryProps) => { return httpRequest(url, 'binary'); }; -export const getBinaryOptional = (props: GetBinaryProps) => { +export const getBinaryOptional = async (props: GetBinaryProps) => { try { - return getBinary(props); + return await getBinary(props); } catch (error) { return null; } From 9a8687546678796c7ff1a8b151044d9a58c4b3cc Mon Sep 17 00:00:00 2001 From: Pavlo Syrotyna Date: Tue, 24 Sep 2024 14:50:20 +0300 Subject: [PATCH 119/624] feat(staking): add earnings projections to the staking modal --- .../components/src/components/Image/images.ts | 1 + .../files/images/svg/gains-graph.svg | 13 +++ .../suite/StakingProcess/InfoRow.tsx | 32 +++++++ .../StakingInfo.tsx | 29 ++++-- .../suite/StakingProcess/Subheading.tsx | 26 +++++ .../suite/StakingProcess/UnstakingInfo.tsx | 87 +++++++++++++++++ .../components/suite/StakingProcess/types.ts | 9 ++ .../StakeEthInANutshellModal/InfoRow.tsx | 28 ------ .../StakeEthInANutshellModal.tsx | 10 +- .../UnstakingInfo.tsx | 72 -------------- .../StakeModal/StakeEthForm/Inputs.tsx | 2 + .../StakeModal/StakeEthForm/StakeButton.tsx | 1 - .../StakeModal/StakeModal.tsx | 12 ++- .../StakingInfoCards/EstimatedGains.tsx | 95 +++++++++++++++++++ .../StakingInfoCards/StakingInfoCards.tsx | 40 ++++++++ .../UnstakeEthForm/UnstakeButton.tsx | 40 ++++++++ .../UnstakeEthForm/UnstakeEthForm.tsx | 28 +----- .../UnstakeModal/UnstakeModal.tsx | 72 ++++++++++---- .../UnstakeModal/UnstakeModalContent.tsx | 17 ---- .../suite/src/components/wallet/Fees/Fees.tsx | 16 +++- .../suite/src/constants/suite/ethStaking.ts | 1 + packages/suite/src/support/messages.ts | 53 +++++++++++ packages/suite/src/utils/suite/stake.ts | 25 ++++- 23 files changed, 528 insertions(+), 181 deletions(-) create mode 100644 packages/suite-data/files/images/svg/gains-graph.svg create mode 100644 packages/suite/src/components/suite/StakingProcess/InfoRow.tsx rename packages/suite/src/components/suite/{modals/ReduxModal/UserContextModal/StakeEthInANutshellModal => StakingProcess}/StakingInfo.tsx (56%) create mode 100644 packages/suite/src/components/suite/StakingProcess/Subheading.tsx create mode 100644 packages/suite/src/components/suite/StakingProcess/UnstakingInfo.tsx create mode 100644 packages/suite/src/components/suite/StakingProcess/types.ts delete mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/InfoRow.tsx delete mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/UnstakingInfo.tsx create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/EstimatedGains.tsx create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/StakingInfoCards.tsx create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeButton.tsx delete mode 100644 packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModalContent.tsx diff --git a/packages/components/src/components/Image/images.ts b/packages/components/src/components/Image/images.ts index 9c9507f04d6..1539fd2f326 100644 --- a/packages/components/src/components/Image/images.ts +++ b/packages/components/src/components/Image/images.ts @@ -37,6 +37,7 @@ export const SVG_IMAGES = { TREZOR_SAFE_PROMO_UNDERLINE: 'trezor-safe-promo-underline.svg', CONFIRM_EVM_EXPLANATION_ETH: 'confirm-evm-explanation-eth.svg', CONFIRM_EVM_EXPLANATION_OTHER: 'confirm-evm-explanation-other.svg', + GAINS_GRAPH: 'gains-graph.svg', } as const; export type PngImage = keyof typeof PNG_IMAGES; diff --git a/packages/suite-data/files/images/svg/gains-graph.svg b/packages/suite-data/files/images/svg/gains-graph.svg new file mode 100644 index 00000000000..21db6d03fdd --- /dev/null +++ b/packages/suite-data/files/images/svg/gains-graph.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/suite/src/components/suite/StakingProcess/InfoRow.tsx b/packages/suite/src/components/suite/StakingProcess/InfoRow.tsx new file mode 100644 index 00000000000..f7e9b5c9140 --- /dev/null +++ b/packages/suite/src/components/suite/StakingProcess/InfoRow.tsx @@ -0,0 +1,32 @@ +import { Badge, Column, List, Paragraph, Row } from '@trezor/components'; +import { Subheading } from './Subheading'; +import { RowContent, RowSubheading } from './types'; + +interface InfoRowProps { + heading: React.ReactNode; + subheading: RowSubheading; + content: RowContent; + isExpanded?: boolean; +} + +export const InfoRow = ({ heading, subheading, content, isExpanded = false }: InfoRowProps) => { + const displayContent = content.isBadge ? ( + {content.text} + ) : ( + + {content.text} + + ); + + return ( + + + + {heading} + + + {displayContent} + + + ); +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakingInfo.tsx b/packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx similarity index 56% rename from packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakingInfo.tsx rename to packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx index 2ef76ac4b70..c31d46c826f 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakingInfo.tsx +++ b/packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { selectAccountStakeTransactions, selectValidatorsQueue, @@ -9,13 +10,15 @@ import { useSelector } from 'react-redux'; import { Translation } from 'src/components/suite'; import { getDaysToAddToPool } from 'src/utils/suite/stake'; import { InfoRow } from './InfoRow'; -import { Account } from 'src/types/wallet'; +import { CoinjoinRootState } from 'src/reducers/wallet/coinjoinReducer'; interface StakingInfoProps { - account?: Account; + isExpanded?: boolean; } -export const StakingInfo = ({ account }: StakingInfoProps) => { +export const StakingInfo = ({ isExpanded }: StakingInfoProps) => { + const { account } = useSelector((state: CoinjoinRootState) => state.wallet.selectedAccount); + const { data } = useSelector((state: StakeRootState) => selectValidatorsQueue(state, account?.symbol)) || {}; @@ -33,11 +36,20 @@ export const StakingInfo = ({ account }: StakingInfoProps) => { const infoRows = [ { - label: , + heading: , + subheading: { isCurrentStep: true }, content: { text: , isBadge: true }, }, { - label: , + heading: , + subheading: { + text: ( + + ), + }, content: { text: ( <> @@ -47,15 +59,16 @@ export const StakingInfo = ({ account }: StakingInfoProps) => { }, }, { - label: , + heading: , + subheading: { text: }, content: { text: `~${ethApy}% p.a.` }, }, ]; return ( <> - {infoRows.map(({ label, content }, index) => ( - + {infoRows.map(({ heading, content, subheading }, index) => ( + ))} ); diff --git a/packages/suite/src/components/suite/StakingProcess/Subheading.tsx b/packages/suite/src/components/suite/StakingProcess/Subheading.tsx new file mode 100644 index 00000000000..31890dff730 --- /dev/null +++ b/packages/suite/src/components/suite/StakingProcess/Subheading.tsx @@ -0,0 +1,26 @@ +import { Icon, Paragraph, Row } from '@trezor/components'; +import { Translation } from '../Translation'; +import { spacings } from '@trezor/theme'; +import { RowSubheading } from './types'; + +interface SubheadingProps { + subheading: RowSubheading; + isExpanded?: boolean; +} + +export const Subheading = ({ isExpanded, subheading }: SubheadingProps) => { + if (!isExpanded || !subheading) return null; + + return subheading.isCurrentStep ? ( + + + + + + + ) : ( + + {subheading.text} + + ); +}; diff --git a/packages/suite/src/components/suite/StakingProcess/UnstakingInfo.tsx b/packages/suite/src/components/suite/StakingProcess/UnstakingInfo.tsx new file mode 100644 index 00000000000..11c9b4387ec --- /dev/null +++ b/packages/suite/src/components/suite/StakingProcess/UnstakingInfo.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { + selectAccountUnstakeTransactions, + selectValidatorsQueue, + TransactionsRootState, + StakeRootState, +} from '@suite-common/wallet-core'; +import { Translation } from 'src/components/suite'; +import { InfoRow } from './InfoRow'; +import { useSelector } from 'react-redux'; +import { getDaysToUnstake } from 'src/utils/suite/stake'; +import { CoinjoinRootState } from 'src/reducers/wallet/coinjoinReducer'; + +interface UnstakingInfoProps { + isExpanded?: boolean; +} + +export const UnstakingInfo = ({ isExpanded }: UnstakingInfoProps) => { + const { account } = useSelector((state: CoinjoinRootState) => state.wallet.selectedAccount); + + const { data } = + useSelector((state: StakeRootState) => selectValidatorsQueue(state, account?.symbol)) || {}; + + const unstakeTxs = useSelector((state: TransactionsRootState) => + selectAccountUnstakeTransactions(state, account?.key ?? ''), + ); + + if (!account) return null; + + const daysToUnstake = getDaysToUnstake(unstakeTxs, data); + const accountSymbol = account.symbol.toUpperCase(); + + const infoRows = [ + { + heading: , + subheading: { isCurrentStep: true }, + content: { + text: , + isBadge: true, + }, + }, + { + heading: , + subheading: { + text: ( + + ), + }, + content: { + text: , + }, + }, + { + heading: ( + + ), + subheading: { + text: ( + + ), + }, + content: { + text: , + isBadge: true, + }, + }, + { + heading: , + subheading: null, + content: { text: null }, + }, + ]; + + return ( + <> + {infoRows.map(({ heading, content, subheading }, index) => ( + + ))} + + ); +}; diff --git a/packages/suite/src/components/suite/StakingProcess/types.ts b/packages/suite/src/components/suite/StakingProcess/types.ts new file mode 100644 index 00000000000..379fc40f18d --- /dev/null +++ b/packages/suite/src/components/suite/StakingProcess/types.ts @@ -0,0 +1,9 @@ +export type RowSubheading = { + text?: React.ReactNode; + isCurrentStep?: boolean; +} | null; + +export type RowContent = { + isBadge?: boolean; + text?: React.ReactNode; +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/InfoRow.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/InfoRow.tsx deleted file mode 100644 index 0b0f722083a..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/InfoRow.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Badge, Paragraph, Row, List } from '@trezor/components'; - -interface InfoRowProps { - label: React.ReactNode; - content: { - isBadge?: boolean; - text: React.ReactNode; - }; -} - -export const InfoRow = ({ label, content }: InfoRowProps) => { - const displayContent = content?.isBadge ? ( - {content.text} - ) : ( - - {content.text} - - ); - - return ( - - - {label} - {displayContent} - - - ); -}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakeEthInANutshellModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakeEthInANutshellModal.tsx index 2cc515760ef..56ed954761d 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakeEthInANutshellModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/StakeEthInANutshellModal.tsx @@ -1,3 +1,5 @@ +import React from 'react'; + import { Icon, IconName, @@ -19,8 +21,8 @@ import { spacings } from '@trezor/theme'; import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; import { getUnstakingPeriodInDays } from 'src/utils/suite/stake'; import { selectValidatorsQueueData } from '@suite-common/wallet-core'; -import { StakingInfo } from './StakingInfo'; -import { UnstakingInfo } from './UnstakingInfo'; +import { StakingInfo } from 'src/components/suite/StakingProcess/StakingInfo'; +import { UnstakingInfo } from 'src/components/suite/StakingProcess/UnstakingInfo'; interface StakingDetails { id: number; @@ -68,7 +70,7 @@ export const StakeEthInANutshellModal = ({ onCancel }: StakeEthInANutshellModalP { heading: , badge: , - content: , + content: , }, { heading: , @@ -78,7 +80,7 @@ export const StakeEthInANutshellModal = ({ onCancel }: StakeEthInANutshellModalP ), - content: , + content: , }, ]; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/UnstakingInfo.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/UnstakingInfo.tsx deleted file mode 100644 index 3d834e86252..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeEthInANutshellModal/UnstakingInfo.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { - selectAccountUnstakeTransactions, - selectValidatorsQueue, - TransactionsRootState, - StakeRootState, -} from '@suite-common/wallet-core'; -import { Translation } from 'src/components/suite'; -import { InfoRow } from './InfoRow'; -import { useSelector } from 'react-redux'; -import { getDaysToUnstake } from 'src/utils/suite/stake'; -import { Account } from 'src/types/wallet'; - -interface StakingInfoProps { - account?: Account; -} -export const UnstakingInfo = ({ account }: StakingInfoProps) => { - const { data } = - useSelector((state: StakeRootState) => selectValidatorsQueue(state, account?.symbol)) || {}; - - const unstakeTxs = useSelector((state: TransactionsRootState) => - selectAccountUnstakeTransactions(state, account?.key ?? ''), - ); - - if (!account) return null; - - const daysToUnstake = getDaysToUnstake(unstakeTxs, data); - - const infoRows = [ - { - label: , - content: { - text: , - isBadge: true, - }, - }, - { - label: , - content: { - text: , - }, - }, - { - label: ( - - ), - content: { - text: , - isBadge: true, - }, - }, - { - label: ( - - ), - content: { text: null }, - }, - ]; - - return ( - <> - {infoRows.map(({ label, content }, index) => ( - - ))} - - ); -}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx index 577138eca07..b4c6a0e6455 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx @@ -15,6 +15,7 @@ import { import { FIAT_INPUT, CRYPTO_INPUT } from 'src/types/wallet/stakeForms'; import { MIN_ETH_FOR_WITHDRAWALS } from 'src/constants/suite/ethStaking'; import { spacings, spacingsPx } from '@trezor/theme'; +import { validateStakingMax } from 'src/utils/suite/stake'; const IconWrapper = styled.div` transform: rotate(90deg); @@ -53,6 +54,7 @@ export const Inputs = () => { required: translationString('AMOUNT_IS_NOT_SET'), validate: { min: validateMin(translationString), + max: validateStakingMax(translationString), decimals: validateDecimals(translationString, { decimals: network.decimals }), reserveOrBalance: validateReserveOrBalance(translationString, { account, diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/StakeButton.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/StakeButton.tsx index 24a4cf6774e..610c2c2d5a1 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/StakeButton.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/StakeButton.tsx @@ -25,7 +25,6 @@ export const StakeButton = () => { return ( void; @@ -15,6 +17,7 @@ export const StakeModal = ({ onCancel }: StakeModalModalProps) => { state => state.wallet.selectedAccount, ) as SelectedAccountLoaded; const stakeEthContextValues = useStakeEthForm({ selectedAccount }); + const isBelowTablet = useMediaQuery(`(max-width: ${variables.SCREEN_SIZE.MD})`); const { account, status } = selectedAccount; // it shouldn't be possible to open this modal without having selected account @@ -23,12 +26,15 @@ export const StakeModal = ({ onCancel }: StakeModalModalProps) => { return ( } onCancel={onCancel} bottomContent={} > - + + + + ); diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/EstimatedGains.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/EstimatedGains.tsx new file mode 100644 index 00000000000..d0bc239ea1f --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/EstimatedGains.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { selectPoolStatsApyData, StakeRootState } from '@suite-common/wallet-core'; +import { Column, Grid, H2, Image, Paragraph, Text } from '@trezor/components'; +import { useSelector } from 'react-redux'; +import { Translation } from 'src/components/suite/Translation'; +import { useStakeEthFormContext } from 'src/hooks/wallet/useStakeEthForm'; +import { CRYPTO_INPUT } from 'src/types/wallet/stakeForms'; +import { FiatValue, FormattedCryptoAmount, TrezorLink } from 'src/components/suite'; +import styled, { useTheme } from 'styled-components'; +import { spacings, spacingsPx } from '@trezor/theme'; +import { calculateGains } from 'src/utils/suite/stake'; +import { HELP_CENTER_ETH_STAKING } from '@trezor/urls'; + +const Heading = styled.div` + margin-bottom: ${spacingsPx.xl}; +`; + +const ImageWrapper = styled.div` + margin-top: -${spacingsPx.xxxxl}; + width: 100%; +`; + +export const EstimatedGains = () => { + const { account, getValues, formState } = useStakeEthFormContext(); + + const theme = useTheme(); + + const value = getValues(CRYPTO_INPUT); + const hasInvalidFormState = + Object.keys(formState.errors).length > 0 && + formState.errors[CRYPTO_INPUT]?.type !== 'reserveOrBalance'; // provide gains calculation even if the user has not enough balance + + const cryptoInput = hasInvalidFormState || !value ? '0' : value; + + const ethApy = useSelector((state: StakeRootState) => + selectPoolStatsApyData(state, account?.symbol), + ); + + const gains = [ + { + label: , + value: calculateGains(cryptoInput, ethApy, 52), + }, + { + label: , + value: calculateGains(cryptoInput, ethApy, 12), + }, + { + label: , + value: calculateGains(cryptoInput, ethApy, 1), + }, + ]; + + return ( + <> + +

+ {ethApy}% +

+ + + + + + +
+ + {gains.map(({ label, value }, index) => ( + + + {label} + + + + + + + + + + ))} + + ( + {chunks} + ), + }} + /> + + + + ); +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/StakingInfoCards.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/StakingInfoCards.tsx new file mode 100644 index 00000000000..c8a80487ebd --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakingInfoCards/StakingInfoCards.tsx @@ -0,0 +1,40 @@ +import { Translation } from 'src/components/suite/Translation'; +import { Card, CollapsibleBox, Column, H3, List } from '@trezor/components'; +import { spacings } from '@trezor/theme'; +import { EstimatedGains } from './EstimatedGains'; +import { StakingInfo } from 'src/components/suite/StakingProcess/StakingInfo'; + +export const StakingInfoCards = () => { + const cards = [ + { + heading: , + content: , + defaultIsOpen: true, + }, + { + heading: , + content: , + defaultIsOpen: false, + }, + ]; + + return ( + + {cards.map((card, index) => ( + + {card.heading}} + fillType="none" + paddingType="none" + hasDivider={false} + defaultIsOpen={card.defaultIsOpen} + > + + {card.content} + + + + ))} + + ); +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeButton.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeButton.tsx new file mode 100644 index 00000000000..ea7fa1d89ce --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeButton.tsx @@ -0,0 +1,40 @@ +import { Tooltip, Button } from '@trezor/components'; +import { Translation } from 'src/components/suite'; +import { useDevice } from 'src/hooks/suite'; +import { CRYPTO_INPUT, FIAT_INPUT } from 'src/types/wallet/stakeForms'; +import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; +import { useUnstakeEthFormContext } from 'src/hooks/wallet/useUnstakeEthForm'; + +export const UnstakeButton = () => { + const { device, isLocked } = useDevice(); + const { isUnstakingDisabled, unstakingMessageContent } = useMessageSystemStaking(); + + const { + isComposing, + formState: { isSubmitting, errors }, + handleSubmit, + watch, + signTx, + } = useUnstakeEthFormContext(); + + const hasValues = Boolean(watch(FIAT_INPUT) || watch(CRYPTO_INPUT)); + // used instead of formState.isValid, which is sometimes returning false even if there are no errors + const formIsValid = Object.keys(errors).length === 0; + + const isDisabled = + !(formIsValid && hasValues) || isSubmitting || isLocked() || !device?.available; + + return ( + + + + ); +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx index 3605ef6ccf2..09b78f54909 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx @@ -1,8 +1,8 @@ import styled from 'styled-components'; -import { Button, Divider, Paragraph, Tooltip, Banner } from '@trezor/components'; +import { Divider, Paragraph, Banner } from '@trezor/components'; import { spacingsPx } from '@trezor/theme'; import { Translation } from 'src/components/suite'; -import { useDevice, useSelector } from 'src/hooks/suite'; +import { useSelector } from 'src/hooks/suite'; import { useUnstakeEthFormContext } from 'src/hooks/wallet/useUnstakeEthForm'; import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; import { CRYPTO_INPUT, FIAT_INPUT } from 'src/types/wallet/stakeForms'; @@ -11,7 +11,6 @@ import { getUnstakingPeriodInDays } from 'src/utils/suite/stake'; import UnstakeFees from './Fees'; import { selectValidatorsQueueData } from '@suite-common/wallet-core'; import { getAccountEverstakeStakingPool } from '@suite-common/wallet-utils'; -import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; // eslint-disable-next-line local-rules/no-override-ds-component const GreyP = styled(Paragraph)` @@ -48,16 +47,12 @@ const UpToDaysWrapper = styled.div` `; export const UnstakeEthForm = () => { - const { device, isLocked } = useDevice(); const selectedAccount = useSelector(selectSelectedAccount); - const { isUnstakingDisabled, unstakingMessageContent } = useMessageSystemStaking(); const { account, - isComposing, - formState: { isSubmitting, errors }, + formState: { errors }, handleSubmit, - watch, signTx, } = useUnstakeEthFormContext(); @@ -67,14 +62,9 @@ export const UnstakeEthForm = () => { selectValidatorsQueueData(state, account?.symbol), ); const unstakingPeriod = getUnstakingPeriodInDays(validatorWithdrawTime); - const hasValues = Boolean(watch(FIAT_INPUT) || watch(CRYPTO_INPUT)); - // used instead of formState.isValid, which is sometimes returning false even if there are no errors - const formIsValid = Object.keys(errors).length === 0; const { canClaim = false, claimableAmount = '0' } = getAccountEverstakeStakingPool(selectedAccount) ?? {}; - const isDisabled = - !(formIsValid && hasValues) || isSubmitting || isLocked() || !device?.available; const inputError = errors[CRYPTO_INPUT] || errors[FIAT_INPUT]; const showError = inputError && inputError.type === 'compose'; @@ -119,18 +109,6 @@ export const UnstakeEthForm = () => { }} /> - - - ); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModal.tsx index 62df631d8f4..98d794bee21 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModal.tsx @@ -1,32 +1,70 @@ -import styled from 'styled-components'; import { useSelector } from 'src/hooks/suite'; -import { Modal, Translation } from 'src/components/suite'; -import { UnstakeModalContent } from './UnstakeModalContent'; - -const StyledModal = styled(Modal)` - width: 512px; - text-align: left; -`; +import { Translation } from 'src/components/suite'; +import { + Card, + CollapsibleBox, + Column, + Grid, + H3, + List, + NewModal, + useMediaQuery, + variables, +} from '@trezor/components'; +import { spacings } from '@trezor/theme'; +import { UnstakingInfo } from 'src/components/suite/StakingProcess/UnstakingInfo'; +import { UnstakeButton } from './UnstakeEthForm/UnstakeButton'; +import { UnstakeEthFormContext, useUnstakeEthForm } from 'src/hooks/wallet/useUnstakeEthForm'; +import { UnstakeEthForm } from './UnstakeEthForm/UnstakeEthForm'; +import { SelectedAccountLoaded } from '@suite-common/wallet-types'; interface UnstakeModalModalProps { onCancel?: () => void; } export const UnstakeModal = ({ onCancel }: UnstakeModalModalProps) => { - const selectedAccount = useSelector(state => state.wallet.selectedAccount); + const selectedAccount = useSelector( + state => state.wallet.selectedAccount, + ) as SelectedAccountLoaded; + const unstakeEthContextValues = useUnstakeEthForm({ selectedAccount }); + const isBelowTablet = useMediaQuery(`(max-width: ${variables.SCREEN_SIZE.MD})`); const { account, status } = selectedAccount; // it shouldn't be possible to open this modal without having selected account if (!account || status !== 'loaded') return null; return ( - } - subheading={} - onCancel={onCancel} - > - - + + } + description={} + onCancel={onCancel} + bottomContent={} + > + + + + + + + + } + fillType="none" + paddingType="none" + hasDivider={false} + defaultIsOpen + > + + + + + + + + + ); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModalContent.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModalContent.tsx deleted file mode 100644 index 4201fd114dc..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeModalContent.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { UnstakeEthFormContext, useUnstakeEthForm } from 'src/hooks/wallet/useUnstakeEthForm'; -import { SelectedAccountLoaded } from '@suite-common/wallet-types'; -import { UnstakeEthForm } from './UnstakeEthForm/UnstakeEthForm'; - -interface UnstakeModalContentProps { - selectedAccount: SelectedAccountLoaded; -} - -export const UnstakeModalContent = ({ selectedAccount }: UnstakeModalContentProps) => { - const unstakeEthContextValues = useUnstakeEthForm({ selectedAccount }); - - return ( - - - - ); -}; diff --git a/packages/suite/src/components/wallet/Fees/Fees.tsx b/packages/suite/src/components/wallet/Fees/Fees.tsx index 86eacf1a6f3..68d9226ac1b 100644 --- a/packages/suite/src/components/wallet/Fees/Fees.tsx +++ b/packages/suite/src/components/wallet/Fees/Fees.tsx @@ -142,6 +142,9 @@ export const Fees = ({ // Solana has only `normal` fee level, so we do not display any feeOptions since there is nothing to choose from const feeOptions = networkType === 'solana' ? [] : buildFeeOptions(feeInfo.levels); + const showNormalFee = showFeeWhilePending || transactionInfo?.type === 'final'; + const shouldAnimateNormalFee = showNormalFee && !isCustomLevel; + return ( @@ -190,11 +193,13 @@ export const Fees = ({ )} - {!isCustomLevel && ( + {shouldAnimateNormalFee && ( ({ feeInfo={feeInfo} selectedLevel={selectedLevel} transactionInfo={transactionInfo} - showFee={showFeeWhilePending || transactionInfo?.type === 'final'} + showFee={showNormalFee} /> )} + {isCustomLevel && ( compound interest.', + }, TR_STAKE_ON_EVERSTAKE: { id: 'TR_STAKE_ON_EVERSTAKE', defaultMessage: 'Stake {symbol} on Everstake?', @@ -7389,6 +7406,26 @@ export default defineMessages({ defaultMessage: 'You received {amount} {symbol} "Instantly". {days, plural, =0 {} one {The rest will be payed out within # day.} other { The rest will be payed out within # days}}', }, + TR_STAKING_GETTING_READY: { + id: 'TR_STAKING_GETTING_READY', + defaultMessage: 'Your {symbol} is getting ready to work', + }, + TR_STAKING_REWARDS_ARE_RESTAKED: { + id: 'TR_STAKING_REWARDS_ARE_RESTAKED', + defaultMessage: 'Rewards are automatically restaked', + }, + TR_STAKING_YOU_ARE_HERE: { + id: 'TR_STAKING_YOU_ARE_HERE', + defaultMessage: "You're here", + }, + TR_STAKING_CONSOLIDATING_FUNDS: { + id: 'TR_STAKING_CONSOLIDATING_FUNDS', + defaultMessage: 'Consolidating your {symbol} for you', + }, + TR_STAKING_YOUR_UNSTAKED_FUNDS: { + id: 'TR_STAKING_YOUR_UNSTAKED_FUNDS', + defaultMessage: 'Your unstaked {symbol} is ready for you', + }, TR_RECEIVING_SYMBOL: { id: 'TR_RECEIVING_SYMBOL', defaultMessage: @@ -8704,6 +8741,22 @@ export default defineMessages({ id: 'TR_STAKE_APY', defaultMessage: 'Annual Percentage Yield', }, + TR_STAKE_APY_ABBR: { + id: 'TR_STAKE_APY_ABBR', + defaultMessage: 'APY', + }, + TR_STAKE_WEEKLY: { + id: 'TR_STAKE_WEEKLY', + defaultMessage: 'Weekly', + }, + TR_STAKE_MONTHLY: { + id: 'TR_STAKE_MONTHLY', + defaultMessage: 'Monthly', + }, + TR_STAKE_YEARLY: { + id: 'TR_STAKE_YEARLY', + defaultMessage: 'Yearly', + }, TR_STAKE_DAYS: { id: 'TR_STAKE_DAYS', defaultMessage: '{count, plural, one {# day} other {# days}}', diff --git a/packages/suite/src/utils/suite/stake.ts b/packages/suite/src/utils/suite/stake.ts index b86d18e6050..1edb8f93283 100644 --- a/packages/suite/src/utils/suite/stake.ts +++ b/packages/suite/src/utils/suite/stake.ts @@ -13,7 +13,11 @@ import TrezorConnect, { EthereumTransaction, Success, InternalTransfer } from '@ import { BigNumber } from '@trezor/utils/src/bigNumber'; import { STAKE_GAS_LIMIT_RESERVE, ValidatorsQueue } from '@suite-common/wallet-core'; import { BlockchainEstimatedFee } from '@trezor/connect/src/types/api/blockchainEstimateFee'; -import { MIN_ETH_AMOUNT_FOR_STAKING } from 'src/constants/suite/ethStaking'; +import { + MIN_ETH_AMOUNT_FOR_STAKING, + MAX_ETH_AMOUNT_FOR_STAKING, +} from 'src/constants/suite/ethStaking'; +import { TranslationFunction } from 'src/hooks/suite/useTranslation'; // source is a required parameter for some functions in the Everstake Wallet SDK. // This parameter is used for some contract calls. @@ -618,3 +622,22 @@ export const getChangedInternalTx = ( return internalTransfer ?? null; }; + +export const calculateGains = (input: string, apy: number, divisor: number) => { + const amount = new BigNumber(input).multipliedBy(apy).dividedBy(100).dividedBy(divisor); + + return amount.toFixed(5, 1); +}; + +interface ValidateMaxOptions { + except?: boolean; +} + +export const validateStakingMax = + (translationString: TranslationFunction, options?: ValidateMaxOptions) => (value: string) => { + if (!options?.except && value && BigNumber(value).gt(MAX_ETH_AMOUNT_FOR_STAKING)) { + return translationString('AMOUNT_EXCEEDS_MAX', { + maxAmount: MAX_ETH_AMOUNT_FOR_STAKING.toString(), + }); + } + }; From bf7ef931f16866a763bd5c9925ed0e8213c56a0b Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Mon, 14 Oct 2024 15:23:36 +0200 Subject: [PATCH 120/624] fix(wallet-utils): don't export from fixtures --- .../suite/src/actions/wallet/__fixtures__/blockchainActions.ts | 2 +- packages/suite/src/storage/__tests__/storage.test.ts | 2 ++ suite-common/wallet-utils/src/index.ts | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/suite/src/actions/wallet/__fixtures__/blockchainActions.ts b/packages/suite/src/actions/wallet/__fixtures__/blockchainActions.ts index 1aca4c90469..e544600da36 100644 --- a/packages/suite/src/actions/wallet/__fixtures__/blockchainActions.ts +++ b/packages/suite/src/actions/wallet/__fixtures__/blockchainActions.ts @@ -1,4 +1,4 @@ -import { analyzeTransactionsFixtures as analyzeTransactions } from '@suite-common/wallet-utils'; +import { analyzeTransactions } from '@suite-common/wallet-utils/src/__fixtures__/transactionUtils'; import { blockchainActions, transactionsActions, accountsActions } from '@suite-common/wallet-core'; import { notificationsActions } from '@suite-common/toast-notifications'; diff --git a/packages/suite/src/storage/__tests__/storage.test.ts b/packages/suite/src/storage/__tests__/storage.test.ts index 4b42e61f005..0a4450270a6 100644 --- a/packages/suite/src/storage/__tests__/storage.test.ts +++ b/packages/suite/src/storage/__tests__/storage.test.ts @@ -1,3 +1,5 @@ +import '@suite-common/test-utils/src/mocks'; + import { db } from '..'; describe('storage', () => { diff --git a/suite-common/wallet-utils/src/index.ts b/suite-common/wallet-utils/src/index.ts index 543272e299f..f4add089ebe 100644 --- a/suite-common/wallet-utils/src/index.ts +++ b/suite-common/wallet-utils/src/index.ts @@ -20,5 +20,3 @@ export * from './stakingUtils'; export * from './reviewTransactionUtils'; export * from './filterReceiveAccounts'; export * from './tokenUtils'; - -export { analyzeTransactions as analyzeTransactionsFixtures } from './__fixtures__/transactionUtils'; From 39c0c639f5dbf486b21f556e0aa6408287126f84 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Wed, 11 Sep 2024 09:43:38 +0200 Subject: [PATCH 121/624] test(suite-web): add a test for t3t1 multishare backup --- .../pageObjects/multiShareBackupObject.ts | 16 +++++ .../pageObjects/settingsDeviceObject.ts | 12 ++++ .../support/pageObjects/settingsMenuObject.ts | 9 +++ .../t3t1-create-addtional-share.test.ts | 67 +++++++++++++++++++ .../MultiShareBackupModal.tsx | 15 ++++- .../MultiShareBackupStep1FirstInfo.tsx | 2 + 6 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 packages/suite-web/e2e/support/pageObjects/multiShareBackupObject.ts create mode 100644 packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts create mode 100644 packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts create mode 100644 packages/suite-web/e2e/tests/backup/t3t1-create-addtional-share.test.ts diff --git a/packages/suite-web/e2e/support/pageObjects/multiShareBackupObject.ts b/packages/suite-web/e2e/support/pageObjects/multiShareBackupObject.ts new file mode 100644 index 00000000000..821974d3ad5 --- /dev/null +++ b/packages/suite-web/e2e/support/pageObjects/multiShareBackupObject.ts @@ -0,0 +1,16 @@ +/// + +class MultiShareBackupModal { + createMultiShareBackup(): void { + cy.getTestElement('@multi-share-backup/checkbox/1').click(); + cy.getTestElement('@multi-share-backup/checkbox/2').click(); + cy.getTestElement('@multi-share-backup/1st-info/submit-button').click(); + cy.getTestElement('@multi-share-backup/2nd-info/submit-button').click(); + } + + finalizeMultiShareBackup(): void { + cy.getTestElement('@multi-share-backup/done/got-it-button').should('be.visible').click(); + } +} + +export const onMultiShareBackupModal = new MultiShareBackupModal(); diff --git a/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts b/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts new file mode 100644 index 00000000000..af47f1fd6c5 --- /dev/null +++ b/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts @@ -0,0 +1,12 @@ +/// + +class SettingsDevicePage { + openCreateMultiShareBackup(): void { + cy.getTestElement('@settings/device/create-multi-share-backup-button') + .should('be.visible') + .click(); + cy.getTestElement('@multi-share-backup/1st-info/submit-button').should('be.visible'); + } +} + +export const onSettingsDevicePage = new SettingsDevicePage(); diff --git a/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts b/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts new file mode 100644 index 00000000000..bb0b4b8d900 --- /dev/null +++ b/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts @@ -0,0 +1,9 @@ +/// + +class SettingsMenu { + openDeviceSettings(): void { + cy.getTestElement('@settings/menu/device').should('be.visible').click(); + } +} + +export const onSettingsMenu = new SettingsMenu(); diff --git a/packages/suite-web/e2e/tests/backup/t3t1-create-addtional-share.test.ts b/packages/suite-web/e2e/tests/backup/t3t1-create-addtional-share.test.ts new file mode 100644 index 00000000000..16d1b518b2f --- /dev/null +++ b/packages/suite-web/e2e/tests/backup/t3t1-create-addtional-share.test.ts @@ -0,0 +1,67 @@ +// @group_device-management +// @retry=2 + +import { onNavBar } from '../../support/pageObjects/topBarObject'; +import { onSettingsMenu } from '../../support/pageObjects/settingsMenuObject'; +import { onSettingsDevicePage } from '../../support/pageObjects/settingsDeviceObject'; +import { onMultiShareBackupModal } from '../../support/pageObjects/multiShareBackupObject'; + +const mnemonic = + 'academic again academic academic academic academic academic academic academic academic academic academic academic academic academic academic academic pecan provide remember'; +describe('Backup success', () => { + beforeEach(() => { + cy.task('startEmu', { wipe: true, model: 'T3T1', version: '2.8.1' }); + cy.task('setupEmu', { + needs_backup: false, + mnemonic, + }); + cy.task('startBridge'); + + cy.viewport('macbook-15').resetDb(); + cy.prefixedVisit('/'); + }); + + it('Successful backup happy path', () => { + // Arrange + cy.getTestElement('@analytics/continue-button', { timeout: 40000 }) + .click() + .getTestElement('@onboarding/exit-app-button') + .click(); + cy.passThroughAuthenticityCheck(); + cy.getTestElement('@onboarding/viewOnly/enable').click(); + cy.getTestElement('@viewOnlyTooltip/gotIt', { timeout: 15000 }) + .should('be.visible') + .click(); + + // Act + // navigate to device settings page + onNavBar.openSettings(); + onSettingsMenu.openDeviceSettings(); + onSettingsDevicePage.openCreateMultiShareBackup(); + onMultiShareBackupModal.createMultiShareBackup(); + + // [device screen] check your backup? + cy.task('swipeEmu', 'up'); + + // [device screen] select the number of words in your backup + cy.task('inputEmu', '20'); + + // [device screen] backup instructions + cy.task('swipeEmu', 'up'); + for (const word of mnemonic.split(' ')) { + // [device screen] enter next word + cy.task('inputEmu', word); + } + + // [device screen] create additional backup? + cy.wait(1000); // without this timeout, backup on device simply disappears, it stinks + cy.task('swipeEmu', 'up'); + + cy.task('readAndConfirmShamirMnemonicEmu', { shares: 3, threshold: 2 }); + + // Assert + onMultiShareBackupModal.finalizeMultiShareBackup(); + }); +}); + +export {}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupModal.tsx index e8d1f4f6af6..3f0b1011a6d 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupModal.tsx @@ -91,7 +91,10 @@ export const MultiShareBackupModal = ({ onCancel }: MultiShareBackupModalProps) ), bottomBarComponents: ( <> - , bottomBarComponents: ( <> - @@ -179,7 +185,10 @@ export const MultiShareBackupModal = ({ onCancel }: MultiShareBackupModalProps) children: , bottomBarComponents: ( <> - diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx index f9c98970b43..8239fcc18b6 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx @@ -60,6 +60,7 @@ export const MultiShareBackupStep1FirstInfo = ({ isChecked={isChecked1} onClick={toggleCheckbox1} variant={checkboxVariant1} + data-testid={`@multi-share-backup/checkbox/1`} > @@ -67,6 +68,7 @@ export const MultiShareBackupStep1FirstInfo = ({ isChecked={isChecked2} onClick={toggleCheckbox2} variant={checkboxVariant2} + data-testid={`@multi-share-backup/checkbox/2`} > From 33e4fe1078f512d5e7724d69220c257752381b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Such=C3=BD?= Date: Tue, 15 Oct 2024 13:04:29 +0200 Subject: [PATCH 122/624] feat(mobile): migrate BottomSheetFlashList to new lib (#14854) --- .../mobile-dependencies.txt | 3 +- .../components/AccountSelectBottomSheet.tsx | 5 +- suite-native/app/package.json | 1 + suite-native/app/src/App.tsx | 5 +- suite-native/atoms/package.json | 1 + .../atoms/src/Sheet/BottomSheetFlashList.tsx | 165 ++++++++---------- yarn.lock | 38 +++- 7 files changed, 116 insertions(+), 102 deletions(-) diff --git a/scripts/list-outdated-dependencies/mobile-dependencies.txt b/scripts/list-outdated-dependencies/mobile-dependencies.txt index 6ba394ced94..8f54c36dd89 100644 --- a/scripts/list-outdated-dependencies/mobile-dependencies.txt +++ b/scripts/list-outdated-dependencies/mobile-dependencies.txt @@ -67,4 +67,5 @@ yup metro metro-react-native-babel-preset jest-expo -intl-pluralrules \ No newline at end of file +intl-pluralrules +@gorhom/bottom-sheet \ No newline at end of file diff --git a/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx b/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx index b6e71496c73..9009b61b5de 100644 --- a/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx +++ b/suite-native/accounts/src/components/AccountSelectBottomSheet.tsx @@ -1,7 +1,7 @@ import React, { useCallback } from 'react'; import { BottomSheetFlashList } from '@suite-native/atoms'; -import { ToastRenderer, useToast } from '@suite-native/toasts'; +import { useToast } from '@suite-native/toasts'; import { Translation } from '@suite-native/intl'; import { AccountSelectBottomSheetSection, OnSelectAccount } from '../types'; @@ -97,8 +97,7 @@ export const AccountSelectBottomSheet = React.memo( data={data} renderItem={renderItem} estimatedItemSize={ESTIMATED_ITEM_SIZE} - estimatedListHeight={ESTIMATED_ITEM_SIZE * data.length} - ExtraProvider={ToastRenderer} + estimatedListHeight={ESTIMATED_ITEM_SIZE * data.length * 1.5} /> ); }, diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 18f2e18aa2e..7ec7cb4c4fe 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -22,6 +22,7 @@ "reverse-ports": "adb reverse tcp:8081 tcp:8081 && adb reverse tcp:21325 tcp:21325 && adb reverse tcp:19121 tcp:19121" }, "dependencies": { + "@gorhom/bottom-sheet": "5.0.1", "@mobily/ts-belt": "^3.13.1", "@react-native-community/netinfo": "11.3.2", "@react-native/metro-config": "0.75.2", diff --git a/suite-native/app/src/App.tsx b/suite-native/app/src/App.tsx index 3d151d75d15..f73abde5ba0 100644 --- a/suite-native/app/src/App.tsx +++ b/suite-native/app/src/App.tsx @@ -5,6 +5,7 @@ import { useDispatch, useSelector } from 'react-redux'; import * as SplashScreen from 'expo-splash-screen'; import * as Sentry from '@sentry/react-native'; +import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; import { selectIsAppReady, selectIsConnectInitialized, StoreProvider } from '@suite-native/state'; import { FormatterProvider } from '@suite-common/formatters'; @@ -65,7 +66,9 @@ const AppComponent = () => { - + + + {/* NOTE: Rendered as last item so that it covers the whole app screen */} diff --git a/suite-native/atoms/package.json b/suite-native/atoms/package.json index f29f32097ad..d3dd9c4b3f2 100644 --- a/suite-native/atoms/package.json +++ b/suite-native/atoms/package.json @@ -11,6 +11,7 @@ "type-check": "yarn g:tsc --build" }, "dependencies": { + "@gorhom/bottom-sheet": "5.0.1", "@mobily/ts-belt": "^3.13.1", "@shopify/flash-list": "1.7.1", "@shopify/react-native-skia": "1.3.11", diff --git a/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx b/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx index d234fc26366..612ef883911 100644 --- a/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx +++ b/suite-native/atoms/src/Sheet/BottomSheetFlashList.tsx @@ -1,35 +1,32 @@ -import { useEffect, useRef, ReactNode } from 'react'; +import { ReactNode, useCallback, useEffect, useMemo, useRef } from 'react'; +import { Dimensions, StyleSheet, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import Animated from 'react-native-reanimated'; -import { PanGestureHandler } from 'react-native-gesture-handler'; -import { GestureResponderEvent, Pressable, Dimensions } from 'react-native'; -import { FlashList, FlashListProps } from '@shopify/flash-list'; +import { + BottomSheetBackdrop, + BottomSheetModal, + BottomSheetFlashList as FlashList, +} from '@gorhom/bottom-sheet'; +import { FlashListProps } from '@shopify/flash-list'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; -import { Box } from '../Box'; -import { BottomSheetContainer } from './BottomSheetContainer'; -import { useBottomSheetAnimation } from './useBottomSheetAnimation'; -import { BottomSheetHeader } from './BottomSheetHeader'; - export type BottomSheetFlashListProps = { isVisible: boolean; isCloseDisplayed?: boolean; onClose: (isVisible: boolean) => void; title?: ReactNode; subtitle?: ReactNode; - ExtraProvider?: React.ComponentType; estimatedListHeight?: number; } & FlashListProps; -const DEFAULT_INSET_BOTTOM = 50; +const DEFAULT_INSET_BOTTOM = 25; -const sheetWrapperStyle = prepareNativeStyle(utils => ({ +const bottomSheetStyle = prepareNativeStyle(utils => ({ backgroundColor: utils.colors.backgroundSurfaceElevation0, + borderTopLeftRadius: utils.borders.radii.r20, borderTopRightRadius: utils.borders.radii.r20, - maxHeight: '80%', })); const sheetContentContainerStyle = prepareNativeStyle<{ @@ -39,107 +36,83 @@ const sheetContentContainerStyle = prepareNativeStyle<{ paddingHorizontal: utils.spacings.sp16, })); -const sheetWithOverlayStyle = prepareNativeStyle(_ => ({ - flex: 1, - justifyContent: 'flex-end', +const handleStyle = prepareNativeStyle(utils => ({ + backgroundColor: utils.colors.borderDashed, })); +const WindowOverlay = ({ children }: { children: ReactNode }) => { + return {children}; +}; + export const BottomSheetFlashList = ({ isVisible, isCloseDisplayed = true, onClose, title, subtitle, - ExtraProvider, estimatedListHeight = 0, ...flashListProps }: BottomSheetFlashListProps) => { const { applyStyle } = useNativeStyles(); const insets = useSafeAreaInsets(); - const { - animatedSheetWithOverlayStyle, - animatedSheetWrapperStyle, - closeSheetAnimated, - openSheetAnimated, - panGestureEvent, - scrollEvent, - } = useBottomSheetAnimation({ - onClose, - isVisible, - }); - const panGestureRef = useRef(null); - const scrollViewRef = useRef(null); - useEffect(() => { - if (isVisible) { - openSheetAnimated(); - } - }, [isVisible, openSheetAnimated]); + const bottomSheetModalRef = useRef(null); - const handlePressOutside = (event: GestureResponderEvent) => { - if (event.target === event.currentTarget) closeSheetAnimated(); - }; + const handleClose = useCallback(() => { + bottomSheetModalRef.current?.dismiss(); + onClose(false); + }, [onClose]); const insetBottom = Math.max(insets.bottom, DEFAULT_INSET_BOTTOM); + const maxHeight = Dimensions.get('window').height * 0.9; + const minHeight = Math.max(Dimensions.get('window').height * 0.4, estimatedListHeight); + // minHeight can be higher than maxHeight because of estimatedListHeight, but it must be capped by maxHeight + const snapPoints = useMemo(() => [Math.min(minHeight, maxHeight)], [minHeight, maxHeight]); + + const handleSheetChanges = useCallback( + (index: number) => { + if (index === -1) { + handleClose(); + } + }, + [handleClose], + ); + + useEffect(() => { + if (isVisible) { + bottomSheetModalRef.current?.present(); + } else { + bottomSheetModalRef.current?.dismiss(); + } + }, [isVisible]); + return ( - ( + + )} + backgroundStyle={applyStyle(bottomSheetStyle)} + handleIndicatorStyle={applyStyle(handleStyle)} + // @ts-expect-error wrong type, doesn't expect children + containerComponent={WindowOverlay} > - - - - - - - - - - - - - - + + ); }; diff --git a/yarn.lock b/yarn.lock index edcce42cec7..db51dc1ce5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4475,6 +4475,40 @@ __metadata: languageName: node linkType: hard +"@gorhom/bottom-sheet@npm:5.0.1": + version: 5.0.1 + resolution: "@gorhom/bottom-sheet@npm:5.0.1" + dependencies: + "@gorhom/portal": "npm:1.0.14" + invariant: "npm:^2.2.4" + peerDependencies: + "@types/react": "*" + "@types/react-native": "*" + react: "*" + react-native: "*" + react-native-gesture-handler: ">=2.16.1" + react-native-reanimated: ">=3.10.1" + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-native": + optional: true + checksum: 10/61134493ac61f96a5bc7aae20f4a6465f19138d7d2d36129d2285022ee52fe02648d7706212b17d5e1c6acdf0d0a5ee0124884b44a34eb468406e89a86c6102c + languageName: node + linkType: hard + +"@gorhom/portal@npm:1.0.14": + version: 1.0.14 + resolution: "@gorhom/portal@npm:1.0.14" + dependencies: + nanoid: "npm:^3.3.1" + peerDependencies: + react: "*" + react-native: "*" + checksum: 10/e0fa06be88b850cccdc6a1417a86e5ac21d82e3bfd1cec7eb05eccf7f3b595babe305541f278fdcbde34f3a9db465097dca2c785445c28bafb83b744e235da0c + languageName: node + linkType: hard + "@graphql-typed-document-node/core@npm:^3.1.0, @graphql-typed-document-node/core@npm:^3.1.1": version: 3.1.1 resolution: "@graphql-typed-document-node/core@npm:3.1.1" @@ -9542,6 +9576,7 @@ __metadata: "@babel/core": "npm:^7.20.0" "@babel/plugin-transform-export-namespace-from": "npm:^7.23.4" "@config-plugins/detox": "npm:^8.0.0" + "@gorhom/bottom-sheet": "npm:5.0.1" "@mobily/ts-belt": "npm:^3.13.1" "@react-native-community/netinfo": "npm:11.3.2" "@react-native/babel-preset": "npm:^0.75.2" @@ -9684,6 +9719,7 @@ __metadata: version: 0.0.0-use.local resolution: "@suite-native/atoms@workspace:suite-native/atoms" dependencies: + "@gorhom/bottom-sheet": "npm:5.0.1" "@mobily/ts-belt": "npm:^3.13.1" "@shopify/flash-list": "npm:1.7.1" "@shopify/react-native-skia": "npm:1.3.11" @@ -32069,7 +32105,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.1.23, nanoid@npm:^3.1.3, nanoid@npm:^3.3.4, nanoid@npm:^3.3.6, nanoid@npm:^3.3.7": +"nanoid@npm:^3.1.23, nanoid@npm:^3.1.3, nanoid@npm:^3.3.1, nanoid@npm:^3.3.4, nanoid@npm:^3.3.6, nanoid@npm:^3.3.7": version: 3.3.7 resolution: "nanoid@npm:3.3.7" bin: From cc33611be943c1b8d2d5578c974da28c4c06317a Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Tue, 15 Oct 2024 12:26:38 +0200 Subject: [PATCH 123/624] feat(type-utils): isArrayMember --- packages/type-utils/src/utils.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/type-utils/src/utils.ts b/packages/type-utils/src/utils.ts index b5e0df410ca..22d5a53f986 100644 --- a/packages/type-utils/src/utils.ts +++ b/packages/type-utils/src/utils.ts @@ -58,3 +58,17 @@ export type PartialRecord = { // distributive conditional types to the rescue! This way we can infer union literal type from ReturnType but exclude undefined export type DefinedUnionMember = T extends string ? T : never; + +/** + * Type-guard if a value is a subset of an array. + * Useful to narrow down a union type `value` to a subset of the union (typeof `arr`). + * + * Example: + * type Variant = 'a' | 'b' | 'c' | 'd'; + * const skippedVariants = ['a', 'b'] satisfies Variant[]; + * if(isArrayMember(variant, skippedVariants)) // variant is 'a' | 'b', else 'c' | 'd' + */ +export const isArrayMember = ( + value: Value, + arr: Subset[], +): value is Subset => arr.some(v => v === value); From 81a5368dd73e51701919417d3990a8923ab5a59c Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Tue, 15 Oct 2024 12:27:32 +0200 Subject: [PATCH 124/624] feat(suite): hide fw hash check banner for old versions --- .../SuiteBanners/FirmwareRevisionCheckBanner.tsx | 12 +++++++++--- .../suite/banners/SuiteBanners/SuiteBanners.tsx | 5 +++-- packages/suite/src/support/messages.ts | 5 ----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx index aaeac2ecbac..a5e2c6dcf24 100644 --- a/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx +++ b/packages/suite/src/components/suite/banners/SuiteBanners/FirmwareRevisionCheckBanner.tsx @@ -2,6 +2,7 @@ import { TranslationKey } from '@suite-common/intl-types'; import { Banner } from '@trezor/components'; import { FirmwareHashCheckError, FirmwareRevisionCheckError } from '@trezor/connect'; import { HELP_CENTER_FIRMWARE_REVISION_CHECK } from '@trezor/urls'; +import { isArrayMember } from '@trezor/type-utils'; import { Translation, TrezorLink } from 'src/components/suite'; import { useSelector } from 'src/hooks/suite'; @@ -17,12 +18,17 @@ const revisionCheckMessages: Record 'firmware-version-unknown': 'TR_FIRMWARE_REVISION_CHECK_FAILED', }; +export const skippedHashCheckErrors = [ + 'check-skipped', + 'check-unsupported', +] satisfies FirmwareHashCheckError[]; +type SkippedHashCheckMessage = (typeof skippedHashCheckErrors)[number]; + const hashCheckMessages: Record< - Exclude, + Exclude, TranslationKey > = { 'hash-mismatch': 'TR_DEVICE_FIRMWARE_HASH_CHECK_HASH_MISMATCH', - 'check-unsupported': 'TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED', 'unknown-release': 'TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE', 'other-error': 'TR_DEVICE_FIRMWARE_HASH_CHECK_OTHER_ERROR', }; @@ -34,7 +40,7 @@ const useAuthenticityCheckMessage = (): TranslationKey | null => { if (firmwareRevisionError) { return revisionCheckMessages[firmwareRevisionError]; } - if (firmwareHashError && firmwareHashError !== 'check-skipped') { + if (firmwareHashError && !isArrayMember(firmwareHashError, skippedHashCheckErrors)) { return hashCheckMessages[firmwareHashError]; } diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx index 2bd8d63da6c..d223961c251 100644 --- a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx +++ b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components'; import { selectBannerMessage } from '@suite-common/message-system'; import { isDeviceAcquired } from '@suite-common/suite-utils'; import { selectDevice } from '@suite-common/wallet-core'; +import { isArrayMember } from '@trezor/type-utils'; import { isDesktop } from '@trezor/env-utils'; import { spacingsPx } from '@trezor/theme'; @@ -23,7 +24,7 @@ import { FailedBackup } from './FailedBackupBanner'; import { SafetyChecksBanner } from './SafetyChecksBanner'; import { TranslationMode } from './TranslationModeBanner'; import { FirmwareHashMismatch } from './FirmwareHashMismatchBanner'; -import { FirmwareRevisionCheckBanner } from './FirmwareRevisionCheckBanner'; +import { FirmwareRevisionCheckBanner, skippedHashCheckErrors } from './FirmwareRevisionCheckBanner'; const Container = styled.div<{ $isVisible?: boolean }>` width: 100%; @@ -71,7 +72,7 @@ export const SuiteBanners = () => { // the regular firmware hash check, and revision id check, either of them may fail else if ( firmwareRevisionError || - (firmwareHashError && firmwareHashError !== 'check-skipped') + (firmwareHashError && !isArrayMember(firmwareHashError, skippedHashCheckErrors)) ) { banner = ; priority = 91; diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 6002729143f..384f412c167 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -7025,11 +7025,6 @@ export default defineMessages({ id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_HASH_MISMATCH', defaultMessage: 'Firmware hash check failed. Your Trezor may be counterfeit.', }, - TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED: { - id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_CHECK_UNSUPPORTED', - defaultMessage: - 'New Trezor firmware is available! Update your device now to get latest security features.', - }, TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE: { id: 'TR_DEVICE_FIRMWARE_HASH_CHECK_UNKNOWN_RELEASE', defaultMessage: 'Firmware unrecognized. Your Trezor may be counterfeit.', From 8b363e7102ac31122892f070c4b4d1c6a72d6cfd Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Tue, 15 Oct 2024 13:02:41 +0200 Subject: [PATCH 125/624] fix(suite): eslint warning unnecessary curly --- .../MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx index 8239fcc18b6..43a5e5877ee 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/MultiShareBackupModal/MultiShareBackupStep1FirstInfo.tsx @@ -60,7 +60,7 @@ export const MultiShareBackupStep1FirstInfo = ({ isChecked={isChecked1} onClick={toggleCheckbox1} variant={checkboxVariant1} - data-testid={`@multi-share-backup/checkbox/1`} + data-testid="@multi-share-backup/checkbox/1" > @@ -68,7 +68,7 @@ export const MultiShareBackupStep1FirstInfo = ({ isChecked={isChecked2} onClick={toggleCheckbox2} variant={checkboxVariant2} - data-testid={`@multi-share-backup/checkbox/2`} + data-testid="@multi-share-backup/checkbox/2" > From 96e81fe5bfcd43821894f3b7c304f03db3e71eac Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Thu, 10 Oct 2024 08:45:00 +0200 Subject: [PATCH 126/624] refactor(connect): dynamic connect --- packages/connect/src/impl/dynamic.ts | 135 ++++++++++++++++++ .../src/utils/proxy-event-emitter.ts | 2 +- 2 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 packages/connect/src/impl/dynamic.ts rename packages/{connect-web => connect}/src/utils/proxy-event-emitter.ts (97%) diff --git a/packages/connect/src/impl/dynamic.ts b/packages/connect/src/impl/dynamic.ts new file mode 100644 index 00000000000..b1bc2f042ac --- /dev/null +++ b/packages/connect/src/impl/dynamic.ts @@ -0,0 +1,135 @@ +import EventEmitter from 'events'; + +import { ConnectFactoryDependencies } from '../factory'; +import type { ConnectSettingsPublic, Manifest } from '../types'; +import { CallMethodPayload } from '../events'; +import { ERRORS } from '../constants'; + +import { ProxyEventEmitter } from '../utils/proxy-event-emitter'; + +type TrezorConnectDynamicParams = { + implementations: { + type: TrezorConnectImplType; + impl: ConnectFactoryDependencies; + }[]; + getInitTarget: (settings: Partial) => TrezorConnectImplType; + handleErrorFallback: (errorCode: string) => Promise; +}; + +/** + * Implementation of TrezorConnect that can dynamically switch between different implementations. + * + */ +export class TrezorConnectDynamic implements ConnectFactoryDependencies { + public eventEmitter: EventEmitter; + + private currentTarget: TrezorConnectImplType; + private implementations: TrezorConnectDynamicParams['implementations']; + private getInitTarget: TrezorConnectDynamicParams['getInitTarget']; + private handleErrorFallback: TrezorConnectDynamicParams['handleErrorFallback']; + + public lastSettings?: { manifest: Manifest } & Partial; + + public constructor({ + implementations, + getInitTarget, + handleErrorFallback, + }: TrezorConnectDynamicParams) { + this.implementations = implementations; + this.currentTarget = this.implementations[0].type; + this.getInitTarget = getInitTarget; + this.handleErrorFallback = handleErrorFallback; + this.eventEmitter = new ProxyEventEmitter( + this.implementations.map(impl => impl.impl.eventEmitter), + ); + } + + private getTarget() { + return this.implementations.find(impl => impl.type === this.currentTarget)!.impl; + } + + public async switchTarget(target: TrezorConnectImplType) { + if (this.currentTarget === target) { + return; + } + + if (!this.lastSettings) { + throw ERRORS.TypedError('Init_NotInitialized'); + } + await this.getTarget().dispose(); + this.currentTarget = target; + await this.getTarget().init(this.lastSettings); + } + + public manifest(manifest: Manifest) { + this.lastSettings = { + ...this.lastSettings, + manifest, + }; + + this.getTarget().manifest(manifest); + } + + public async init(settings: { manifest: Manifest } & Partial) { + if (!settings?.manifest) { + throw ERRORS.TypedError('Init_ManifestMissing'); + } + // Save settings for later use + this.lastSettings = settings; + + this.currentTarget = this.getInitTarget(settings); + + // Initialize the target + try { + return await this.getTarget().init(this.lastSettings); + } catch (error) { + // Handle error by switching to other implementation if available as defined in `handleErrorFallback`. + if (await this.handleErrorFallback(error.code)) { + return await this.getTarget().init(settings); + } + + throw error; + } + } + + public async call(params: CallMethodPayload) { + const response = await this.getTarget().call(params); + if (!response.success) { + if (await this.handleErrorFallback(response.payload.code)) { + return await this.getTarget().call(params); + } + } + + return response; + } + + public requestLogin(params: any) { + return this.getTarget().requestLogin(params); + } + + public uiResponse(params: any) { + return this.getTarget().uiResponse(params); + } + + public renderWebUSBButton() { + return this.getTarget().renderWebUSBButton(); + } + + public disableWebUSB() { + return this.getTarget().disableWebUSB(); + } + + public requestWebUSBDevice() { + return this.getTarget().requestWebUSBDevice(); + } + + public cancel(error?: string) { + return this.getTarget().cancel(error); + } + + public dispose() { + this.eventEmitter.removeAllListeners(); + + return this.getTarget().dispose(); + } +} diff --git a/packages/connect-web/src/utils/proxy-event-emitter.ts b/packages/connect/src/utils/proxy-event-emitter.ts similarity index 97% rename from packages/connect-web/src/utils/proxy-event-emitter.ts rename to packages/connect/src/utils/proxy-event-emitter.ts index 77c0ea2b036..ad92f7b3728 100644 --- a/packages/connect-web/src/utils/proxy-event-emitter.ts +++ b/packages/connect/src/utils/proxy-event-emitter.ts @@ -4,7 +4,7 @@ import EventEmitter from 'events'; * ProxyEventEmitter is an EventEmitter that allows to use multiple EventEmitters as one * This is used in connect-web to allow switching between iframe and core-in-popup implementations */ -export default class ProxyEventEmitter implements EventEmitter { +export class ProxyEventEmitter implements EventEmitter { private eventEmitters: EventEmitter[]; constructor(eventEmitters: EventEmitter[]) { From 887889288fefac258e30ac928d74805de49af3ea Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Thu, 10 Oct 2024 08:45:32 +0200 Subject: [PATCH 127/624] refactor(connect-web): use dynamic from connect package --- packages/connect-web/src/index.ts | 153 ++++++------------------------ 1 file changed, 29 insertions(+), 124 deletions(-) diff --git a/packages/connect-web/src/index.ts b/packages/connect-web/src/index.ts index 7ead4ff22a5..afafff44368 100644 --- a/packages/connect-web/src/index.ts +++ b/packages/connect-web/src/index.ts @@ -1,107 +1,44 @@ -import { ConnectFactoryDependencies, factory } from '@trezor/connect/src/factory'; +import { factory } from '@trezor/connect/src/factory'; +import { TrezorConnectDynamic } from '@trezor/connect/src/impl/dynamic'; import { CoreInIframe } from './impl/core-in-iframe'; import { CoreInPopup } from './impl/core-in-popup'; -import ProxyEventEmitter from './utils/proxy-event-emitter'; -import type { ConnectSettings, ConnectSettingsPublic, Manifest } from '@trezor/connect/src/types'; -import EventEmitter from 'events'; -import { CallMethodPayload } from '@trezor/connect/src/events'; +import type { ConnectSettingsPublic } from '@trezor/connect'; import { getEnv } from './connectSettings'; -type TrezorConnectType = 'core-in-popup' | 'iframe'; - const IFRAME_ERRORS = ['Init_IframeBlocked', 'Init_IframeTimeout', 'Transport_Missing']; -/** - * Implementation of TrezorConnect that can dynamically switch between iframe and core-in-popup implementations - */ -export class TrezorConnectDynamicImpl implements ConnectFactoryDependencies { - public eventEmitter: EventEmitter; - - private currentTarget: TrezorConnectType = 'iframe'; - private coreInIframeImpl: CoreInIframe; - private coreInPopupImpl: CoreInPopup; - - private lastSettings?: Partial; - - public constructor() { - this.coreInIframeImpl = new CoreInIframe(); - this.coreInPopupImpl = new CoreInPopup(); - this.eventEmitter = new ProxyEventEmitter([ - this.coreInIframeImpl.eventEmitter, - this.coreInPopupImpl.eventEmitter, - ]); - } - - private getTarget() { - return this.currentTarget === 'iframe' ? this.coreInIframeImpl : this.coreInPopupImpl; - } - - private async switchTarget(target: TrezorConnectType) { - if (this.currentTarget === target) { - return; - } - - await this.getTarget().dispose(); - this.currentTarget = target; - await this.getTarget().init(this.lastSettings); - } - - public manifest(manifest: Manifest) { - this.lastSettings = { - ...this.lastSettings, - manifest, - }; - - this.getTarget().manifest(manifest); - } - - public async init(settings: Partial = {}) { +const impl = new TrezorConnectDynamic<'core-in-popup' | 'iframe'>({ + implementations: [ + { + type: 'iframe', + impl: new CoreInIframe(), + }, + { + type: 'core-in-popup', + impl: new CoreInPopup(), + }, + ], + getInitTarget: (settings: Partial) => { const env = getEnv(); if (settings.coreMode === 'iframe' || settings.popup === false || env === 'webextension') { - this.currentTarget = 'iframe'; + return 'iframe'; } else if (settings.coreMode === 'popup') { - this.currentTarget = 'core-in-popup'; + return 'core-in-popup'; } else { - // Default to auto mode with iframe as the first choice - settings.coreMode = 'auto'; - this.currentTarget = 'iframe'; - } - - // Save settings for later use - this.lastSettings = settings; - - // Initialize the target - try { - return await this.getTarget().init(settings); - } catch (error) { - // Handle iframe errors by switching to core-in-popup - if (await this.handleErrorFallback(error.code)) { - return await this.getTarget().init(settings); - } - - throw error; - } - } - - public async call(params: CallMethodPayload) { - const response = await this.getTarget().call(params); - if (!response.success) { - if (await this.handleErrorFallback(response.payload.code)) { - return await this.getTarget().call(params); - } + return 'iframe'; } + }, + handleErrorFallback: async (errorCode: string) => { + const isCoreModeAuto = + impl.lastSettings?.coreMode === 'auto' || impl.lastSettings?.coreMode === undefined; - return response; - } - - private async handleErrorFallback(errorCode: string) { // Handle iframe errors by switching to core-in-popup - if (this.lastSettings?.coreMode === 'auto' && IFRAME_ERRORS.includes(errorCode)) { + if (isCoreModeAuto && IFRAME_ERRORS.includes(errorCode)) { // Check if WebUSB is available and enabled - const webUsbUnavailableInBrowser = !navigator.usb; + const webUsbUnavailableInBrowser = !(navigator as any)?.usb; const webUsbDisabledInSettings = - this.lastSettings.transports?.includes('WebUsbTransport') === false || - this.lastSettings.webusb === false; + impl.lastSettings?.transports?.includes('WebUsbTransport') === false || + impl.lastSettings?.webusb === false; if ( errorCode === 'Transport_Missing' && (webUsbUnavailableInBrowser || webUsbDisabledInSettings) @@ -110,46 +47,14 @@ export class TrezorConnectDynamicImpl implements ConnectFactoryDependencies { return false; } - await this.switchTarget('core-in-popup'); + await impl.switchTarget('core-in-popup'); return true; } return false; - } - - public requestLogin(params: any) { - return this.getTarget().requestLogin(params); - } - - public uiResponse(params: any) { - return this.getTarget().uiResponse(params); - } - - public renderWebUSBButton() { - return this.getTarget().renderWebUSBButton(); - } - - public disableWebUSB() { - return this.getTarget().disableWebUSB(); - } - - public requestWebUSBDevice() { - return this.getTarget().requestWebUSBDevice(); - } - - public cancel(error?: string) { - return this.getTarget().cancel(error); - } - - public dispose() { - this.eventEmitter.removeAllListeners(); - - return this.getTarget().dispose(); - } -} - -const impl = new TrezorConnectDynamicImpl(); + }, +}); const TrezorConnect = factory({ eventEmitter: impl.eventEmitter, From 1b88b3b72be644fd4c87ac0202ce0674a5351cad Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Tue, 1 Oct 2024 15:04:23 +0200 Subject: [PATCH 128/624] feat(connect): take deeplinkUrl from connectSrc --- packages/connect/src/data/__tests__/DataManager.test.ts | 1 + packages/connect/src/data/connectSettings.ts | 2 ++ packages/connect/src/types/settings.ts | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/connect/src/data/__tests__/DataManager.test.ts b/packages/connect/src/data/__tests__/DataManager.test.ts index a06976cc4bb..919ae0bc544 100644 --- a/packages/connect/src/data/__tests__/DataManager.test.ts +++ b/packages/connect/src/data/__tests__/DataManager.test.ts @@ -17,6 +17,7 @@ const settings = { iframeSrc: '', popupSrc: '', webusbSrc: '', + deeplinkUrl: '', version: '9.0.0', priority: 1, trustedHost: true, diff --git a/packages/connect/src/data/connectSettings.ts b/packages/connect/src/data/connectSettings.ts index fa7e193e39d..31fad0ceea4 100644 --- a/packages/connect/src/data/connectSettings.ts +++ b/packages/connect/src/data/connectSettings.ts @@ -28,6 +28,7 @@ const initialSettings: ConnectSettings = { timestamp: new Date().getTime(), interactionTimeout: 600, // 5 minutes sharedLogger: true, + deeplinkUrl: `${DEFAULT_DOMAIN}deeplink/${VERSION}/`, }; const parseManifest = (manifest?: Manifest) => { @@ -83,6 +84,7 @@ export const parseConnectSettings = (input: Partial = {}) => { settings.iframeSrc = `${src}iframe.html`; settings.popupSrc = `${src}popup.html`; settings.webusbSrc = `${src}webusb.html`; + settings.deeplinkUrl = `${src}deeplink/${VERSION}/`; if (typeof input.transportReconnect === 'boolean') { settings.transportReconnect = input.transportReconnect; diff --git a/packages/connect/src/types/settings.ts b/packages/connect/src/types/settings.ts index 915427f7650..0ed54c02995 100644 --- a/packages/connect/src/types/settings.ts +++ b/packages/connect/src/types/settings.ts @@ -33,7 +33,6 @@ export interface ConnectSettingsPublic { _sessionsBackgroundUrl?: string; deeplinkOpen?: (url: string) => void; deeplinkCallbackUrl?: string; - deeplinkUrl?: string; // URL for binary files such as firmware, may be local or remote. If not provided, firmware hash check won't be done. binFilesBaseUrl?: string; } @@ -53,6 +52,7 @@ export interface ConnectSettingsInternal { proxy?: Proxy; sharedLogger?: boolean; useCoreInPopup?: boolean; + deeplinkUrl: string; } export type ConnectSettings = ConnectSettingsPublic & ConnectSettingsInternal; From 3e1f9cc28bf18920108fa8e5207755be290df0ea Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Tue, 1 Oct 2024 15:05:18 +0200 Subject: [PATCH 129/624] feat(connect-deeplink): use deeplinkUrl from settings --- packages/connect-deeplink/src/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/connect-deeplink/src/index.ts b/packages/connect-deeplink/src/index.ts index b4b8422a0bc..c44e36661dd 100644 --- a/packages/connect-deeplink/src/index.ts +++ b/packages/connect-deeplink/src/index.ts @@ -19,7 +19,6 @@ export class TrezorConnectDeeplink implements ConnectFactoryDependencies { private _settings: ConnectSettings; private messagePromises: Record> = {}; private messageID = 0; - private defaultDeeplinkUrl = 'trezorsuitelite://connect'; public constructor() { this._settings = { @@ -48,7 +47,6 @@ export class TrezorConnectDeeplink implements ConnectFactoryDependencies { ...parseConnectSettings({ ...this._settings, ...settings }), deeplinkOpen: settings.deeplinkOpen, deeplinkCallbackUrl: settings.deeplinkCallbackUrl, - deeplinkUrl: settings.deeplinkUrl || this.defaultDeeplinkUrl, }; return Promise.resolve(); @@ -156,7 +154,7 @@ export class TrezorConnectDeeplink implements ConnectFactoryDependencies { delete this.messagePromises[id]; } - resolveMessagePromises(resolvePayload: Record) { + private resolveMessagePromises(resolvePayload: Record) { Object.keys(this.messagePromises).forEach(id => { this.messagePromises[id as any].resolve({ id, From 1ff479c54547dcd3f6595d9c6924bf27b1c79f23 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Tue, 1 Oct 2024 15:14:04 +0200 Subject: [PATCH 130/624] chore(connect-examples): change from deeplinkUrl to connectSrc --- packages/connect-examples/deeplink-expo/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/connect-examples/deeplink-expo/App.tsx b/packages/connect-examples/deeplink-expo/App.tsx index ba4d3d5811e..3402a11065f 100644 --- a/packages/connect-examples/deeplink-expo/App.tsx +++ b/packages/connect-examples/deeplink-expo/App.tsx @@ -29,13 +29,13 @@ export const App = () => { email: 'developer@xyz.com', appUrl: 'http://your.application.com', }, + connectSrc: 'https://dev.suite.sldev.cz/connect/develop/', deeplinkOpen: url => { // eslint-disable-next-line no-console console.log('deeplinkOpen', url); Linking.openURL(url); }, deeplinkCallbackUrl: Linking.createURL('/connect'), - // deeplinkUrl: 'https://dev.suite.sldev.cz/connect/develop/deeplink/', }); }; From fe8499ec1ce408f7c94d72d54704f2cf9aad8f0c Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Tue, 1 Oct 2024 15:14:39 +0200 Subject: [PATCH 131/624] feat(module-connect-popup): add version check to app link parser --- packages/connect/src/constants/errors.ts | 2 ++ suite-native/intl/src/en.ts | 2 ++ .../src/hooks/useConnectParseParams.ts | 34 +++++++++++++++---- .../src/screens/ConnectPopupScreen.tsx | 30 ++++++++++++++-- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/packages/connect/src/constants/errors.ts b/packages/connect/src/constants/errors.ts index eccb6436d4d..59fc4e42a10 100644 --- a/packages/connect/src/constants/errors.ts +++ b/packages/connect/src/constants/errors.ts @@ -49,6 +49,8 @@ export const ERROR_CODES = { Failure_PinCancelled: 'PIN cancelled', Failure_PinMismatch: 'PIN mismatch', Failure_WipeCodeMismatch: 'Wipe code mismatch', + + Deeplink_VersionMismatch: 'Not compatible with current version of the app', } as const; export type ErrorCode = keyof typeof ERROR_CODES; diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts index 635ec3b84d0..6a1b5d59b46 100644 --- a/suite-native/intl/src/en.ts +++ b/suite-native/intl/src/en.ts @@ -275,6 +275,8 @@ export const en = { errors: { deviceNotConnected: 'Device not connected.', invalidCallback: 'Invalid callback URL', + invalidParams: 'Invalid parameters from calling app', + versionUnsupported: 'Unsupported version. Please update your Trezor Suite app.', }, bottomSheets: { confirmOnDeviceMessage: 'Go to your device and verify the details of the operation.', diff --git a/suite-native/module-connect-popup/src/hooks/useConnectParseParams.ts b/suite-native/module-connect-popup/src/hooks/useConnectParseParams.ts index dcf0b2635d5..62a6e1d6afd 100644 --- a/suite-native/module-connect-popup/src/hooks/useConnectParseParams.ts +++ b/suite-native/module-connect-popup/src/hooks/useConnectParseParams.ts @@ -3,10 +3,27 @@ import { useMemo } from 'react'; import { ParsedURL } from 'expo-linking'; import TrezorConnect from '@trezor/connect'; +import { DEEPLINK_VERSION } from '@trezor/connect/src/data/version'; +import { TypedError, TrezorError } from '@trezor/connect/src/constants/errors'; -export const useConnectParseParams = (url: ParsedURL) => { - const popupOptions = useMemo(() => { - const { queryParams } = url; +type UseConnectParseParamsType = + | { + popupOptions: { + method: string; + params: any; + callback: string; + }; + parseParamsError: undefined; + } + | { + popupOptions: undefined; + parseParamsError: TrezorError; + }; + +export const useConnectParseParams = (url: ParsedURL): UseConnectParseParamsType => { + return useMemo(() => { + const { queryParams, path } = url; + const version = path && path.split('/').slice(-2, -1)[0]; if ( !queryParams?.method || !queryParams?.params || @@ -16,13 +33,16 @@ export const useConnectParseParams = (url: ParsedURL) => { typeof queryParams?.callback !== 'string' || !TrezorConnect.hasOwnProperty(queryParams?.method) ) { - return undefined; + return { parseParamsError: TypedError('Method_InvalidParameter') }; + } + + if (!version || parseInt(version) > DEEPLINK_VERSION) { + return { parseParamsError: TypedError('Deeplink_VersionMismatch') }; } + const params = JSON.parse(queryParams.params); const { method: methodName, callback } = queryParams; - return { method: methodName, params, callback }; + return { popupOptions: { method: methodName, params, callback } }; }, [url]); - - return popupOptions; }; diff --git a/suite-native/module-connect-popup/src/screens/ConnectPopupScreen.tsx b/suite-native/module-connect-popup/src/screens/ConnectPopupScreen.tsx index 0c50d9d6dd3..1f875e86064 100644 --- a/suite-native/module-connect-popup/src/screens/ConnectPopupScreen.tsx +++ b/suite-native/module-connect-popup/src/screens/ConnectPopupScreen.tsx @@ -46,7 +46,7 @@ export const ConnectPopupScreen = ({ const [callResult, setCallResult] = useState(); const [loading, setLoading] = useState(false); - const popupOptions = useConnectParseParams(route.params.parsedUrl); + const { popupOptions, parseParamsError } = useConnectParseParams(route.params.parsedUrl); const { method, methodError } = useConnectMethod(popupOptions); const callDevice = useCallback(async () => { @@ -130,6 +130,23 @@ export const ConnectPopupScreen = ({ ); } + + if (parseParamsError) { + return ( + + } + /> + ); + } + if (methodError) { return ; } @@ -148,7 +165,16 @@ export const ConnectPopupScreen = ({ /> ); } - }, [validDevice, method, popupOptions, methodError, loading, discoveryActive, callDevice]); + }, [ + validDevice, + method, + popupOptions, + parseParamsError, + methodError, + loading, + discoveryActive, + callDevice, + ]); return ( Date: Mon, 14 Oct 2024 13:12:21 +0200 Subject: [PATCH 132/624] feat(connect): use separate versioning for deeplink protocol --- packages/connect/src/data/connectSettings.ts | 6 +++--- packages/connect/src/data/version.ts | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/connect/src/data/connectSettings.ts b/packages/connect/src/data/connectSettings.ts index 31fad0ceea4..8fccff5e916 100644 --- a/packages/connect/src/data/connectSettings.ts +++ b/packages/connect/src/data/connectSettings.ts @@ -1,7 +1,7 @@ // origin: https://github.com/trezor/connect/blob/develop/src/js/data/ConnectSettings.js import type { Manifest, ConnectSettings } from '../types'; -import { VERSION, DEFAULT_DOMAIN } from './version'; +import { VERSION, DEFAULT_DOMAIN, DEEPLINK_VERSION } from './version'; /* * Initial settings for connect. @@ -28,7 +28,7 @@ const initialSettings: ConnectSettings = { timestamp: new Date().getTime(), interactionTimeout: 600, // 5 minutes sharedLogger: true, - deeplinkUrl: `${DEFAULT_DOMAIN}deeplink/${VERSION}/`, + deeplinkUrl: `${DEFAULT_DOMAIN}deeplink/${DEEPLINK_VERSION}/`, }; const parseManifest = (manifest?: Manifest) => { @@ -84,7 +84,7 @@ export const parseConnectSettings = (input: Partial = {}) => { settings.iframeSrc = `${src}iframe.html`; settings.popupSrc = `${src}popup.html`; settings.webusbSrc = `${src}webusb.html`; - settings.deeplinkUrl = `${src}deeplink/${VERSION}/`; + settings.deeplinkUrl = `${src}deeplink/${DEEPLINK_VERSION}/`; if (typeof input.transportReconnect === 'boolean') { settings.transportReconnect = input.transportReconnect; diff --git a/packages/connect/src/data/version.ts b/packages/connect/src/data/version.ts index 2f5e69f32b4..4594473b594 100644 --- a/packages/connect/src/data/version.ts +++ b/packages/connect/src/data/version.ts @@ -10,3 +10,5 @@ export const DEFAULT_DOMAIN = isBeta // Increment with content script changes export const CONTENT_SCRIPT_VERSION = 1; +// Increment with deeplink protocol changes +export const DEEPLINK_VERSION = 1; From e86e6aa5b3a7b734ddba1a4da3db9ade87956c8a Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Mon, 14 Oct 2024 13:40:29 +0200 Subject: [PATCH 133/624] chore(connect-popup): move deeplink fallback page to versioned url --- .../connect-popup/src/static/deeplink.html | 8 +++---- .../webpack/prod.webpack.config.ts | 22 ++++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/connect-popup/src/static/deeplink.html b/packages/connect-popup/src/static/deeplink.html index a19d5b56e17..454103ddc5b 100644 --- a/packages/connect-popup/src/static/deeplink.html +++ b/packages/connect-popup/src/static/deeplink.html @@ -16,10 +16,10 @@ - - + + - + @@ -27,7 +27,7 @@ diff --git a/packages/connect-popup/webpack/prod.webpack.config.ts b/packages/connect-popup/webpack/prod.webpack.config.ts index 3840b4b4fbe..81300ba31a9 100644 --- a/packages/connect-popup/webpack/prod.webpack.config.ts +++ b/packages/connect-popup/webpack/prod.webpack.config.ts @@ -4,6 +4,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin'; import TerserPlugin from 'terser-webpack-plugin'; import CopyPlugin from 'copy-webpack-plugin'; import * as URLS from '@trezor/urls'; +import { DEEPLINK_VERSION } from '@trezor/connect/src/data/version'; import { version } from '../package.json'; import { execSync } from 'child_process'; @@ -83,14 +84,19 @@ const config: webpack.Configuration = { minify: false, urls: URLS, }), - new HtmlWebpackPlugin({ - chunks: ['deeplink'], - template: `${STATIC_SRC}/deeplink.html`, - filename: 'deeplink/index.html', - inject: false, - minify: false, - urls: URLS, - }), + // deeplink fallback page for all versions + ...Array.from( + { length: DEEPLINK_VERSION }, + (_, i) => + new HtmlWebpackPlugin({ + chunks: ['deeplink'], + template: `${STATIC_SRC}/deeplink.html`, + filename: `deeplink/${i + 1}/index.html`, + inject: false, + minify: false, + urls: URLS, + }), + ), new HtmlWebpackPlugin({ chunks: ['log'], template: `${STATIC_SRC}/log.html`, From b1c80b19c1e9ec0ec45b380d56fcf4aa02519330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Vytick=20Vytrhl=C3=ADk?= Date: Tue, 15 Oct 2024 12:03:43 +0200 Subject: [PATCH 134/624] feat(suite-native): show correct network data for receive on POL and BNB --- suite-native/intl/src/en.ts | 6 ++++- .../TokenAccountDetailScreenSubHeader.tsx | 11 ++++++-- .../receive/src/components/ReceiveAccount.tsx | 2 +- .../src/components/ReceiveAddressCard.tsx | 13 ++++++---- .../src/components/TokenReceiveCard.tsx | 25 +++++++++++++++---- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts index 6a1b5d59b46..512583a9238 100644 --- a/suite-native/intl/src/en.ts +++ b/suite-native/intl/src/en.ts @@ -361,12 +361,16 @@ export const en = { screenTitle: '{coinSymbol} Receive address', accountNotFound: 'Account {accountKey} not found.', deviceCancelError: 'Address confirmation canceled.', + tokens: { + runOn: 'Run on {accountLabel}', + errorMessage: 'Token not found.', + }, receiveAddressCard: { alert: { success: 'Receive address has been confirmed on your Trezor.', longCardanoAddress: 'Cardano (ADA) address exceeds Trezor device’s screen. Scroll here and on the device to view it and confirm.', - ethereumToken: 'Your receive address is your Ethereum address', + token: 'Your receive address is your {networkName} address', }, unverifiedWarning: { portfolioTracker: { diff --git a/suite-native/module-accounts-management/src/components/TokenAccountDetailScreenSubHeader.tsx b/suite-native/module-accounts-management/src/components/TokenAccountDetailScreenSubHeader.tsx index 6b95c039ccb..a8ecfd9c8bc 100644 --- a/suite-native/module-accounts-management/src/components/TokenAccountDetailScreenSubHeader.tsx +++ b/suite-native/module-accounts-management/src/components/TokenAccountDetailScreenSubHeader.tsx @@ -9,7 +9,11 @@ import { ScreenSubHeader, GoBackIcon, } from '@suite-native/navigation'; -import { AccountsRootState, selectAccountLabel } from '@suite-common/wallet-core'; +import { + AccountsRootState, + selectAccountLabel, + selectAccountNetworkSymbol, +} from '@suite-common/wallet-core'; import { CryptoIcon } from '@suite-common/icons-deprecated'; import { useTranslate } from '@suite-native/intl'; @@ -26,6 +30,9 @@ export const TokenAccountDetailScreenSubHeader = ({ const accountLabel = useSelector((state: AccountsRootState) => selectAccountLabel(state, accountKey), ); + const networkSymbol = useSelector((state: AccountsRootState) => + selectAccountNetworkSymbol(state, accountKey), + )!; const route = useRoute>(); const { closeActionType } = route.params; @@ -37,7 +44,7 @@ export const TokenAccountDetailScreenSubHeader = ({ {tokenName} - + void; - isEthereumTokenAddress?: boolean; + isTokenAddress?: boolean; }; export const ReceiveAddressCard = ({ @@ -27,12 +27,12 @@ export const ReceiveAddressCard = ({ isReceiveApproved, onShowAddress, networkSymbol, - isEthereumTokenAddress = false, + isTokenAddress = false, }: ReceiveAddressCardProps) => { const isPortfolioTrackerDevice = useSelector(selectIsPortfolioTrackerDevice); const isDeviceInViewOnlyMode = useSelector(selectIsDeviceInViewOnlyMode); - const { networkType } = networks[networkSymbol]; + const { networkType, name: networkName } = networks[networkSymbol]; const getCardAlertProps = () => { if (isReceiveApproved && !isPortfolioTrackerDevice && !isDeviceInViewOnlyMode) { @@ -49,10 +49,13 @@ export const ReceiveAddressCard = ({ alertVariant: 'info', } as const; } - if (isEthereumTokenAddress) { + if (isTokenAddress) { return { alertTitle: ( - + ), alertVariant: 'info', } as const; diff --git a/suite-native/receive/src/components/TokenReceiveCard.tsx b/suite-native/receive/src/components/TokenReceiveCard.tsx index b162c6ad35d..042b4b4298a 100644 --- a/suite-native/receive/src/components/TokenReceiveCard.tsx +++ b/suite-native/receive/src/components/TokenReceiveCard.tsx @@ -7,12 +7,17 @@ import { } from '@suite-native/formatters'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; import { AccountKey, TokenAddress } from '@suite-common/wallet-types'; -import { AccountsRootState, selectAccountLabel } from '@suite-common/wallet-core'; +import { + AccountsRootState, + selectAccountLabel, + selectAccountNetworkSymbol, +} from '@suite-common/wallet-core'; import { getTokenName, selectAccountTokenInfo, selectAccountTokenSymbol, } from '@suite-native/tokens'; +import { Translation } from '@suite-native/intl'; type TokenReceiveCardProps = { accountKey: AccountKey; @@ -36,7 +41,9 @@ export const TokenReceiveCard = ({ contract, accountKey }: TokenReceiveCardProps const accountLabel = useSelector((state: AccountsRootState) => selectAccountLabel(state, accountKey), ); - + const accountNetworkSymbol = useSelector((state: AccountsRootState) => + selectAccountNetworkSymbol(state, accountKey), + )!; const token = useSelector((state: AccountsRootState) => selectAccountTokenInfo(state, accountKey, contract), ); @@ -45,7 +52,10 @@ export const TokenReceiveCard = ({ contract, accountKey }: TokenReceiveCardProps selectAccountTokenSymbol(state, accountKey, contract), ); - if (!token) return ; + if (!token) + return ( + } /> + ); const tokenName = getTokenName(token.name); @@ -59,8 +69,13 @@ export const TokenReceiveCard = ({ contract, accountKey }: TokenReceiveCardProps {tokenName} + } + icon={accountNetworkSymbol} size="small" iconSize="extraSmall" /> From 0542a55ea41d98d6d674344bd816a66ba4bc2c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Vytick=20Vytrhl=C3=ADk?= Date: Mon, 14 Oct 2024 13:24:08 +0200 Subject: [PATCH 135/624] feat(suite-native): correct network name for tokens in account detail --- suite-native/intl/src/en.ts | 4 ++ .../src/components/IncludeTokensToggle.tsx | 60 ++++++++++++------- .../src/components/TransactionListHeader.tsx | 2 + 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts index 512583a9238..af78fca987d 100644 --- a/suite-native/intl/src/en.ts +++ b/suite-native/intl/src/en.ts @@ -726,6 +726,10 @@ export const en = { inputs: 'Inputs & Outputs', }, }, + tokens: { + toggleTokens: 'Include tokens', + title: 'Note, your {networkName} balance doesn’t include tokens.', + }, }, deviceManager: { deviceButtons: { diff --git a/suite-native/module-accounts-management/src/components/IncludeTokensToggle.tsx b/suite-native/module-accounts-management/src/components/IncludeTokensToggle.tsx index a0ca34467df..336a77996d7 100644 --- a/suite-native/module-accounts-management/src/components/IncludeTokensToggle.tsx +++ b/suite-native/module-accounts-management/src/components/IncludeTokensToggle.tsx @@ -1,31 +1,47 @@ import Animated, { FadeIn } from 'react-native-reanimated'; import { AlertBox, Box, Toggle, VStack } from '@suite-native/atoms'; +import { getNetwork, NetworkSymbol } from '@suite-common/wallet-config'; +import { Translation } from '@suite-native/intl'; type IncludeTokensToggleProps = { + networkSymbol: NetworkSymbol; isToggled: boolean; onToggle: () => void; }; -export const IncludeTokensToggle = ({ isToggled, onToggle }: IncludeTokensToggleProps) => ( - - - - - {isToggled && ( - - - - - - )} - -); +export const IncludeTokensToggle = ({ + networkSymbol, + isToggled, + onToggle, +}: IncludeTokensToggleProps) => { + const networkName = getNetwork(networkSymbol).name; + + return ( + + + } + isToggled={isToggled} + onToggle={onToggle} + /> + + {isToggled && ( + + + + } + /> + + + )} + + ); +}; diff --git a/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx b/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx index c6871099bca..f9956dfd4ae 100644 --- a/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx +++ b/suite-native/module-accounts-management/src/components/TransactionListHeader.tsx @@ -102,6 +102,7 @@ export const TransactionListHeader = memo( const account = useSelector((state: AccountsRootState) => selectAccountByKey(state, accountKey), ); + const accountHasTransactions = useSelector((state: AccountsRootState) => selectHasAccountTransactions(state, accountKey), ); @@ -192,6 +193,7 @@ export const TransactionListHeader = memo( {canHaveTokens && accountHasTransactions && ( From 1f87a7ceff958b1f31eef06f1ceacbdef5496ccb Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Tue, 15 Oct 2024 12:57:41 +0200 Subject: [PATCH 136/624] feat(suite): new fw hash check error case --- packages/connect/src/device/Device.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/connect/src/device/Device.ts b/packages/connect/src/device/Device.ts index 44ab951eeef..4577ace75a7 100644 --- a/packages/connect/src/device/Device.ts +++ b/packages/connect/src/device/Device.ts @@ -643,13 +643,20 @@ export class Device extends TypedEmitter { randomBytes(32), ); - const deviceResponse = await this.getCommands().typedCall( - 'GetFirmwareHash', - 'FirmwareHash', - { challenge }, - ); + // handle rejection of call by a counterfeit device. If unhandled, it crashes device initialization, + // so device can't be used, but it's preferable to display proper message about counterfeit device + const getFirmwareHashOptional = async () => { + try { + return await this.getCommands().typedCall('GetFirmwareHash', 'FirmwareHash', { + challenge, + }); + } catch (e) { + return null; + } + }; + const deviceResponse = await getFirmwareHashOptional(); - if (!deviceResponse.message.hash) return createFailResult('other-error'); + if (!deviceResponse?.message?.hash) return createFailResult('other-error'); if (deviceResponse.message.hash !== expectedHash) return createFailResult('hash-mismatch'); From 0cbb900aadabf7da896ce222c0d4b8d4b1021ef7 Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Tue, 15 Oct 2024 13:09:08 +0200 Subject: [PATCH 137/624] fix: remove upgrade FW banner (it is duplicate info now) --- .../e2e/tests/firmware/firmware.test.ts | 5 +--- .../banners/SuiteBanners/SuiteBanners.tsx | 10 -------- .../SuiteBanners/UpdateFirmwareBanner.tsx | 25 ------------------- .../Update/UpdateNotificationBanner.tsx | 6 ++++- packages/suite/src/support/messages.ts | 4 --- 5 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 packages/suite/src/components/suite/banners/SuiteBanners/UpdateFirmwareBanner.tsx diff --git a/packages/suite-web/e2e/tests/firmware/firmware.test.ts b/packages/suite-web/e2e/tests/firmware/firmware.test.ts index b847811b9bd..80bfbce6113 100644 --- a/packages/suite-web/e2e/tests/firmware/firmware.test.ts +++ b/packages/suite-web/e2e/tests/firmware/firmware.test.ts @@ -13,10 +13,7 @@ describe('Firmware', () => { cy.task('startBridge'); cy.prefixedVisit('/'); cy.passThroughInitialRun(); - cy.getTestElement('@suite-layout/body').matchImageSnapshot('outdated-notification-banner', { - clip: { x: 0, y: 0, height: 100, width: 1080 }, - }); - cy.getTestElement('@notification/update-firmware/button').click(); + cy.getTestElement('@notification/update-notification-banner').click(); // initial screen cy.getTestElement('@firmware/install-button').click(); diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx index d223961c251..919685fad68 100644 --- a/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx +++ b/packages/suite/src/components/suite/banners/SuiteBanners/SuiteBanners.tsx @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react'; import styled from 'styled-components'; import { selectBannerMessage } from '@suite-common/message-system'; -import { isDeviceAcquired } from '@suite-common/suite-utils'; import { selectDevice } from '@suite-common/wallet-core'; import { isArrayMember } from '@trezor/type-utils'; import { isDesktop } from '@trezor/env-utils'; @@ -18,7 +17,6 @@ import { import { MessageSystemBanner } from '../MessageSystemBanner'; import { NoConnectionBanner } from './NoConnectionBanner'; import { UpdateBridge } from './UpdateBridgeBanner'; -import { UpdateFirmware } from './UpdateFirmwareBanner'; import { NoBackup } from './NoBackupBanner'; import { FailedBackup } from './FailedBackupBanner'; import { SafetyChecksBanner } from './SafetyChecksBanner'; @@ -98,14 +96,6 @@ export const SuiteBanners = () => { } else if (showUpdateBridge()) { banner = ; priority = 30; - } else if ( - device?.connected && - isDeviceAcquired(device) && - device.mode !== 'bootloader' && - ['outdated'].includes(device.firmware) - ) { - banner = ; - priority = 10; } // message system banners should always be visible in the app even if app body is blurred diff --git a/packages/suite/src/components/suite/banners/SuiteBanners/UpdateFirmwareBanner.tsx b/packages/suite/src/components/suite/banners/SuiteBanners/UpdateFirmwareBanner.tsx deleted file mode 100644 index 74449b4ffe8..00000000000 --- a/packages/suite/src/components/suite/banners/SuiteBanners/UpdateFirmwareBanner.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Translation } from 'src/components/suite'; -import { goto } from 'src/actions/suite/routerActions'; -import { useDispatch } from 'src/hooks/suite'; -import { Banner } from '@trezor/components'; - -export const UpdateFirmware = () => { - const dispatch = useDispatch(); - - return ( - dispatch(goto('firmware-index'))} - data-testid="@notification/update-firmware/button" - > - - - } - > - - - ); -}; diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx index 1692be91f63..f42295dfabe 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/Sidebar/QuickActions/Update/UpdateNotificationBanner.tsx @@ -107,7 +107,11 @@ export const UpdateNotificationBanner = ({ return ( - + diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 384f412c167..884ede5d4e8 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -2861,10 +2861,6 @@ export default defineMessages({ defaultMessage: 'New Trezor Bridge is available.', id: 'TR_NEW_TREZOR_BRIDGE_IS_AVAILABLE', }, - TR_NEW_TREZOR_FIRMWARE_IS_AVAILABLE_DOT: { - defaultMessage: 'New Trezor firmware is available! Update your device now.', - id: 'TR_NEW_TREZOR_FIRMWARE_IS_AVAILABLE_DOT', - }, TR_NO_PASSPHRASE_WALLET: { defaultMessage: 'Standard wallet', id: 'TR_NO_PASSPHRASE_WALLET', From d1c2bd746460dab9d246fa4fffeeeb3b6373bc98 Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Tue, 15 Oct 2024 14:13:45 +0200 Subject: [PATCH 138/624] chore: rename connect-deeplink to connect-mobile --- .../{deeplink-expo => mobile-expo}/.gitignore | 0 .../{deeplink-expo => mobile-expo}/App.tsx | 2 +- .../{deeplink-expo => mobile-expo}/README.md | 4 +- .../{deeplink-expo => mobile-expo}/app.json | 4 +- .../babel.config.js | 0 .../{deeplink-expo => mobile-expo}/index.js | 0 .../package.json | 4 +- .../tsconfig.json | 2 +- .../README.md | 10 ++-- .../package.json | 2 +- .../src/index.ts | 0 .../tsconfig.json | 0 .../module-connect-popup/package.json | 2 +- .../components/ConnectPopupDebugOptions.tsx | 2 +- .../module-connect-popup/tsconfig.json | 2 +- tsconfig.json | 8 +-- yarn.lock | 52 +++++++++---------- 17 files changed, 47 insertions(+), 47 deletions(-) rename packages/connect-examples/{deeplink-expo => mobile-expo}/.gitignore (100%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/App.tsx (98%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/README.md (75%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/app.json (72%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/babel.config.js (100%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/index.js (100%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/package.json (85%) rename packages/connect-examples/{deeplink-expo => mobile-expo}/tsconfig.json (73%) rename packages/{connect-deeplink => connect-mobile}/README.md (68%) rename packages/{connect-deeplink => connect-mobile}/package.json (91%) rename packages/{connect-deeplink => connect-mobile}/src/index.ts (100%) rename packages/{connect-deeplink => connect-mobile}/tsconfig.json (100%) diff --git a/packages/connect-examples/deeplink-expo/.gitignore b/packages/connect-examples/mobile-expo/.gitignore similarity index 100% rename from packages/connect-examples/deeplink-expo/.gitignore rename to packages/connect-examples/mobile-expo/.gitignore diff --git a/packages/connect-examples/deeplink-expo/App.tsx b/packages/connect-examples/mobile-expo/App.tsx similarity index 98% rename from packages/connect-examples/deeplink-expo/App.tsx rename to packages/connect-examples/mobile-expo/App.tsx index 3402a11065f..ca6ea229dba 100644 --- a/packages/connect-examples/deeplink-expo/App.tsx +++ b/packages/connect-examples/mobile-expo/App.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'; import { StatusBar } from 'expo-status-bar'; import * as Linking from 'expo-linking'; -import TrezorConnect from '@trezor/connect-deeplink'; +import TrezorConnect from '@trezor/connect-mobile'; const styles = StyleSheet.create({ container: { diff --git a/packages/connect-examples/deeplink-expo/README.md b/packages/connect-examples/mobile-expo/README.md similarity index 75% rename from packages/connect-examples/deeplink-expo/README.md rename to packages/connect-examples/mobile-expo/README.md index 045a7fa4901..9feaaf60873 100644 --- a/packages/connect-examples/deeplink-expo/README.md +++ b/packages/connect-examples/mobile-expo/README.md @@ -1,6 +1,6 @@ -## Deep link example with Expo +## Mobile example with Expo -`@trezor/connect-deeplink` running with a React Native + Expo app +`@trezor/connect-mobile` running with a React Native + Expo app ### Run it diff --git a/packages/connect-examples/deeplink-expo/app.json b/packages/connect-examples/mobile-expo/app.json similarity index 72% rename from packages/connect-examples/deeplink-expo/app.json rename to packages/connect-examples/mobile-expo/app.json index be288d3acbe..cf0cfbc7048 100644 --- a/packages/connect-examples/deeplink-expo/app.json +++ b/packages/connect-examples/mobile-expo/app.json @@ -1,7 +1,7 @@ { "expo": { - "name": "connect-deeplink-example", - "slug": "connect-deeplink-example", + "name": "connect-mobile-example", + "slug": "connect-mobile-example", "version": "1.0.0", "orientation": "portrait", "userInterfaceStyle": "light", diff --git a/packages/connect-examples/deeplink-expo/babel.config.js b/packages/connect-examples/mobile-expo/babel.config.js similarity index 100% rename from packages/connect-examples/deeplink-expo/babel.config.js rename to packages/connect-examples/mobile-expo/babel.config.js diff --git a/packages/connect-examples/deeplink-expo/index.js b/packages/connect-examples/mobile-expo/index.js similarity index 100% rename from packages/connect-examples/deeplink-expo/index.js rename to packages/connect-examples/mobile-expo/index.js diff --git a/packages/connect-examples/deeplink-expo/package.json b/packages/connect-examples/mobile-expo/package.json similarity index 85% rename from packages/connect-examples/deeplink-expo/package.json rename to packages/connect-examples/mobile-expo/package.json index 6b1da406517..8d337b14eb4 100644 --- a/packages/connect-examples/deeplink-expo/package.json +++ b/packages/connect-examples/mobile-expo/package.json @@ -1,5 +1,5 @@ { - "name": "connect-deeplink-expo-example", + "name": "connect-mobile-example", "version": "1.0.0", "main": "index.js", "scripts": { @@ -9,7 +9,7 @@ "web": "expo start --web" }, "dependencies": { - "@trezor/connect-deeplink": "workspace:*", + "@trezor/connect-mobile": "workspace:*", "expo": "51.0.31", "expo-linking": "6.3.1", "expo-status-bar": "1.12.1", diff --git a/packages/connect-examples/deeplink-expo/tsconfig.json b/packages/connect-examples/mobile-expo/tsconfig.json similarity index 73% rename from packages/connect-examples/deeplink-expo/tsconfig.json rename to packages/connect-examples/mobile-expo/tsconfig.json index 969501df44d..a3f46dccb10 100644 --- a/packages/connect-examples/deeplink-expo/tsconfig.json +++ b/packages/connect-examples/mobile-expo/tsconfig.json @@ -2,6 +2,6 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "./libDev" }, "references": [ - { "path": "../../connect-deeplink" } + { "path": "../../connect-mobile" } ] } diff --git a/packages/connect-deeplink/README.md b/packages/connect-mobile/README.md similarity index 68% rename from packages/connect-deeplink/README.md rename to packages/connect-mobile/README.md index 4604d578a9f..64228cb9628 100644 --- a/packages/connect-deeplink/README.md +++ b/packages/connect-mobile/README.md @@ -1,8 +1,8 @@ -# @trezor/connect-deeplink +# @trezor/connect-mobile -[![NPM](https://img.shields.io/npm/v/@trezor/connect-deeplink.svg)](https://www.npmjs.org/package/@trezor/connect-deeplink) +[![NPM](https://img.shields.io/npm/v/@trezor/connect-mobile.svg)](https://www.npmjs.org/package/@trezor/connect-mobile) -The `@trezor/connect-deeplink` package provides an implementation of `@trezor/connect` which uses deep links to communicate with the Trezor Suite Lite app. +The `@trezor/connect-mobile` package provides an implementation of `@trezor/connect` which uses deep links to communicate with the Trezor Suite Lite app. Currently the library is still under development, only supports read-only methods and does not communicate with the production Suite Lite app. @@ -13,7 +13,7 @@ To run a dev version of the Suite mobile app follow the instructions in [@suite- To use the library, you need to initialize it with the `deeplinkOpen` and `deeplinkCallbackUrl` settings. ```javascript -import TrezorConnect from '@trezor/connect-deeplink'; +import TrezorConnect from '@trezor/connect-mobile'; TrezorConnect.init({ manifest: { @@ -43,4 +43,4 @@ useEffect(() => { ## Example -The [Connect deeplink example](https://github.com/trezor/trezor-suite/tree/develop/packages/connect-examples/deeplink-expo) shows how to use the library in a React Native + Expo app. +The [Connect mobile example](https://github.com/trezor/trezor-suite/tree/develop/packages/connect-examples/mobile-expo) shows how to use the library in a React Native + Expo app. diff --git a/packages/connect-deeplink/package.json b/packages/connect-mobile/package.json similarity index 91% rename from packages/connect-deeplink/package.json rename to packages/connect-mobile/package.json index 0329d95bc88..159dc211474 100644 --- a/packages/connect-deeplink/package.json +++ b/packages/connect-mobile/package.json @@ -1,5 +1,5 @@ { - "name": "@trezor/connect-deeplink", + "name": "@trezor/connect-mobile", "version": "1.0.0", "private": true, "license": "See LICENSE.md in repo root", diff --git a/packages/connect-deeplink/src/index.ts b/packages/connect-mobile/src/index.ts similarity index 100% rename from packages/connect-deeplink/src/index.ts rename to packages/connect-mobile/src/index.ts diff --git a/packages/connect-deeplink/tsconfig.json b/packages/connect-mobile/tsconfig.json similarity index 100% rename from packages/connect-deeplink/tsconfig.json rename to packages/connect-mobile/tsconfig.json diff --git a/suite-native/module-connect-popup/package.json b/suite-native/module-connect-popup/package.json index 041789e62e7..f5d510ffd33 100644 --- a/suite-native/module-connect-popup/package.json +++ b/suite-native/module-connect-popup/package.json @@ -22,7 +22,7 @@ "@suite-native/intl": "workspace:^", "@suite-native/navigation": "workspace:*", "@trezor/connect": "workspace:*", - "@trezor/connect-deeplink": "workspace:*", + "@trezor/connect-mobile": "workspace:*", "expo-linking": "^6.3.1", "react": "18.2.0", "react-native": "0.75.2", diff --git a/suite-native/module-connect-popup/src/components/ConnectPopupDebugOptions.tsx b/suite-native/module-connect-popup/src/components/ConnectPopupDebugOptions.tsx index f0ab00e5825..18eaf61b557 100644 --- a/suite-native/module-connect-popup/src/components/ConnectPopupDebugOptions.tsx +++ b/suite-native/module-connect-popup/src/components/ConnectPopupDebugOptions.tsx @@ -3,7 +3,7 @@ import React, { useEffect } from 'react'; import * as Linking from 'expo-linking'; import { BottomSheet, Button } from '@suite-native/atoms'; -import TrezorConnectDeeplink from '@trezor/connect-deeplink'; +import TrezorConnectDeeplink from '@trezor/connect-mobile'; type ConnectPopupDebugOptionsProps = React.PropsWithChildren<{ showDebug: boolean; diff --git a/suite-native/module-connect-popup/tsconfig.json b/suite-native/module-connect-popup/tsconfig.json index 73d2d31066d..c5028852616 100644 --- a/suite-native/module-connect-popup/tsconfig.json +++ b/suite-native/module-connect-popup/tsconfig.json @@ -17,7 +17,7 @@ { "path": "../navigation" }, { "path": "../../packages/connect" }, { - "path": "../../packages/connect-deeplink" + "path": "../../packages/connect-mobile" } ] } diff --git a/tsconfig.json b/tsconfig.json index b93626b2dcc..6074a6bb994 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -133,12 +133,12 @@ { "path": "packages/connect" }, { "path": "packages/connect-analytics" }, { "path": "packages/connect-common" }, - { "path": "packages/connect-deeplink" }, { "path": "packages/connect-explorer" }, { "path": "packages/connect-explorer-theme" }, { "path": "packages/connect-iframe" }, + { "path": "packages/connect-mobile" }, { "path": "packages/connect-plugin-ethereum" }, @@ -192,9 +192,6 @@ { "path": "packages/connect-examples/webextension-mv3-sw-ts" }, - { - "path": "packages/connect-examples/deeplink-expo" - }, { "path": "packages/connect-examples/electron-main-process" }, @@ -206,6 +203,9 @@ }, { "path": "packages/connect-examples/node" + }, + { + "path": "packages/connect-examples/mobile-expo" } ] } diff --git a/yarn.lock b/yarn.lock index db51dc1ce5c..d56c82383bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10259,7 +10259,7 @@ __metadata: "@suite-native/intl": "workspace:^" "@suite-native/navigation": "workspace:*" "@trezor/connect": "workspace:*" - "@trezor/connect-deeplink": "workspace:*" + "@trezor/connect-mobile": "workspace:*" expo-linking: "npm:^6.3.1" react: "npm:18.2.0" react-native: "npm:0.75.2" @@ -11279,15 +11279,6 @@ __metadata: languageName: unknown linkType: soft -"@trezor/connect-deeplink@workspace:*, @trezor/connect-deeplink@workspace:packages/connect-deeplink": - version: 0.0.0-use.local - resolution: "@trezor/connect-deeplink@workspace:packages/connect-deeplink" - dependencies: - "@trezor/connect": "workspace:^" - "@trezor/utils": "workspace:^" - languageName: unknown - linkType: soft - "@trezor/connect-explorer-theme@workspace:^, @trezor/connect-explorer-theme@workspace:packages/connect-explorer-theme": version: 0.0.0-use.local resolution: "@trezor/connect-explorer-theme@workspace:packages/connect-explorer-theme" @@ -11407,6 +11398,15 @@ __metadata: languageName: unknown linkType: soft +"@trezor/connect-mobile@workspace:*, @trezor/connect-mobile@workspace:packages/connect-mobile": + version: 0.0.0-use.local + resolution: "@trezor/connect-mobile@workspace:packages/connect-mobile" + dependencies: + "@trezor/connect": "workspace:^" + "@trezor/utils": "workspace:^" + languageName: unknown + linkType: soft + "@trezor/connect-plugin-ethereum@workspace:packages/connect-plugin-ethereum": version: 0.0.0-use.local resolution: "@trezor/connect-plugin-ethereum@workspace:packages/connect-plugin-ethereum" @@ -18069,22 +18069,6 @@ __metadata: languageName: node linkType: hard -"connect-deeplink-expo-example@workspace:packages/connect-examples/deeplink-expo": - version: 0.0.0-use.local - resolution: "connect-deeplink-expo-example@workspace:packages/connect-examples/deeplink-expo" - dependencies: - "@babel/core": "npm:^7.20.0" - "@trezor/connect-deeplink": "workspace:*" - "@types/react": "npm:18.2.45" - expo: "npm:51.0.31" - expo-linking: "npm:6.3.1" - expo-status-bar: "npm:1.12.1" - react: "npm:18.2.0" - react-native: "npm:0.75.2" - typescript: "npm:^5.3.3" - languageName: unknown - linkType: soft - "connect-example-electron-main@workspace:packages/connect-examples/electron-main-process": version: 0.0.0-use.local resolution: "connect-example-electron-main@workspace:packages/connect-examples/electron-main-process" @@ -18146,6 +18130,22 @@ __metadata: languageName: node linkType: hard +"connect-mobile-example@workspace:packages/connect-examples/mobile-expo": + version: 0.0.0-use.local + resolution: "connect-mobile-example@workspace:packages/connect-examples/mobile-expo" + dependencies: + "@babel/core": "npm:^7.20.0" + "@trezor/connect-mobile": "workspace:*" + "@types/react": "npm:18.2.45" + expo: "npm:51.0.31" + expo-linking: "npm:6.3.1" + expo-status-bar: "npm:1.12.1" + react: "npm:18.2.0" + react-native: "npm:0.75.2" + typescript: "npm:^5.3.3" + languageName: unknown + linkType: soft + "connect@npm:^3.6.5, connect@npm:^3.7.0": version: 3.7.0 resolution: "connect@npm:3.7.0" From edffb358ba713992662160b4b080fec770673e0c Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Tue, 15 Oct 2024 13:27:52 +0200 Subject: [PATCH 139/624] fix(suite-native): send amount inputs scrolling --- .../src/components/AmountInputs.tsx | 100 ++++++++++-------- .../src/components/CryptoAmountInput.tsx | 5 +- .../src/components/FiatAmountInput.tsx | 1 + suite-native/module-send/src/types.ts | 2 +- 4 files changed, 63 insertions(+), 45 deletions(-) diff --git a/suite-native/module-send/src/components/AmountInputs.tsx b/suite-native/module-send/src/components/AmountInputs.tsx index f830d2d96ea..2444456332b 100644 --- a/suite-native/module-send/src/components/AmountInputs.tsx +++ b/suite-native/module-send/src/components/AmountInputs.tsx @@ -1,6 +1,6 @@ import { useSharedValue, withTiming } from 'react-native-reanimated'; import { useRef, useState } from 'react'; -import { NativeSyntheticEvent, TextInput, TextInputFocusEventData } from 'react-native'; +import { TextInput, View, findNodeHandle } from 'react-native'; import { useSelector } from 'react-redux'; import { VStack, HStack, Box, Text } from '@suite-native/atoms'; @@ -57,6 +57,7 @@ export const AmountInputs = ({ index, accountKey }: AmountInputProps) => { const [isCryptoSelected, setIsCryptoSelected] = useState(true); const scrollView = useScrollView(); + const amountInputsWrapperRef = useRef(null); const cryptoRef = useRef(null); const cryptoScale = useSharedValue(SCALE_FOCUSED); @@ -91,53 +92,66 @@ export const AmountInputs = ({ index, accountKey }: AmountInputProps) => { setIsCryptoSelected(!isCryptoSelected); }; - const handleInputFocus = (e: NativeSyntheticEvent) => { - e.target?.measureInWindow((_, y) => { - scrollView?.scrollTo({ x: 0, y, animated: true }); - }); + const handleInputFocus = () => { + const amountInputsWrapper = amountInputsWrapperRef.current; + const scrollViewNodeHandle = findNodeHandle(scrollView); + + if (!amountInputsWrapper || !scrollViewNodeHandle) return; + + // Timeout is needed so the position is calculated after keyboard and footer animations are finished. + setTimeout( + () => + // Scroll so the whole amount inputs section is visible. + amountInputsWrapper.measureLayout(scrollViewNodeHandle, (_, y) => { + scrollView?.scrollTo({ y, animated: true }); + }), + 400, + ); }; if (!networkSymbol) return null; return ( - - - - - - {/* TODO: SEND MAX button */} - {/* */} - - - - {isFiatDisplayed && ( - <> - - - - )} - - - + */} + + + + {isFiatDisplayed && ( + <> + + + + )} + + + + ); }; diff --git a/suite-native/module-send/src/components/CryptoAmountInput.tsx b/suite-native/module-send/src/components/CryptoAmountInput.tsx index b988ccfee60..2e3a236248a 100644 --- a/suite-native/module-send/src/components/CryptoAmountInput.tsx +++ b/suite-native/module-send/src/components/CryptoAmountInput.tsx @@ -74,7 +74,10 @@ export const CryptoAmountInput = ({ const transformedValue = cryptoAmountTransformer(newValue); onChange(transformedValue); setValue(fiatFieldName, converters?.convertCryptoToFiat?.(transformedValue)); - debounce(() => trigger(cryptoFieldName)); + debounce(() => { + trigger(cryptoFieldName); + onFocus?.(); + }); }; const handleBlur = () => { diff --git a/suite-native/module-send/src/components/FiatAmountInput.tsx b/suite-native/module-send/src/components/FiatAmountInput.tsx index 649a58f9b8e..b8e51b6390e 100644 --- a/suite-native/module-send/src/components/FiatAmountInput.tsx +++ b/suite-native/module-send/src/components/FiatAmountInput.tsx @@ -57,6 +57,7 @@ export const FiatAmountInput = ({ setValue(cryptoFieldName, converters?.convertFiatToCrypto?.(transformedValue), { shouldValidate: true, }); + onFocus?.(); }; return ( diff --git a/suite-native/module-send/src/types.ts b/suite-native/module-send/src/types.ts index f1891456a32..3248f67e1c7 100644 --- a/suite-native/module-send/src/types.ts +++ b/suite-native/module-send/src/types.ts @@ -18,5 +18,5 @@ export type SendAmountInputProps = { translateValue: SharedValue; isDisabled?: boolean; onPress?: TextInputProps['onPress']; - onFocus?: TextInputProps['onFocus']; + onFocus?: () => void; }; From c56f0654755cd3061431b1664a3d719448176f62 Mon Sep 17 00:00:00 2001 From: Matej Kriz Date: Tue, 15 Oct 2024 16:12:27 +0200 Subject: [PATCH 140/624] fix(suite-native): show correct device label for each device - https://github.com/trezor/trezor-suite/pull/14483 broke device label in case of multiple devices. Device label of selected device was reused for all of them. --- .../src/components/DeviceItem/DeviceItemContent.tsx | 4 ++-- .../module-settings/src/components/ViewOnly/WalletRow.tsx | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx b/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx index 5f1ab2fce13..d02d6c61319 100644 --- a/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx +++ b/suite-native/device-manager/src/components/DeviceItem/DeviceItemContent.tsx @@ -8,7 +8,7 @@ import { DeviceRootState, PORTFOLIO_TRACKER_DEVICE_ID, selectHasOnlyEmptyPortfolioTracker, - selectDeviceLabelOrName, + selectDeviceLabelOrNameById, } from '@suite-common/wallet-core'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; import { TypographyStyle } from '@trezor/theme'; @@ -67,7 +67,7 @@ export const DeviceItemContent = React.memo( return { id: d.id, name: d.name, - label: selectDeviceLabelOrName(state), + label: selectDeviceLabelOrNameById(state, d.id), walletNumber: d.walletNumber, useEmptyPassphrase: d.useEmptyPassphrase, }; diff --git a/suite-native/module-settings/src/components/ViewOnly/WalletRow.tsx b/suite-native/module-settings/src/components/ViewOnly/WalletRow.tsx index bc52feab9c7..0f8421785b3 100644 --- a/suite-native/module-settings/src/components/ViewOnly/WalletRow.tsx +++ b/suite-native/module-settings/src/components/ViewOnly/WalletRow.tsx @@ -4,8 +4,9 @@ import { Button, HStack, Loader, Text } from '@suite-native/atoms'; import { Translation } from '@suite-native/intl'; import { ConnectDeviceSettings, + DeviceRootState, deviceActions, - selectDeviceLabelOrName, + selectDeviceLabelOrNameById, selectHasDeviceDiscovery, } from '@suite-common/wallet-core'; import { analytics, EventType } from '@suite-native/analytics'; @@ -33,7 +34,9 @@ export const WalletRow = ({ device }: WalletRowProps) => { const { showToast } = useToast(); const { applyStyle } = useNativeStyles(); const hasDiscovery = useSelector(selectHasDeviceDiscovery); - const deviceLabel = useSelector(selectDeviceLabelOrName); + const deviceLabel = useSelector((state: DeviceRootState) => + selectDeviceLabelOrNameById(state, device?.id), + ); const walletNameLabel = device.useEmptyPassphrase ? ( From b52bfba948e6185e9d7159c4e3e0d1d9d566457b Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Mon, 14 Oct 2024 14:14:24 +0200 Subject: [PATCH 141/624] chore: code improvement for arrayShuffle --- packages/utils/src/arrayShuffle.ts | 9 ++++++--- packages/utils/tests/arrayShuffle.test.ts | 11 ++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/utils/src/arrayShuffle.ts b/packages/utils/src/arrayShuffle.ts index 80fed358b75..00ccb64e34a 100644 --- a/packages/utils/src/arrayShuffle.ts +++ b/packages/utils/src/arrayShuffle.ts @@ -1,8 +1,11 @@ /** - * Randomly shuffles the elements in an array. This method - * does not mutate the original array. + * Implementation of the Fisher-Yates shuffle algorithm. + * The algorithm produces an unbiased permutation: every permutation is equally likely. + * @link https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + * + * This method does not mutate the original array. */ -export const arrayShuffle = (array: readonly T[]) => { +export const arrayShuffle = (array: readonly T[]): T[] => { const shuffled = array.slice(); for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); diff --git a/packages/utils/tests/arrayShuffle.test.ts b/packages/utils/tests/arrayShuffle.test.ts index 46db9c18bf0..cf2a94a5d43 100644 --- a/packages/utils/tests/arrayShuffle.test.ts +++ b/packages/utils/tests/arrayShuffle.test.ts @@ -5,19 +5,24 @@ const SAMPLES = 10000; const TOLERANCE = 0.1; const EXPECTED = SAMPLES / KEYS.length; -describe('arrayShuffle', () => { +const LOWER_BOUND = (1 - TOLERANCE) * EXPECTED; +const UPPER_BOUND = (1 + TOLERANCE) * EXPECTED; + +describe(arrayShuffle.name, () => { it('shuffles randomly', () => { const samples = Object.fromEntries(KEYS.map(key => [key, new Array(KEYS.length).fill(0)])); + for (let sample = 0; sample < SAMPLES; ++sample) { const shuffled = arrayShuffle(KEYS); for (let i = 0; i < shuffled.length; ++i) { samples[shuffled[i]][i]++; } } + KEYS.forEach(key => samples[key].forEach(count => { - expect(count).toBeGreaterThanOrEqual((1 - TOLERANCE) * EXPECTED); - expect(count).toBeLessThanOrEqual((1 + TOLERANCE) * EXPECTED); + expect(count).toBeGreaterThanOrEqual(LOWER_BOUND); + expect(count).toBeLessThanOrEqual(UPPER_BOUND); }), ); }); From 4f66613553084e28d81e13e9d3be4bfae889c335 Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Tue, 15 Oct 2024 14:25:07 +0200 Subject: [PATCH 142/624] chore: add better naming for random function which is not using strong source of randomness --- .../coinjoin/src/client/round/endedRound.ts | 4 ++-- .../src/client/round/inputRegistration.ts | 4 ++-- packages/coinjoin/src/utils/roundUtils.ts | 4 ++-- .../tests/client/CoinjoinRound.test.ts | 4 ++-- .../tests/client/transactionSigning.test.ts | 8 ++++---- .../coinjoin/tests/utils/roundUtils.test.ts | 20 +++++++++---------- .../TransactionList/NoSearchResults.tsx | 4 ++-- packages/utils/src/getRandomNumberInRange.ts | 2 -- .../utils/src/getWeakRandomNumberInRange.ts | 2 ++ packages/utils/src/index.ts | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) delete mode 100644 packages/utils/src/getRandomNumberInRange.ts create mode 100644 packages/utils/src/getWeakRandomNumberInRange.ts diff --git a/packages/coinjoin/src/client/round/endedRound.ts b/packages/coinjoin/src/client/round/endedRound.ts index 844af2a7324..1d561b9f35f 100644 --- a/packages/coinjoin/src/client/round/endedRound.ts +++ b/packages/coinjoin/src/client/round/endedRound.ts @@ -1,4 +1,4 @@ -import { enumUtils, getRandomNumberInRange } from '@trezor/utils'; +import { enumUtils, getWeakRandomNumberInRange } from '@trezor/utils'; import type { CoinjoinRound, CoinjoinRoundOptions } from '../CoinjoinRound'; import { EndRoundState, WabiSabiProtocolErrorCode } from '../../enums'; @@ -56,7 +56,7 @@ export const ended = (round: CoinjoinRound, { logger, network }: CoinjoinRoundOp // repeated input-registration will tell if they are really banned, // make sure that addresses registered in round are recycled (reset Infinity sentence) const minute = 60 * 1000; - const sentenceEnd = getRandomNumberInRange(5 * minute, 10 * minute); + const sentenceEnd = getWeakRandomNumberInRange(5 * minute, 10 * minute); [...inputs, ...addresses].forEach(vinvout => prison.detain(vinvout, { sentenceEnd, diff --git a/packages/coinjoin/src/client/round/inputRegistration.ts b/packages/coinjoin/src/client/round/inputRegistration.ts index 2e20812a4a3..9bc93b77d5b 100644 --- a/packages/coinjoin/src/client/round/inputRegistration.ts +++ b/packages/coinjoin/src/client/round/inputRegistration.ts @@ -1,4 +1,4 @@ -import { getRandomNumberInRange } from '@trezor/utils'; +import { getWeakRandomNumberInRange } from '@trezor/utils'; import * as coordinator from '../coordinator'; import * as middleware from '../middleware'; @@ -56,7 +56,7 @@ const registerInput = async ( // setup random delay for registration request. we want each input to be registered in different time as different TOR identity // note that this may cause that the input will not be registered if phase change before expected deadline const deadline = round.phaseDeadline - Date.now() - ROUND_SELECTION_REGISTRATION_OFFSET; - const delay = deadline > 0 ? getRandomNumberInRange(0, deadline) : 0; + const delay = deadline > 0 ? getWeakRandomNumberInRange(0, deadline) : 0; logger.info( `Trying to register ~~${input.outpoint}~~ to ~~${round.id}~~ with delay ${delay}ms and deadline ${round.phaseDeadline}`, ); diff --git a/packages/coinjoin/src/utils/roundUtils.ts b/packages/coinjoin/src/utils/roundUtils.ts index 93fa5ab67d1..763d294a43b 100644 --- a/packages/coinjoin/src/utils/roundUtils.ts +++ b/packages/coinjoin/src/utils/roundUtils.ts @@ -1,5 +1,5 @@ import { bufferutils, Transaction, Network } from '@trezor/utxo-lib'; -import { getRandomNumberInRange } from '@trezor/utils'; +import { getWeakRandomNumberInRange } from '@trezor/utils'; import { COORDINATOR_FEE_RATE_FALLBACK, @@ -88,7 +88,7 @@ export const scheduleDelay = ( // and at most 1 sec before the calculated max (so there's room for randomness) const min = clamp(minimumDelay, 0, max - 1000); - return getRandomNumberInRange(min, max); + return getWeakRandomNumberInRange(min, max); }; // NOTE: deadlines are not accurate. phase may change earlier diff --git a/packages/coinjoin/tests/client/CoinjoinRound.test.ts b/packages/coinjoin/tests/client/CoinjoinRound.test.ts index f6a3dc638d4..4b17e5ee079 100644 --- a/packages/coinjoin/tests/client/CoinjoinRound.test.ts +++ b/packages/coinjoin/tests/client/CoinjoinRound.test.ts @@ -188,7 +188,7 @@ describe(`CoinjoinRound`, () => { it('onPhaseChange lock cool off resolved', async () => { const delayMock = jest - .spyOn(trezorUtils, 'getRandomNumberInRange') + .spyOn(trezorUtils, 'getWeakRandomNumberInRange') .mockImplementation(() => 800); const constantsMock = jest @@ -396,7 +396,7 @@ describe(`CoinjoinRound`, () => { it('unregisterAccount when round is locked', async () => { const delayMock = jest - .spyOn(trezorUtils, 'getRandomNumberInRange') + .spyOn(trezorUtils, 'getWeakRandomNumberInRange') .mockImplementation(() => 800); const constantsMock = jest diff --git a/packages/coinjoin/tests/client/transactionSigning.test.ts b/packages/coinjoin/tests/client/transactionSigning.test.ts index 35db099f4f4..96addd9da80 100644 --- a/packages/coinjoin/tests/client/transactionSigning.test.ts +++ b/packages/coinjoin/tests/client/transactionSigning.test.ts @@ -1,5 +1,5 @@ import { networks } from '@trezor/utxo-lib'; -import { getRandomNumberInRange } from '@trezor/utils'; +import { getWeakRandomNumberInRange } from '@trezor/utils'; import { transactionSigning } from '../../src/client/round/transactionSigning'; import { createServer } from '../mocks/server'; @@ -529,7 +529,7 @@ describe('transactionSigning signature delay', () => { ); // signature is sent in range 17-67 sec. (resolve time is less than 50 sec TX_SIGNING_DELAY) - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(17000, 67000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(17000, 67000); expect(response.isSignedSuccessfully()).toBe(true); }); @@ -558,7 +558,7 @@ describe('transactionSigning signature delay', () => { ); // signature is sent in range 0-46.21 sec. (resolve time is greater than 50 sec of TX_SIGNING_DELAY) - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 46210); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 46210); expect(response.isSignedSuccessfully()).toBe(true); }); @@ -588,7 +588,7 @@ describe('transactionSigning signature delay', () => { ); // signature is sent in default range 0-1 sec. - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); expect(response.isSignedSuccessfully()).toBe(true); }); }); diff --git a/packages/coinjoin/tests/utils/roundUtils.test.ts b/packages/coinjoin/tests/utils/roundUtils.test.ts index fbb6597ea29..1d54ea200f9 100644 --- a/packages/coinjoin/tests/utils/roundUtils.test.ts +++ b/packages/coinjoin/tests/utils/roundUtils.test.ts @@ -1,4 +1,4 @@ -import { getRandomNumberInRange } from '@trezor/utils'; +import { getWeakRandomNumberInRange } from '@trezor/utils'; import { getCommitmentData, @@ -150,38 +150,38 @@ describe('roundUtils', () => { // default (no min, no max) range 0-10 sec. resultInRange(scheduleDelay(60000), 0, 10000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 10000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 10000); // range 3-10sec. resultInRange(scheduleDelay(20000, 3000), 3000, 10000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(3000, 10000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(3000, 10000); // deadlineOffset < 0, range 0-1 sec. resultInRange(scheduleDelay(1000, 3000), 0, 1000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); // deadline < min, range 9-10 sec. resultInRange(scheduleDelay(60000, 61000), 9000, 10000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(9000, 10000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(9000, 10000); // deadline < min && deadline < max, range 49-50 sec. resultInRange(scheduleDelay(60000, 61000, 62000), 49000, 50000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(49000, 50000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(49000, 50000); // deadline > min && deadline < max, range 3-20 sec. resultInRange(scheduleDelay(30000, 3000, 50000), 3000, 20000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(3000, 20000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(3000, 20000); // min < 0 && deadline < max && deadlineOffset > 0, range 0-2.5 sec. resultInRange(scheduleDelay(12500, -3000, 50000), 0, 2500); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 2500); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 2500); // min < 0 && max < 0 && deadlineOffset > 0, range 0-1 sec. resultInRange(scheduleDelay(12500, -10000, -5000), 0, 1000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); // min < 0 && max < 0 && deadlineOffset < 0, range 0-1 sec. resultInRange(scheduleDelay(7500, -10000, -5000), 0, 1000); - expect(getRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); + expect(getWeakRandomNumberInRange).toHaveBeenLastCalledWith(0, 1000); }); }); diff --git a/packages/suite/src/views/wallet/transactions/TransactionList/NoSearchResults.tsx b/packages/suite/src/views/wallet/transactions/TransactionList/NoSearchResults.tsx index e3b3b586d11..a1479ead448 100644 --- a/packages/suite/src/views/wallet/transactions/TransactionList/NoSearchResults.tsx +++ b/packages/suite/src/views/wallet/transactions/TransactionList/NoSearchResults.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import styled from 'styled-components'; import { Card, Column, variables } from '@trezor/components'; import { Translation } from 'src/components/suite'; -import { getRandomNumberInRange } from '@trezor/utils'; +import { getWeakRandomNumberInRange } from '@trezor/utils'; import { typography } from '@trezor/theme'; const NoResults = styled.div` @@ -46,7 +46,7 @@ const getTip = (num: number) => { }; export const NoSearchResults = () => { - const [tip] = useState(getRandomNumberInRange(1, 10)); + const [tip] = useState(getWeakRandomNumberInRange(1, 10)); return ( diff --git a/packages/utils/src/getRandomNumberInRange.ts b/packages/utils/src/getRandomNumberInRange.ts deleted file mode 100644 index 045e0789027..00000000000 --- a/packages/utils/src/getRandomNumberInRange.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const getRandomNumberInRange = (min: number, max: number) => - Math.floor(Math.random() * (max - min + 1)) + min; diff --git a/packages/utils/src/getWeakRandomNumberInRange.ts b/packages/utils/src/getWeakRandomNumberInRange.ts new file mode 100644 index 00000000000..3c16a0315e0 --- /dev/null +++ b/packages/utils/src/getWeakRandomNumberInRange.ts @@ -0,0 +1,2 @@ +export const getWeakRandomNumberInRange = (min: number, max: number) => + Math.floor(Math.random() * (max - min + 1)) + min; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index d1b93bc1c1a..29f1bc009f3 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -19,7 +19,7 @@ export * from './createTimeoutPromise'; export * from './getLocaleSeparators'; export * from './getMutex'; export * from './getNumberFromPixelString'; -export * from './getRandomNumberInRange'; +export * from './getWeakRandomNumberInRange'; export * from './getSynchronize'; export * from './getWeakRandomId'; export * from './hasUppercaseLetter'; From e1fe4b85d4885e52a080798539b215c6366afeaa Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Tue, 15 Oct 2024 14:45:51 +0200 Subject: [PATCH 143/624] chore: allow passing of the source of randomness for arrayShuffle --- .../src/backend/CoinjoinBackendClient.ts | 4 +-- .../src/client/round/outputRegistration.ts | 8 +++--- .../src/client/round/transactionSigning.ts | 4 +-- .../tests/client/CoinjoinRound.test.ts | 2 +- .../client/connectionConfirmation.test.ts | 2 +- .../tests/client/inputRegistration.test.ts | 2 +- .../tests/client/outputRegistration.test.ts | 2 +- .../tests/client/transactionSigning.test.ts | 2 +- .../coinjoin/tests/utils/roundUtils.test.ts | 2 +- packages/utils/src/arrayShuffle.ts | 8 ++++-- packages/utils/src/getWeakRandomInt.ts | 13 ++++++++++ .../utils/src/getWeakRandomNumberInRange.ts | 6 +++++ packages/utils/src/index.ts | 1 + packages/utils/tests/arrayShuffle.test.ts | 3 ++- packages/utils/tests/getWeakRandomInt.test.ts | 26 +++++++++++++++++++ .../tests/getWeakRandomNumberInRange.test.ts | 11 ++++++++ 16 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 packages/utils/src/getWeakRandomInt.ts create mode 100644 packages/utils/tests/getWeakRandomInt.test.ts create mode 100644 packages/utils/tests/getWeakRandomNumberInRange.test.ts diff --git a/packages/coinjoin/src/backend/CoinjoinBackendClient.ts b/packages/coinjoin/src/backend/CoinjoinBackendClient.ts index 99de08ffa84..449ed206f0a 100644 --- a/packages/coinjoin/src/backend/CoinjoinBackendClient.ts +++ b/packages/coinjoin/src/backend/CoinjoinBackendClient.ts @@ -1,4 +1,4 @@ -import { scheduleAction, arrayShuffle, urlToOnion } from '@trezor/utils'; +import { scheduleAction, arrayShuffle, urlToOnion, getWeakRandomInt } from '@trezor/utils'; import { TypedEmitter } from '@trezor/utils'; import type { BlockbookAPI } from '@trezor/blockchain-link/src/workers/blockbook/websocket'; @@ -38,7 +38,7 @@ export class CoinjoinBackendClient { constructor(settings: CoinjoinBackendClientSettings) { this.logger = settings.logger; - this.blockbookUrls = arrayShuffle(settings.blockbookUrls); + this.blockbookUrls = arrayShuffle(settings.blockbookUrls, { randomInt: getWeakRandomInt }); this.onionDomains = settings.onionDomains ?? {}; this.blockbookRequestId = Math.floor(Math.random() * settings.blockbookUrls.length); this.websockets = new CoinjoinWebsocketController(settings); diff --git a/packages/coinjoin/src/client/round/outputRegistration.ts b/packages/coinjoin/src/client/round/outputRegistration.ts index 19d9c5a8153..6c7ac003408 100644 --- a/packages/coinjoin/src/client/round/outputRegistration.ts +++ b/packages/coinjoin/src/client/round/outputRegistration.ts @@ -1,4 +1,4 @@ -import { getWeakRandomId, arrayShuffle } from '@trezor/utils'; +import { getWeakRandomId, arrayShuffle, getWeakRandomInt } from '@trezor/utils'; import * as coordinator from '../coordinator'; import * as middleware from '../middleware'; @@ -160,7 +160,7 @@ export const outputRegistration = async ( const assignedAddresses: AccountAddress[] = []; return Promise.all( - arrayShuffle(outputs).map(output => + arrayShuffle(outputs, { randomInt: getWeakRandomInt }).map(output => registerOutput(round, account, output, assignedAddresses, options), ), ); @@ -170,7 +170,9 @@ export const outputRegistration = async ( round.setSessionPhase(SessionPhase.AwaitingOthersOutputs); // inform coordinator that each registered input is ready to sign await Promise.all( - arrayShuffle(round.inputs).map(input => readyToSign(round, input, options)), + arrayShuffle(round.inputs, { randomInt: getWeakRandomInt }).map(input => + readyToSign(round, input, options), + ), ); logger.info(`Ready to sign ~~${round.id}~~`); } catch (error) { diff --git a/packages/coinjoin/src/client/round/transactionSigning.ts b/packages/coinjoin/src/client/round/transactionSigning.ts index d8a5677696a..9424d587daf 100644 --- a/packages/coinjoin/src/client/round/transactionSigning.ts +++ b/packages/coinjoin/src/client/round/transactionSigning.ts @@ -1,4 +1,4 @@ -import { arrayShuffle } from '@trezor/utils'; +import { arrayShuffle, getWeakRandomInt } from '@trezor/utils'; import * as coordinator from '../coordinator'; import * as middleware from '../middleware'; @@ -234,7 +234,7 @@ export const transactionSigning = async ( round.setSessionPhase(SessionPhase.SendingSignature); await Promise.all( - arrayShuffle(round.inputs).map(input => + arrayShuffle(round.inputs, { randomInt: getWeakRandomInt }).map(input => sendTxSignature(round, resolvedTime, input, options), ), ); diff --git a/packages/coinjoin/tests/client/CoinjoinRound.test.ts b/packages/coinjoin/tests/client/CoinjoinRound.test.ts index 4b17e5ee079..3de3079a476 100644 --- a/packages/coinjoin/tests/client/CoinjoinRound.test.ts +++ b/packages/coinjoin/tests/client/CoinjoinRound.test.ts @@ -12,7 +12,7 @@ jest.mock('@trezor/utils', () => { return { __esModule: true, ...originalModule, - getRandomNumberInRange: () => 0, + getWeakRandomNumberInRange: () => 0, }; }); diff --git a/packages/coinjoin/tests/client/connectionConfirmation.test.ts b/packages/coinjoin/tests/client/connectionConfirmation.test.ts index 985863ec82e..573358c02a2 100644 --- a/packages/coinjoin/tests/client/connectionConfirmation.test.ts +++ b/packages/coinjoin/tests/client/connectionConfirmation.test.ts @@ -14,7 +14,7 @@ jest.mock('@trezor/utils', () => { return { __esModule: true, ...originalModule, - getRandomNumberInRange: () => 0, + getWeakRandomNumberInRange: () => 0, }; }); diff --git a/packages/coinjoin/tests/client/inputRegistration.test.ts b/packages/coinjoin/tests/client/inputRegistration.test.ts index d6afb9f851f..b90b12437aa 100644 --- a/packages/coinjoin/tests/client/inputRegistration.test.ts +++ b/packages/coinjoin/tests/client/inputRegistration.test.ts @@ -10,7 +10,7 @@ jest.mock('@trezor/utils', () => { return { __esModule: true, ...originalModule, - getRandomNumberInRange: () => 0, + getWeakRandomNumberInRange: () => 0, }; }); diff --git a/packages/coinjoin/tests/client/outputRegistration.test.ts b/packages/coinjoin/tests/client/outputRegistration.test.ts index 890efd0155d..f927f41d9ca 100644 --- a/packages/coinjoin/tests/client/outputRegistration.test.ts +++ b/packages/coinjoin/tests/client/outputRegistration.test.ts @@ -11,7 +11,7 @@ jest.mock('@trezor/utils', () => { return { __esModule: true, ...originalModule, - getRandomNumberInRange: () => 0, + getWeakRandomNumberInRange: () => 0, }; }); diff --git a/packages/coinjoin/tests/client/transactionSigning.test.ts b/packages/coinjoin/tests/client/transactionSigning.test.ts index 96addd9da80..66cf63eb7b4 100644 --- a/packages/coinjoin/tests/client/transactionSigning.test.ts +++ b/packages/coinjoin/tests/client/transactionSigning.test.ts @@ -13,7 +13,7 @@ jest.mock('@trezor/utils', () => { return { __esModule: true, ...originalModule, - getRandomNumberInRange: jest.fn(() => 0), + getWeakRandomNumberInRange: jest.fn(() => 0), }; }); diff --git a/packages/coinjoin/tests/utils/roundUtils.test.ts b/packages/coinjoin/tests/utils/roundUtils.test.ts index 1d54ea200f9..c28166694fe 100644 --- a/packages/coinjoin/tests/utils/roundUtils.test.ts +++ b/packages/coinjoin/tests/utils/roundUtils.test.ts @@ -19,7 +19,7 @@ jest.mock('@trezor/utils', () => { return { __esModule: true, ...originalModule, - getRandomNumberInRange: jest.fn(originalModule.getRandomNumberInRange), + getWeakRandomNumberInRange: jest.fn(originalModule.getWeakRandomNumberInRange), }; }); diff --git a/packages/utils/src/arrayShuffle.ts b/packages/utils/src/arrayShuffle.ts index 00ccb64e34a..ee5b0f6d33a 100644 --- a/packages/utils/src/arrayShuffle.ts +++ b/packages/utils/src/arrayShuffle.ts @@ -5,10 +5,14 @@ * * This method does not mutate the original array. */ -export const arrayShuffle = (array: readonly T[]): T[] => { +export const arrayShuffle = ( + array: readonly T[], + { randomInt }: { randomInt: (min: number, max: number) => number }, +): T[] => { const shuffled = array.slice(); for (let i = shuffled.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); + const j = randomInt(0, i + 1); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } diff --git a/packages/utils/src/getWeakRandomInt.ts b/packages/utils/src/getWeakRandomInt.ts new file mode 100644 index 00000000000..df458c5c025 --- /dev/null +++ b/packages/utils/src/getWeakRandomInt.ts @@ -0,0 +1,13 @@ +/** + * @param min Inclusive + * @param max Exclusive + */ +export const getWeakRandomInt = (min: number, max: number) => { + if (min >= max) { + throw new RangeError( + `The value of "max" is out of range. It must be greater than the value of "min" (${min}). Received ${max}`, + ); + } + + return Math.floor(Math.random() * (max - min) + min); +}; diff --git a/packages/utils/src/getWeakRandomNumberInRange.ts b/packages/utils/src/getWeakRandomNumberInRange.ts index 3c16a0315e0..ba9c2e225e8 100644 --- a/packages/utils/src/getWeakRandomNumberInRange.ts +++ b/packages/utils/src/getWeakRandomNumberInRange.ts @@ -1,2 +1,8 @@ +/** + * @deprecated Use `getWeakRandomInt` instead. + * + * @param min Inclusive + * @param max Inclusive + */ export const getWeakRandomNumberInRange = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 29f1bc009f3..9c295f83da1 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -22,6 +22,7 @@ export * from './getNumberFromPixelString'; export * from './getWeakRandomNumberInRange'; export * from './getSynchronize'; export * from './getWeakRandomId'; +export * from './getWeakRandomInt'; export * from './hasUppercaseLetter'; export * from './isAscii'; export * from './isHex'; diff --git a/packages/utils/tests/arrayShuffle.test.ts b/packages/utils/tests/arrayShuffle.test.ts index cf2a94a5d43..5cb3bb21d0d 100644 --- a/packages/utils/tests/arrayShuffle.test.ts +++ b/packages/utils/tests/arrayShuffle.test.ts @@ -1,4 +1,5 @@ import { arrayShuffle } from '../src/arrayShuffle'; +import { getWeakRandomInt } from '../src/getWeakRandomInt'; const KEYS = ['a', 'b', 'c', 'd', 'e']; const SAMPLES = 10000; @@ -13,7 +14,7 @@ describe(arrayShuffle.name, () => { const samples = Object.fromEntries(KEYS.map(key => [key, new Array(KEYS.length).fill(0)])); for (let sample = 0; sample < SAMPLES; ++sample) { - const shuffled = arrayShuffle(KEYS); + const shuffled = arrayShuffle(KEYS, { randomInt: getWeakRandomInt }); for (let i = 0; i < shuffled.length; ++i) { samples[shuffled[i]][i]++; } diff --git a/packages/utils/tests/getWeakRandomInt.test.ts b/packages/utils/tests/getWeakRandomInt.test.ts new file mode 100644 index 00000000000..0f1e6132a20 --- /dev/null +++ b/packages/utils/tests/getWeakRandomInt.test.ts @@ -0,0 +1,26 @@ +import { getWeakRandomInt } from '../src'; + +describe(getWeakRandomInt.name, () => { + it('raises same error as randomInt from crypto when max <= min', () => { + const EXPECTED_ERROR = new RangeError( + 'The value of "max" is out of range. It must be greater than the value of "min" (0). Received -1', + ); + + expect(() => getWeakRandomInt(0, -1)).toThrowError(EXPECTED_ERROR); + }); + + it('returns same value when range is trivial', () => { + expect(getWeakRandomInt(0, 1)).toEqual(0); + expect(getWeakRandomInt(100, 101)).toEqual(100); + }); + + it('returns same value when range is trivial', () => { + for (let i = 0; i < 10_000; i++) { + const result = getWeakRandomInt(0, 100); + + expect(Number.isInteger(result)).toBe(true); + expect(result).toBeGreaterThanOrEqual(0); + expect(result).toBeLessThan(100); + } + }); +}); diff --git a/packages/utils/tests/getWeakRandomNumberInRange.test.ts b/packages/utils/tests/getWeakRandomNumberInRange.test.ts new file mode 100644 index 00000000000..25d22909761 --- /dev/null +++ b/packages/utils/tests/getWeakRandomNumberInRange.test.ts @@ -0,0 +1,11 @@ +import { getWeakRandomNumberInRange } from '../src'; + +describe(getWeakRandomNumberInRange.name, () => { + it('returns value in range', () => { + for (let i = 0; i < 10_000; i++) { + const result = getWeakRandomNumberInRange(0, 100); + expect(result).toBeGreaterThanOrEqual(0); + expect(result).toBeLessThanOrEqual(100); + } + }); +}); From 9f8f1c1bd25834075fa7eb7af8ad6a439e63546a Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Fri, 20 Sep 2024 13:50:28 +0200 Subject: [PATCH 144/624] docs(connect): mobile connect popup --- .../public/images/schema-connect-deeplink.svg | 37 +++++ .../src/components/icons/IconMobile.tsx | 20 +++ .../src/pages/details/deeplinking.mdx | 66 +++++++++ packages/connect-explorer/src/pages/index.mdx | 136 +++++++++++++++++- .../src/pages/readme/[name].mdx | 2 +- packages/connect-mobile/README.md | 2 + 6 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 packages/connect-explorer/public/images/schema-connect-deeplink.svg create mode 100644 packages/connect-explorer/src/components/icons/IconMobile.tsx create mode 100644 packages/connect-explorer/src/pages/details/deeplinking.mdx diff --git a/packages/connect-explorer/public/images/schema-connect-deeplink.svg b/packages/connect-explorer/public/images/schema-connect-deeplink.svg new file mode 100644 index 00000000000..0425f91f571 --- /dev/null +++ b/packages/connect-explorer/public/images/schema-connect-deeplink.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/connect-explorer/src/components/icons/IconMobile.tsx b/packages/connect-explorer/src/components/icons/IconMobile.tsx new file mode 100644 index 00000000000..e5e986c1bcf --- /dev/null +++ b/packages/connect-explorer/src/components/icons/IconMobile.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +function IconMobile() { + return ( + + + + ); +} + +export default IconMobile; diff --git a/packages/connect-explorer/src/pages/details/deeplinking.mdx b/packages/connect-explorer/src/pages/details/deeplinking.mdx new file mode 100644 index 00000000000..2ab5ad318d9 --- /dev/null +++ b/packages/connect-explorer/src/pages/details/deeplinking.mdx @@ -0,0 +1,66 @@ +import { Callout } from 'nextra/components'; + +# Deep linking specification + +To support connecting to Trezor devices from 3rd party apps on mobile devices, Trezor Suite Lite provides a communication interface via deep linking. + + + **This feature is still in beta and is subject to change. It's currently available only in + development builds of Trezor Suite Lite.** + + +## Base URL + +The base URL for deep linking is different depending on the environment. + +| Environment | Base URL | +| ----------- | ------------------------------------------------------ | +| Production | currently unavailable | +| Development | `https://dev.suite.sldev.cz/connect/develop/deeplink/` | +| Local | `trezorsuitelite://connect` | + +## Query parameters + +The method call is specified using the query parameters. + +| Parameter | Type | Required | Description | +| ---------- | ----------- | -------- | -------------------------------------------------------- | +| `method` | string | yes | The name of the Connect method to call (eg. getAddress). | +| `params` | JSON object | yes | The parameters for the method call encoded as JSON. | +| `callback` | string | yes | The URL to redirect to after the method call is made. | + +## Callback + +To receive the result of the method call, the app must specify a callback URL. The callback URL is called with the result of the method call. + +The following query parameters are passed in the callback URL: + +| Parameter | Type | Description | +| ---------- | ----------- | --------------------------------------------------------------------------- | +| `id` | integer | ID of the call | +| `response` | JSON object | Result of the method call, equivalent to the object returned by the method. | + +## Example + +Let's imagine we want to convert the following call to a deep link: + +``` +const address = await TrezorConnect.getAddress({ + coin: 'btc', + path: "m/44'/0'/0'/0/0", +}); +``` + +The parameters would be: + +- **method**: `getAddress` +- **params**: `{"coin":"btc","path":"m/44'/0'/0'/0/0"}` +- **callback**: `https://httpbin.org/get` (as an example) + +The encoded deep link URL would then be: + +``` +trezorsuitelite://connect?method=getAddress¶ms=%7B%22coin%22%3A%22btc%22%2C%22path%22%3A%22m%2F44%27%2F0%27%2F0%27%2F0%2F0%22%7D&callback=https%3A%2F%2Fhttpbin.org%2Fget +``` + +When the user returns to the app, the callback URL is called with the result of the method call. diff --git a/packages/connect-explorer/src/pages/index.mdx b/packages/connect-explorer/src/pages/index.mdx index 1d0e7c31414..56df35182aa 100644 --- a/packages/connect-explorer/src/pages/index.mdx +++ b/packages/connect-explorer/src/pages/index.mdx @@ -19,6 +19,7 @@ import { import IconNode from '../components/icons/IconNode'; import IconWeb from '../components/icons/IconWeb'; import IconExtension from '../components/icons/IconExtension'; +import IconMobile from '../components/icons/IconMobile'; import ZoomableIllustration from '../components/ZoomableIllustration'; export const SectionCard = ({ children }) => ( @@ -106,10 +107,11 @@ export const ExampleHeading = styled.h3` Depending on your environment you need to chose the right package and follow the particular guide: - + } title="Node.js" href="#nodejs" /> } title="Web" href="#web" /> } title="Web extension" href="#web-extension" /> + } title="Mobile" href="#mobile" /> @@ -498,3 +500,135 @@ export const ExampleHeading = styled.h3` + + + +### Mobile + + + + + + Mobile + Using deep linking + + + + + + + + + + + #### About + + `@trezor/connect-mobile` is a package that allows you to communicate with Trezor devices from your mobile app. + This package is somewhat different from the other SDKs, as it doesn't provide a direct API to the device. Instead, it uses deep linking to open the Trezor Suite app and communicate with the device. + + #### Use deep linking without SDK + + If you are not able to use the SDK, for example on non-supported platforms, you can still use deep linking to open the Trezor Suite app and communicate with the device. + + This can be done by implementing the following specification. + + + + + + + + Examples: + - [Expo App example](https://github.com/trezor/trezor-suite/tree/develop/packages/connect-examples/mobile-expo) + + + + + + {

Installation of the package

} + + Simply install the package using your preferred package manager: + + ```bash + npm install @trezor/connect-mobile + # or + yarn add @trezor/connect-mobile + ``` + + {

Initialization of the API

} + + ```javascript + import * as Linking from 'expo-linking'; + + TrezorConnect.init({ + manifest: { + email: 'developer@xyz.com', + appUrl: 'http://your.application.com', + }, + deeplinkOpen: url => { + Linking.openURL(url); + }, + deeplinkCallbackUrl: Linking.createURL('/connect'), + }); + ``` + + Trezor Connect Manifest requires that you, as a Trezor Connect integrator, share your email and application URL with us. This provides us with the ability to reach you in case of any required maintenance. This subscription is mandatory. + + The deeplink SDK needs two extra parameters: `deeplinkOpen` and `deeplinkCallbackUrl`. The `deeplinkOpen` function is used to open the Trezor Suite app, and the `deeplinkCallbackUrl` is the URL that the app will redirect to after the operation is complete. + + In this example, we are using the `Linking` API from Expo to open the Trezor Suite app, however this may be different depending on your mobile app's environment. + + {

Handling callbacks

} + + The app needs to pass results from the callback URL back to the SDK. This can be done by listening to the URL and passing the data to the SDK using the `handleDeeplink` method. + + ```javascript + useEffect(() => { + const subscription = Linking.addEventListener('url', event => { + TrezorConnect.handleDeeplink(event.url); + }); + + return () => subscription?.remove(); + }, []); + ``` + + {

How to use?

} + + Here is an example of how to get the device's public key: + + ```javascript + TrezorConnect.getPublicKey({ + path: "m/44'/0'/0'/0/0", + showOnTrezor: true, + }); + ``` + + More methods with detailed explanation can be found on the left under the 'Coin methods' section. You can also try the Method Testing Tool, where you can try interacting with the device by yourself. +
+
+ +
diff --git a/packages/connect-explorer/src/pages/readme/[name].mdx b/packages/connect-explorer/src/pages/readme/[name].mdx index 3296b9dbed7..fce0c2d0f55 100644 --- a/packages/connect-explorer/src/pages/readme/[name].mdx +++ b/packages/connect-explorer/src/pages/readme/[name].mdx @@ -4,7 +4,7 @@ import rehypeSectionize from '@hbsnow/rehype-sectionize'; import remarkGemoji from 'remark-gemoji'; export const getStaticPaths = () => { - const packages = ["connect", "connect-web", "connect-webextension"] + const packages = ["connect", "connect-web", "connect-webextension", "connect-mobile"] const paths = packages.map((name) => ({ params: { name, diff --git a/packages/connect-mobile/README.md b/packages/connect-mobile/README.md index 64228cb9628..c7ae4c9bf4b 100644 --- a/packages/connect-mobile/README.md +++ b/packages/connect-mobile/README.md @@ -4,6 +4,8 @@ The `@trezor/connect-mobile` package provides an implementation of `@trezor/connect` which uses deep links to communicate with the Trezor Suite Lite app. +## 🚧 BETA version, work in progress 🚧 + Currently the library is still under development, only supports read-only methods and does not communicate with the production Suite Lite app. To run a dev version of the Suite mobile app follow the instructions in [@suite-native/app](https://github.com/trezor/trezor-suite/blob/develop/suite-native/app/README.md) From f2a5f7460ef956853df62ac9bd7c5ff193b0b95a Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Thu, 26 Sep 2024 15:50:39 +0200 Subject: [PATCH 145/624] feat(connect-explorer): call deeplinks from method tester --- packages/connect-explorer/package.json | 1 + .../src/actions/methodActions.ts | 6 ++-- .../src/actions/trezorConnectActions.ts | 28 +++++++++++++++++-- .../connect-explorer/src/pages/_meta.json | 4 +++ .../connect-explorer/src/pages/callback.mdx | 20 +++++++++++++ .../connect-explorer/src/pages/settings.mdx | 7 +++++ .../src/reducers/trezorConnectReducer.ts | 5 +++- packages/connect-explorer/tsconfig.json | 1 + packages/connect-mobile/src/index.ts | 5 ++++ yarn.lock | 3 +- 10 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 packages/connect-explorer/src/pages/callback.mdx diff --git a/packages/connect-explorer/package.json b/packages/connect-explorer/package.json index a2fabc6c895..306af433770 100644 --- a/packages/connect-explorer/package.json +++ b/packages/connect-explorer/package.json @@ -18,6 +18,7 @@ "@trezor/components": "workspace:^", "@trezor/connect": "workspace:^", "@trezor/connect-explorer-theme": "workspace:^", + "@trezor/connect-mobile": "workspace:^", "@trezor/connect-web": "workspace:^", "@trezor/connect-webextension": "workspace:^", "@trezor/protobuf": "workspace:^", diff --git a/packages/connect-explorer/src/actions/methodActions.ts b/packages/connect-explorer/src/actions/methodActions.ts index ac777b0cec4..7551ef87432 100644 --- a/packages/connect-explorer/src/actions/methodActions.ts +++ b/packages/connect-explorer/src/actions/methodActions.ts @@ -2,6 +2,7 @@ import { TSchema } from '@sinclair/typebox'; import JSON5 from 'json5'; import TrezorConnect from '@trezor/connect-web'; +import TrezorConnectMobile from '@trezor/connect-mobile'; import { getDeepValue } from '@trezor/schema-utils/src/utils'; import { GetState, Dispatch, Field } from '../types'; @@ -80,10 +81,11 @@ export const onSetManualMode = (manualMode: boolean) => ({ }); export const onSubmit = () => async (dispatch: Dispatch, getState: GetState) => { - const { method } = getState(); + const { method, connect } = getState(); if (!method?.name) throw new Error('method name not specified'); dispatch({ type: SET_METHOD_PROCESSING, payload: true }); - const connectMethod = TrezorConnect[method.name]; + const trezorConnectImpl = connect.deeplink ? TrezorConnectMobile : TrezorConnect; + const connectMethod = trezorConnectImpl[method.name]; if (typeof connectMethod !== 'function') { dispatch( onResponse({ diff --git a/packages/connect-explorer/src/actions/trezorConnectActions.ts b/packages/connect-explorer/src/actions/trezorConnectActions.ts index d56caf9a952..354e6217f25 100644 --- a/packages/connect-explorer/src/actions/trezorConnectActions.ts +++ b/packages/connect-explorer/src/actions/trezorConnectActions.ts @@ -5,6 +5,8 @@ import TrezorConnect, { WEBEXTENSION, } from '@trezor/connect-web'; +import TrezorConnectMobile from '@trezor/connect-mobile'; + import { TrezorConnectDevice, Dispatch, Field, GetState } from '../types'; import * as ACTIONS from './index'; @@ -15,7 +17,7 @@ export type TrezorConnectAction = | { type: typeof DEVICE.CONNECT; device: TrezorConnectDevice } | { type: typeof DEVICE.CONNECT_UNACQUIRED; device: TrezorConnectDevice } | { type: typeof DEVICE.DISCONNECT; device: TrezorConnectDevice } - | { type: typeof ACTIONS.ON_CHANGE_CONNECT_OPTIONS; payload: ConnectOptions } + | { type: typeof ACTIONS.ON_CHANGE_CONNECT_OPTIONS; payload: ConnectOptions; deeplink: boolean } | { type: typeof ACTIONS.ON_HANDSHAKE_CONFIRMED } | { type: typeof ACTIONS.ON_INIT_ERROR; payload: string } | { @@ -143,6 +145,7 @@ export const init = // Get default coreMode from URL params (?core-mode=auto) const urlParams = new URLSearchParams(window.location.search); const coreMode = (urlParams.get('core-mode') as ConnectOptions['coreMode']) || 'auto'; + const deeplink = urlParams.get('deeplink') === 'true'; const connectOptions = { coreMode, @@ -160,20 +163,39 @@ export const init = }; try { - await TrezorConnect.init(connectOptions); + if (deeplink) { + await TrezorConnectMobile.init({ + ...connectOptions, + deeplinkOpen(url) { + window.open(url, '_blank'); + }, + deeplinkCallbackUrl: + (process.env.CONNECT_EXPLORER_FULL_URL || window.location.origin) + + '/callback', + }); + const bc = new BroadcastChannel('trezor_connect_callback'); + bc.onmessage = e => { + if (e.data.type === 'popup_callback') { + TrezorConnectMobile.handleDeeplink(e.data.url); + } + }; + } else { + await TrezorConnect.init(connectOptions); + } } catch (err) { dispatch({ type: ACTIONS.ON_INIT_ERROR, payload: err.message }); return; } - dispatch({ type: ACTIONS.ON_CHANGE_CONNECT_OPTIONS, payload: connectOptions }); + dispatch({ type: ACTIONS.ON_CHANGE_CONNECT_OPTIONS, payload: connectOptions, deeplink }); }; export const onSubmitInit = () => async (dispatch: Dispatch, getState: GetState) => { const { connect } = getState(); // Disposing TrezorConnect to init it again. await TrezorConnect.dispose(); + await TrezorConnectMobile.dispose(); return dispatch(init(connect.options)); }; diff --git a/packages/connect-explorer/src/pages/_meta.json b/packages/connect-explorer/src/pages/_meta.json index 65a2f1571e4..bfddddd1a63 100644 --- a/packages/connect-explorer/src/pages/_meta.json +++ b/packages/connect-explorer/src/pages/_meta.json @@ -9,5 +9,9 @@ "test": { "title": "Test", "display": "hidden" + }, + "callback": { + "title": "Callback", + "display": "hidden" } } diff --git a/packages/connect-explorer/src/pages/callback.mdx b/packages/connect-explorer/src/pages/callback.mdx new file mode 100644 index 00000000000..8ec2ef41e86 --- /dev/null +++ b/packages/connect-explorer/src/pages/callback.mdx @@ -0,0 +1,20 @@ +import { useEffect } from 'react'; +import { Button } from '@trezor/components'; + +export const CallbackHandler = () => { + useEffect(() => { + const bc = new BroadcastChannel('trezor_connect_callback'); + bc.postMessage({ type: 'popup_callback', url: window.location.href }); + }, []); + + return
; + +}; + +# Trezor Connect Callback + +Callback received. You can close this window now. + + + + diff --git a/packages/connect-explorer/src/pages/settings.mdx b/packages/connect-explorer/src/pages/settings.mdx index 7d3308a156c..22c4145b9e7 100644 --- a/packages/connect-explorer/src/pages/settings.mdx +++ b/packages/connect-explorer/src/pages/settings.mdx @@ -29,6 +29,7 @@ export const Settings = () => { trustedHost: state.connect?.options?.trustedHost, connectSrc: state.connect?.options?.connectSrc, coreMode: state?.connect?.options?.coreMode, + deeplink: state?.connect?.options?.deeplink })); const initError = useSelector(state => state.connect?.initError); @@ -64,6 +65,12 @@ export const Settings = () => { key: 'connectSrc', value: connectOptions?.connectSrc || '', }, + { + name: 'mobile deeplink', + type: 'checkbox', + key: 'deeplink', + value: connectOptions?.deeplink || false + } ]; return ( diff --git a/packages/connect-explorer/src/reducers/trezorConnectReducer.ts b/packages/connect-explorer/src/reducers/trezorConnectReducer.ts index ec600143b04..7a0e972be8a 100644 --- a/packages/connect-explorer/src/reducers/trezorConnectReducer.ts +++ b/packages/connect-explorer/src/reducers/trezorConnectReducer.ts @@ -3,13 +3,14 @@ import TrezorConnect, { DEVICE } from '@trezor/connect-web'; import * as ACTIONS from '../actions/index'; import { TrezorConnectDevice, Action, Field } from '../types'; -type ConnectState = { +export type ConnectState = { devices: TrezorConnectDevice[]; selectedDevice?: string; options?: Parameters<(typeof TrezorConnect)['init']>[0]; isHandshakeConfirmed: boolean; isInitSuccess: boolean; initError?: string; + deeplink?: boolean; }; const initialState: ConnectState = { @@ -19,6 +20,7 @@ const initialState: ConnectState = { isHandshakeConfirmed: false, isInitSuccess: false, initError: undefined, + deeplink: false, }; const findDeviceIndexByPath = (devices: TrezorConnectDevice[], path: string): number => @@ -102,6 +104,7 @@ export default function connect(state: ConnectState = initialState, action: Acti initError: undefined, isInitSuccess: true, options: action.payload, + deeplink: action.deeplink, }; case ACTIONS.ON_HANDSHAKE_CONFIRMED: return { diff --git a/packages/connect-explorer/tsconfig.json b/packages/connect-explorer/tsconfig.json index ba288a9840b..587719a4cd5 100644 --- a/packages/connect-explorer/tsconfig.json +++ b/packages/connect-explorer/tsconfig.json @@ -18,6 +18,7 @@ { "path": "../components" }, { "path": "../connect" }, { "path": "../connect-explorer-theme" }, + { "path": "../connect-mobile" }, { "path": "../connect-web" }, { "path": "../connect-webextension" }, { "path": "../protobuf" }, diff --git a/packages/connect-mobile/src/index.ts b/packages/connect-mobile/src/index.ts index c44e36661dd..9783ff8ac9e 100644 --- a/packages/connect-mobile/src/index.ts +++ b/packages/connect-mobile/src/index.ts @@ -123,6 +123,11 @@ export class TrezorConnectDeeplink implements ConnectFactoryDependencies { return; } + if (!this.messagePromises[id]) { + // Most likely old ID, ignore + return; + } + const responseParam = parsedUrl.searchParams.get('response'); if (!responseParam) { this.messagePromises[id].resolve({ diff --git a/yarn.lock b/yarn.lock index d56c82383bc..810a06b3253 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11336,6 +11336,7 @@ __metadata: "@trezor/components": "workspace:^" "@trezor/connect": "workspace:^" "@trezor/connect-explorer-theme": "workspace:^" + "@trezor/connect-mobile": "workspace:^" "@trezor/connect-web": "workspace:^" "@trezor/connect-webextension": "workspace:^" "@trezor/protobuf": "workspace:^" @@ -11398,7 +11399,7 @@ __metadata: languageName: unknown linkType: soft -"@trezor/connect-mobile@workspace:*, @trezor/connect-mobile@workspace:packages/connect-mobile": +"@trezor/connect-mobile@workspace:*, @trezor/connect-mobile@workspace:^, @trezor/connect-mobile@workspace:packages/connect-mobile": version: 0.0.0-use.local resolution: "@trezor/connect-mobile@workspace:packages/connect-mobile" dependencies: From 21e0d42c6d8b8190ca164e5c8712387c34817cc0 Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Tue, 15 Oct 2024 16:19:19 +0200 Subject: [PATCH 146/624] feat(connect-explorer): hiding beta-only content --- packages/connect-explorer/src/components/BetaOnly.tsx | 11 +++++++++++ .../src/pages/details/deeplinking.mdx | 5 +++++ packages/connect-explorer/src/pages/index.mdx | 9 ++++++++- packages/connect-explorer/src/pages/readme/[name].mdx | 7 ++++++- packages/connect-explorer/src/pages/settings.mdx | 5 +++-- 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 packages/connect-explorer/src/components/BetaOnly.tsx diff --git a/packages/connect-explorer/src/components/BetaOnly.tsx b/packages/connect-explorer/src/components/BetaOnly.tsx new file mode 100644 index 00000000000..18995f7d04b --- /dev/null +++ b/packages/connect-explorer/src/components/BetaOnly.tsx @@ -0,0 +1,11 @@ +export const isBetaOnly = !process.env.CONNECT_EXPLORER_FULL_URL?.startsWith( + 'https://connect.trezor.io/9/', +); + +export const BetaOnly = (props: React.PropsWithChildren) => { + if (isBetaOnly) { + return <>{props.children}; + } + + return null; +}; diff --git a/packages/connect-explorer/src/pages/details/deeplinking.mdx b/packages/connect-explorer/src/pages/details/deeplinking.mdx index 2ab5ad318d9..a56977f7eaf 100644 --- a/packages/connect-explorer/src/pages/details/deeplinking.mdx +++ b/packages/connect-explorer/src/pages/details/deeplinking.mdx @@ -1,7 +1,10 @@ import { Callout } from 'nextra/components'; +import { BetaOnly } from '../../components/BetaOnly'; # Deep linking specification + + To support connecting to Trezor devices from 3rd party apps on mobile devices, Trezor Suite Lite provides a communication interface via deep linking. @@ -64,3 +67,5 @@ trezorsuitelite://connect?method=getAddress¶ms=%7B%22coin%22%3A%22btc%22%2C% ``` When the user returns to the app, the callback URL is called with the result of the method call. + + diff --git a/packages/connect-explorer/src/pages/index.mdx b/packages/connect-explorer/src/pages/index.mdx index 56df35182aa..fc3c48f34a2 100644 --- a/packages/connect-explorer/src/pages/index.mdx +++ b/packages/connect-explorer/src/pages/index.mdx @@ -21,6 +21,7 @@ import IconWeb from '../components/icons/IconWeb'; import IconExtension from '../components/icons/IconExtension'; import IconMobile from '../components/icons/IconMobile'; import ZoomableIllustration from '../components/ZoomableIllustration'; +import { BetaOnly } from '../components/BetaOnly'; export const SectionCard = ({ children }) => ( {children} @@ -111,7 +112,9 @@ export const ExampleHeading = styled.h3` } title="Node.js" href="#nodejs" /> } title="Web" href="#web" /> } title="Web extension" href="#web-extension" /> - } title="Mobile" href="#mobile" /> + + } title="Mobile" href="#mobile" /> +
@@ -501,6 +504,8 @@ export const ExampleHeading = styled.h3` + + ### Mobile @@ -632,3 +637,5 @@ export const ExampleHeading = styled.h3` + + diff --git a/packages/connect-explorer/src/pages/readme/[name].mdx b/packages/connect-explorer/src/pages/readme/[name].mdx index fce0c2d0f55..43e6042968b 100644 --- a/packages/connect-explorer/src/pages/readme/[name].mdx +++ b/packages/connect-explorer/src/pages/readme/[name].mdx @@ -2,9 +2,14 @@ import { RemoteContent } from 'nextra/data'; import { buildDynamicMDX, buildDynamicMeta } from 'nextra/remote'; import rehypeSectionize from '@hbsnow/rehype-sectionize'; import remarkGemoji from 'remark-gemoji'; +import { isBetaOnly } from '../../components/BetaOnly'; export const getStaticPaths = () => { - const packages = ["connect", "connect-web", "connect-webextension", "connect-mobile"] + const packages = ["connect", "connect-web", "connect-webextension"]; + if(isBetaOnly) { + packages.push("connect-mobile"); + } + const paths = packages.map((name) => ({ params: { name, diff --git a/packages/connect-explorer/src/pages/settings.mdx b/packages/connect-explorer/src/pages/settings.mdx index 22c4145b9e7..80c4c870c68 100644 --- a/packages/connect-explorer/src/pages/settings.mdx +++ b/packages/connect-explorer/src/pages/settings.mdx @@ -6,6 +6,7 @@ import { Callout } from 'nextra/components'; import * as trezorConnectActions from '../actions/trezorConnectActions'; import { useSelector, useActions } from '../hooks'; import { getField } from '../components/Method'; +import { isBetaOnly } from '../components/BetaOnly'; export const SettingsContent = styled.section` flex: 1; @@ -65,12 +66,12 @@ export const Settings = () => { key: 'connectSrc', value: connectOptions?.connectSrc || '', }, - { + ...(isBetaOnly ? [{ name: 'mobile deeplink', type: 'checkbox', key: 'deeplink', value: connectOptions?.deeplink || false - } + }] : []) ]; return ( From 7b5d0b3de0cf71c584671293af1216e1adeed207 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Tue, 15 Oct 2024 17:15:01 +0200 Subject: [PATCH 147/624] chore(device-utils): stricter getFirmwareVersion return type --- packages/device-utils/src/firmwareUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/device-utils/src/firmwareUtils.ts b/packages/device-utils/src/firmwareUtils.ts index 1a93ceaf753..2d80c078359 100644 --- a/packages/device-utils/src/firmwareUtils.ts +++ b/packages/device-utils/src/firmwareUtils.ts @@ -19,12 +19,13 @@ export const getFirmwareVersionArray = (device?: Device): VersionArray | null => return [features.major_version, features.minor_version, features.patch_version]; }; -export const getFirmwareVersion = (device?: Device) => { +export const getFirmwareVersion = (device?: Device): '' | `${number}.${number}.${number}` => { if (!device?.features) { return ''; } const { features } = device; if (isDeviceInBootloaderMode(device)) { + // @ts-expect-error fw_minor and fw_patch is imho always defined. maybe only for some very old firmwares only major version is defined. return features.fw_major ? `${features.fw_major}.${features.fw_minor}.${features.fw_patch}` : ''; From 6f4c0b1102e3df30853adce30c53a0de8453a48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Vytick=20Vytrhl=C3=ADk?= Date: Mon, 14 Oct 2024 20:18:51 +0200 Subject: [PATCH 148/624] feat(suite-native): refactor ethereum formatters to generic token formatters --- .../AccountsList/AccountsListTokenItem.tsx | 13 ++++----- ...Formatter.tsx => TokenAmountFormatter.tsx} | 6 ++--- ...ter.tsx => TokenToFiatAmountFormatter.tsx} | 11 +++++--- suite-native/formatters/src/index.ts | 4 +-- .../components/TransactionEventTooltip.tsx | 4 +-- .../components/AccountImportSummaryForm.tsx | 7 ++--- ...thereumTokenInfo.tsx => TokenInfoCard.tsx} | 27 ++++++++++--------- .../components/AccountDetailCryptoValue.tsx | 8 ++---- .../src/components/TokenReceiveCard.tsx | 17 +++++++----- .../TransactionDetailHeader.tsx | 9 ++++--- .../TransactionDetailInputsSheetSection.tsx | 4 +-- .../TokenTransferListItem.tsx | 10 +++---- 12 files changed, 62 insertions(+), 58 deletions(-) rename suite-native/formatters/src/components/{EthereumTokenAmountFormatter.tsx => TokenAmountFormatter.tsx} (87%) rename suite-native/formatters/src/components/{EthereumTokenToFiatAmountFormatter.tsx => TokenToFiatAmountFormatter.tsx} (86%) rename suite-native/module-accounts-import/src/components/{EthereumTokenInfo.tsx => TokenInfoCard.tsx} (61%) diff --git a/suite-native/accounts/src/components/AccountsList/AccountsListTokenItem.tsx b/suite-native/accounts/src/components/AccountsList/AccountsListTokenItem.tsx index a26556a20d7..8b484401536 100644 --- a/suite-native/accounts/src/components/AccountsList/AccountsListTokenItem.tsx +++ b/suite-native/accounts/src/components/AccountsList/AccountsListTokenItem.tsx @@ -3,10 +3,7 @@ import { useSelector } from 'react-redux'; import { AccountsRootState } from '@suite-common/wallet-core'; import { Account, TokenInfoBranded } from '@suite-common/wallet-types'; import { RoundedIcon } from '@suite-native/atoms'; -import { - EthereumTokenAmountFormatter, - EthereumTokenToFiatAmountFormatter, -} from '@suite-native/formatters'; +import { TokenAmountFormatter, TokenToFiatAmountFormatter } from '@suite-native/formatters'; import { getTokenName, selectAccountTokenSymbol } from '@suite-native/tokens'; import { AccountsListItemBase } from './AccountsListItemBase'; @@ -43,10 +40,14 @@ export const AccountsListTokenItem = ({ icon={} title={getTokenName(token.name)} mainValue={ - + } secondaryValue={ - & TextProps; -export const EthereumTokenAmountFormatter = ({ +export const TokenAmountFormatter = ({ value, symbol, isDiscreetText = true, @@ -22,7 +22,7 @@ export const EthereumTokenAmountFormatter = ({ variant = 'hint', color = 'textSubdued', ...rest -}: EthereumTokenAmountFormatterProps) => { +}: TokenAmountFormatterProps) => { const decimalValue = convertTokenValueToDecimal(value, decimals); const formattedValue = `${localizeNumber(decimalValue)} ${symbol}`; diff --git a/suite-native/formatters/src/components/EthereumTokenToFiatAmountFormatter.tsx b/suite-native/formatters/src/components/TokenToFiatAmountFormatter.tsx similarity index 86% rename from suite-native/formatters/src/components/EthereumTokenToFiatAmountFormatter.tsx rename to suite-native/formatters/src/components/TokenToFiatAmountFormatter.tsx index 84b62a6a184..3c6fe05d888 100644 --- a/suite-native/formatters/src/components/EthereumTokenToFiatAmountFormatter.tsx +++ b/suite-native/formatters/src/components/TokenToFiatAmountFormatter.tsx @@ -2,13 +2,15 @@ import { TextProps, Box } from '@suite-native/atoms'; import { useFormatters } from '@suite-common/formatters'; import { TokenAddress } from '@suite-common/wallet-types'; import { SignValue } from '@suite-common/suite-types'; +import { NetworkSymbol } from '@suite-common/wallet-config'; import { FormatterProps } from '../types'; import { AmountText } from './AmountText'; import { SignValueFormatter } from './SignValueFormatter'; import { useFiatFromCryptoValue } from '../hooks/useFiatFromCryptoValue'; -type EthereumTokenToFiatAmountFormatterProps = { +type TokenToFiatAmountFormatterProps = { + networkSymbol: NetworkSymbol; contract: TokenAddress; isDiscreetText?: boolean; decimals?: number; @@ -19,7 +21,8 @@ type EthereumTokenToFiatAmountFormatterProps = { } & FormatterProps & TextProps; -export const EthereumTokenToFiatAmountFormatter = ({ +export const TokenToFiatAmountFormatter = ({ + networkSymbol, value, contract, isDiscreetText = true, @@ -30,11 +33,11 @@ export const EthereumTokenToFiatAmountFormatter = ({ historicRate, useHistoricRate, ...rest -}: EthereumTokenToFiatAmountFormatterProps) => { +}: TokenToFiatAmountFormatterProps) => { const { FiatAmountFormatter } = useFormatters(); const fiatValue = useFiatFromCryptoValue({ cryptoValue: String(value), - network: 'eth', + network: networkSymbol, tokenAddress: contract, tokenDecimals: decimals, historicRate, diff --git a/suite-native/formatters/src/index.ts b/suite-native/formatters/src/index.ts index 00b516f3216..c0f2aab22d1 100644 --- a/suite-native/formatters/src/index.ts +++ b/suite-native/formatters/src/index.ts @@ -5,8 +5,8 @@ export { TransactionIdFormatter } from './components/TransactionIdFormatter'; export { PercentageDifferenceFormatter } from './components/PercentageDifferenceFormatter'; export { FiatAmountFormatter } from './components/FiatAmountFormatter'; export { CryptoAmountFormatter } from './components/CryptoAmountFormatter'; -export { EthereumTokenAmountFormatter } from './components/EthereumTokenAmountFormatter'; -export { EthereumTokenToFiatAmountFormatter } from './components/EthereumTokenToFiatAmountFormatter'; +export { TokenAmountFormatter } from './components/TokenAmountFormatter'; +export { TokenToFiatAmountFormatter } from './components/TokenToFiatAmountFormatter'; export { SignValueFormatter } from './components/SignValueFormatter'; export { FeeFormatter } from './components/FeeFormatter'; export { useFiatFromCryptoValue } from './hooks/useFiatFromCryptoValue'; diff --git a/suite-native/graph/src/components/TransactionEventTooltip.tsx b/suite-native/graph/src/components/TransactionEventTooltip.tsx index 94d6b1351d4..e26f60e059a 100644 --- a/suite-native/graph/src/components/TransactionEventTooltip.tsx +++ b/suite-native/graph/src/components/TransactionEventTooltip.tsx @@ -7,7 +7,7 @@ import { G, N } from '@mobily/ts-belt'; import { Card, Box, Text } from '@suite-native/atoms'; import { CryptoAmountFormatter, - EthereumTokenAmountFormatter, + TokenAmountFormatter, SignValueFormatter, } from '@suite-native/formatters'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; @@ -82,7 +82,7 @@ const TokenAmountTooltipFormatter = ({ // We might want to add support for other networks in the future. if (getNetworkType(networkSymbol) === 'ethereum') { return ( - ( - ), - [], + [networkSymbol], ); return ( diff --git a/suite-native/module-accounts-import/src/components/EthereumTokenInfo.tsx b/suite-native/module-accounts-import/src/components/TokenInfoCard.tsx similarity index 61% rename from suite-native/module-accounts-import/src/components/EthereumTokenInfo.tsx rename to suite-native/module-accounts-import/src/components/TokenInfoCard.tsx index 6f01532635d..db4fe53bc28 100644 --- a/suite-native/module-accounts-import/src/components/EthereumTokenInfo.tsx +++ b/suite-native/module-accounts-import/src/components/TokenInfoCard.tsx @@ -6,14 +6,13 @@ import { selectIsSpecificCoinDefinitionKnown, } from '@suite-common/token-definitions'; import { TokenAddress, TokenSymbol } from '@suite-common/wallet-types'; -import { - EthereumTokenAmountFormatter, - EthereumTokenToFiatAmountFormatter, -} from '@suite-native/formatters'; +import { TokenAmountFormatter, TokenToFiatAmountFormatter } from '@suite-native/formatters'; +import { NetworkSymbol } from '@suite-common/wallet-config'; import { AccountImportOverviewCard } from './AccountImportOverviewCard'; -type EthereumTokenInfoProps = { +type TokenInfoCardProps = { + networkSymbol: NetworkSymbol; symbol?: TokenSymbol; balance?: string; name?: string; @@ -21,26 +20,27 @@ type EthereumTokenInfoProps = { contract: TokenAddress; }; -export const EthereumTokenInfo = ({ +export const TokenInfoCard = ({ + networkSymbol, symbol, balance, name, decimals, contract, -}: EthereumTokenInfoProps) => { - const ethereumSymbolHasFiatRates = useSelector((state: TokenDefinitionsRootState) => - selectIsSpecificCoinDefinitionKnown(state, 'eth', contract), +}: TokenInfoCardProps) => { + const isSpecificCoinDefinitionKnown = useSelector((state: TokenDefinitionsRootState) => + selectIsSpecificCoinDefinitionKnown(state, networkSymbol, contract), ); - if (!symbol || !balance || !name || !ethereumSymbolHasFiatRates) return null; + if (!symbol || !balance || !name || !isSpecificCoinDefinitionKnown) return null; return ( } > - {tokenSymbol ? ( - + ) : ( + selectAccountNetworkSymbol(state, accountKey), + ); + + if (!token || !network) { return ( } /> ); + } const tokenName = getTokenName(token.name); @@ -82,11 +84,12 @@ export const TokenReceiveCard = ({ contract, accountKey }: TokenReceiveCardProps
- - {tokenTransfer ? ( - {tokenTransfer ? ( - ) : ( - - - Date: Wed, 9 Oct 2024 13:27:37 +0200 Subject: [PATCH 149/624] fix(suite-desktop-core): restart app when using autostart --- packages/suite-desktop-core/src/app.ts | 3 ++- .../suite-desktop-core/src/libs/app-utils.ts | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/suite-desktop-core/src/app.ts b/packages/suite-desktop-core/src/app.ts index 49009a7d19c..baa2919cf72 100644 --- a/packages/suite-desktop-core/src/app.ts +++ b/packages/suite-desktop-core/src/app.ts @@ -138,7 +138,8 @@ const init = async () => { // Daemon mode with no UI const { wasOpenedAtLogin } = app.getLoginItemSettings(); const daemon = app.commandLine.hasSwitch('bridge-daemon') || wasOpenedAtLogin; - if (daemon) { + const daemonShowUI = app.commandLine.hasSwitch('bridge-daemon-show-ui'); // show UI immediately even in daemon mode + if (daemon && !daemonShowUI) { logger.info('main', 'App is hidden, starting bridge only'); app.dock?.hide(); // hide dock icon on macOS const waitForFullStart = createDeferred(); diff --git a/packages/suite-desktop-core/src/libs/app-utils.ts b/packages/suite-desktop-core/src/libs/app-utils.ts index c2afe09e5e0..b985c4f231a 100644 --- a/packages/suite-desktop-core/src/libs/app-utils.ts +++ b/packages/suite-desktop-core/src/libs/app-utils.ts @@ -1,22 +1,29 @@ -import { app } from 'electron'; - import { mergeDeepObject } from '@trezor/utils'; +import { app } from '../typed-electron'; + export const restartApp = () => { const { logger } = global; logger.info('app', `Relaunching app with ${process.argv.slice(1).join(', ')} arguments.`); - const options: Electron.RelaunchOptions = { args: process.argv }; + const options: Electron.RelaunchOptions = { args: process.argv ?? [] }; if (process.env.APPIMAGE) { options.execPath = process.env.APPIMAGE; - options.args = options.args ?? []; - options.args.unshift('--appimage-extract-and-run'); + options.args?.unshift('--appimage-extract-and-run'); + } + + // If in daemon/autostart mode, add a flag to show the UI right after restart + if (app.getLoginItemSettings().openAtLogin) { + options.args?.push('--bridge-daemon'); + } + if (options.args?.includes('--bridge-daemon')) { + options.args?.push('--bridge-daemon-show-ui'); + // In daemon mode, first quit call only hides the app + app.quit(); } - // too: not sure why it was here - // app.removeAllListeners('before-quit'); - app.relaunch(); + app.relaunch(options); app.quit(); }; From 3cdf290d0c7242b68b244adc096ff0ca4ef4526d Mon Sep 17 00:00:00 2001 From: Ondrej Hajek Date: Wed, 16 Oct 2024 10:22:19 +0200 Subject: [PATCH 150/624] chore(e2e): updated tenv image in e2e tests --- docker/docker-compose.connect-popup-ci.yml | 2 +- docker/docker-compose.connect-popup-test.yml | 2 +- docker/docker-compose.connect-test.yml | 2 +- docker/docker-compose.connect-webextension-test.yml | 2 +- docker/docker-compose.suite-ci.yml | 2 +- docker/docker-compose.suite-desktop-ci.yml | 2 +- docker/docker-compose.suite-dev.yml | 2 +- docker/docker-compose.suite-native-ci.yml | 2 +- docker/docker-compose.suite-test.yml | 2 +- docker/docker-compose.transport-test-ci.yml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docker/docker-compose.connect-popup-ci.yml b/docker/docker-compose.connect-popup-ci.yml index ba56b58495c..7c4323bac8e 100644 --- a/docker/docker-compose.connect-popup-ci.yml +++ b/docker/docker-compose.connect-popup-ci.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp diff --git a/docker/docker-compose.connect-popup-test.yml b/docker/docker-compose.connect-popup-test.yml index 37dbbfbf477..fdb3855cb0c 100644 --- a/docker/docker-compose.connect-popup-test.yml +++ b/docker/docker-compose.connect-popup-test.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - DISPLAY=$DISPLAY - QT_X11_NO_MITSHM=1 diff --git a/docker/docker-compose.connect-test.yml b/docker/docker-compose.connect-test.yml index 1f356dd38a2..2c4a44bdec6 100644 --- a/docker/docker-compose.connect-test.yml +++ b/docker/docker-compose.connect-test.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp diff --git a/docker/docker-compose.connect-webextension-test.yml b/docker/docker-compose.connect-webextension-test.yml index 79ee3393bf4..9ecbc345cc0 100644 --- a/docker/docker-compose.connect-webextension-test.yml +++ b/docker/docker-compose.connect-webextension-test.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp diff --git a/docker/docker-compose.suite-ci.yml b/docker/docker-compose.suite-ci.yml index 630a554a1be..e6cc7ede163 100644 --- a/docker/docker-compose.suite-ci.yml +++ b/docker/docker-compose.suite-ci.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp diff --git a/docker/docker-compose.suite-desktop-ci.yml b/docker/docker-compose.suite-desktop-ci.yml index 69196cf66b7..cdb8d3c1572 100644 --- a/docker/docker-compose.suite-desktop-ci.yml +++ b/docker/docker-compose.suite-desktop-ci.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp diff --git a/docker/docker-compose.suite-dev.yml b/docker/docker-compose.suite-dev.yml index 6390b28d3af..b18d41127a0 100644 --- a/docker/docker-compose.suite-dev.yml +++ b/docker/docker-compose.suite-dev.yml @@ -4,7 +4,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - DISPLAY=$DISPLAY - QT_X11_NO_MITSHM=1 diff --git a/docker/docker-compose.suite-native-ci.yml b/docker/docker-compose.suite-native-ci.yml index b09cfedf752..db94a27d90f 100644 --- a/docker/docker-compose.suite-native-ci.yml +++ b/docker/docker-compose.suite-native-ci.yml @@ -3,7 +3,7 @@ services: trezor-user-env-unix: network_mode: "host" container_name: trezor-user-env.unix - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp diff --git a/docker/docker-compose.suite-test.yml b/docker/docker-compose.suite-test.yml index e113aa1dd55..d08c8695626 100644 --- a/docker/docker-compose.suite-test.yml +++ b/docker/docker-compose.suite-test.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - DISPLAY=$DISPLAY - QT_X11_NO_MITSHM=1 diff --git a/docker/docker-compose.transport-test-ci.yml b/docker/docker-compose.transport-test-ci.yml index d755f65637b..1fed373e836 100644 --- a/docker/docker-compose.transport-test-ci.yml +++ b/docker/docker-compose.transport-test-ci.yml @@ -1,7 +1,7 @@ version: "3.9" services: trezor-user-env-unix: - image: ghcr.io/trezor/trezor-user-env:4ba1d062469911b9be78eff2c0503ac77b06f598 + image: ghcr.io/trezor/trezor-user-env:766f7d2cd13635fbdb61afa569f6aeb927085bf1 environment: - SDL_VIDEODRIVER=dummy - XDG_RUNTIME_DIR=/var/tmp From 013c7862504c4376e681cf1e9bb848850bccd7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Vytick=20Vytrhl=C3=ADk?= Date: Tue, 15 Oct 2024 21:12:41 +0200 Subject: [PATCH 151/624] feat(suite-common): add pol and bnb to graph --- packages/blockchain-link-types/src/common.ts | 2 +- suite-common/graph/src/balanceHistoryUtils.ts | 9 +++++++-- suite-common/graph/src/constants.ts | 7 ++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/blockchain-link-types/src/common.ts b/packages/blockchain-link-types/src/common.ts index 2c7039f2179..46c8b4a80e8 100644 --- a/packages/blockchain-link-types/src/common.ts +++ b/packages/blockchain-link-types/src/common.ts @@ -34,7 +34,7 @@ export interface ServerInfo { consensusBranchId?: number; // zcash current branch id } -export type TokenStandard = 'ERC20' | 'ERC1155' | 'ERC721' | 'SPL'; +export type TokenStandard = 'ERC20' | 'ERC1155' | 'ERC721' | 'SPL' | 'BEP20'; export type TransferType = 'sent' | 'recv' | 'self' | 'unknown'; diff --git a/suite-common/graph/src/balanceHistoryUtils.ts b/suite-common/graph/src/balanceHistoryUtils.ts index 6944f85b9c4..dfe5a6ddf3f 100644 --- a/suite-common/graph/src/balanceHistoryUtils.ts +++ b/suite-common/graph/src/balanceHistoryUtils.ts @@ -134,6 +134,7 @@ const getAccountHistoryMovementItemRipple = ({ return { main: Array.from(summaryMap.values()).sort((a, b) => a.time - b.time), tokens: {} }; }; +// this can be also used for networks of Ethereum type (like ETH, POL or BNB) export const getAccountHistoryMovementItemETH = ({ transactions, from, @@ -230,8 +231,10 @@ export const getAccountHistoryMovementItemETH = ({ } tx.tokens.forEach(token => { - // skip empty amounts and non-ERC20 tokens - if (token.amount === '' || token.standard !== 'ERC20') return; + // skip empty amounts and non-ERC20 non-BEP20 tokens + // BEP20 is BNB Smart Chain (BSC) token standard + if (token.amount === '' || (token.standard !== 'ERC20' && token.standard !== 'BEP20')) + return; if (token.type === 'sent' || token.type === 'recv' || token.type === 'self') { const tokenSummary: AccountHistoryMovementItem = { @@ -320,6 +323,8 @@ export const getAccountHistoryMovementFromTransactions = ({ case 'xrp': return getAccountHistoryMovementItemRipple({ transactions, from, to }); case 'eth': + case 'pol': + case 'bnb': return getAccountHistoryMovementItemETH({ transactions, from, to }); default: coin satisfies never; diff --git a/suite-common/graph/src/constants.ts b/suite-common/graph/src/constants.ts index fc60edaeb20..6e95134e2df 100644 --- a/suite-common/graph/src/constants.ts +++ b/suite-common/graph/src/constants.ts @@ -3,7 +3,12 @@ import { NetworkSymbol } from '@suite-common/wallet-config'; // Going over 180 will broke graph in mobile app export const NUMBER_OF_POINTS = 40; -export const LOCAL_BALANCE_HISTORY_COINS = ['eth', 'xrp'] satisfies Array; +export const LOCAL_BALANCE_HISTORY_COINS = [ + 'eth', + 'pol', + 'bnb', + 'xrp', +] satisfies Array; export type LocalBalanceHistoryCoin = (typeof LOCAL_BALANCE_HISTORY_COINS)[number]; export const isLocalBalanceHistoryCoin = ( From fb157ef3186e55d6fa89c255b6dc8a03ba966d4b Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Wed, 16 Oct 2024 13:36:14 +0200 Subject: [PATCH 152/624] chore(connect-mobile): update package.json for publishing --- packages/connect-mobile/package.json | 25 ++++++++++++++++++----- packages/connect-mobile/tsconfig.lib.json | 15 ++++++++++++++ yarn.lock | 3 +++ 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 packages/connect-mobile/tsconfig.lib.json diff --git a/packages/connect-mobile/package.json b/packages/connect-mobile/package.json index 159dc211474..7b89182713b 100644 --- a/packages/connect-mobile/package.json +++ b/packages/connect-mobile/package.json @@ -1,17 +1,32 @@ { "name": "@trezor/connect-mobile", - "version": "1.0.0", - "private": true, + "version": "0.0.0", "license": "See LICENSE.md in repo root", "sideEffects": false, - "main": "src/index", + "main": "src/index.ts", + "publishConfig": { + "main": "lib/index.js" + }, + "npmPublishAccess": "public", + "files": [ + "lib/" + ], "scripts": { - "depcheck": "yarn g:depcheck", "lint:js": "yarn g:eslint '**/*.{ts,tsx,js}'", - "type-check": "yarn g:tsc --build" + "depcheck": "yarn g:depcheck", + "type-check": "yarn g:tsc --build", + "build:lib": "yarn g:rimraf ./lib && yarn g:tsc --build tsconfig.lib.json && ../../scripts/replace-imports.sh ./lib", + "prepublishOnly": "yarn tsx ../../scripts/prepublishNPM.js", + "prepublish": "yarn tsx ../../scripts/prepublish.js" + }, + "devDependencies": { + "tsx": "^4.16.3" }, "dependencies": { "@trezor/connect": "workspace:^", "@trezor/utils": "workspace:^" + }, + "peerDependencies": { + "tslib": "^2.6.2" } } diff --git a/packages/connect-mobile/tsconfig.lib.json b/packages/connect-mobile/tsconfig.lib.json new file mode 100644 index 00000000000..dfc917a9a0d --- /dev/null +++ b/packages/connect-mobile/tsconfig.lib.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.lib.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src"], + "references": [ + { + "path": "../connect" + }, + { + "path": "../utils" + } + ] +} diff --git a/yarn.lock b/yarn.lock index 810a06b3253..a5351462df6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11405,6 +11405,9 @@ __metadata: dependencies: "@trezor/connect": "workspace:^" "@trezor/utils": "workspace:^" + tsx: "npm:^4.16.3" + peerDependencies: + tslib: ^2.6.2 languageName: unknown linkType: soft From 22030e3f4375f3cb564705dcf7ba58e4cafc7605 Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Fri, 11 Oct 2024 10:19:45 +0200 Subject: [PATCH 153/624] feat(suite): add coin selection prompt to empty passphrase wallet --- .../components/src/components/Flex/Flex.tsx | 3 + .../components/src/components/Icon/Icon.tsx | 15 +- .../DeviceSelector/DeviceStatus.tsx | 25 +-- .../modals/ModalSwitcher/DiscoveryLoader.tsx | 30 ++- .../DeviceContextModal/PassphraseModal.tsx | 190 ++++++++---------- .../PassphraseWalletConfirmation.tsx | 37 ++-- .../PassphraseWalletConfirmationStep1.tsx | 172 ++++++++++------ .../PassphraseDuplicateModal.tsx | 56 +++--- .../PassphraseMismatchModal.tsx | 16 +- packages/suite/src/support/messages.ts | 12 ++ .../dashboard/PortfolioCard/EmptyWallet.tsx | 90 +++++---- .../dashboard/PortfolioCard/PortfolioCard.tsx | 23 ++- .../PortfolioCard/PortfolioCardException.tsx | 55 +---- .../DeviceItem/AddWalletButton.tsx | 85 ++++---- .../SwitchDevice/DeviceItem/DeviceDetail.tsx | 26 +-- .../SwitchDevice/DeviceItem/DeviceItem.tsx | 44 ++-- .../views/suite/SwitchDevice/SwitchDevice.tsx | 39 ++-- .../suite/SwitchDevice/SwitchDeviceModal.tsx | 55 +++-- .../SwitchDevice/SwitchDeviceRenderer.tsx | 33 --- 19 files changed, 462 insertions(+), 544 deletions(-) delete mode 100644 packages/suite/src/views/suite/SwitchDevice/SwitchDeviceRenderer.tsx diff --git a/packages/components/src/components/Flex/Flex.tsx b/packages/components/src/components/Flex/Flex.tsx index bb5635eee9a..6c999576e03 100644 --- a/packages/components/src/components/Flex/Flex.tsx +++ b/packages/components/src/components/Flex/Flex.tsx @@ -147,6 +147,7 @@ export type FlexProps = AllowedFrameProps & { className?: string; onClick?: () => void; 'data-testid'?: string; + as?: string; }; const Flex = ({ @@ -160,6 +161,7 @@ const Flex = ({ isReversed = false, className, 'data-testid': dataTestId, + as = 'div', hasDivider = false, dividerColor, onClick, @@ -186,6 +188,7 @@ const Flex = ({ elevation, })} onClick={onClick} + as={as} {...frameProps} > {children} diff --git a/packages/components/src/components/Icon/Icon.tsx b/packages/components/src/components/Icon/Icon.tsx index 44b02c5bd03..9b8d8396a9f 100644 --- a/packages/components/src/components/Icon/Icon.tsx +++ b/packages/components/src/components/Icon/Icon.tsx @@ -120,19 +120,6 @@ const SVG = styled(ReactSVG)` stroke 0.15s, fill 0.15s; } - - ${({ onClick }) => - onClick && - css` - cursor: pointer; - - &:focus-visible { - svg { - transition: opacity 0.2s; - opacity: 0.5; - } - } - `} ` as typeof ReactSVG; export type IconName = IconNameNew | IconNameDeprecated; @@ -193,7 +180,7 @@ export const Icon = forwardRef( return ( ` display: flex; - opacity: ${({ $isLowerOpacity }) => $isLowerOpacity && 0.4}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledRotateDeviceImage = styled(RotateDeviceImage)` width: 24px; - - /* do not apply the darkening filter in dark mode on device images */ - filter: none; + opacity: ${({ $isLowerOpacity }) => $isLowerOpacity && 0.4}; `; export const DeviceStatus = ({ @@ -48,9 +35,9 @@ export const DeviceStatus = ({ const deviceLabel = useSelector(state => selectDeviceLabelOrNameById(state, device?.id)); return ( - + - )} - + ); }; diff --git a/packages/suite/src/components/suite/modals/ModalSwitcher/DiscoveryLoader.tsx b/packages/suite/src/components/suite/modals/ModalSwitcher/DiscoveryLoader.tsx index ac4400080e0..b4e39c8356f 100644 --- a/packages/suite/src/components/suite/modals/ModalSwitcher/DiscoveryLoader.tsx +++ b/packages/suite/src/components/suite/modals/ModalSwitcher/DiscoveryLoader.tsx @@ -1,4 +1,4 @@ -import { H3, Spinner, NewModal, Column } from '@trezor/components'; +import { H3, Spinner, Column } from '@trezor/components'; import { Translation } from 'src/components/suite'; import { CardWithDevice } from 'src/views/suite/SwitchDevice/CardWithDevice'; import { SwitchDeviceModal } from 'src/views/suite/SwitchDevice/SwitchDeviceModal'; @@ -11,20 +11,18 @@ export const DiscoveryLoader = () => { if (!device) return null; return ( - - - - - -

- -

-
-
-
-
+ + + + +

+ +

+
+
+
); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx index a5509ae47ca..7c35a4f453a 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx @@ -1,6 +1,6 @@ import { useCallback } from 'react'; -import { Paragraph, NewModal, Column, H3, List, Icon } from '@trezor/components'; +import { Paragraph, Column, H3, List, Icon } from '@trezor/components'; import { selectIsDiscoveryAuthConfirmationRequired, onPassphraseSubmit, @@ -76,107 +76,91 @@ export const PassphraseModal = ({ device }: PassphraseModalProps) => { } return ( - - - {hasDeviceState ? ( - // "view-only" is active, device is reconnected and you fired an action that needs passphrase (e.g. add coin, show receive address) - - -

- -

- - - - } - type="hidden" - singleColModal - offerPassphraseOnDevice={onDeviceOffer} - onSubmit={onSubmit} - deviceModel={deviceModel ?? undefined} - learnMoreTooltipOnClick={ - - } - /> -
-
- ) : ( - // first step of adding passphrase wallet from switch device modal - - -

- -

- - }> - ( - - {chunks} - - ), - }} - /> - - }> - - - } - > - - - - } - type="hidden" - singleColModal - offerPassphraseOnDevice={onDeviceOffer} - onSubmit={onSubmit} - deviceModel={deviceModel ?? undefined} - learnMoreTooltipOnClick={ - - } - /> -
-
- )} -
-
+ + {hasDeviceState ? ( + // "view-only" is active, device is reconnected and you fired an action that needs passphrase (e.g. add coin, show receive address) + + +

+ +

+ + + + } + type="hidden" + singleColModal + offerPassphraseOnDevice={onDeviceOffer} + onSubmit={onSubmit} + deviceModel={deviceModel ?? undefined} + learnMoreTooltipOnClick={ + + } + /> +
+
+ ) : ( + // first step of adding passphrase wallet from switch device modal + + +

+ +

+ + }> + ( + + {chunks} + + ), + }} + /> + + }> + + + }> + + + + } + type="hidden" + singleColModal + offerPassphraseOnDevice={onDeviceOffer} + onSubmit={onSubmit} + deviceModel={deviceModel ?? undefined} + learnMoreTooltipOnClick={ + + } + /> +
+
+ )} +
); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx index e27a3bf1038..26ede6c296b 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx @@ -6,12 +6,12 @@ import { PassphraseWalletConfirmationStep1 } from './PassphraseWalletConfirmatio import { PassphraseWalletConfirmationStep2 } from './PassphraseWalletConfirmationStep2'; import { PassphraseWalletConfirmationStep3 } from './PassphraseWalletConfirmationStep3'; import { ContentType } from './types'; -import { NewModal } from '@trezor/components'; type PassphraseWalletConfirmationContentProps = { onSubmit: (value: string, passphraseOnDevice?: boolean) => void; onDeviceOffer: boolean; onRetry: () => void; + onCancel: () => void; contentType: ContentType; setContentType: Dispatch>; }; @@ -20,6 +20,7 @@ const PassphraseWalletConfirmationContent = ({ onSubmit, onDeviceOffer, onRetry, + onCancel, contentType, setContentType, }: PassphraseWalletConfirmationContentProps): React.JSX.Element => { @@ -29,6 +30,7 @@ const PassphraseWalletConfirmationContent = ({ ); case 'step2': @@ -71,23 +73,22 @@ export const PassphraseWalletConfirmation = ({ }; return ( - - - + + - - - - + /> + + ); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmationStep1.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmationStep1.tsx index b272be19b29..2894cfbf709 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmationStep1.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmationStep1.tsx @@ -1,78 +1,124 @@ -import { Column, Card, Row, Button, Text, H3, Paragraph } from '@trezor/components'; +import { Dispatch } from 'react'; +import { spacings } from '@trezor/theme'; +import { Column, Card, Row, Button, H3, Paragraph } from '@trezor/components'; import { HELP_CENTER_PASSPHRASE_URL } from '@trezor/urls'; +import { selectDeviceSupportedNetworks } from '@suite-common/wallet-core'; +import { CoinLogo } from '@trezor/product-components'; + import { Translation } from 'src/components/suite/Translation'; import { TrezorLink } from 'src/components/suite/TrezorLink'; import { ContentType } from './types'; -import { Dispatch } from 'react'; -import { spacings } from '@trezor/theme'; +import { useSelector, useDispatch } from 'src/hooks/suite'; +import { goto } from 'src/actions/suite/routerActions'; +import { onCancel as onCancelModal } from 'src/actions/suite/modalActions'; +import { useEnabledNetworks } from 'src/hooks/settings/useEnabledNetworks'; type PassphraseWalletConfirmationStep1Props = { setContentType: Dispatch>; onRetry: () => void; + onCancel: () => void; 'data-testid'?: string; }; export const PassphraseWalletConfirmationStep1 = ({ setContentType, onRetry, + onCancel, 'data-testid': dataTest, -}: PassphraseWalletConfirmationStep1Props) => ( - -

- -

- - - - - - - } - > - - - - - - - - - - - - - - - -
-); +}: PassphraseWalletConfirmationStep1Props) => { + const { enabledNetworks, mainnets } = useEnabledNetworks(); + const deviceSupportedNetworkSymbols = useSelector(selectDeviceSupportedNetworks); + const dispatch = useDispatch(); + + const supportedNetworks = mainnets.filter(({ symbol }) => + deviceSupportedNetworkSymbols.includes(symbol), + ); + + const areAllNetworksEnabled = supportedNetworks.length === enabledNetworks.length; + + return ( + +

+ +

+ + + + + + + } + > + + + + + + + + + + + + + {!areAllNetworksEnabled && ( + + + : + + + {enabledNetworks.map(network => ( + + ))} + + + + )} + + + +
+ ); +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseDuplicateModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseDuplicateModal.tsx index 0969cd8e621..bb65f9c6680 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseDuplicateModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseDuplicateModal.tsx @@ -1,12 +1,13 @@ import { Button, Column, H3, Text } from '@trezor/components'; import { authorizeDeviceThunk, switchDuplicatedDevice } from '@suite-common/wallet-core'; +import { spacings } from '@trezor/theme'; import { Translation } from 'src/components/suite'; import { useDevice, useDispatch } from 'src/hooks/suite'; import { TrezorDevice } from 'src/types/suite'; -import { SwitchDeviceRenderer } from 'src/views/suite/SwitchDevice/SwitchDeviceRenderer'; import { CardWithDevice } from 'src/views/suite/SwitchDevice/CardWithDevice'; +import { SwitchDeviceModal } from 'src/views/suite/SwitchDevice/SwitchDeviceModal'; type PassphraseDuplicateModalProps = { device: TrezorDevice; @@ -23,34 +24,35 @@ export const PassphraseDuplicateModal = ({ device, duplicate }: PassphraseDuplic const handleAuthorizeDevice = () => dispatch(authorizeDeviceThunk()); return ( - + -

- -

- - - - - - - + +

+ +

+ + + + + + +
-
+ ); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseMismatchModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseMismatchModal.tsx index 3fe72dea61e..63e85c150ac 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseMismatchModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/PassphraseMismatchModal.tsx @@ -1,7 +1,7 @@ import { Button, H3, Column, Text } from '@trezor/components'; +import { spacings } from '@trezor/theme'; import { useDevice, useDispatch } from 'src/hooks/suite'; -import { SwitchDeviceRenderer } from 'src/views/suite/SwitchDevice/SwitchDeviceRenderer'; import { CardWithDevice } from 'src/views/suite/SwitchDevice/CardWithDevice'; import { Translation } from '../../../Translation'; import { passwordMismatchResetThunk } from '@suite-common/wallet-core'; @@ -10,6 +10,7 @@ import { redirectAfterWalletSelectedThunk, } from 'src/actions/wallet/addWalletThunk'; import { WalletType } from '@suite-common/wallet-types'; +import { SwitchDeviceModal } from 'src/views/suite/SwitchDevice/SwitchDeviceModal'; export const PassphraseMismatchModal = ({ onCancel }: { onCancel: () => void }) => { const { isLocked, device: selectDevice } = useDevice(); @@ -29,17 +30,20 @@ export const PassphraseMismatchModal = ({ onCancel }: { onCancel: () => void }) }; return ( - + - -

+ +

- - + ); }; diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 884ede5d4e8..a9ad751199c 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -116,6 +116,10 @@ export default defineMessages({ id: 'TR_ACTIVE', defaultMessage: 'active', }, + TR_ADD: { + id: 'TR_ADD', + defaultMessage: 'Add', + }, TR_ADD_ACCOUNT: { defaultMessage: 'Add account', id: 'TR_ADD_ACCOUNT', @@ -330,6 +334,14 @@ export default defineMessages({ defaultMessage: 'Confirm address', id: 'TR_CONFIRM_ADDRESS', }, + TR_COINS_CHECKED: { + defaultMessage: 'Coins checked', + id: 'TR_COINS_CHECKED', + }, + TR_CHECKED_BALANCES_ON: { + defaultMessage: 'Checked balances on', + id: 'TR_CHECKED_BALANCES_ON', + }, TR_ALL_NETWORKS: { defaultMessage: 'All networks ({networkCount})', id: 'TR_ALL_NETWORKS', diff --git a/packages/suite/src/views/dashboard/PortfolioCard/EmptyWallet.tsx b/packages/suite/src/views/dashboard/PortfolioCard/EmptyWallet.tsx index 3dc8efdfd4c..c459c4f14c5 100644 --- a/packages/suite/src/views/dashboard/PortfolioCard/EmptyWallet.tsx +++ b/packages/suite/src/views/dashboard/PortfolioCard/EmptyWallet.tsx @@ -1,48 +1,54 @@ -import styled from 'styled-components'; -import { variables, H3, Image } from '@trezor/components'; -import { Translation } from 'src/components/suite'; - -const Wrapper = styled.div` - display: flex; - padding: 54px 42px; - align-items: center; - justify-content: center; - flex-direction: column; +import { H3, Image, Row, Paragraph, Button, Column } from '@trezor/components'; +import { CoinLogo } from '@trezor/product-components'; +import { spacings } from '@trezor/theme'; - @media (max-width: ${variables.SCREEN_SIZE.SM}) { - padding: 54px 20px; - } -`; - -const Content = styled.div` - display: flex; - flex-direction: column; - align-items: center; -`; +import { Translation } from 'src/components/suite'; +import { useSelector, useDispatch } from 'src/hooks/suite'; +import { selectIsDeviceUsingPassphrase } from '@suite-common/wallet-core'; +import { goto } from 'src/actions/suite/routerActions'; +import { useEnabledNetworks } from 'src/hooks/settings/useEnabledNetworks'; +import { selectDeviceSupportedNetworks } from '@suite-common/wallet-core'; -// eslint-disable-next-line local-rules/no-override-ds-component -const Title = styled(H3)` - color: ${({ theme }) => theme.legacy.TYPE_DARK_GREY}; - margin-bottom: 30px; +export const EmptyWallet = () => { + const { enabledNetworks, mainnets } = useEnabledNetworks(); + const isPassphraseType = useSelector(selectIsDeviceUsingPassphrase); + const deviceSupportedNetworkSymbols = useSelector(selectDeviceSupportedNetworks); + const dispatch = useDispatch(); - @media (max-width: ${variables.SCREEN_SIZE.MD}) { - text-align: center; - } -`; + const supportedNetworks = mainnets.filter(({ symbol }) => + deviceSupportedNetworkSymbols.includes(symbol), + ); -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledImage = styled(Image)` - display: flex; - margin-bottom: 24px; -`; + const areAllNetworksEnabled = supportedNetworks.length === enabledNetworks.length; -export const EmptyWallet = () => ( - - - - + return ( + <Column gap={spacings.xxs} data-testid="@dashboard/wallet-ready"> + <Image image="UNI_SUCCESS" /> + <H3 margin={{ top: spacings.md }}> <Translation id="TR_YOUR_WALLET_IS_READY_WHAT" /> - - - -); +

+ {isPassphraseType && !areAllNetworksEnabled && ( + + + : + + + {enabledNetworks.map(network => ( + + ))} + + + + )} +
+ ); +}; diff --git a/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCard.tsx b/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCard.tsx index 37fa31f7044..7a007de003a 100644 --- a/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCard.tsx +++ b/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCard.tsx @@ -1,7 +1,8 @@ import { memo, useMemo } from 'react'; import styled from 'styled-components'; -import { Dropdown, Card, Tooltip } from '@trezor/components'; +import { Dropdown, Card, Tooltip, Column } from '@trezor/components'; +import { spacings } from '@trezor/theme'; import { GraphScaleDropdownItem, GraphSkeleton, Translation } from 'src/components/suite'; import { DashboardSection } from 'src/components/dashboard'; import { useDevice, useDiscovery, useDispatch, useSelector } from 'src/hooks/suite'; @@ -18,14 +19,6 @@ import { selectCurrentFiatRates } from '@suite-common/wallet-core'; import { selectLocalCurrency } from 'src/reducers/wallet/settingsReducer'; import { hasBitcoinOnlyFirmware } from '@trezor/device-utils'; -const Body = styled.div` - align-items: center; - justify-content: center; - padding: 0 20px; - min-height: 329px; - flex: 1; -`; - // eslint-disable-next-line local-rules/no-override-ds-component const StyledDropdown = styled(Dropdown)` display: flex; @@ -165,7 +158,17 @@ export const PortfolioCard = memo(() => { /> )} - {body && {body}} + {body && ( + + {body} + + )}
); diff --git a/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCardException.tsx b/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCardException.tsx index 24e984d4646..bb62009dd72 100644 --- a/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCardException.tsx +++ b/packages/suite/src/views/dashboard/PortfolioCard/PortfolioCardException.tsx @@ -1,15 +1,14 @@ import { ComponentProps } from 'react'; -import styled from 'styled-components'; - import { authConfirm, authorizeDeviceThunk, restartDiscoveryThunk as restartDiscovery, } from '@suite-common/wallet-core'; import { getNetwork, NetworkType } from '@suite-common/wallet-config'; -import { variables, Button, H3, Image, IconName } from '@trezor/components'; +import { Button, H3, Image, IconName, Column, Row, Paragraph } from '@trezor/components'; import { Discovery } from '@suite-common/wallet-types'; +import { spacings } from '@trezor/theme'; import { Translation } from 'src/components/suite'; import { useDevice, useDispatch } from 'src/hooks/suite'; @@ -18,38 +17,6 @@ import { goto } from 'src/actions/suite/routerActions'; import { DiscoveryStatusType } from 'src/types/wallet'; import { TranslationKey } from 'src/components/suite/Translation'; -const Wrapper = styled.div` - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - padding: 20px; - width: 100%; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const Title = styled(H3)` - color: ${({ theme }) => theme.legacy.TYPE_DARK_GREY}; -`; - -const Description = styled.div` - font-size: ${variables.FONT_SIZE.SMALL}; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; - text-align: center; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledImage = styled(Image)` - margin: 24px 0; -`; - -const Actions = styled.div` - display: flex; - justify-content: space-around; - width: 100%; - margin-top: 24px; -`; - interface CTA { label?: TranslationKey; variant?: ComponentProps['variant']; @@ -70,21 +37,21 @@ const Container = ({ title, description, cta, dataTestBase }: ContainerProps) => const actions = Array.isArray(cta) ? cta : [cta]; return ( - - - + <Column gap={spacings.xxs} data-testid={`@exception/${dataTestBase}`}> + <Image image="UNI_ERROR" /> + <H3 margin={{ top: spacings.md }}> <Translation id={title} /> - + {description && ( - + {typeof description === 'string' ? ( ) : ( description )} - + )} - + {actions.map(a => ( ))} - - + + ); }; diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx index 6fe01a6a181..b5715e6a3c6 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx @@ -1,5 +1,3 @@ -import styled from 'styled-components'; - import { Button, Column, HotkeyBadge, Row, Tooltip } from '@trezor/components'; import { Translation } from 'src/components/suite'; @@ -10,17 +8,6 @@ import { spacings } from '@trezor/theme'; import { WalletType } from '@suite-common/wallet-types'; import { addWalletThunk } from 'src/actions/wallet/addWalletThunk'; -const AddWallet = styled.div` - display: flex; - width: 100%; - margin-top: 10px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledTooltip = styled(Tooltip)` - width: 100%; -`; - interface AddWalletButtonProps { device: TrezorDevice; instances: AcquiredDevice[]; @@ -49,43 +36,41 @@ export const AddWalletButton = ({ device, instances, onCancel }: AddWalletButton }; return ( - - } - cursor="pointer" - placement="bottom" - > - - {!emptyPassphraseWalletExists && ( - - )} + } + cursor="pointer" + placement="bottom" + > + + {!emptyPassphraseWalletExists && ( + + )} - {isPassphraseProtectionEnabled && ( - - )} - - - + {isPassphraseProtectionEnabled && ( + + )} + + ); }; diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceDetail.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceDetail.tsx index 539fd5da242..070900240e5 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceDetail.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceDetail.tsx @@ -1,27 +1,9 @@ -import { TruncateWithTooltip } from '@trezor/components'; -import { spacingsPx, typography } from '@trezor/theme'; +import { TruncateWithTooltip, Column } from '@trezor/components'; import { ReactNode } from 'react'; -import styled from 'styled-components'; - -const Container = styled.div` - display: flex; - flex: 1; - flex-direction: column; - overflow: hidden; - align-self: center; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const DeviceLabel = styled(TruncateWithTooltip)` - ${typography.body}; - margin-bottom: -${spacingsPx.xxs}; - min-width: 0; - color: ${({ theme }) => theme.textDefault}; -`; export const DeviceDetail = ({ label, children }: { label: string; children: ReactNode }) => ( - - {label} + + {label} {children} - + ); diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceItem.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceItem.tsx index c21ab481fc1..65301c1ba90 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceItem.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/DeviceItem.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components'; -import { variables } from '@trezor/components'; +import { variables, Column } from '@trezor/components'; import * as deviceUtils from '@suite-common/suite-utils'; import { selectDevice, selectDeviceThunk } from '@suite-common/wallet-core'; @@ -10,7 +10,7 @@ import { AddWalletButton } from './AddWalletButton'; import { acquireDevice } from '@suite-common/wallet-core'; import type { TrezorDevice, AcquiredDevice, ForegroundAppProps } from 'src/types/suite'; -import { spacingsPx } from '@trezor/theme'; +import { spacings } from '@trezor/theme'; import { CardWithDevice } from '../CardWithDevice'; import { DeviceWarning } from './DeviceWarning'; import { redirectAfterWalletSelectedThunk } from 'src/actions/wallet/addWalletThunk'; @@ -25,12 +25,6 @@ const WalletsWrapper = styled.div<{ $enabled: boolean }>` } `; -const InstancesWrapper = styled.div` - display: flex; - flex-direction: column; - gap: ${spacingsPx.xs}; -`; - interface DeviceItemProps { device: TrezorDevice; instances: AcquiredDevice[]; @@ -79,20 +73,26 @@ export const DeviceItem = ({ isFullHeaderVisible={isFullHeaderVisible} > - - {instancesWithState.map((instance, index) => ( - - ))} - - - + + {instancesWithState.length > 0 && ( + + {instancesWithState.map((instance, index) => ( + + ))} + + )} + + ); diff --git a/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx b/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx index 424b637f454..e1f7251682b 100644 --- a/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx @@ -1,20 +1,13 @@ import * as deviceUtils from '@suite-common/suite-utils'; import { selectDevice, selectDevices } from '@suite-common/wallet-core'; -import { NewModal } from '@trezor/components'; +import { Column } from '@trezor/components'; import { ForegroundAppProps } from 'src/types/suite'; import { useSelector } from 'src/hooks/suite'; import { DeviceItem } from './DeviceItem/DeviceItem'; import { SwitchDeviceModal } from './SwitchDeviceModal'; -import styled from 'styled-components'; -import { spacingsPx } from '@trezor/theme'; - -const Flex = styled.div` - display: flex; - flex-direction: column; - gap: ${spacingsPx.xs}; -`; +import { spacings } from '@trezor/theme'; export const SwitchDevice = ({ onCancel }: ForegroundAppProps) => { const selectedDevice = useSelector(selectDevice); @@ -32,20 +25,18 @@ export const SwitchDevice = ({ onCancel }: ForegroundAppProps) => { } return ( - - - - {sortedDevices.map((device, index) => ( - - ))} - - - + + + {sortedDevices.map((device, index) => ( + + ))} + + ); }; diff --git a/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceModal.tsx b/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceModal.tsx index 26668a5baf6..220ca04df7b 100644 --- a/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceModal.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceModal.tsx @@ -1,13 +1,12 @@ import { useEvent } from 'react-use'; import styled from 'styled-components'; import { motion } from 'framer-motion'; -import { spacingsPx } from '@trezor/theme'; +import { spacings } from '@trezor/theme'; +import { NewModal, Column } from '@trezor/components'; import { TrafficLightOffset } from '../../../components/suite/TrafficLightOffset'; type SwitchDeviceModalProps = { children?: React.ReactNode; - isCancelable?: boolean; - onBackClick?: () => void; onCancel?: () => void; 'data-testid'?: string; isAnimationEnabled?: boolean; @@ -17,14 +16,6 @@ const Container = styled.div` width: 378px; `; -const DeviceItemsWrapper = styled.div` - display: flex; - flex-direction: column; - align-items: flex-start; - gap: ${spacingsPx.md}; - flex: 1; -`; - const initial = { width: 279, height: 70, @@ -43,25 +34,27 @@ export const SwitchDeviceModal = ({ }); return ( - - e.stopPropagation()} // needed because of the Backdrop implementation - data-testid={dataTest} - > - - - {children} - - - - + + + e.stopPropagation()} // needed because of the Backdrop implementation + data-testid={dataTest} + > + + + {children} + + + + + ); }; diff --git a/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceRenderer.tsx b/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceRenderer.tsx deleted file mode 100644 index 88a0e12d598..00000000000 --- a/packages/suite/src/views/suite/SwitchDevice/SwitchDeviceRenderer.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { ReactPortal } from 'react'; -import { createPortal } from 'react-dom'; -import { ModalProps } from '@trezor/components'; -import { useModalTarget } from 'src/support/suite/ModalContext'; -import { SwitchDeviceModal } from './SwitchDeviceModal'; -import { ModalEnvironment } from 'src/components/suite/modals/ModalEnvironment'; - -export const SwitchDeviceRenderer = ({ - headerComponent, - isCancelable, - onCancel, - isAnimationEnabled = false, - ...rest -}: ModalProps & { isAnimationEnabled?: boolean }): ReactPortal | null => { - const modalTarget = useModalTarget(); - - if (!modalTarget) return null; - - const modal = ( - - - - ); - - return createPortal(modal, modalTarget); -}; From 501d8fcbf2db1d3353f20664aa518f3f488ba637 Mon Sep 17 00:00:00 2001 From: Jakub Ondracek Date: Mon, 26 Aug 2024 20:26:27 +0200 Subject: [PATCH 154/624] test: enabling skipped tests --- packages/suite-web/e2e/support/commands.ts | 3 ++ .../e2e/support/pageObjects/modalObject.ts | 9 ++++ .../pageObjects/settingsDeviceObject.ts | 4 ++ .../support/pageObjects/settingsMenuObject.ts | 4 ++ .../suite-web/e2e/support/utils/shortcuts.ts | 31 +++++++++++++ .../e2e/tests/analytics/events.test.ts | 5 +- .../e2e/tests/backup/t2t1-misc.test.ts | 10 ++-- .../e2e/tests/dashboard/assets.test.ts | 46 +++++++++---------- .../tests/metadata/remembered-device.test.ts | 10 ++-- .../tests/onboarding/firmware-update.test.ts | 2 +- .../onboarding/t1b1-create-wallet.test.ts | 6 +-- .../onboarding/t1b1-recovery-advanced.test.ts | 2 + .../onboarding/t2t1-create-wallet.test.ts | 11 +++-- .../tests/settings/custom-firmware.test.ts | 6 ++- .../settings/t1b1-device-settings.test.ts | 28 +++++++---- .../settings/t2t1-device-settings.test.ts | 12 +++-- .../e2e/tests/suite/passphrase-input.test.ts | 34 ++++++++------ .../e2e/tests/suite/unacquired-device.test.ts | 16 +++---- .../tests/wallet/add-account-types.test.ts | 43 +++++++++-------- .../e2e/tests/wallet/cardano.test.ts | 22 ++++----- .../tests/wallet/send-form-regtest.test.ts | 6 +-- .../AccountTopPanel/AccountNavigation.tsx | 2 + 22 files changed, 195 insertions(+), 117 deletions(-) create mode 100644 packages/suite-web/e2e/support/pageObjects/modalObject.ts diff --git a/packages/suite-web/e2e/support/commands.ts b/packages/suite-web/e2e/support/commands.ts index 911447f406b..cef79c7faa6 100644 --- a/packages/suite-web/e2e/support/commands.ts +++ b/packages/suite-web/e2e/support/commands.ts @@ -27,6 +27,7 @@ import { enterPinOnBlindMatrix, addHiddenWallet, changeViewOnlyState, + clearInput, } from './utils/shortcuts'; import { interceptInvityApi } from './utils/intercept-invity-api'; import { SuiteAnalyticsEvent } from '@trezor/suite-analytics'; @@ -144,6 +145,7 @@ declare global { walletIndex: number, desiredState: 'enabled' | 'disabled', ) => Chainable; + clearInput: (elementSelector: string) => Chainable; } } } @@ -196,3 +198,4 @@ Cypress.Commands.add('findAnalyticsEventByType', findAnalyticsEventByType); Cypress.Commands.add('enterPinOnBlindMatrix', enterPinOnBlindMatrix); Cypress.Commands.add('addHiddenWallet', addHiddenWallet); Cypress.Commands.add('changeViewOnlyState', changeViewOnlyState); +Cypress.Commands.add('clearInput', clearInput); diff --git a/packages/suite-web/e2e/support/pageObjects/modalObject.ts b/packages/suite-web/e2e/support/pageObjects/modalObject.ts new file mode 100644 index 00000000000..6221687cb96 --- /dev/null +++ b/packages/suite-web/e2e/support/pageObjects/modalObject.ts @@ -0,0 +1,9 @@ +/// + +class Modal { + close(): void { + cy.getTestElement('@modal/close-button').should('be.visible').click(); + } +} + +export const onModal = new Modal(); diff --git a/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts b/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts index af47f1fd6c5..2b214d243f0 100644 --- a/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts +++ b/packages/suite-web/e2e/support/pageObjects/settingsDeviceObject.ts @@ -7,6 +7,10 @@ class SettingsDevicePage { .click(); cy.getTestElement('@multi-share-backup/1st-info/submit-button').should('be.visible'); } + + togglePinSwitch(): void { + cy.getTestElement('@settings/device/pin-switch').should('be.visible').wait(500).click(); + } } export const onSettingsDevicePage = new SettingsDevicePage(); diff --git a/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts b/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts index bb0b4b8d900..0244bd17a20 100644 --- a/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts +++ b/packages/suite-web/e2e/support/pageObjects/settingsMenuObject.ts @@ -4,6 +4,10 @@ class SettingsMenu { openDeviceSettings(): void { cy.getTestElement('@settings/menu/device').should('be.visible').click(); } + + openWalletSettings(): void { + cy.getTestElement('@settings/menu/wallet').should('be.visible').click(); + } } export const onSettingsMenu = new SettingsMenu(); diff --git a/packages/suite-web/e2e/support/utils/shortcuts.ts b/packages/suite-web/e2e/support/utils/shortcuts.ts index 2146d216958..eaa5023ad20 100644 --- a/packages/suite-web/e2e/support/utils/shortcuts.ts +++ b/packages/suite-web/e2e/support/utils/shortcuts.ts @@ -62,6 +62,7 @@ export const passThroughBackupShamir = (shares: number, threshold: number) => { cy.log('Create Shamir backup on device'); cy.getTestElement('@backup/start-button').click(); cy.getTestElement('@onboarding/confirm-on-device'); + cy.wait(1000); // It seems that there is a race condition and the next task fails sometimes, because it hits the homescreen instead of the expected one cy.task('readAndConfirmShamirMnemonicEmu', { shares, threshold }); cy.getTestElement('@backup/close-button').click(); @@ -212,3 +213,33 @@ export const changeViewOnlyState = (walletIndex: number, desiredState: 'enabled' } }); }; + +export const clearInput = (elementSelector: string) => { + cy.getTestElement(elementSelector).then(element => { + // get number of characters in the input + const charCount = element.attr('value')?.length ?? 0; + cy.getTestElement(elementSelector).type('{rightArrow}'.repeat(charCount)); + for (let i = 0; i < charCount; i++) { + cy.getTestElement(elementSelector).type('{backspace}'); + } + }); +}; + +export const forceLightMode = { + onBeforeLoad(win: Window): void { + const matchMediaStub = cy.stub().callsFake(query => { + return { + matches: query === '(prefers-color-scheme: light)', + media: query, + onchange: null, + addListener: cy.stub(), + removeListener: cy.stub(), + addEventListener: cy.stub(), + removeEventListener: cy.stub(), + dispatchEvent: cy.stub(), + }; + }); + + cy.stub(win, 'matchMedia').callsFake(matchMediaStub); + }, +}; diff --git a/packages/suite-web/e2e/tests/analytics/events.test.ts b/packages/suite-web/e2e/tests/analytics/events.test.ts index e4cd1223654..514b896519e 100644 --- a/packages/suite-web/e2e/tests/analytics/events.test.ts +++ b/packages/suite-web/e2e/tests/analytics/events.test.ts @@ -5,6 +5,7 @@ import { EventType } from '@trezor/suite-analytics'; import { ExtractByEventType, Requests } from '../../support/types'; import { onNavBar } from '../../support/pageObjects/topBarObject'; +import { forceLightMode } from '../../support/utils/shortcuts'; let requests: Requests; @@ -85,7 +86,7 @@ describe('Analytics Events', () => { cy.wrap(requests).its(3).should('have.property', 'c_type', EventType.DeviceDisconnect); }); - it.only('reports suite-ready after enabling analytics on app initial run', () => { + it('reports suite-ready after enabling analytics on app initial run', () => { cy.task('startEmu', { wipe: true }); cy.task('setupEmu', { needs_backup: false, @@ -94,7 +95,7 @@ describe('Analytics Events', () => { cy.interceptDataTrezorIo(requests); - cy.prefixedVisit('/'); + cy.prefixedVisit('/', forceLightMode); // change few settings to see if it is different from default values in suite-ready onNavBar.openSettings(); diff --git a/packages/suite-web/e2e/tests/backup/t2t1-misc.test.ts b/packages/suite-web/e2e/tests/backup/t2t1-misc.test.ts index 6acba3a63a9..87804117c67 100644 --- a/packages/suite-web/e2e/tests/backup/t2t1-misc.test.ts +++ b/packages/suite-web/e2e/tests/backup/t2t1-misc.test.ts @@ -7,9 +7,10 @@ describe('Backup misc', () => { cy.task('setupEmu', { needs_backup: true }); cy.task('startBridge'); - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1920, 1080).resetDb(); cy.prefixedVisit('/'); cy.passThroughInitialRun(); + cy.discoveryShouldFinish(); }); it('Backup should reset if modal is closed', () => { @@ -37,10 +38,13 @@ describe('Backup misc', () => { cy.getTestElement('@backup/check-item/has-enough-time').click(); cy.task('stopEmu'); cy.getTestElement('@backup/no-device', { timeout: 20000 }); - cy.task('stopBridge'); + + cy.wait(2000); + // latest (2.3.1 at the time of writing this) has default behavior needs_backup false - cy.task('startEmu', { wipe: true }); + cy.task('startEmu', { wipe: true, model: 'T2T1' }); cy.task('setupEmu'); + // noticed that it failed here times: 1 cy.getTestElement('@backup/already-finished-message'); }); diff --git a/packages/suite-web/e2e/tests/dashboard/assets.test.ts b/packages/suite-web/e2e/tests/dashboard/assets.test.ts index b4d14a3c145..0d0c979a9cb 100644 --- a/packages/suite-web/e2e/tests/dashboard/assets.test.ts +++ b/packages/suite-web/e2e/tests/dashboard/assets.test.ts @@ -7,7 +7,7 @@ import { onNavBar } from '../../support/pageObjects/topBarObject'; let requests: Requests; -describe('Assets', () => { +describe.skip('Assets', () => { beforeEach(() => { cy.task('startEmu', { wipe: true }); cy.task('setupEmu', { @@ -21,7 +21,7 @@ describe('Assets', () => { cy.interceptDataTrezorIo(requests); }); - it.skip('checks that BTC and ETH accounts are available', () => { + it('checks that BTC and ETH accounts are available', () => { cy.prefixedVisit('/'); cy.passThroughInitialRun(); @@ -48,31 +48,31 @@ describe('Assets', () => { cy.findAnalyticsEventByType>( requests, EventType.AccountsStatus, - ).then(accountsStatusEvent => { - expect(parseInt(accountsStatusEvent.btc_normal.toString(), 10)).to.not.equal(NaN); - expect(parseInt(accountsStatusEvent.btc_taproot.toString(), 10)).to.not.equal(NaN); - expect(parseInt(accountsStatusEvent.btc_segwit.toString(), 10)).to.not.equal(NaN); - expect(parseInt(accountsStatusEvent.btc_legacy.toString(), 10)).to.not.equal(NaN); + ).then(() => { + // expect(parseInt(accountsStatusEvent.btc_normal.toString(), 10)).to.not.equal(NaN); + // expect(parseInt(accountsStatusEvent.btc_taproot.toString(), 10)).to.not.equal(NaN); + // expect(parseInt(accountsStatusEvent.btc_segwit.toString(), 10)).to.not.equal(NaN); + // expect(parseInt(accountsStatusEvent.btc_legacy.toString(), 10)).to.not.equal(NaN); // expect(parseInt(accountsStatusEvent.eth_normal.toString(), 10)).to.not.equal(NaN); }); - cy.findAnalyticsEventByType>( - requests, - EventType.AccountsNonZeroBalance, - ).then(accountsNonZeroBalanceEvent => { - // 0x73d0385F4d8E00C5e6504C6030F47BF6212736A8 has token and nobody will be able to move it without ETH - expect(parseInt(accountsNonZeroBalanceEvent.eth_normal.toString(), 10)).to.not.equal( - NaN, - ); - }); + // cy.findAnalyticsEventByType>( + // requests, + // EventType.AccountsNonZeroBalance, + // ).then(accountsNonZeroBalanceEvent => { + // // 0x73d0385F4d8E00C5e6504C6030F47BF6212736A8 has token and nobody will be able to move it without ETH + // expect(parseInt(accountsNonZeroBalanceEvent.eth_normal.toString(), 10)).to.not.equal( + // NaN, + // ); + // }); - cy.findAnalyticsEventByType>( - requests, - EventType.AccountsTokensStatus, - ).then(accountsTokensStatusEvent => { - // 0x73d0385F4d8E00C5e6504C6030F47BF6212736A8 has token and nobody will be able to move it without ETH - expect(parseInt(accountsTokensStatusEvent.eth.toString(), 10)).to.not.equal(NaN); - }); + // cy.findAnalyticsEventByType>( + // requests, + // EventType.AccountsTokensStatus, + // ).then(accountsTokensStatusEvent => { + // // 0x73d0385F4d8E00C5e6504C6030F47BF6212736A8 has token and nobody will be able to move it without ETH + // expect(parseInt(accountsTokensStatusEvent.eth.toString(), 10)).to.not.equal(NaN); + // }); }); }); diff --git a/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts b/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts index 074efec6b41..83e61ab83ca 100644 --- a/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts +++ b/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts @@ -26,9 +26,8 @@ describe( cy.viewport(1440, 2560).resetDb(); }); - //TODO: this test case will require substantial refactoring as the "remember wallet" has been changed with the view-only mode providers.forEach(f => { - it.skip(f.provider, () => { + it(f.provider, () => { // prepare test cy.task('stopBridge'); cy.task('startEmu', { wipe: true }); @@ -121,14 +120,13 @@ describe( // device saved, disconnect provider cy.getTestElement('@menu/switch-device').click(); - cy.getTestElement('@switch-device/wallet-on-index/0/toggle-remember-switch').click({ - force: true, - }); cy.getTestElement('@switch-device/wallet-on-index/0').click(); cy.task('stopEmu'); cy.log('Device is saved, when disconnected, user still can edit labels'); - cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/edit-label-button").click(); + cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/edit-label-button").click({ + force: true, + }); cy.getTestElement('@metadata/input').type(' edited for remembered{enter}'); cy.log('Now again, lets try disconnecting provider'); diff --git a/packages/suite-web/e2e/tests/onboarding/firmware-update.test.ts b/packages/suite-web/e2e/tests/onboarding/firmware-update.test.ts index ec729c47869..e2f1f84dd9f 100644 --- a/packages/suite-web/e2e/tests/onboarding/firmware-update.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/firmware-update.test.ts @@ -63,7 +63,7 @@ describe.skip('fw update from empty device bootloader 2.0.3 to firmware 2.5.1', cy.prefixedVisit('/'); }); - it.skip('firmware update error', () => { + it('firmware update error', () => { cy.getTestElement('@analytics/continue-button').click(); // hook into redux actions to bypass firmware hash check diff --git a/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts b/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts index fc65fe82815..643f3d80b9d 100644 --- a/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/t1b1-create-wallet.test.ts @@ -5,20 +5,20 @@ describe('Onboarding - create wallet', () => { beforeEach(() => { cy.task('startEmu', { model: 'T1B1', version: '1-latest', wipe: true }); cy.task('startBridge'); - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1920, 1080).resetDb(); cy.prefixedVisit('/'); cy.disableFirmwareHashCheck(); }); // todo: skipping for it is too flaky.. // after calling "resetDevice" we almost always receive "device disconnected during action" which is error sent by bridge. - it.skip('Success (basic)', () => { + it('Success (basic)', () => { cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@firmware/continue-button').click(); cy.getTestElement('@onboarding/path-create-button').click(); - cy.getTestElement('@onboarding/only-backup-option-button').click(); + // cy.getTestElement('@onboarding/only-backup-option-button').click(); cy.getTestElement('@onboarding/confirm-on-device').should('be.visible'); cy.task('pressYes'); diff --git a/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts b/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts index 09336323726..7a79a6c6b22 100644 --- a/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/t1b1-recovery-advanced.test.ts @@ -9,6 +9,8 @@ describe('Onboarding - recover wallet T1B1', () => { cy.viewport(1440, 2560).resetDb(); cy.prefixedVisit('/'); cy.disableFirmwareHashCheck(); + // TODO: Remove this compromised device workaround + cy.contains('Back').click(); }); it('Incomplete run of advanced recovery', () => { diff --git a/packages/suite-web/e2e/tests/onboarding/t2t1-create-wallet.test.ts b/packages/suite-web/e2e/tests/onboarding/t2t1-create-wallet.test.ts index 98a47283ee1..17100ebad5c 100644 --- a/packages/suite-web/e2e/tests/onboarding/t2t1-create-wallet.test.ts +++ b/packages/suite-web/e2e/tests/onboarding/t2t1-create-wallet.test.ts @@ -4,16 +4,21 @@ describe('Onboarding - create wallet', () => { beforeEach(() => { cy.task('startBridge'); - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1920, 1080).resetDb(); cy.prefixedVisit('/'); + + // TODO: add workaround that switches off the firmware revision check in settings/device }); - // TODO: shamir process has changed somewhat, test needs to be adjusted. Skipping for now. - it.skip('Success (Shamir backup)', () => { + it('Success (Shamir backup)', () => { // note: this is an example of test that can not be parametrized to be both integration (isolated) test and e2e test. // the problem is that it always needs to run the newest possible emulator. If this was pinned to use emulator which is currently // in production, and we locally bumped emulator version, we would get into a screen saying "update your firmware" and the test would fail. cy.task('startEmu', { wipe: true, model: 'T2T1', version: '2-main' }); + + // TODO: compromised device workaround, refactor into more stable solution + cy.contains('Back').click(); + cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@analytics/continue-button').click(); cy.getTestElement('@firmware/continue-button').click(); diff --git a/packages/suite-web/e2e/tests/settings/custom-firmware.test.ts b/packages/suite-web/e2e/tests/settings/custom-firmware.test.ts index 811fa95ee4b..234456a0f30 100644 --- a/packages/suite-web/e2e/tests/settings/custom-firmware.test.ts +++ b/packages/suite-web/e2e/tests/settings/custom-firmware.test.ts @@ -8,9 +8,10 @@ describe('Install custom firmware', () => { cy.task('startEmu', { wipe: true }); cy.task('setupEmu'); cy.task('startBridge'); - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1920, 1080).resetDb(); cy.prefixedVisit('/'); cy.passThroughInitialRun(); + cy.discoveryShouldFinish(); }); /* @@ -19,7 +20,8 @@ describe('Install custom firmware', () => { * 3. Select the custom firmware * 4. Complete the FW instalation on the device */ - it.skip('go to device settings and check if custom FW modal appears', () => { + //TODO: skipped due to #13926 + it('go to device settings and check if custom FW modal appears', () => { // // Test preparation // diff --git a/packages/suite-web/e2e/tests/settings/t1b1-device-settings.test.ts b/packages/suite-web/e2e/tests/settings/t1b1-device-settings.test.ts index 1e95aad6a40..9b1f3651d61 100644 --- a/packages/suite-web/e2e/tests/settings/t1b1-device-settings.test.ts +++ b/packages/suite-web/e2e/tests/settings/t1b1-device-settings.test.ts @@ -1,24 +1,32 @@ // @group_settings // @retry=2 +import { onSettingsDevicePage } from '../../support/pageObjects/settingsDeviceObject'; +import { onSettingsMenu } from '../../support/pageObjects/settingsMenuObject'; +import { onNavBar } from '../../support/pageObjects/topBarObject'; + // TODO: t1 tests are flaky in CI. I suspect it is something in bridge/udp layer. So next step is implementing // udp transport in suite and trying to enable this test again. -describe.skip('T1B1 - Device settings', () => { +describe('T1B1 - Device settings', () => { beforeEach(() => { cy.task('startEmu', { model: 'T1B1', version: '1-latest', wipe: true }); cy.task('setupEmu', { needs_backup: false }); cy.task('startBridge'); + cy.viewport(1440, 2560).resetDb(); + cy.prefixedVisit('/'); + // TODO: Remove this compromised device workaround + cy.contains('Back').click(); + cy.passThroughInitialRun(); }); afterEach(() => { cy.task('stopEmu'); }); it('enable pin', () => { - cy.viewport(1440, 2560).resetDb(); - cy.prefixedVisit('/settings/device'); - cy.passThroughInitialRun(); + onNavBar.openSettings(); + onSettingsMenu.openDeviceSettings(); + onSettingsDevicePage.togglePinSwitch(); - cy.getTestElement('@settings/device/pin-switch').click({ force: true }); cy.getTestElement('@prompts/confirm-on-device'); cy.task('pressYes'); @@ -32,11 +40,10 @@ describe.skip('T1B1 - Device settings', () => { }); it('pin mismatch', () => { - cy.viewport(1440, 2560).resetDb(); - cy.prefixedVisit('/settings/device'); - cy.passThroughInitialRun(); + onNavBar.openSettings(); + onSettingsMenu.openDeviceSettings(); + onSettingsDevicePage.togglePinSwitch(); - cy.getTestElement('@settings/device/pin-switch').click({ force: true }); cy.getTestElement('@prompts/confirm-on-device'); cy.task('pressYes'); cy.getTestElement('@pin/input/1').click(); @@ -66,8 +73,9 @@ describe.skip('T1B1 - Device settings', () => { // cy.viewport(1440, 2560).resetDb(); - cy.prefixedVisit('/settings/device'); + cy.visit('/'); cy.passThroughInitialRun(); + cy.discoveryShouldFinish(); cy.getTestElement('@settings/device/homescreen').scrollIntoView(); cy.getTestElement('@settings/device/homescreen-gallery').click(); diff --git a/packages/suite-web/e2e/tests/settings/t2t1-device-settings.test.ts b/packages/suite-web/e2e/tests/settings/t2t1-device-settings.test.ts index 8f74e3a0f24..6f18ab2a243 100644 --- a/packages/suite-web/e2e/tests/settings/t2t1-device-settings.test.ts +++ b/packages/suite-web/e2e/tests/settings/t2t1-device-settings.test.ts @@ -5,7 +5,7 @@ import { onNavBar } from '../../support/pageObjects/topBarObject'; describe('T2T1 - Device settings', () => { beforeEach(() => { - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1920, 1080).resetDb(); cy.task('startBridge'); }); // TODO: cypress open: seems like entering urls (/settings/device) directly does not work anymore? @@ -60,9 +60,7 @@ describe('T2T1 - Device settings', () => { // change display rotation cy.log('change display rotation'); - cy.getTestElement('@settings/device/rotation-button/90') - .click() - .getConfirmActionOnDeviceModal(); + cy.getTestElement('select-bar/90').click().getConfirmActionOnDeviceModal(); cy.task('pressYes'); cy.getConfirmActionOnDeviceModal().should('not.exist'); }); @@ -88,6 +86,10 @@ describe('T2T1 - Device settings', () => { cy.task('setupEmu'); cy.prefixedVisit('/'); + + // TODO: compromised device workaround, refactor into more stable solution + cy.contains('Back').click(); + cy.passThroughInitialRun(); onNavBar.openSettings(); cy.getTestElement('@settings/menu/device').click(); @@ -99,7 +101,7 @@ describe('T2T1 - Device settings', () => { cy.get('#original_t2t1').should('exist'); }); - it.only('backup in settings', () => { + it('backup in settings', () => { cy.task('startEmu', { wipe: true }); cy.task('setupEmu', { needs_backup: false }); diff --git a/packages/suite-web/e2e/tests/suite/passphrase-input.test.ts b/packages/suite-web/e2e/tests/suite/passphrase-input.test.ts index d67cfba605f..84b74782b56 100644 --- a/packages/suite-web/e2e/tests/suite/passphrase-input.test.ts +++ b/packages/suite-web/e2e/tests/suite/passphrase-input.test.ts @@ -9,13 +9,20 @@ describe('Passphrase', () => { cy.task('setupEmu', { mnemonic: 'mnemonic_all' }); cy.task('startBridge'); - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1980, 1080).resetDb(); cy.prefixedVisit('/'); cy.passThroughInitialRun(); + cy.discoveryShouldFinish(); }); // TODO: there is a problem with clearing our password input element -> cypress deletes only last char with {selectAll}{backspace} and totally ignores .clear() command - it.skip('just test passphrase input', () => { + it('just test passphrase input', () => { + // enable passphrase on device + cy.getTestElement('@suite/menu/settings').click(); + cy.getTestElement('@settings/menu/device').click(); + cy.getTestElement('@settings/device/passphrase-switch').click(); + cy.task('pressYes'); + cy.getTestElement('@menu/switch-device').click(); cy.getTestElement('@switch-device/add-hidden-wallet-button').click(); cy.task('pressYes'); @@ -37,9 +44,9 @@ describe('Passphrase', () => { cy.getTestElement('@passphrase/input').should('have.value', 'ab12ef'); // toggle hidden/visible keeps caret position - // cy.getTestElement('@passphrase/input').clear(); - cy.getTestElement('@passphrase/input').type('{selectall}'); - cy.getTestElement('@passphrase/input').type('1'); + cy.getTestElement('@passphrase/input').click(); + cy.clearInput('@passphrase/input'); + cy.getTestElement('@passphrase/input').should('be.empty').type('1'); cy.getTestElement('@passphrase/input').type('{backspace}'); cy.getTestElement('@passphrase/input').type('123{leftarrow}'); cy.getTestElement('@passphrase/show-toggle').click(); @@ -52,18 +59,19 @@ describe('Passphrase', () => { cy.getTestElement('@passphrase/input').should('have.value', '12abc3xyz'); // when selectionStart===0 (looking at you nullish coalescing) - cy.getTestElement('@passphrase/input') - .clear() - .type('123{leftarrow}{leftarrow}{leftarrow}abc'); + cy.clearInput('@passphrase/input'); + cy.getTestElement('@passphrase/input').type('123{leftarrow}{leftarrow}{leftarrow}abc'); cy.getTestElement('@passphrase/input').should('have.value', 'abc123'); - cy.getTestElement('@passphrase/input') - .clear() - .type('123{leftarrow}{leftarrow}{leftarrow}{backspace}{del}'); + cy.clearInput('@passphrase/input'); + cy.getTestElement('@passphrase/input').type( + '123{leftarrow}{leftarrow}{leftarrow}{backspace}{del}', + ); cy.getTestElement('@passphrase/input').should('have.value', '23'); // todo: make sure that setting caret position via mouse click works as well could not make it, click does not move caret using cypress? - // cy.getTestElement('@passphrase/input').clear().type('123456'); - // cy.getTestElement('@passphrase/input').trigger('click', 40, 25); + cy.clearInput('@passphrase/input'); + cy.getTestElement('@passphrase/input').type('123456'); + cy.getTestElement('@passphrase/input').trigger('click', 40, 25); // todo: select part of test + copy/paste }); diff --git a/packages/suite-web/e2e/tests/suite/unacquired-device.test.ts b/packages/suite-web/e2e/tests/suite/unacquired-device.test.ts index ca545a324de..290ebf0dc16 100644 --- a/packages/suite-web/e2e/tests/suite/unacquired-device.test.ts +++ b/packages/suite-web/e2e/tests/suite/unacquired-device.test.ts @@ -3,19 +3,16 @@ describe('unacquired device', () => { beforeEach(() => { - cy.viewport(1440, 2560).resetDb(); + cy.viewport(1920, 1080).resetDb(); cy.task('startEmu', { wipe: true }); cy.task('setupEmu', { passphrase_protection: true, pin_protection: false }); cy.task('startBridge'); - }); - - it.skip('someone steals session, device status turns inactive', () => { cy.prefixedVisit('/'); cy.passThroughInitialRun(); - // cy.getTestElement('@deviceStatus-connected').click(); - // cy.getTestElement('@passphrase-type/standard').click(); - // cy.discoveryShouldFinish(); + cy.discoveryShouldFinish(); + }); + it('someone steals session, device status turns inactive', () => { // simulate stolen session from another window. device receives indicative button cy.task('stealBridgeSession'); cy.getTestElement('@menu/switch-device').click(); @@ -27,9 +24,8 @@ describe('unacquired device', () => { cy.task('stealBridgeSession'); cy.getTestElement('@switch-device/1/solve-issue-button'); cy.reload(); - cy.getTestElement('@device-acquire').click(); - cy.getTestElement('@passphrase-type/standard').click(); - cy.discoveryShouldFinish(); + cy.getTestElement('@menu/switch-device').click(); + cy.getTestElement('@switch-device/1/solve-issue-button').click(); }); // todo: diff --git a/packages/suite-web/e2e/tests/wallet/add-account-types.test.ts b/packages/suite-web/e2e/tests/wallet/add-account-types.test.ts index 082be4d1a0b..eb6d2e1882a 100644 --- a/packages/suite-web/e2e/tests/wallet/add-account-types.test.ts +++ b/packages/suite-web/e2e/tests/wallet/add-account-types.test.ts @@ -111,7 +111,7 @@ describe('Account types suite', () => { * 7. Get the number of accounts again * 8. Verify that the current number is equal to previous number + 1 */ - it.skip('Add-account-types-non-BTC-coins', () => { + it('Add-account-types-non-BTC-coins', () => { // // Test execution // @@ -128,30 +128,29 @@ describe('Account types suite', () => { onNavBar.openDefaultAcccount(); cy.discoveryShouldFinish(); // cardano - coins.forEach((coin: NetworkSymbol) => { onAccountsPage.applyCoinFilter(coin); // get the element containing all accounts - cy.get(`[type="normal"] [data-testid*="@account-menu/${coin}/normal"]`).then( - currentAccounts => { - const numberOfAccounts1 = currentAccounts.length; - - cy.getTestElement('@account-menu/add-account').should('be.visible').click(); - cy.getTestElement('@modal').should('be.visible'); - cy.get(`[data-testid="@settings/wallet/network/${coin}"]`) - .should('be.visible') - .click(); - cy.getTestElement('@add-account').click(); - cy.discoveryShouldFinish(); - - cy.get(`[type="normal"] [data-testid*="@account-menu/${coin}/normal"]`).then( - newAccounts => { - const numberOfAccounts2 = newAccounts.length; - expect(numberOfAccounts2).to.be.equal(numberOfAccounts1 + 1); - }, - ); - }, - ); + cy.get( + `[data-testid="@account-menu/normal/group"] > [data-testid*="@account-menu/${coin}/normal"]`, + ).then(currentAccounts => { + const numberOfAccounts1 = currentAccounts.length; + + cy.getTestElement('@account-menu/add-account').should('be.visible').click(); + cy.getTestElement('@modal').should('be.visible'); + cy.get(`[data-testid="@settings/wallet/network/${coin}"]`) + .should('be.visible') + .click(); + cy.getTestElement('@add-account').click(); + cy.discoveryShouldFinish(); + + cy.get( + `[data-testid="@account-menu/normal/group"] > [data-testid*="@account-menu/${coin}/normal"]`, + ).then(newAccounts => { + const numberOfAccounts2 = newAccounts.length; + expect(numberOfAccounts2).to.be.equal(numberOfAccounts1 + 1); + }); + }); }); cy.findAnalyticsEventByType>( diff --git a/packages/suite-web/e2e/tests/wallet/cardano.test.ts b/packages/suite-web/e2e/tests/wallet/cardano.test.ts index e4f8e1d8a0f..2f6d539eb38 100644 --- a/packages/suite-web/e2e/tests/wallet/cardano.test.ts +++ b/packages/suite-web/e2e/tests/wallet/cardano.test.ts @@ -1,6 +1,8 @@ // @group_wallet // @retry=2 +import { onModal } from '../../support/pageObjects/modalObject'; +import { onSettingsMenu } from '../../support/pageObjects/settingsMenuObject'; import { onNavBar } from '../../support/pageObjects/topBarObject'; describe('Cardano', () => { @@ -15,11 +17,14 @@ describe('Cardano', () => { cy.task('startBridge'); cy.viewport(1440, 2560).resetDb(); - cy.prefixedVisit('/settings/coins'); + cy.prefixedVisit('/'); cy.passThroughInitialRun(); + cy.discoveryShouldFinish(); + onNavBar.openSettings(); + onSettingsMenu.openWalletSettings(); }); - it.skip('Basic cardano walkthrough', () => { + it('Basic cardano walkthrough', () => { // go to coin settings and enable cardano cy.getTestElement('@settings/wallet/network/tada').click(); @@ -31,9 +36,8 @@ describe('Cardano', () => { // go to cardano account #1 cy.getTestElement('@suite/menu/suite-index').click(); - cy.getTestElement('@suite/menu/wallet-index').click(); - cy.getTestElement('@account-menu/tada/normal/0').click(); cy.discoveryShouldFinish(); + cy.getTestElement('@account-menu/tada/normal/0').click(); // go to cardano account #1 - account details cy.getTestElement('@wallet/menu/wallet-details').click(); @@ -43,12 +47,7 @@ describe('Cardano', () => { cy.getTestElement('@wallets/details/show-xpub-button').click(); // todo: matchImageSnapshot producing diff not obvious why. cy.getTestElement('@modal').screenshot('cardano-show-xpub'); - cy.get('body').type('{esc}'); - - // todo: enable staking - cardano lib problem - // go to cardano account #1 - staking - // cy.getTestElement('@wallet/menu/wallet-staking').click(); - // cy.getTestElement('@app').matchImageSnapshot(); + onModal.close(); // go to cardano account #1 - send cy.getTestElement('@wallet/menu/wallet-send').click(); @@ -59,11 +58,12 @@ describe('Cardano', () => { cy.getTestElement('@wallet/receive/reveal-address-button').click(); cy.getTestElement('@modal').matchImageSnapshot('cardano-receive'); cy.task('pressYes'); + cy.wait(501); cy.getTestElement('@modal/close-button').click(); cy.getTestElement('@account-subpage/back').last().click(); // go to cardano account #1 - staking - cy.getTestElement('@wallet/menu/wallet-tokens-coins').click(); + cy.getTestElement('@wallet/menu/staking').click(); cy.getTestElement('@app').matchImageSnapshot('cardano-tokens'); // lets 'hack' routing diff --git a/packages/suite-web/e2e/tests/wallet/send-form-regtest.test.ts b/packages/suite-web/e2e/tests/wallet/send-form-regtest.test.ts index 3be8f08b1d9..30a683e6530 100644 --- a/packages/suite-web/e2e/tests/wallet/send-form-regtest.test.ts +++ b/packages/suite-web/e2e/tests/wallet/send-form-regtest.test.ts @@ -30,7 +30,7 @@ describe('Send form for bitcoin', () => { cy.wait(100); // wait until is the form interactive }); - it.skip('add and remove output in send form, toggle form options, input data', () => { + it('add and remove output in send form, toggle form options, input data', () => { // test adding and removing outputs cy.getTestElement('outputs.0.amount').type('0.3'); cy.getTestElement('add-output').click(); @@ -46,7 +46,7 @@ describe('Send form for bitcoin', () => { // add locktime cy.getTestElement('add-locktime-button').click(); - cy.getTestElement('locktime-input').type('100'); + cy.getTestElement('locktime-input').type('1000'); // assert final state of form using screenshot cy.getTestElement('@wallet/send/outputs-and-options').matchImageSnapshot('bitcoin-send'); @@ -57,7 +57,7 @@ describe('Send form for bitcoin', () => { cy.task('pressYes'); cy.task('pressYes'); - // broadcast is off due to locktime, so we do not see '@modal/send' + // broadcast is off due to locktime, so we do not see '@modal/send', this is also affected by the current number of mined blocks thus I increased locktime number to 1000 cy.getTestElement('@send/copy-raw-transaction'); }); diff --git a/packages/suite/src/components/wallet/WalletLayout/AccountTopPanel/AccountNavigation.tsx b/packages/suite/src/components/wallet/WalletLayout/AccountTopPanel/AccountNavigation.tsx index e55e1ca9bef..0e55ca620a8 100644 --- a/packages/suite/src/components/wallet/WalletLayout/AccountTopPanel/AccountNavigation.tsx +++ b/packages/suite/src/components/wallet/WalletLayout/AccountTopPanel/AccountNavigation.tsx @@ -51,6 +51,7 @@ export const AccountNavigation = () => { title: , isHidden: !['cardano', 'ethereum', 'solana'].includes(networkType), activeRoutes: ['wallet-tokens-coins', 'wallet-tokens-hidden'], + 'data-testid': '@wallet/menu/wallet-tokens-coins', }, { id: 'wallet-staking', @@ -59,6 +60,7 @@ export const AccountNavigation = () => { }, title: , isHidden: !hasNetworkFeatures(account, 'staking'), + 'data-testid': '@wallet/menu/staking', }, { id: 'wallet-details', From 679a6dbc86ca89e96950115d84f13d076913c49e Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:43 +0000 Subject: [PATCH 155/624] npm-prerelease: @trezor/blockchain-link 2.3.2-beta.1 --- packages/blockchain-link/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/blockchain-link/package.json b/packages/blockchain-link/package.json index 77b72c32733..8772a4b972d 100644 --- a/packages/blockchain-link/package.json +++ b/packages/blockchain-link/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/blockchain-link", - "version": "2.3.1", + "version": "2.3.2-beta.1", "author": "Trezor ", "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/blockchain-link", "description": "High-level javascript interface for blockchain communication", From 54ab781bf9e835c4b9a7805e4a9b234c4f0aa964 Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:44 +0000 Subject: [PATCH 156/624] npm-prerelease: @trezor/blockchain-link-utils 1.2.2-beta.1 --- packages/blockchain-link-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/blockchain-link-utils/package.json b/packages/blockchain-link-utils/package.json index 113a2fdec92..4dc28c5915b 100644 --- a/packages/blockchain-link-utils/package.json +++ b/packages/blockchain-link-utils/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/blockchain-link-utils", - "version": "1.2.1", + "version": "1.2.2-beta.1", "license": "See LICENSE.md in repo root", "sideEffects": false, "main": "src/index.ts", From 552d5487f355fa092e4a3fede7259cdeae23e4a9 Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:45 +0000 Subject: [PATCH 157/624] npm-prerelease: @trezor/blockchain-link-types 1.2.2-beta.1 --- packages/blockchain-link-types/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/blockchain-link-types/package.json b/packages/blockchain-link-types/package.json index 123b2a9839b..a66a4c7b52a 100644 --- a/packages/blockchain-link-types/package.json +++ b/packages/blockchain-link-types/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/blockchain-link-types", - "version": "1.2.1", + "version": "1.2.2-beta.1", "license": "See LICENSE.md in repo root", "sideEffects": false, "main": "src/index.ts", From 49887bb666d6100e8eb399130057e959ae397c76 Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:46 +0000 Subject: [PATCH 158/624] npm-prerelease: @trezor/type-utils 1.1.1-beta.1 --- packages/type-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/type-utils/package.json b/packages/type-utils/package.json index 70ac19f4630..3e463420e7a 100644 --- a/packages/type-utils/package.json +++ b/packages/type-utils/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/type-utils", - "version": "1.1.0", + "version": "1.1.1-beta.1", "license": "See LICENSE.md in repo root", "sideEffects": false, "main": "src/index", From 412da596f155be3eb832cf0834b85239903a0fc4 Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:47 +0000 Subject: [PATCH 159/624] npm-prerelease: @trezor/connect-common 0.2.3-beta.1 --- packages/connect-common/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/connect-common/package.json b/packages/connect-common/package.json index 2e26e81620f..68a36bc77f6 100644 --- a/packages/connect-common/package.json +++ b/packages/connect-common/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/connect-common", - "version": "0.2.2", + "version": "0.2.3-beta.1", "author": "Trezor ", "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/connect-common", "keywords": [ From 48637b29752241ee2e0bf281de49bd0a2a5c094c Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:49 +0000 Subject: [PATCH 160/624] npm-prerelease: @trezor/transport 1.3.3-beta.1 --- packages/transport/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/transport/package.json b/packages/transport/package.json index c2c6a12c7e7..e95b88000e2 100644 --- a/packages/transport/package.json +++ b/packages/transport/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/transport", - "version": "1.3.2", + "version": "1.3.3-beta.1", "description": "Low level library facilitating protocol buffers based communication with Trezor devices", "npmPublishAccess": "public", "license": "SEE LICENSE IN LICENSE.md", From 0b4f84fa7d5c600b6c83767b9c00fc1c8bafa08e Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:50 +0000 Subject: [PATCH 161/624] npm-prerelease: @trezor/protobuf 1.2.3-beta.1 --- packages/protobuf/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protobuf/package.json b/packages/protobuf/package.json index 898cadbb197..5b674de8806 100644 --- a/packages/protobuf/package.json +++ b/packages/protobuf/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/protobuf", - "version": "1.2.2", + "version": "1.2.3-beta.1", "license": "See LICENSE.md in repo root", "repository": { "type": "git", From f3fd24f0d6486ed3786f0a3b5d49b3e9e1873fd7 Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:51 +0000 Subject: [PATCH 162/624] npm-prerelease: @trezor/utils 9.2.2-beta.1 --- packages/utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index eb612f4872f..447f39b5a71 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/utils", - "version": "9.2.1", + "version": "9.2.2-beta.1", "author": "Trezor ", "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/utils", "description": "A collection of typescript utils that are intended to be used across trezor-suite monorepo.", From 2ebcea3542ba108a678cb19521a4ca10c849a6e6 Mon Sep 17 00:00:00 2001 From: trezor-ci Date: Wed, 16 Oct 2024 14:16:56 +0000 Subject: [PATCH 163/624] npm-release: @trezor/connect 9.4.3-beta.1 --- packages/connect-web/package.json | 2 +- .../src/webextension/trezor-usb-permissions.js | 2 +- packages/connect-webextension/package.json | 2 +- packages/connect/CHANGELOG.md | 18 +++++++++--------- packages/connect/README.md | 2 +- packages/connect/package.json | 2 +- packages/connect/src/data/version.ts | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/connect-web/package.json b/packages/connect-web/package.json index fb194105987..eb456758e72 100644 --- a/packages/connect-web/package.json +++ b/packages/connect-web/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/connect-web", - "version": "9.4.2", + "version": "9.4.3-beta.1", "author": "Trezor ", "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/connect-web", "description": "High-level javascript interface for Trezor hardware wallet in web environment.", diff --git a/packages/connect-web/src/webextension/trezor-usb-permissions.js b/packages/connect-web/src/webextension/trezor-usb-permissions.js index 9d56e26e1c4..2db66aac004 100644 --- a/packages/connect-web/src/webextension/trezor-usb-permissions.js +++ b/packages/connect-web/src/webextension/trezor-usb-permissions.js @@ -1,4 +1,4 @@ -const VERSION = '9.4.2'; +const VERSION = '9.4.3-beta.1'; const versionN = VERSION.split('.').map(s => parseInt(s, 10)); const isBeta = VERSION.includes('beta'); diff --git a/packages/connect-webextension/package.json b/packages/connect-webextension/package.json index 1bd1ccd2fd7..672150b47de 100644 --- a/packages/connect-webextension/package.json +++ b/packages/connect-webextension/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/connect-webextension", - "version": "9.4.2", + "version": "9.4.3-beta.1", "author": "Trezor ", "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/connect-webextension", "description": "High-level javascript interface for Trezor hardware wallet in webextension serviceworker environment.", diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md index 0ab12f364f2..e7399edca45 100644 --- a/packages/connect/CHANGELOG.md +++ b/packages/connect/CHANGELOG.md @@ -1,12 +1,12 @@ -| Package | Stable | Canary | -| :------------------------------: | :----: | :----: | -| npm @trezor/connect | 9.4.2 | - | -| npm @trezor/connect-web | 9.4.2 | - | -| npm @trezor/connect-webextension | 9.4.2 | - | - -| Deployment | Stable | Canary | -| :----------------: | :----: | :----: | -| connect.trezor.io/ | 9.4.2 | - | +| Package | Stable | Canary | +| :------------------------------: | :----: | :----------: | +| npm @trezor/connect | 9.4.2 | 9.4.3-beta.1 | +| npm @trezor/connect-web | 9.4.2 | 9.4.3-beta.1 | +| npm @trezor/connect-webextension | 9.4.2 | 9.4.3-beta.1 | + +| Deployment | Stable | Canary | +| :----------------: | :----: | :----------: | +| connect.trezor.io/ | 9.4.2 | 9.4.3-beta.1 | Use the persistent link [connect.trezor.io/9](https://connect.trezor.io/9/) to access the latest stable version of Connect Explorer. diff --git a/packages/connect/README.md b/packages/connect/README.md index 101cef35161..ee583ac450b 100644 --- a/packages/connect/README.md +++ b/packages/connect/README.md @@ -1,6 +1,6 @@ # @trezor/connect -API version 9.4.2 +API version 9.4.3-beta.1 [![Build Status](https://github.com/trezor/trezor-suite/actions/workflows/test-connect.yml/badge.svg)](https://github.com/trezor/trezor-suite/actions/workflows/test-connect.yml) [![NPM](https://img.shields.io/npm/v/@trezor/connect.svg)](https://www.npmjs.org/package/@trezor/connect) diff --git a/packages/connect/package.json b/packages/connect/package.json index 1de183bfa4e..b1613e60117 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/connect", - "version": "9.4.2", + "version": "9.4.3-beta.1", "author": "Trezor ", "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/connect", "description": "High-level javascript interface for Trezor hardware wallet.", diff --git a/packages/connect/src/data/version.ts b/packages/connect/src/data/version.ts index 4594473b594..2a7f9555159 100644 --- a/packages/connect/src/data/version.ts +++ b/packages/connect/src/data/version.ts @@ -1,4 +1,4 @@ -export const VERSION = '9.4.2'; +export const VERSION = '9.4.3-beta.1'; const versionN = VERSION.split('.').map(s => parseInt(s, 10)); From 80661870b960ac8fcd4b2827bba7e25016cec96f Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Wed, 16 Oct 2024 16:24:45 +0200 Subject: [PATCH 164/624] chore(connect): update changelog for 9.4.3-beta.1 --- packages/connect/CHANGELOG.md | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md index e7399edca45..94b6c666034 100644 --- a/packages/connect/CHANGELOG.md +++ b/packages/connect/CHANGELOG.md @@ -10,6 +10,48 @@ Use the persistent link [connect.trezor.io/9](https://connect.trezor.io/9/) to access the latest stable version of Connect Explorer. +# 9.4.3-beta.1 + +This release introduces `@trezor/connect-mobile`, which allows mobile apps to integrate with Trezor Suite mobile using deeplinks. +This package is still beta and work in progress. + +### Connect Mobile related changes + +- chore(connect-mobile): update package.json for publishing (fb157ef318) +- feat(connect-explorer): hiding beta-only content (21e0d42c6d) +- feat(connect-explorer): call deeplinks from method tester (f2a5f7460e) +- docs(connect): mobile connect popup (9f8f1c1bd2) +- chore(connect-popup): move deeplink fallback page to versioned url (e86e6aa5b3) +- chore: rename connect-deeplink to connect-mobile (d1c2bd7464) +- feat(connect): use separate versioning for deeplink protocol (40f3b53a34) +- feat(module-connect-popup): add version check to app link parser (fe8499ec1c) +- chore(connect-examples): change from deeplinkUrl to connectSrc (1ff479c545) +- feat(connect): take deeplinkUrl from connectSrc (1b88b3b72b) + +### Other changes + +- refactor(connect-web): use dynamic from connect package (887889288f) +- refactor(connect): dynamic connect (96e81fe5bf) +- fix(connect): make getBinaryOptional async (e583e84c32) +- test(connect-popup): fix log going to (9dee606f43) +- feat(connect): fw hash check automatically for T1B1 (0fd023dbe8) +- docs(connect-web): Support matrix (44ed16a45d) +- chore: update backends for bsc and op (458f0fe3d9) +- docs(connect-explorer): mention address can be used in getAccountInfo (722a2b2b7f) +- chore(connect): cleanup some duplicities in fw download util (53456df94d) +- chore(connect): a cosmetic change in Device types (b718af4a2b) +- chore(connect): use import from @trezor/connect-analytics (1ee270b1cd) +- chore(protobuf): update messages.json (71bbde850b) +- feat(connect): add Optimism (c2fb244649) +- chore(connect): pol only to pol backend (fe589cf6bc) +- chore(connect): rename 'getAssetByUrl' to a more apt fn name 'tryLocalAssetRequire' (f5e8f256ae) +- docs(connect-explorer): remove trailing commas from json excerpts (dc0147900d) +- refactor(transport): background sessions improved (7644107353) +- refactor(connect): connect error codes typing (57815188d1) +- chore(connect): update device authenticity config (063d68379f) +- docs: fix header level in connect changelog (ac53d354cc) +- fix(connect): add other-error to FirmwareRevisionCheckResult errors (4361aba5b7) + # 9.4.2 This release fixes an issue with TypeScript and certain libraries not being resolved correctly in the previous version. From f63e983754ac14b942bb63c0bc0a15559408e15c Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Wed, 16 Oct 2024 16:17:20 +0200 Subject: [PATCH 165/624] chore(suite-native): bump app version to 24.10.2 --- suite-native/app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 7ec7cb4c4fe..128152f5126 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -1,7 +1,7 @@ { "name": "@suite-native/app", "version": "1.0.0", - "suiteNativeVersion": "24.10.1", + "suiteNativeVersion": "24.10.2", "main": "index.js", "scripts": { "android": "expo run:android", From 2a0d13af7640e7ca56dbe149252ec4f81f779ea7 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Thu, 17 Oct 2024 10:07:22 +0200 Subject: [PATCH 166/624] fix(suite): KB link to be next to configuration for Tor snowflake --- packages/suite/src/constants/suite/experimental.ts | 4 ++-- .../suite/src/views/settings/SettingsGeneral/TorSnowflake.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/suite/src/constants/suite/experimental.ts b/packages/suite/src/constants/suite/experimental.ts index 1a3205299b5..e6951c463d5 100644 --- a/packages/suite/src/constants/suite/experimental.ts +++ b/packages/suite/src/constants/suite/experimental.ts @@ -1,5 +1,5 @@ import { TranslationKey } from '@suite-common/intl-types'; -import { EXPERIMENTAL_PASSWORD_MANAGER_KB_URL, TOR_SNOWFLAKE_KB_URL, Url } from '@trezor/urls'; +import { EXPERIMENTAL_PASSWORD_MANAGER_KB_URL, TOR_SNOWFLAKE_PROJECT_URL, Url } from '@trezor/urls'; import { Dispatch } from '../../types/suite'; @@ -26,6 +26,6 @@ export const EXPERIMENTAL_FEATURES: Record { } description={} - buttonLink={TOR_SNOWFLAKE_PROJECT_URL} + buttonLink={TOR_SNOWFLAKE_KB_URL} /> From 2d3edbcc8991d015b12894d0d42df6f6b8507cc4 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Mon, 9 Sep 2024 08:20:14 +0200 Subject: [PATCH 167/624] chore: update socks-proxy-agent from 6.1.1 to 8.0.4 --- packages/blockchain-link-types/package.json | 2 +- packages/blockchain-link/package.json | 2 +- packages/request-manager/package.json | 2 +- yarn.lock | 63 +++++++++++++-------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/packages/blockchain-link-types/package.json b/packages/blockchain-link-types/package.json index a66a4c7b52a..73aedb1fa14 100644 --- a/packages/blockchain-link-types/package.json +++ b/packages/blockchain-link-types/package.json @@ -23,7 +23,7 @@ "@solana/web3.js": "^1.95.0", "@trezor/type-utils": "workspace:*", "@trezor/utxo-lib": "workspace:*", - "socks-proxy-agent": "6.1.1" + "socks-proxy-agent": "8.0.4" }, "devDependencies": { "tsx": "^4.16.3" diff --git a/packages/blockchain-link/package.json b/packages/blockchain-link/package.json index 8772a4b972d..157e23e02bb 100644 --- a/packages/blockchain-link/package.json +++ b/packages/blockchain-link/package.json @@ -86,7 +86,7 @@ "@types/web": "^0.0.162", "events": "^3.3.0", "ripple-lib": "^1.10.1", - "socks-proxy-agent": "6.1.1", + "socks-proxy-agent": "8.0.4", "ws": "^8.18.0" }, "peerDependencies": { diff --git a/packages/request-manager/package.json b/packages/request-manager/package.json index 37d4f21411b..daafb5645a3 100644 --- a/packages/request-manager/package.json +++ b/packages/request-manager/package.json @@ -14,7 +14,7 @@ "dependencies": { "@trezor/node-utils": "workspace:^", "@trezor/utils": "workspace:*", - "socks-proxy-agent": "6.1.1" + "socks-proxy-agent": "8.0.4" }, "devDependencies": { "ts-node": "^10.9.1", diff --git a/yarn.lock b/yarn.lock index a5351462df6..72f1675de4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11139,7 +11139,7 @@ __metadata: "@solana/web3.js": "npm:^1.95.0" "@trezor/type-utils": "workspace:*" "@trezor/utxo-lib": "workspace:*" - socks-proxy-agent: "npm:6.1.1" + socks-proxy-agent: "npm:8.0.4" tsx: "npm:^4.16.3" peerDependencies: tslib: ^2.6.2 @@ -11180,7 +11180,7 @@ __metadata: fs-extra: "npm:^11.2.0" html-webpack-plugin: "npm:^5.6.0" ripple-lib: "npm:^1.10.1" - socks-proxy-agent: "npm:6.1.1" + socks-proxy-agent: "npm:8.0.4" tiny-worker: "npm:^2.3.0" tsx: "npm:^4.16.3" webpack: "npm:^5.94.0" @@ -11763,7 +11763,7 @@ __metadata: dependencies: "@trezor/node-utils": "workspace:^" "@trezor/utils": "workspace:*" - socks-proxy-agent: "npm:6.1.1" + socks-proxy-agent: "npm:8.0.4" ts-node: "npm:^10.9.1" ws: "npm:^8.18.0" languageName: unknown @@ -14759,12 +14759,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: "npm:^4.3.4" - checksum: 10/f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + checksum: 10/c478fec8f79953f118704d007a38f2a185458853f5c45579b9669372bd0e12602e88dc2ad0233077831504f7cd6fcc8251c383375bba5eaaf563b102938bda26 languageName: node linkType: hard @@ -25977,6 +25977,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c + languageName: node + linkType: hard + "ip-regex@npm:^2.1.0": version: 2.1.0 resolution: "ip-regex@npm:2.1.0" @@ -27709,6 +27719,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef + languageName: node + linkType: hard + "jsbn@npm:~0.1.0": version: 0.1.1 resolution: "jsbn@npm:0.1.1" @@ -38474,14 +38491,14 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:6.1.1": - version: 6.1.1 - resolution: "socks-proxy-agent@npm:6.1.1" +"socks-proxy-agent@npm:8.0.4": + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" dependencies: - agent-base: "npm:^6.0.2" - debug: "npm:^4.3.1" - socks: "npm:^2.6.1" - checksum: 10/53fb7d34bf3e5ed9cf4de73bf5c18b351d75c4a8757a0c0e384c2a7c86adf688e5f5e8f72eee7bc6c01ff619458f621ccf9d172bc986adb05f10fa0c9599c39e + agent-base: "npm:^7.1.1" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10/c8e7c2b398338b49a0a0f4d2bae5c0602aeeca6b478b99415927b6c5db349ca258448f2c87c6958ebf83eea17d42cbc5d1af0bfecb276cac10b9658b0f07f7d7 languageName: node linkType: hard @@ -38496,13 +38513,13 @@ __metadata: languageName: node linkType: hard -"socks@npm:^2.6.1, socks@npm:^2.6.2": - version: 2.7.1 - resolution: "socks@npm:2.7.1" +"socks@npm:^2.6.2, socks@npm:^2.8.3": + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: - ip: "npm:^2.0.0" + ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10/5074f7d6a13b3155fa655191df1c7e7a48ce3234b8ccf99afa2ccb56591c195e75e8bb78486f8e9ea8168e95a29573cbaad55b2b5e195160ae4d2ea6811ba833 + checksum: 10/ffcb622c22481dfcd7589aae71fbfd71ca34334064d181df64bf8b7feaeee19706aba4cffd1de35cc7bbaeeaa0af96be2d7f40fcbc7bc0ab69533a7ae9ffc4fb languageName: node linkType: hard @@ -38733,10 +38750,10 @@ __metadata: languageName: node linkType: hard -"sprintf-js@npm:^1.1.2": - version: 1.1.2 - resolution: "sprintf-js@npm:1.1.2" - checksum: 10/0044322a252b36bffc3d8a462a4882de57830e18d37d1cc000104ff4744b512d6a9b1ca6240e7ad141a987a1eaad071668fe12d11c496c11d3641c4797a6cf3f +"sprintf-js@npm:^1.1.2, sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb languageName: node linkType: hard From 4a4d439aab70ac9c3ce7acfc03d29a85529079e0 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Mon, 14 Oct 2024 11:37:20 +0200 Subject: [PATCH 168/624] chore(blockchain-link-types): keep legacy type SocksProxyAgentOptions --- packages/blockchain-link-types/src/common.ts | 22 +++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/blockchain-link-types/src/common.ts b/packages/blockchain-link-types/src/common.ts index 46c8b4a80e8..87be144fef0 100644 --- a/packages/blockchain-link-types/src/common.ts +++ b/packages/blockchain-link-types/src/common.ts @@ -1,4 +1,6 @@ -import type { SocksProxyAgentOptions } from 'socks-proxy-agent'; +import type tls from 'tls'; +import type { Url } from 'url'; +import type { SocksProxy } from 'socks'; import type { Transaction as BlockbookTransaction, VinVout } from './blockbook'; import type { @@ -10,6 +12,24 @@ import type { /* Common types used in both params and responses */ +type AgentOptions = { + timeout?: number | undefined; +}; + +interface BaseSocksProxyAgentOptions { + host?: string | null; + port?: string | number | null; + username?: string | null; + tls?: tls.ConnectionOptions | null; +} + +// todo: connect10 here we are using the old `SocksProxyAgentOptions` from older version of socks-proxy-agent +// but we keep the old API so we do not introduce breaking changes. +interface SocksProxyAgentOptions + extends AgentOptions, + BaseSocksProxyAgentOptions, + Partial> {} + export interface BlockchainSettings { name: string; worker: string | (() => any); From e54f8d736edc657b54055a68825dba4261787820 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Mon, 14 Oct 2024 11:38:10 +0200 Subject: [PATCH 169/624] chore(blockchain-link): update proxyAgent to new socks-proxy-agent --- .../blockchain-link/src/workers/baseWorker.ts | 17 ++++++++++++----- .../src/workers/electrum/sockets/tor.ts | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/blockchain-link/src/workers/baseWorker.ts b/packages/blockchain-link/src/workers/baseWorker.ts index e842786caa3..cfe6d8f069d 100644 --- a/packages/blockchain-link/src/workers/baseWorker.ts +++ b/packages/blockchain-link/src/workers/baseWorker.ts @@ -5,7 +5,7 @@ // and // new BlockchainLink({ worker: () => new BlockchainLinkModule() }); -import SocksProxyAgent from 'socks-proxy-agent'; +import { SocksProxyAgent } from 'socks-proxy-agent'; import { CustomError } from '@trezor/blockchain-link-types/src/constants/errors'; import { WorkerState } from './state'; import { prioritizeEndpoints } from './utils'; @@ -31,7 +31,7 @@ export type ContextType = { export abstract class BaseWorker { api: API | undefined; - proxyAgent: ReturnType | undefined; + proxyAgent: SocksProxyAgent | undefined; settings: Partial = {}; state: WorkerState; post: (data: Response) => void; @@ -141,9 +141,16 @@ export abstract class BaseWorker { if (data.type === MESSAGES.HANDSHAKE) { this.settings = data.settings; - this.proxyAgent = data.settings.proxy - ? SocksProxyAgent(data.settings.proxy) - : undefined; + const { proxy } = data.settings; + if (proxy) { + const agentUri = + typeof proxy === 'string' ? proxy : `socks://${proxy.host}:${proxy.port}`; + const socketOptions = + typeof proxy === 'object' ? { timeout: proxy?.timeout } : undefined; + this.proxyAgent = new SocksProxyAgent(agentUri, socketOptions); + } else { + this.proxyAgent = undefined; + } return true; } diff --git a/packages/blockchain-link/src/workers/electrum/sockets/tor.ts b/packages/blockchain-link/src/workers/electrum/sockets/tor.ts index a1cc5ce1aa6..c4907cc569a 100644 --- a/packages/blockchain-link/src/workers/electrum/sockets/tor.ts +++ b/packages/blockchain-link/src/workers/electrum/sockets/tor.ts @@ -17,7 +17,7 @@ export class TorSocket extends SocketBase { protected async openSocket(listener: SocketListener) { const { host, port } = this; const socket = await this.proxyAgent - .callback(null as any, { host, port, timeout: this.timeout, secureEndpoint: false }) + .connect(null as any, { host, port, timeout: this.timeout, secureEndpoint: false }) .catch(e => { listener.onError(e); throw e; From 915af25c576c258bc232e2f9efa42ff3d9adb675 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Mon, 14 Oct 2024 11:38:53 +0200 Subject: [PATCH 170/624] chore(coinjoin): update SocksProxyAgent to new API --- packages/coinjoin/tests/tools/benchmark-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/coinjoin/tests/tools/benchmark-test.ts b/packages/coinjoin/tests/tools/benchmark-test.ts index bf020c0b6b2..af5a2df5340 100644 --- a/packages/coinjoin/tests/tools/benchmark-test.ts +++ b/packages/coinjoin/tests/tools/benchmark-test.ts @@ -15,7 +15,7 @@ const TIMEOUT = 20000; const [bestKnownHash, batchSizeString = '500', torSocket = ''] = process.argv.slice(2); const batchSize = Number(batchSizeString); const [host, port] = torSocket.split(':'); -const agent = host && port ? new SocksProxyAgent({ host, port }) : undefined; +const agent = host && port ? new SocksProxyAgent(`socks://${host}:${port}`) : undefined; // Copied from request-manager to remove disallowed headers because of Wasabi const stripHeaders = () => { From 881e1d677e79bb8ecaf629aaaedf765cbdc52e59 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Mon, 14 Oct 2024 11:39:19 +0200 Subject: [PATCH 171/624] chore(request-manager): update SocksProxyAgent to new API --- packages/request-manager/src/torIdentities.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/request-manager/src/torIdentities.ts b/packages/request-manager/src/torIdentities.ts index d6794f08b4d..fd593ef17f0 100644 --- a/packages/request-manager/src/torIdentities.ts +++ b/packages/request-manager/src/torIdentities.ts @@ -29,13 +29,11 @@ export class TorIdentities { const { host, port } = this.getTorSettings(); // TODO clean agents when host/port changes? - if (!this.identities[user]) { - this.identities[user] = new SocksProxyAgent({ - hostname: host, - port, - userId: user, - password: password || user, + const socksServerUrl = new URL(`socks://${host}:${port}`); + socksServerUrl.username = user; + socksServerUrl.password = password; + this.identities[user] = new SocksProxyAgent(socksServerUrl, { timeout, }); } From 327ed789cfee7b762b30f273ac7e4f76edaf4d20 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Ortiz karliatto Date: Tue, 15 Oct 2024 13:58:52 +0200 Subject: [PATCH 172/624] chore(blockchain-link-types): remove socks-proxy-agent dependency --- packages/blockchain-link-types/package.json | 3 +-- packages/blockchain-link-types/src/common.ts | 11 +++++------ yarn.lock | 1 - 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/blockchain-link-types/package.json b/packages/blockchain-link-types/package.json index 73aedb1fa14..1c2646a9312 100644 --- a/packages/blockchain-link-types/package.json +++ b/packages/blockchain-link-types/package.json @@ -22,8 +22,7 @@ "dependencies": { "@solana/web3.js": "^1.95.0", "@trezor/type-utils": "workspace:*", - "@trezor/utxo-lib": "workspace:*", - "socks-proxy-agent": "8.0.4" + "@trezor/utxo-lib": "workspace:*" }, "devDependencies": { "tsx": "^4.16.3" diff --git a/packages/blockchain-link-types/src/common.ts b/packages/blockchain-link-types/src/common.ts index 87be144fef0..75004777e2c 100644 --- a/packages/blockchain-link-types/src/common.ts +++ b/packages/blockchain-link-types/src/common.ts @@ -1,6 +1,4 @@ import type tls from 'tls'; -import type { Url } from 'url'; -import type { SocksProxy } from 'socks'; import type { Transaction as BlockbookTransaction, VinVout } from './blockbook'; import type { @@ -21,14 +19,15 @@ interface BaseSocksProxyAgentOptions { port?: string | number | null; username?: string | null; tls?: tls.ConnectionOptions | null; + ipaddress?: string; + type: 4 | 5; + userId?: string; + password?: string; } // todo: connect10 here we are using the old `SocksProxyAgentOptions` from older version of socks-proxy-agent // but we keep the old API so we do not introduce breaking changes. -interface SocksProxyAgentOptions - extends AgentOptions, - BaseSocksProxyAgentOptions, - Partial> {} +interface SocksProxyAgentOptions extends AgentOptions, BaseSocksProxyAgentOptions {} export interface BlockchainSettings { name: string; diff --git a/yarn.lock b/yarn.lock index 72f1675de4b..717d634f2c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11139,7 +11139,6 @@ __metadata: "@solana/web3.js": "npm:^1.95.0" "@trezor/type-utils": "workspace:*" "@trezor/utxo-lib": "workspace:*" - socks-proxy-agent: "npm:8.0.4" tsx: "npm:^4.16.3" peerDependencies: tslib: ^2.6.2 From d13307a2639b232ebef213cc1566fcce47d76485 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Thu, 17 Oct 2024 14:06:48 +0200 Subject: [PATCH 173/624] npm-release: @trezor/connect-mobile 0.0.1.beta.1 --- packages/connect-mobile/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/connect-mobile/package.json b/packages/connect-mobile/package.json index 7b89182713b..c6a164ccaa8 100644 --- a/packages/connect-mobile/package.json +++ b/packages/connect-mobile/package.json @@ -1,6 +1,6 @@ { "name": "@trezor/connect-mobile", - "version": "0.0.0", + "version": "0.0.1-beta.1", "license": "See LICENSE.md in repo root", "sideEffects": false, "main": "src/index.ts", From de58841260c001937005f70cf0987e3675c28150 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Wed, 2 Oct 2024 08:07:07 +0200 Subject: [PATCH 174/624] chore(address-validator): replace new Buffer with Buffer.from or Buffer.alloc --- packages/address-validator/src/crypto/blake256.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/address-validator/src/crypto/blake256.js b/packages/address-validator/src/crypto/blake256.js index a65a8e3d2f6..39ba7e83e81 100644 --- a/packages/address-validator/src/crypto/blake256.js +++ b/packages/address-validator/src/crypto/blake256.js @@ -27,7 +27,7 @@ Blake256.u256 = [ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, ]; -Blake256.padding = new Buffer([ +Blake256.padding = Buffer.from([ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -44,7 +44,7 @@ Blake256.prototype._length_carry = function (arr) { }; Blake256.prototype.update = function (data, encoding) { - data = new Buffer(data, encoding); + data = Buffer.from(data, encoding); var block = this._block; var offset = 0; @@ -62,8 +62,8 @@ Blake256.prototype.update = function (data, encoding) { return this; }; -var zo = new Buffer([0x01]); -var oo = new Buffer([0x81]); +var zo = Buffer.from([0x01]); +var oo = Buffer.from([0x81]); function rot(x, n) { return ((x << (32 - n)) | (x >>> n)) >>> 0; @@ -91,7 +91,7 @@ function Blake256() { this._s = [0, 0, 0, 0]; - this._block = new Buffer(64); + this._block = Buffer.alloc(64); this._blockOffset = 0; this._length = [0, 0]; @@ -144,7 +144,7 @@ Blake256.prototype._padding = function () { hi += 1; } - var msglen = new Buffer(8); + var msglen = Buffer.alloc(8); msglen.writeUInt32BE(hi, 0); msglen.writeUInt32BE(lo, 4); @@ -175,7 +175,7 @@ Blake256.prototype._padding = function () { Blake256.prototype.digest = function (encoding) { this._padding(); - var buffer = new Buffer(32); + var buffer = Buffer.alloc(32); for (var i = 0; i < 8; ++i) buffer.writeUInt32BE(this._h[i], i * 4); return buffer.toString(encoding); }; From 4764484da9d985ab32b9b39f1d00e537795b0029 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Tue, 15 Oct 2024 17:45:25 +0200 Subject: [PATCH 175/624] chore(device-utils): acccept only PartialDevice as param --- packages/device-utils/src/bootloaderUtils.ts | 8 ++++---- packages/device-utils/src/firmwareUtils.ts | 15 +++++++++------ packages/device-utils/src/modeUtils.ts | 7 ++++--- packages/device-utils/src/types.ts | 6 ++++++ suite-common/suite-utils/src/device.ts | 2 +- 5 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 packages/device-utils/src/types.ts diff --git a/packages/device-utils/src/bootloaderUtils.ts b/packages/device-utils/src/bootloaderUtils.ts index 016e67f5a72..6e035046f55 100644 --- a/packages/device-utils/src/bootloaderUtils.ts +++ b/packages/device-utils/src/bootloaderUtils.ts @@ -1,10 +1,10 @@ -import { Device } from '@trezor/connect'; - import { isDeviceInBootloaderMode } from './modeUtils'; +import { PartialDevice } from './types'; -export const getBootloaderHash = (device?: Device) => device?.features?.bootloader_hash || ''; +export const getBootloaderHash = (device?: PartialDevice) => + device?.features?.bootloader_hash || ''; -export const getBootloaderVersion = (device?: Device) => { +export const getBootloaderVersion = (device?: PartialDevice) => { if (!device?.features) { return ''; } diff --git a/packages/device-utils/src/firmwareUtils.ts b/packages/device-utils/src/firmwareUtils.ts index 2d80c078359..f595bb6e514 100644 --- a/packages/device-utils/src/firmwareUtils.ts +++ b/packages/device-utils/src/firmwareUtils.ts @@ -1,10 +1,11 @@ -import { FirmwareType, Device, VersionArray } from '@trezor/connect'; +import { FirmwareType, VersionArray } from '@trezor/connect'; import { isDeviceInBootloaderMode } from './modeUtils'; +import { PartialDevice } from './types'; -export const getFirmwareRevision = (device?: Device) => device?.features?.revision || ''; +export const getFirmwareRevision = (device?: PartialDevice) => device?.features?.revision || ''; -export const getFirmwareVersionArray = (device?: Device): VersionArray | null => { +export const getFirmwareVersionArray = (device?: PartialDevice): VersionArray | null => { if (!device?.features) { return null; } @@ -19,7 +20,9 @@ export const getFirmwareVersionArray = (device?: Device): VersionArray | null => return [features.major_version, features.minor_version, features.patch_version]; }; -export const getFirmwareVersion = (device?: Device): '' | `${number}.${number}.${number}` => { +export const getFirmwareVersion = ( + device?: PartialDevice, +): '' | `${number}.${number}.${number}` => { if (!device?.features) { return ''; } @@ -35,9 +38,9 @@ export const getFirmwareVersion = (device?: Device): '' | `${number}.${number}.$ }; // This can give a false negative in bootloader mode for T1B1 and T2T1. -export const hasBitcoinOnlyFirmware = (device?: Device) => +export const hasBitcoinOnlyFirmware = (device?: PartialDevice) => device?.firmwareType === FirmwareType.BitcoinOnly; // Bitcoin-only device with Universal firmware is treated as a regular device. -export const isBitcoinOnlyDevice = (device?: Device) => +export const isBitcoinOnlyDevice = (device?: PartialDevice) => !!device?.features?.unit_btconly && device?.firmwareType !== FirmwareType.Regular; diff --git a/packages/device-utils/src/modeUtils.ts b/packages/device-utils/src/modeUtils.ts index 4694d9cf593..8efde1e9cc8 100644 --- a/packages/device-utils/src/modeUtils.ts +++ b/packages/device-utils/src/modeUtils.ts @@ -1,8 +1,9 @@ -import { Device } from '@trezor/connect'; +import { PartialDevice } from './types'; -export const isDeviceInBootloaderMode = (device?: Device) => !!device?.features?.bootloader_mode; +export const isDeviceInBootloaderMode = (device?: PartialDevice) => + !!device?.features?.bootloader_mode; -export const getDeviceMode = (device?: Device) => { +export const getDeviceMode = (device?: PartialDevice) => { if (device?.features?.bootloader_mode) return 'bootloader'; if (!device?.features?.initialized) return 'initialize'; if (device?.features?.no_backup) return 'seedless'; diff --git a/packages/device-utils/src/types.ts b/packages/device-utils/src/types.ts new file mode 100644 index 00000000000..9dc084d4f30 --- /dev/null +++ b/packages/device-utils/src/types.ts @@ -0,0 +1,6 @@ +import { Device } from '@trezor/connect'; + +export type PartialDevice = { + features?: Device['features']; + firmwareType?: Device['firmwareType']; +}; diff --git a/suite-common/suite-utils/src/device.ts b/suite-common/suite-utils/src/device.ts index b8bd16c3e46..8c7b7a1dab5 100644 --- a/suite-common/suite-utils/src/device.ts +++ b/suite-common/suite-utils/src/device.ts @@ -140,7 +140,7 @@ export const isSelectedDevice = (selected?: TrezorDevice | Device, device?: Trez return selected.id === device.id; }; -export const getFwUpdateVersion = (device: Device) => +export const getFwUpdateVersion = (device: TrezorDevice) => device.firmwareRelease?.release?.version?.join('.') || null; export const getCoinUnavailabilityMessage = (reason: UnavailableCapability) => { From 842be0d7314f2f19fe36859d92f4ca57d2823ec7 Mon Sep 17 00:00:00 2001 From: Marek Polak Date: Thu, 17 Oct 2024 14:36:46 +0200 Subject: [PATCH 176/624] chore(suite): tiny ui improvements --- packages/coinjoin/src/client/Status.ts | 18 +++++++++--------- packages/suite/src/services/coinjoin/config.ts | 2 +- .../BalancePrivacyBreakdown.tsx | 1 + .../CoinjoinSummary/CoinjoinBalanceSection.tsx | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/coinjoin/src/client/Status.ts b/packages/coinjoin/src/client/Status.ts index 47ca5535d4c..68ea510ddd9 100644 --- a/packages/coinjoin/src/client/Status.ts +++ b/packages/coinjoin/src/client/Status.ts @@ -240,15 +240,15 @@ export class Status extends TypedEmitter { identity: this.identities[0], attempts: 3, // schedule 3 attempts on start }, - ).then(patchResponse); - - return version - ? ({ - majorVersion: version.BackenMajordVersion, - commitHash: version.CommitHash, - legalDocumentsVersion: version.Ww2LegalDocumentsVersion, - } as CoinjoinClientVersion) - : undefined; + ) + .then(patchResponse) + .catch(() => undefined); + + return { + majorVersion: version?.BackenMajordVersion ?? '0', + commitHash: version?.CommitHash ?? 'deadbeef', + legalDocumentsVersion: version?.Ww2LegalDocumentsVersion ?? '1.0', + } as CoinjoinClientVersion; } async start() { diff --git a/packages/suite/src/services/coinjoin/config.ts b/packages/suite/src/services/coinjoin/config.ts index e10d924ee8c..4a47aba2137 100644 --- a/packages/suite/src/services/coinjoin/config.ts +++ b/packages/suite/src/services/coinjoin/config.ts @@ -21,7 +21,7 @@ export const COINJOIN_NETWORKS: PartialRecord network: 'btc', coordinatorName: 'CoinJoinCoordinatorIdentifier', coordinatorUrl: 'https://wasabiwallet.io/wabisabi/', - wabisabiBackendUrl: 'https://wasabiwallet.io/', + wabisabiBackendUrl: 'https://api.wasabiwallet.io/', blockbookUrls: [ 'https://btc1.trezor.io', 'https://btc2.trezor.io', diff --git a/packages/suite/src/views/wallet/transactions/CoinjoinSummary/BalancePrivacyBreakdown/BalancePrivacyBreakdown.tsx b/packages/suite/src/views/wallet/transactions/CoinjoinSummary/BalancePrivacyBreakdown/BalancePrivacyBreakdown.tsx index a9841f60d37..1b62f6c8d83 100644 --- a/packages/suite/src/views/wallet/transactions/CoinjoinSummary/BalancePrivacyBreakdown/BalancePrivacyBreakdown.tsx +++ b/packages/suite/src/views/wallet/transactions/CoinjoinSummary/BalancePrivacyBreakdown/BalancePrivacyBreakdown.tsx @@ -15,6 +15,7 @@ const BalanceContainer = styled.div` display: flex; flex-wrap: wrap; align-items: center; + align-self: normal; gap: 12px; padding: 0 10px; `; diff --git a/packages/suite/src/views/wallet/transactions/CoinjoinSummary/CoinjoinBalanceSection.tsx b/packages/suite/src/views/wallet/transactions/CoinjoinSummary/CoinjoinBalanceSection.tsx index 3295e8f9f84..c60f6f7f938 100644 --- a/packages/suite/src/views/wallet/transactions/CoinjoinSummary/CoinjoinBalanceSection.tsx +++ b/packages/suite/src/views/wallet/transactions/CoinjoinSummary/CoinjoinBalanceSection.tsx @@ -48,7 +48,7 @@ export const CoinjoinBalanceSection = ({ accountKey }: CoinjoinBalanceSectionPro return ( - + {errorMessageConfig ? ( ) : ( From 2fbb8392b0ff5296235617e18d5f61efa7dc9f28 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Thu, 10 Oct 2024 09:55:40 +0200 Subject: [PATCH 177/624] feat(connect): expose stricter device.path type - branded PathPublic --- packages/connect/src/types/device.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/connect/src/types/device.ts b/packages/connect/src/types/device.ts index 974d6b1bc85..59fc8279a32 100644 --- a/packages/connect/src/types/device.ts +++ b/packages/connect/src/types/device.ts @@ -1,3 +1,4 @@ +import { Descriptor } from '@trezor/transport'; import type { PROTO } from '../constants'; import type { ReleaseInfo } from './firmware'; @@ -66,7 +67,7 @@ export type FirmwareHashCheckResult = | { success: false; error: FirmwareHashCheckError }; type BaseDevice = { - path: string; + path: Descriptor['path']; name: string; }; From 5144bd5ac9769c363c9277f89d05e172c05c6b04 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Thu, 10 Oct 2024 09:56:07 +0200 Subject: [PATCH 178/624] chore(suite): adapt to device.path (PathPublic) type --- packages/suite/src/storage/definitions.ts | 5 ++--- packages/suite/src/utils/suite/storage.ts | 8 ++++++-- suite-common/suite-types/src/device.ts | 5 +++++ suite-common/test-utils/src/mocks.ts | 16 ++++++++++++---- .../wallet-core/src/device/deviceConstants.ts | 1 + .../wallet-core/src/device/deviceReducer.ts | 1 + .../storage/src/transforms/deviceTransforms.ts | 7 +++++-- 7 files changed, 32 insertions(+), 11 deletions(-) diff --git a/packages/suite/src/storage/definitions.ts b/packages/suite/src/storage/definitions.ts index 297ebc287e1..345f09c689d 100644 --- a/packages/suite/src/storage/definitions.ts +++ b/packages/suite/src/storage/definitions.ts @@ -3,11 +3,10 @@ import { FieldValues } from 'react-hook-form'; import type { SuiteState } from 'src/reducers/suite/suiteReducer'; import type { FormState, RatesByTimestamps } from '@suite-common/wallet-types'; -import type { AcquiredDevice } from 'src/types/suite'; import type { MetadataState } from 'src/types/suite/metadata'; import type { Trade } from 'src/types/wallet/coinmarketCommonTypes'; import type { MessageState } from '@suite-common/message-system'; -import type { MessageSystem } from '@suite-common/suite-types'; +import type { DeviceWithEmptyPath, MessageSystem } from '@suite-common/suite-types'; import type { Account, Discovery, WalletAccountTransaction } from 'src/types/wallet'; import { NetworkSymbol } from '@suite-common/wallet-config'; import type { CoinjoinAccount, CoinjoinDebugSettings } from 'src/types/wallet/coinjoin'; @@ -60,7 +59,7 @@ export interface SuiteDBSchema extends DBSchema { }; devices: { key: string; - value: AcquiredDevice; + value: DeviceWithEmptyPath; }; accounts: { key: string[]; diff --git a/packages/suite/src/utils/suite/storage.ts b/packages/suite/src/utils/suite/storage.ts index 416072ec271..d1c158a03ed 100644 --- a/packages/suite/src/utils/suite/storage.ts +++ b/packages/suite/src/utils/suite/storage.ts @@ -3,6 +3,7 @@ import { connectInitThunk } from '@suite-common/connect-init'; import { AcquiredDevice } from 'src/types/suite'; import { CoinjoinAccount } from 'src/types/wallet/coinjoin'; +import { DeviceWithEmptyPath } from '@suite-common/suite-types'; /** * Strip unserializable fields from Discovery (eg. promises) @@ -15,8 +16,11 @@ export const serializeDiscovery = (discovery: Discovery) => ({ ...discovery, run * Strip fields from Device * @param {AcquiredDevice} device */ -export const serializeDevice = (device: AcquiredDevice, forceRemember?: true) => { - const sd = { +export const serializeDevice = ( + device: AcquiredDevice, + forceRemember?: true, +): DeviceWithEmptyPath => { + const sd: DeviceWithEmptyPath = { ...device, path: '', remember: true, diff --git a/suite-common/suite-types/src/device.ts b/suite-common/suite-types/src/device.ts index b0bfefeed8d..f515262a018 100644 --- a/suite-common/suite-types/src/device.ts +++ b/suite-common/suite-types/src/device.ts @@ -52,3 +52,8 @@ export type UnknownDevice = UnknownDeviceBase & ExtendedDevice; export type UnreadableDevice = UnreadableDeviceBase & ExtendedDevice; export type TrezorDevice = AcquiredDevice | UnknownDevice | UnreadableDevice; + +/** + * used when saving device to storage + */ +export type DeviceWithEmptyPath = Omit & { path: '' }; diff --git a/suite-common/test-utils/src/mocks.ts b/suite-common/test-utils/src/mocks.ts index c812fe731d5..d8e895df14d 100644 --- a/suite-common/test-utils/src/mocks.ts +++ b/suite-common/test-utils/src/mocks.ts @@ -142,11 +142,15 @@ const getDeviceFeatures = (feat?: Partial): Features => ({ * @param {Partial} [feat] * @returns {Device} */ -const getConnectDevice = (dev?: Partial, feat?: Partial): Device => { +const getConnectDevice = ( + dev?: Partial & { path: `${number}` }>, + feat?: Partial, +): Device => { + const path = (dev && dev.path ? dev.path : '1') as `${number}` & { __type: 'PathPublic' }; if (dev && typeof dev.type === 'string' && dev.type === 'unreadable') { return { type: 'unreadable', - path: dev && dev.path ? dev.path : '1', + path, label: 'Unreadable device', name: 'name of unreadable device', error: 'unreadable device', @@ -156,7 +160,7 @@ const getConnectDevice = (dev?: Partial, feat?: Partial): Devi if (dev && typeof dev.type === 'string' && dev.type === 'unacquired') { return { type: dev.type, - path: dev && dev.path ? dev.path : '1', + path, label: 'Unacquired device', name: 'name of unacquired device', }; @@ -166,6 +170,7 @@ const getConnectDevice = (dev?: Partial, feat?: Partial): Devi return { id: features.device_id, + // @ts-expect-error path: '', label: 'My Trezor', firmware: 'valid', @@ -197,7 +202,10 @@ const getConnectDevice = (dev?: Partial, feat?: Partial): Devi * @param {Partial} [feat] * @returns {TrezorDevice} */ -const getSuiteDevice = (dev?: Partial, feat?: Partial): TrezorDevice => { +const getSuiteDevice = ( + dev?: Partial & { path: `${number}` }>, + feat?: Partial, +): TrezorDevice => { const device = getConnectDevice(dev, feat); if (device.type === 'acquired') { return { diff --git a/suite-common/wallet-core/src/device/deviceConstants.ts b/suite-common/wallet-core/src/device/deviceConstants.ts index c387c055b23..92d94cb1f29 100644 --- a/suite-common/wallet-core/src/device/deviceConstants.ts +++ b/suite-common/wallet-core/src/device/deviceConstants.ts @@ -15,6 +15,7 @@ export const portfolioTrackerDevice: TrezorDevice = { mode: 'normal', state: PORTFOLIO_TRACKER_DEVICE_STATE, label: 'My assets', + // @ts-expect-error - local override path: 'imported-1', firmware: 'valid', name: 'Portfolio Tracker', diff --git a/suite-common/wallet-core/src/device/deviceReducer.ts b/suite-common/wallet-core/src/device/deviceReducer.ts index c947fe221ef..dc78313e9bd 100644 --- a/suite-common/wallet-core/src/device/deviceReducer.ts +++ b/suite-common/wallet-core/src/device/deviceReducer.ts @@ -274,6 +274,7 @@ const disconnectDevice = (draft: State, device: Device) => { if (skip) { d.connected = false; d.available = false; + // @ts-expect-error d.path = ''; } else { draft.devices.splice(draft.devices.indexOf(d), 1); diff --git a/suite-native/storage/src/transforms/deviceTransforms.ts b/suite-native/storage/src/transforms/deviceTransforms.ts index 0f4f84b09d7..4f5eba3b8fd 100644 --- a/suite-native/storage/src/transforms/deviceTransforms.ts +++ b/suite-native/storage/src/transforms/deviceTransforms.ts @@ -3,7 +3,7 @@ import { createTransform } from 'redux-persist'; import { TrezorDevice } from '@suite-common/suite-types'; -const serializeDevice = (device: TrezorDevice) => ({ +const serializeDevice = (device: TrezorDevice): Omit & { path: '' } => ({ ...device, path: '', remember: true, @@ -11,7 +11,10 @@ const serializeDevice = (device: TrezorDevice) => ({ buttonRequests: [], }); -export const devicePersistTransform = createTransform>( +export const devicePersistTransform = createTransform< + TrezorDevice[], + Readonly<(Omit & { path: '' })[]> +>( inboundState => { return pipe( inboundState, From 7a278d871fd47ee2091e483521f5814b752c9478 Mon Sep 17 00:00:00 2001 From: Pavlo Syrotyna Date: Thu, 22 Aug 2024 12:38:10 +0300 Subject: [PATCH 179/624] fix(staking): max with low amount --- .../wallet/stake/stakeFormEthereumActions.ts | 31 ++++++---- .../components/suite/FormFractionButtons.tsx | 7 +-- .../StakeModal/StakeEthForm/Inputs.tsx | 35 +++++++---- .../suite/src/hooks/wallet/useStakeEthForm.ts | 60 ++++++++++++++----- packages/suite/src/support/messages.ts | 5 ++ .../wallet-core/src/stake/stakeTypes.ts | 1 + 6 files changed, 98 insertions(+), 41 deletions(-) diff --git a/packages/suite/src/actions/wallet/stake/stakeFormEthereumActions.ts b/packages/suite/src/actions/wallet/stake/stakeFormEthereumActions.ts index 661ec78dc13..a249a47a408 100644 --- a/packages/suite/src/actions/wallet/stake/stakeFormEthereumActions.ts +++ b/packages/suite/src/actions/wallet/stake/stakeFormEthereumActions.ts @@ -31,7 +31,11 @@ import { prepareStakeEthTx, prepareUnstakeEthTx, } from 'src/utils/suite/stake'; -import { MIN_ETH_FOR_WITHDRAWALS } from 'src/constants/suite/ethStaking'; +import { + MIN_ETH_AMOUNT_FOR_STAKING, + MIN_ETH_BALANCE_FOR_STAKING, + MIN_ETH_FOR_WITHDRAWALS, +} from 'src/constants/suite/ethStaking'; import { NetworkSymbol } from '@suite-common/wallet-config'; import { ComposeActionContext } from '@suite-common/wallet-core'; @@ -42,28 +46,33 @@ const calculate = ( compareWithAmount = true, symbol: NetworkSymbol, ): PrecomposedTransaction => { - const feeInSatoshi = calculateEthFee( - toWei(feeLevel.feePerUnit, 'gwei'), - feeLevel.feeLimit || '0', - ); + const feeInWei = calculateEthFee(toWei(feeLevel.feePerUnit, 'gwei'), feeLevel.feeLimit || '0'); let amount: string; let max: string | undefined; if (output.type === 'send-max' || output.type === 'send-max-noaddress') { - max = new BigNumber(calculateMax(availableBalance, feeInSatoshi)) - .minus(toWei(MIN_ETH_FOR_WITHDRAWALS.toString(), 'ether')) - .toString(); + const minEthBalanceForStakingWei = toWei(MIN_ETH_BALANCE_FOR_STAKING.toString(), 'ether'); + const minAmountWithFeeWei = new BigNumber(minEthBalanceForStakingWei).plus(feeInWei); + + if (new BigNumber(availableBalance).lt(minAmountWithFeeWei)) { + max = toWei(MIN_ETH_AMOUNT_FOR_STAKING.toString(), 'ether'); + } else { + max = new BigNumber(calculateMax(availableBalance, feeInWei)) + .minus(toWei(MIN_ETH_FOR_WITHDRAWALS.toString(), 'ether')) + .toString(); + } + amount = max; } else { amount = output.amount; } // total ETH spent (amount + fee), in ERC20 only fee - const totalSpent = new BigNumber(calculateTotal(amount, feeInSatoshi)); + const totalSpent = new BigNumber(calculateTotal(amount, feeInWei)); if ( - new BigNumber(feeInSatoshi).gt(availableBalance) || + new BigNumber(feeInWei).gt(availableBalance) || (compareWithAmount && totalSpent.isGreaterThan(availableBalance)) ) { const error = 'TR_STAKE_NOT_ENOUGH_FUNDS'; @@ -80,7 +89,7 @@ const calculate = ( type: 'nonfinal' as const, totalSpent: totalSpent.toString(), max, - fee: feeInSatoshi, + fee: feeInWei, feePerByte: feeLevel.feePerUnit, feeLimit: feeLevel.feeLimit, bytes: 0, // TODO: calculate diff --git a/packages/suite/src/components/suite/FormFractionButtons.tsx b/packages/suite/src/components/suite/FormFractionButtons.tsx index 3b8294ee2f4..642a8dbdd8f 100644 --- a/packages/suite/src/components/suite/FormFractionButtons.tsx +++ b/packages/suite/src/components/suite/FormFractionButtons.tsx @@ -2,10 +2,7 @@ import styled from 'styled-components'; import { Translation } from 'src/components/suite'; import { Button, Tooltip } from '@trezor/components'; import { BigNumber } from '@trezor/utils/src/bigNumber'; -import { - MIN_ETH_AMOUNT_FOR_STAKING, - MIN_ETH_BALANCE_FOR_STAKING, -} from 'src/constants/suite/ethStaking'; +import { MIN_ETH_AMOUNT_FOR_STAKING } from 'src/constants/suite/ethStaking'; import { NetworkSymbol } from '@suite-common/wallet-config'; const Flex = styled.div` @@ -50,7 +47,7 @@ export const FormFractionButtons = ({ const is25PercentDisabled = isDisabled || isFractionButtonDisabled(4); const is50PercentDisabled = isDisabled || isFractionButtonDisabled(2); const isMaxDisabled = - isDisabled || new BigNumber(totalAmount || '0').lt(MIN_ETH_BALANCE_FOR_STAKING); + isDisabled || new BigNumber(totalAmount || '0').lt(MIN_ETH_AMOUNT_FOR_STAKING); return ( diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx index b4c6a0e6455..5f3a6191dd9 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx @@ -14,7 +14,7 @@ import { } from 'src/utils/suite/validation'; import { FIAT_INPUT, CRYPTO_INPUT } from 'src/types/wallet/stakeForms'; import { MIN_ETH_FOR_WITHDRAWALS } from 'src/constants/suite/ethStaking'; -import { spacings, spacingsPx } from '@trezor/theme'; +import { spacingsPx } from '@trezor/theme'; import { validateStakingMax } from 'src/utils/suite/stake'; const IconWrapper = styled.div` @@ -36,6 +36,7 @@ export const Inputs = () => { onFiatAmountChange, localCurrency, isAmountForWithdrawalWarningShown, + isLessAmountForWithdrawalWarningShown, isAdviceForWithdrawalWarningShown, currentRate, } = useStakeEthFormContext(); @@ -66,6 +67,25 @@ export const Inputs = () => { }, }; + const shouldShowAmountForWithdrawalWarning = + isLessAmountForWithdrawalWarningShown || isAmountForWithdrawalWarningShown; + const amountForWithdrawalTranslation = isLessAmountForWithdrawalWarningShown ? ( + + ) : ( + + ); + return ( { )} - {isAmountForWithdrawalWarningShown && ( - - - + {shouldShowAmountForWithdrawalWarning && ( + {amountForWithdrawalTranslation} )} + {isAdviceForWithdrawalWarningShown && ( { + setIsAmountForWithdrawalWarningShown(false); + setIsLessAmountForWithdrawalWarningShown(false); + setIsAdviceForWithdrawalWarningShown(false); + }, []); + const shouldShowAdvice = useCallback( (amount: string, formattedBalance: string) => { const cryptoValue = new BigNumber(amount); @@ -201,8 +210,7 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC const onCryptoAmountChange = useCallback( async (amount: string) => { - setIsAmountForWithdrawalWarningShown(false); - setIsAdviceForWithdrawalWarningShown(false); + clearWithdrawalWarnings(); if (currentRate) { const fiatValue = toFiatCurrency(amount, currentRate?.rate); @@ -215,14 +223,20 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC shouldShowAdvice(amount, account.formattedBalance); }, - [account.formattedBalance, composeRequest, currentRate, setValue, shouldShowAdvice], + [ + account.formattedBalance, + composeRequest, + currentRate, + setValue, + shouldShowAdvice, + clearWithdrawalWarnings, + ], ); const onFiatAmountChange = useCallback( async (amount: string) => { setValue('setMaxOutputId', undefined, { shouldDirty: true }); - setIsAmountForWithdrawalWarningShown(false); - setIsAdviceForWithdrawalWarningShown(false); + clearWithdrawalWarnings(); if (!currentRate) return; const cryptoValue = fromFiatCurrency(amount, network.decimals, currentRate?.rate); @@ -241,6 +255,7 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC network.decimals, setValue, shouldShowAdvice, + clearWithdrawalWarnings, ], ); @@ -248,8 +263,7 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC async (divisor: number) => { setValue('setMaxOutputId', undefined, { shouldDirty: true }); clearErrors([FIAT_INPUT, CRYPTO_INPUT]); - setIsAmountForWithdrawalWarningShown(false); - setIsAdviceForWithdrawalWarningShown(false); + clearWithdrawalWarnings(); const amount = new BigNumber(account.formattedBalance) .dividedBy(divisor) @@ -259,28 +273,45 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC setValue(CRYPTO_INPUT, amount, { shouldDirty: true, shouldValidate: true }); await onCryptoAmountChange(amount); }, - [account.formattedBalance, clearErrors, network.decimals, onCryptoAmountChange, setValue], + [ + account.formattedBalance, + clearErrors, + network.decimals, + onCryptoAmountChange, + setValue, + clearWithdrawalWarnings, + ], ); const setMax = useCallback(async () => { setIsAdviceForWithdrawalWarningShown(false); setValue('setMaxOutputId', 0, { shouldDirty: true }); clearErrors([FIAT_INPUT, CRYPTO_INPUT]); - const amount = new BigNumber(account.formattedBalance) - .minus(MIN_ETH_FOR_WITHDRAWALS) - .toString(); + + const amount = new BigNumber(account.formattedBalance).toString(); + + if (amount < MIN_ETH_BALANCE_FOR_STAKING.toString()) { + setIsLessAmountForWithdrawalWarningShown(true); + } + setValue(OUTPUT_AMOUNT, amount || '', { shouldDirty: true }); await composeRequest(CRYPTO_INPUT); setIsAmountForWithdrawalWarningShown(true); }, [account.formattedBalance, clearErrors, composeRequest, setValue]); + useEffect(() => { + if (formState.errors[CRYPTO_INPUT]) { + setIsAmountForWithdrawalWarningShown(false); + setIsLessAmountForWithdrawalWarningShown(false); + } + }, [formState]); + const clearForm = useCallback(async () => { removeDraft(account.key); reset(defaultValues); await composeRequest(CRYPTO_INPUT); - setIsAdviceForWithdrawalWarningShown(false); - setIsAmountForWithdrawalWarningShown(false); - }, [account.key, composeRequest, defaultValues, removeDraft, reset]); + clearWithdrawalWarnings(); + }, [account.key, composeRequest, defaultValues, removeDraft, reset, clearWithdrawalWarnings]); const { translationString } = useTranslation(); useEffect(() => { @@ -366,6 +397,7 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC setMax, setRatioAmount, isAmountForWithdrawalWarningShown, + isLessAmountForWithdrawalWarningShown, isAdviceForWithdrawalWarningShown, selectedFee, feeInfo, diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index a9ad751199c..54ff955d989 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -8697,6 +8697,11 @@ export default defineMessages({ id: 'TR_STAKE_LEFT_AMOUNT_FOR_WITHDRAWAL', defaultMessage: 'We’ve left {amount} {symbol} out so you can pay for withdrawal fees.', }, + TR_STAKE_LEFT_SMALL_AMOUNT_FOR_WITHDRAWAL: { + id: 'TR_STAKE_LEFT_SMALL_AMOUNT_FOR_WITHDRAWAL', + defaultMessage: + 'We’ve left a small amount of {symbol} out so you can pay for withdrawal fees.', + }, TR_STAKE_RECOMMENDED_AMOUNT_FOR_WITHDRAWALS: { id: 'TR_STAKE_RECOMMENDED_AMOUNT_FOR_WITHDRAWALS', defaultMessage: diff --git a/suite-common/wallet-core/src/stake/stakeTypes.ts b/suite-common/wallet-core/src/stake/stakeTypes.ts index e6b4eb9f421..e37bfdf6a7b 100644 --- a/suite-common/wallet-core/src/stake/stakeTypes.ts +++ b/suite-common/wallet-core/src/stake/stakeTypes.ts @@ -97,6 +97,7 @@ export type StakeContextValues = UseFormReturn & isDraft: boolean; amountLimits: AmountLimitsString; isAmountForWithdrawalWarningShown: boolean; + isLessAmountForWithdrawalWarningShown: boolean; isAdviceForWithdrawalWarningShown: boolean; isConfirmModalOpen: boolean; onCryptoAmountChange: (amount: string) => void; From 67ebaa50e21d88c040626ef54a9718283340ea37 Mon Sep 17 00:00:00 2001 From: tomasklim Date: Tue, 8 Oct 2024 18:32:49 +0200 Subject: [PATCH 180/624] fix(suite): space between staking amount input and reserve banner --- .../UserContextModal/StakeModal/StakeEthForm/Inputs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx index 5f3a6191dd9..b987bd71e85 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx @@ -127,7 +127,7 @@ export const Inputs = () => { )} {isAdviceForWithdrawalWarningShown && ( - + Date: Thu, 17 Oct 2024 16:19:42 +0200 Subject: [PATCH 181/624] fix(suite): staking fraction buttons tooltip --- .../components/suite/FormFractionButtons.tsx | 68 ++++++++++--------- .../StakeModal/StakeEthForm/Inputs.tsx | 30 ++++---- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/packages/suite/src/components/suite/FormFractionButtons.tsx b/packages/suite/src/components/suite/FormFractionButtons.tsx index 642a8dbdd8f..322a986a3b9 100644 --- a/packages/suite/src/components/suite/FormFractionButtons.tsx +++ b/packages/suite/src/components/suite/FormFractionButtons.tsx @@ -53,16 +53,17 @@ export const FormFractionButtons = ({ + is10PercentDisabled && ( + + ) } cursor="pointer" - disabled={!is10PercentDisabled} > setRatioAmount(10)}> 10% @@ -70,16 +71,17 @@ export const FormFractionButtons = ({ + is25PercentDisabled && ( + + ) } cursor="pointer" - disabled={!is25PercentDisabled} > setRatioAmount(4)}> 25% @@ -87,16 +89,17 @@ export const FormFractionButtons = ({ + is50PercentDisabled && ( + + ) } cursor="pointer" - disabled={!is50PercentDisabled} > setRatioAmount(2)}> 50% @@ -104,16 +107,17 @@ export const FormFractionButtons = ({ + isMaxDisabled && ( + + ) } cursor="pointer" - disabled={!is50PercentDisabled} > diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx index b987bd71e85..b06cb593525 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx @@ -69,22 +69,6 @@ export const Inputs = () => { const shouldShowAmountForWithdrawalWarning = isLessAmountForWithdrawalWarningShown || isAmountForWithdrawalWarningShown; - const amountForWithdrawalTranslation = isLessAmountForWithdrawalWarningShown ? ( - - ) : ( - - ); return ( @@ -123,7 +107,19 @@ export const Inputs = () => { )} {shouldShowAmountForWithdrawalWarning && ( - {amountForWithdrawalTranslation} + + + )} {isAdviceForWithdrawalWarningShown && ( From cc22068b2a8ad490487749c26c71212797e44d02 Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Thu, 17 Oct 2024 16:00:50 +0200 Subject: [PATCH 182/624] fix(schema-utils): typescript + typebox package resolution issue --- packages/schema-utils/src/index.ts | 2 +- scripts/replace-imports.sh | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/schema-utils/src/index.ts b/packages/schema-utils/src/index.ts index 589e4e45918..64fd196a1d0 100644 --- a/packages/schema-utils/src/index.ts +++ b/packages/schema-utils/src/index.ts @@ -121,4 +121,4 @@ export function AssertWeak( export const Type = new CustomTypeBuilder(); export { Optional, CloneType }; -export type { Static, TObject, TSchema }; +export type * from '@sinclair/typebox'; diff --git a/scripts/replace-imports.sh b/scripts/replace-imports.sh index 7e66968ed9c..fd66ba6cf49 100755 --- a/scripts/replace-imports.sh +++ b/scripts/replace-imports.sh @@ -24,14 +24,3 @@ if grep -Rl "$SEARCH_PATTERN" "$1"; then else echo "All occurrences of '@trezor/*/src' have been successfully replaced." fi - -# Patch for Typebox import issue, where TS uses an ESM import path, but our package is CommonJS -# @sinclair/typebox/build/esm/index.mjs -> @sinclair/typebox - -REGEX="s/@sinclair\/typebox\/build\/esm\/index.mjs/@sinclair\/typebox/g" - -if [[ "$OS" == "Darwin" ]]; then - find "$1" -type f -exec sed -i '' -E "$REGEX" {} + -else - find "$1" -type f -exec sed -i -E "$REGEX" {} + -fi From be706df310f81fe2358c6059adc45ac5ff681b73 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Tue, 8 Oct 2024 11:52:43 +0200 Subject: [PATCH 183/624] feat(suite-native): single fee option ui --- suite-native/intl/src/en.ts | 2 +- .../module-send/src/components/FeeOption.tsx | 51 ++++++++++--------- .../src/components/FeeOptionsList.tsx | 3 ++ 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts index af78fca987d..ad675b98947 100644 --- a/suite-native/intl/src/en.ts +++ b/suite-native/intl/src/en.ts @@ -913,7 +913,7 @@ export const en = { }, levels: { low: 'Low', - medium: 'Medium', + normal: 'Normal', high: 'High', }, error: 'You don’t have enough balance to use this fee.', diff --git a/suite-native/module-send/src/components/FeeOption.tsx b/suite-native/module-send/src/components/FeeOption.tsx index 8c065fd2fc9..98174bc06bf 100644 --- a/suite-native/module-send/src/components/FeeOption.tsx +++ b/suite-native/module-send/src/components/FeeOption.tsx @@ -29,9 +29,18 @@ import { NativeSupportedFeeLevel } from '../types'; import { FeeOptionErrorMessage } from './FeeOptionErrorMessage'; import { updateDraftFeeLevelThunk } from '../sendFormThunks'; +type FeeOptionProps = { + feeKey: SendFeesFormValues['feeLevel']; + feeLevel: GeneralPrecomposedTransactionFinal; + networkSymbol: NetworkSymbol; + transactionBytes: number; + accountKey: AccountKey; + isInteractive?: boolean; +}; + const feeLabelsMap = { economy: 'moduleSend.fees.levels.low', - normal: 'moduleSend.fees.levels.medium', + normal: 'moduleSend.fees.levels.normal', high: 'moduleSend.fees.levels.high', } as const satisfies Record; @@ -47,20 +56,13 @@ const valuesWrapperStyle = prepareNativeStyle(utils => ({ padding: utils.spacings.sp16, })); -type FeeOptionProps = { - feeKey: SendFeesFormValues['feeLevel']; - feeLevel: GeneralPrecomposedTransactionFinal; - networkSymbol: NetworkSymbol; - transactionBytes: number; - accountKey: AccountKey; -}; - export const FeeOption = ({ feeKey, feeLevel, networkSymbol, transactionBytes, accountKey, + isInteractive = true, }: FeeOptionProps) => { const { utils } = useNativeStyles(); const { applyStyle } = useNativeStyles(); @@ -102,12 +104,12 @@ export const FeeOption = ({ const animatedCardStyle = useAnimatedStyle( () => ({ borderColor: interpolateColor( - borderAnimationValue.value, + isInteractive ? borderAnimationValue.value : 0, [0, 1], [utils.colors.backgroundSurfaceElevation0, utils.colors[highlightColor]], ), }), - [borderAnimationValue, highlightColor], + [borderAnimationValue, highlightColor, isInteractive], ); const label = feeLabelsMap[feeKey]; @@ -120,13 +122,8 @@ export const FeeOption = ({ const fee = isErrorFee ? mockedFee.toString() : feeLevel.fee; return ( - - + + - + {isInteractive && ( + + )} diff --git a/suite-native/module-send/src/components/FeeOptionsList.tsx b/suite-native/module-send/src/components/FeeOptionsList.tsx index 9d5c08ff3d2..14a7e5ece6b 100644 --- a/suite-native/module-send/src/components/FeeOptionsList.tsx +++ b/suite-native/module-send/src/components/FeeOptionsList.tsx @@ -28,6 +28,8 @@ export const FeeOptionsList = ({ feeLevels, networkSymbol, accountKey }: FeeOpti const normalLevel = predefinedFeeLevels.normal as PrecomposedTransactionFinal; const transactionBytes = normalLevel.bytes; + const isMultipleOptionsDisplayed = Object.keys(predefinedFeeLevels).length > 1; + return ( {Object.entries(predefinedFeeLevels).map(([feeKey, feeLevel]) => ( @@ -38,6 +40,7 @@ export const FeeOptionsList = ({ feeLevels, networkSymbol, accountKey }: FeeOpti accountKey={accountKey} networkSymbol={networkSymbol} transactionBytes={transactionBytes} + isInteractive={isMultipleOptionsDisplayed} /> ))} From e448a0462a15aa722b197c3adde51acb2e1dfbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Such=C3=BD?= Date: Fri, 18 Oct 2024 11:04:17 +0200 Subject: [PATCH 184/624] chore(repo): update eslint (#14814) --- package.json | 20 +- yarn.lock | 1245 +++++++++++++++++++++++++++----------------------- 2 files changed, 683 insertions(+), 582 deletions(-) diff --git a/package.json b/package.json index 095a6c3dcdf..c55a94488a6 100644 --- a/package.json +++ b/package.json @@ -126,19 +126,19 @@ "@types/prettier": "^3.0.0", "@types/semver": "^7.5.6", "@types/tar": "^6.1.11", - "@typescript-eslint/eslint-plugin": "^8.5.0", - "@typescript-eslint/parser": "^8.5.0", + "@typescript-eslint/eslint-plugin": "^8.8.1", + "@typescript-eslint/parser": "^8.8.1", "babel-jest": "29.7.0", "depcheck": "^1.4.7", - "eslint": "^8.56.0", - "eslint-plugin-chai-friendly": "^0.7.4", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.3", - "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint": "^8.57.1", + "eslint-plugin-chai-friendly": "^1.0.1", + "eslint-plugin-cypress": "^3.5.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest": "^28.8.3", + "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-local-rules": "^3.0.2", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react": "^7.37.1", + "eslint-plugin-react-hooks": "^4.6.2", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "jest-expo": "^50.0.2", diff --git a/yarn.lock b/yarn.lock index 717d634f2c5..384e26d2c46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3337,9 +3337,9 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.6.1": - version: 4.11.0 - resolution: "@eslint-community/regexpp@npm:4.11.0" - checksum: 10/f053f371c281ba173fe6ee16dbc4fe544c84870d58035ccca08dba7f6ce1830d895ce3237a0db89ba37616524775dca82f1c502066b58e2d5712d7f87f5ba17c + version: 4.11.1 + resolution: "@eslint-community/regexpp@npm:4.11.1" + checksum: 10/934b6d3588c7f16b18d41efec4fdb89616c440b7e3256b8cb92cfd31ae12908600f2b986d6c1e61a84cbc10256b1dd3448cd1eec79904bd67ac365d0f1aba2e2 languageName: node linkType: hard @@ -3360,10 +3360,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 10/97a4b5ccf7e24f4d205a1fb0f21cdcd610348ecf685f6798a48dd41ba443f2c1eedd3050ff5a0b8f30b8cf6501ab512aa9b76e531db15e59c9ebaa41f3162e37 +"@eslint/js@npm:8.57.1": + version: 8.57.1 + resolution: "@eslint/js@npm:8.57.1" + checksum: 10/7562b21be10c2adbfa4aa5bb2eccec2cb9ac649a3569560742202c8d1cb6c931ce634937a2f0f551e078403a1c1285d6c2c0aa345dafc986149665cd69fe8b59 languageName: node linkType: hard @@ -4567,14 +4567,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": - version: 0.11.13 - resolution: "@humanwhocodes/config-array@npm:0.11.13" +"@humanwhocodes/config-array@npm:^0.13.0": + version: 0.13.0 + resolution: "@humanwhocodes/config-array@npm:0.13.0" dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.1" - debug: "npm:^4.1.1" + "@humanwhocodes/object-schema": "npm:^2.0.3" + debug: "npm:^4.3.1" minimatch: "npm:^3.0.5" - checksum: 10/9f655e1df7efa5a86822cd149ca5cef57240bb8ffd728f0c07cc682cc0a15c6bdce68425fbfd58f9b3e8b16f79b3fd8cb1e96b10c434c9a76f20b2a89f213272 + checksum: 10/524df31e61a85392a2433bf5d03164e03da26c03d009f27852e7dcfdafbc4a23f17f021dacf88e0a7a9fe04ca032017945d19b57a16e2676d9114c22a53a9d11 languageName: node linkType: hard @@ -4585,10 +4585,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 10/dbddfd0465aecf92ed845ec30d06dba3f7bb2496d544b33b53dac7abc40370c0e46b8787b268d24a366730d5eeb5336ac88967232072a183905ee4abf7df4dab +"@humanwhocodes/object-schema@npm:^2.0.3": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: 10/05bb99ed06c16408a45a833f03a732f59bf6184795d4efadd33238ff8699190a8c871ad1121241bb6501589a9598dc83bf25b99dcbcf41e155cdf36e35e937a3 languageName: node linkType: hard @@ -7663,6 +7663,13 @@ __metadata: languageName: node linkType: hard +"@rtsao/scc@npm:^1.1.0": + version: 1.1.0 + resolution: "@rtsao/scc@npm:1.1.0" + checksum: 10/17d04adf404e04c1e61391ed97bca5117d4c2767a76ae3e879390d6dec7b317fcae68afbf9e98badee075d0b64fa60f287729c4942021b4d19cd01db77385c01 + languageName: node + linkType: hard + "@sagold/json-pointer@npm:^5.1.1, @sagold/json-pointer@npm:^5.1.2": version: 5.1.2 resolution: "@sagold/json-pointer@npm:5.1.2" @@ -12817,7 +12824,14 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:1.0.5, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d + languageName: node + linkType: hard + +"@types/estree@npm:1.0.5": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" checksum: 10/7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 @@ -13105,9 +13119,9 @@ __metadata: linkType: hard "@types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": - version: 7.0.14 - resolution: "@types/json-schema@npm:7.0.14" - checksum: 10/84b5efed51984c077f9cb7c5a3dcb8d8288ce1ae8825952b173c3506a0cfc90bc961d7f2a8847c440310d02bbd570cf918ac463d8310b0c9dce2252baa1ba4e0 + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 languageName: node linkType: hard @@ -13644,7 +13658,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.3.12, @types/semver@npm:^7.3.4, @types/semver@npm:^7.5.6, @types/semver@npm:^7.5.8": +"@types/semver@npm:^7.3.4, @types/semver@npm:^7.5.6, @types/semver@npm:^7.5.8": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" checksum: 10/3496808818ddb36deabfe4974fd343a78101fa242c4690044ccdc3b95dcf8785b494f5d628f2f47f38a702f8db9c53c67f47d7818f2be1b79f2efb09692e1178 @@ -13914,15 +13928,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.5.0" +"@typescript-eslint/eslint-plugin@npm:^8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.8.1" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.5.0" - "@typescript-eslint/type-utils": "npm:8.5.0" - "@typescript-eslint/utils": "npm:8.5.0" - "@typescript-eslint/visitor-keys": "npm:8.5.0" + "@typescript-eslint/scope-manager": "npm:8.8.1" + "@typescript-eslint/type-utils": "npm:8.8.1" + "@typescript-eslint/utils": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -13933,101 +13947,66 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/344f5aca7e167544af718b81269b87b8c2a041210882cac76e1608dbec7c2a646de74387920ca9a5704fcd4c24ada052c2bc5adbeee39e950e7bce83647dae7d + checksum: 10/6d45d7c3b2993f9d4130794596b029e72646f69581741ff2032b33f5c5d6b46c241b854556d04f769c2ef491e117c7d73013a07d74de3a0e0b557e648bc82a9c languageName: node linkType: hard -"@typescript-eslint/parser@npm:^8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/parser@npm:8.5.0" +"@typescript-eslint/parser@npm:^8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/parser@npm:8.8.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.5.0" - "@typescript-eslint/types": "npm:8.5.0" - "@typescript-eslint/typescript-estree": "npm:8.5.0" - "@typescript-eslint/visitor-keys": "npm:8.5.0" + "@typescript-eslint/scope-manager": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/typescript-estree": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/f0d5a11a8d4b42750c3e7a3a8f6874740c7bb006b6bf3037a2b1422ba8f4eb2ff2d46e673a9f54007b95d3e4302b7966677b2481da58b6307d0ceb962478ee95 + checksum: 10/f19e9be6e8d3e4b574d5f2b1d7e23e3594ea8d5f0b2bd2e59d2fd237bd0a379597f4b7ba466b7e290c5f3c7bce044107a73b20159c17dc54a4cc6b2ca9470b4b languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.60.0": - version: 5.60.0 - resolution: "@typescript-eslint/scope-manager@npm:5.60.0" +"@typescript-eslint/scope-manager@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/scope-manager@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:5.60.0" - "@typescript-eslint/visitor-keys": "npm:5.60.0" - checksum: 10/157daafbefdb4e773d2cfdcd65f57f56470fbf38dcdb41827785421c653ced9cc3c5615dbd058ab3f112ffc644ce75b3f6ed412e26dd7247b4fe37f48bd30ffb + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" + checksum: 10/ab86b533d0cadaa3f325404ae8cda2c1c8e0b820d7b2265ad376a233bb073aa89783a8d20c2effa77552426f38405edaa71e4aa6a2676613ae8dec0e1f1ba061 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/scope-manager@npm:8.5.0" +"@typescript-eslint/type-utils@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/type-utils@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:8.5.0" - "@typescript-eslint/visitor-keys": "npm:8.5.0" - checksum: 10/18f9958cdf196a0beede93535e564313d27dfd392a335952c785e46c32def55fdeae8c3c7d46f07c81c105ed2b48e9cd36a1fe5101fccd80e83c04cf1693dbed - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/type-utils@npm:8.5.0" - dependencies: - "@typescript-eslint/typescript-estree": "npm:8.5.0" - "@typescript-eslint/utils": "npm:8.5.0" + "@typescript-eslint/typescript-estree": "npm:8.8.1" + "@typescript-eslint/utils": "npm:8.8.1" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10/ed487c8b530a0a6ea292385c82b2d9d9d94b99768ddd93882899be3319ea6af09c1b9f1a07e0381beb6149bbbb1f66ae95a635279fad8946345fd2298bce3549 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.60.0": - version: 5.60.0 - resolution: "@typescript-eslint/types@npm:5.60.0" - checksum: 10/5a5d7961e7431f2e15597309de0679752726c7df7dfe70093664485ad3bcbe729249b96a4241c2b5a3fcc08541eeb4ece0e785cf295d85aeaee82c9c4626371d + checksum: 10/3aed62459e68a49f468004d966c914457db2288979234a9452043bff6d5ac7f2d46490fe13f4bb06fd91af085a50e6ac63b69eb66f9a27ee477f958af4738587 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/types@npm:8.5.0" - checksum: 10/5cc55411fbf3f46d1571fe6ad1ef88f937093629a58e2b7bafb389646dde8a4e29d938fd57309eb30ee3f20978b4bdc5f823b31d718e053ba4c54c637a6df4e4 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.60.0": - version: 5.60.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.60.0" - dependencies: - "@typescript-eslint/types": "npm:5.60.0" - "@typescript-eslint/visitor-keys": "npm:5.60.0" - debug: "npm:^4.3.4" - globby: "npm:^11.1.0" - is-glob: "npm:^4.0.3" - semver: "npm:^7.3.7" - tsutils: "npm:^3.21.0" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/78a3934a383874b8cf85292cd6328928b23983b65204fd855c61227deb6f4dcc196fdeef7c977670dc4070feb2d810df44a38da7409be5e31385c326f14b2378 +"@typescript-eslint/types@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/types@npm:8.8.1" + checksum: 10/5ac571810f24a266e1d46a8ce2a6665498fddf757a70eeeec959c993991f72d06a2bee7b848a6b27db958f7771034d8169a77117fd6ca7ed2c3166da9d27396b languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.5.0" +"@typescript-eslint/typescript-estree@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:8.5.0" - "@typescript-eslint/visitor-keys": "npm:8.5.0" + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -14037,59 +14016,31 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/69f21c49a158c394106e0d627f57451430cf32449a6c01118ee4afbb9f92f06be3aa87f3478ffc84d1062c3b21dca983e458f70f2cbe4fee1ad206f84ab97eb8 + checksum: 10/b569cd362c5f68cf0e1ca53a85bf78c989f10fe4b680423d47c6089bef7cb60b3ed10927232f57dd666e457e43259cec9415da54f2c7b2425062d7acd2e7c98e languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/utils@npm:8.5.0" +"@typescript-eslint/utils@npm:8.8.1, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.8.1 + resolution: "@typescript-eslint/utils@npm:8.8.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.5.0" - "@typescript-eslint/types": "npm:8.5.0" - "@typescript-eslint/typescript-estree": "npm:8.5.0" + "@typescript-eslint/scope-manager": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/typescript-estree": "npm:8.8.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10/f4727ebdee15082debe61a815eaad588f006a4f93d7fe94d065da563b4d3f91b7b7f795b5c77aa4cdebdf0936f83aa878089f22b8dbdbb738c557e8974129f54 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:^5.10.0": - version: 5.60.0 - resolution: "@typescript-eslint/utils@npm:5.60.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@types/json-schema": "npm:^7.0.9" - "@types/semver": "npm:^7.3.12" - "@typescript-eslint/scope-manager": "npm:5.60.0" - "@typescript-eslint/types": "npm:5.60.0" - "@typescript-eslint/typescript-estree": "npm:5.60.0" - eslint-scope: "npm:^5.1.1" - semver: "npm:^7.3.7" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10/41044f37ab049ded83f4d3baaf93986e9e7162d5bd9d055575004dce8e6a09697f9a93bbcd5385262c263c0c45cb9a47d4a5a4a9fee20b8283211d0d0b51c8a1 + checksum: 10/8ecd827af49d3c69ebe65283e5a4e6b44b48f24392319ed9336b8eec47e84fcbcc3e1b5f855ed6b782996cfc0cd289a0a14e40dd69234fd60eeee0a29047bde5 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.60.0": - version: 5.60.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.60.0" +"@typescript-eslint/visitor-keys@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:5.60.0" - eslint-visitor-keys: "npm:^3.3.0" - checksum: 10/5b8a5a47668b2d6f1368bb1a7c5a81d992e18a2011c59957a260e32d6a25eb14aff2d80848c6a3a1eb21d24e94875e11641bf8cc7de2f5f57cec11b03e12f391 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.5.0": - version: 8.5.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.5.0" - dependencies: - "@typescript-eslint/types": "npm:8.5.0" + "@typescript-eslint/types": "npm:8.8.1" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10/32cc9d8120531bb1b5da79d697ab80bbbf18e5630d74c8b6c0f835d7914be7833ed9e5b95fa05f6f7b724d928cd4208b4028a2cc9d767401434d88214614887b + checksum: 10/b5bfb4c9a98d3320639abcfd5aae52dd9c8af477743c5e324ceee1a9ea5f101e0ff7da3de08d3ef66e57854a86e155359bafff13f184493db9e0dffaf9e363c7 languageName: node linkType: hard @@ -14727,11 +14678,11 @@ __metadata: linkType: hard "acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.10.0, acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" + version: 8.12.1 + resolution: "acorn@npm:8.12.1" bin: acorn: bin/acorn - checksum: 10/b688e7e3c64d9bfb17b596e1b35e4da9d50553713b3b3630cf5690f2b023a84eac90c56851e6912b483fe60e8b4ea28b254c07e92f17ef83d72d78745a8352dd + checksum: 10/d08c2d122bba32d0861e0aa840b2ee25946c286d5dc5990abca991baf8cdbfbe199b05aacb221b979411a2fea36f83e26b5ac4f6b4e0ce49038c62316c1848f0 languageName: node linkType: hard @@ -15174,7 +15125,7 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.0.0, aria-query@npm:^5.3.0": +"aria-query@npm:^5.0.0": version: 5.3.0 resolution: "aria-query@npm:5.3.0" dependencies: @@ -15183,6 +15134,15 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:~5.1.3": + version: 5.1.3 + resolution: "aria-query@npm:5.1.3" + dependencies: + deep-equal: "npm:^2.0.5" + checksum: 10/e5da608a7c4954bfece2d879342b6c218b6b207e2d9e5af270b5e38ef8418f02d122afdc948b68e32649b849a38377785252059090d66fa8081da95d1609c0d2 + languageName: node + linkType: hard + "array-back@npm:^3.0.1, array-back@npm:^3.1.0": version: 3.1.0 resolution: "array-back@npm:3.1.0" @@ -15190,13 +15150,13 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "array-buffer-byte-length@npm:1.0.0" +"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: - call-bind: "npm:^1.0.2" - is-array-buffer: "npm:^3.0.1" - checksum: 10/044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 + call-bind: "npm:^1.0.5" + is-array-buffer: "npm:^3.0.4" + checksum: 10/53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e languageName: node linkType: hard @@ -15221,16 +15181,17 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" is-string: "npm:^1.0.7" - checksum: 10/856a8be5d118967665936ad33ff3b07adfc50b06753e596e91fb80c3da9b8c022e92e3cc6781156d6ad95db7109b9f603682c7df2d6a529ed01f7f6b39a4a360 + checksum: 10/290b206c9451f181fb2b1f79a3bf1c0b66bb259791290ffbada760c79b284eef6f5ae2aeb4bcff450ebc9690edd25732c4c73a3c2b340fcc0f4563aed83bf488 languageName: node linkType: hard @@ -15241,16 +15202,31 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" +"array.prototype.findlast@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.1" - checksum: 10/063cbab8eeac3aa01f3e980eecb9a8c5d87723032b49f7f814ecc6d75c33c03c17e3f43a458127a62e16303cab412f95d6ad9dc7e0ae6d9dc27a9bb76c24df7a + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/7dffcc665aa965718ad6de7e17ac50df0c5e38798c0a5bf9340cf24feb8594df6ec6f3fcbe714c1577728a1b18b5704b15669474b27bceeca91ef06ce2a23c31 + languageName: node + linkType: hard + +"array.prototype.findlastindex@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/7c5c821f357cd53ab6cc305de8086430dd8d7a2485db87b13f843e868055e9582b1fd338f02338f67fc3a1603ceaf9610dd2a470b0b506f9d18934780f95b246 languageName: node linkType: hard @@ -15266,7 +15242,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.flatmap@npm:^1.3.1, array.prototype.flatmap@npm:^1.3.2": +"array.prototype.flatmap@npm:^1.3.2": version: 1.3.2 resolution: "array.prototype.flatmap@npm:1.3.2" dependencies: @@ -15291,31 +15267,32 @@ __metadata: languageName: node linkType: hard -"array.prototype.tosorted@npm:^1.1.1": - version: 1.1.1 - resolution: "array.prototype.tosorted@npm:1.1.1" +"array.prototype.tosorted@npm:^1.1.4": + version: 1.1.4 + resolution: "array.prototype.tosorted@npm:1.1.4" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.1.3" - checksum: 10/23e86074d0dda9260aaa137ec45ae5a8196916ee3f256e41665381f120fdb5921bd84ad93eeba8d0234e5cd355093049585167ba2307fde340e5cee15b12415d + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.3" + es-errors: "npm:^1.3.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/874694e5d50e138894ff5b853e639c29b0aa42bbd355acda8e8e9cd337f1c80565f21edc15e8c727fa4c0877fd9d8783c575809e440cc4d2d19acaa048bf967d languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.2": - version: 1.0.2 - resolution: "arraybuffer.prototype.slice@npm:1.0.2" +"arraybuffer.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "arraybuffer.prototype.slice@npm:1.0.3" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" - is-array-buffer: "npm:^3.0.2" + array-buffer-byte-length: "npm:^1.0.1" + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.22.3" + es-errors: "npm:^1.2.1" + get-intrinsic: "npm:^1.2.3" + is-array-buffer: "npm:^3.0.4" is-shared-array-buffer: "npm:^1.0.2" - checksum: 10/c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3 + checksum: 10/0221f16c1e3ec7b67da870ee0e1f12b825b5f9189835392b59a22990f715827561a4f4cd5330dc7507de272d8df821be6cd4b0cb569babf5ea4be70e365a2f3d languageName: node linkType: hard @@ -15487,15 +15464,6 @@ __metadata: languageName: node linkType: hard -"asynciterator.prototype@npm:^1.0.0": - version: 1.0.0 - resolution: "asynciterator.prototype@npm:1.0.0" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10/e8ebfd9493ac651cf9b4165e9d64030b3da1d17181bb1963627b59e240cdaf021d9b59d44b827dc1dde4e22387ec04c2d0f8720cf58a1c282e34e40cc12721b3 - languageName: node - linkType: hard - "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -15542,10 +15510,12 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: 10/4d4d5e86ea0425696f40717882f66a570647b94ac8d273ddc7549a9b61e5da099e149bf431530ccbd776bd74e02039eb8b5edf426e3e2211ee61af16698a9064 +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10/6c9da3a66caddd83c875010a1ca8ef11eac02ba15fb592dc9418b2b5e7b77b645fa7729380a92d9835c2f05f2ca1b6251f39b993e0feb3f1517c74fa1af02cab languageName: node linkType: hard @@ -15563,10 +15533,10 @@ __metadata: languageName: node linkType: hard -"axe-core@npm:=4.7.0": - version: 4.7.0 - resolution: "axe-core@npm:4.7.0" - checksum: 10/615c0f7722c3c9fcf353dbd70b00e2ceae234d4c17cbc839dd85c01d16797c4e4da45f8d27c6118e9e6b033fb06efd196106e13651a1b2f3a10e0f11c7b2f660 +"axe-core@npm:^4.10.0": + version: 4.10.0 + resolution: "axe-core@npm:4.10.0" + checksum: 10/6158489a7a704edc98bd30ed56243b8280c5203c60e095a2feb5bff95d9bf2ef10becfe359b1cbc8601338418999c26cf4eee704181dedbcb487f4d63a06d8d5 languageName: node linkType: hard @@ -15611,12 +15581,10 @@ __metadata: languageName: node linkType: hard -"axobject-query@npm:^3.2.1": - version: 3.2.1 - resolution: "axobject-query@npm:3.2.1" - dependencies: - dequal: "npm:^2.0.3" - checksum: 10/675af2548ed4ece75ad6d50cc0473cfdec7579eac77ec9861e7088d03ffb171aa697b70d2877423bee2ce16460ef62c698c6442a105612cc015719e8ea06b0bd +"axobject-query@npm:^4.1.0": + version: 4.1.0 + resolution: "axobject-query@npm:4.1.0" + checksum: 10/e275dea9b673f71170d914f2d2a18be5d57d8d29717b629e7fedd907dcc2ebdc7a37803ff975874810bd423f222f299c020d28fde40a146f537448bf6bfecb6e languageName: node linkType: hard @@ -16975,7 +16943,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5, call-bind@npm:^1.0.7": +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": version: 1.0.7 resolution: "call-bind@npm:1.0.7" dependencies: @@ -19418,6 +19386,39 @@ __metadata: languageName: node linkType: hard +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10/5919a39a18ee919573336158fd162fdf8ada1bc23a139f28543fd45fac48e0ea4a3ad3bfde91de124d4106e65c4a7525f6a84c20ba0797ec890a77a96d13a82a + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10/f33c65e58d8d0432ad79761f2e8a579818d724b5dc6dc4e700489b762d963ab30873c0f1c37d8f2ed12ef51c706d1195f64422856d25f067457aeec50cc40aac + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10/96f34f151bf02affb7b9f98762fb7aca1dd5f4553cb57b80bce750ca609c15d33ca659568ef1d422f7e35680736cbccb893a3d4b012760c758c1446bbdc4c6db + languageName: node + linkType: hard + "dataloader@npm:^1.4.0": version: 1.4.0 resolution: "dataloader@npm:1.4.0" @@ -19617,6 +19618,32 @@ __metadata: languageName: node linkType: hard +"deep-equal@npm:^2.0.5": + version: 2.2.3 + resolution: "deep-equal@npm:2.2.3" + dependencies: + array-buffer-byte-length: "npm:^1.0.0" + call-bind: "npm:^1.0.5" + es-get-iterator: "npm:^1.1.3" + get-intrinsic: "npm:^1.2.2" + is-arguments: "npm:^1.1.1" + is-array-buffer: "npm:^3.0.2" + is-date-object: "npm:^1.0.5" + is-regex: "npm:^1.1.4" + is-shared-array-buffer: "npm:^1.0.2" + isarray: "npm:^2.0.5" + object-is: "npm:^1.1.5" + object-keys: "npm:^1.1.1" + object.assign: "npm:^4.1.4" + regexp.prototype.flags: "npm:^1.5.1" + side-channel: "npm:^1.0.4" + which-boxed-primitive: "npm:^1.0.2" + which-collection: "npm:^1.0.1" + which-typed-array: "npm:^1.1.13" + checksum: 10/1ce49d0b71d0f14d8ef991a742665eccd488dfc9b3cada069d4d7a86291e591c92d2589c832811dea182b4015736b210acaaebce6184be356c1060d176f5a05f + languageName: node + linkType: hard + "deep-equal@npm:~1.0.1": version: 1.0.1 resolution: "deep-equal@npm:1.0.1" @@ -20844,50 +20871,57 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.2, es-abstract@npm:^1.20.1, es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.19.2, es-abstract@npm:^1.20.1, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - arraybuffer.prototype.slice: "npm:^1.0.2" - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.5" - es-set-tostringtag: "npm:^2.0.1" + array-buffer-byte-length: "npm:^1.0.1" + arraybuffer.prototype.slice: "npm:^1.0.3" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" + data-view-buffer: "npm:^1.0.1" + data-view-byte-length: "npm:^1.0.1" + data-view-byte-offset: "npm:^1.0.0" + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + es-set-tostringtag: "npm:^2.0.3" es-to-primitive: "npm:^1.2.1" function.prototype.name: "npm:^1.1.6" - get-intrinsic: "npm:^1.2.2" - get-symbol-description: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" + get-symbol-description: "npm:^1.0.2" globalthis: "npm:^1.0.3" gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.0" - has-proto: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.0.3" has-symbols: "npm:^1.0.3" - hasown: "npm:^2.0.0" - internal-slot: "npm:^1.0.5" - is-array-buffer: "npm:^3.0.2" + hasown: "npm:^2.0.2" + internal-slot: "npm:^1.0.7" + is-array-buffer: "npm:^3.0.4" is-callable: "npm:^1.2.7" - is-negative-zero: "npm:^2.0.2" + is-data-view: "npm:^1.0.1" + is-negative-zero: "npm:^2.0.3" is-regex: "npm:^1.1.4" - is-shared-array-buffer: "npm:^1.0.2" + is-shared-array-buffer: "npm:^1.0.3" is-string: "npm:^1.0.7" - is-typed-array: "npm:^1.1.12" + is-typed-array: "npm:^1.1.13" is-weakref: "npm:^1.0.2" object-inspect: "npm:^1.13.1" object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.4" - regexp.prototype.flags: "npm:^1.5.1" - safe-array-concat: "npm:^1.0.1" - safe-regex-test: "npm:^1.0.0" - string.prototype.trim: "npm:^1.2.8" - string.prototype.trimend: "npm:^1.0.7" - string.prototype.trimstart: "npm:^1.0.7" - typed-array-buffer: "npm:^1.0.0" - typed-array-byte-length: "npm:^1.0.0" - typed-array-byte-offset: "npm:^1.0.0" - typed-array-length: "npm:^1.0.4" + object.assign: "npm:^4.1.5" + regexp.prototype.flags: "npm:^1.5.2" + safe-array-concat: "npm:^1.1.2" + safe-regex-test: "npm:^1.0.3" + string.prototype.trim: "npm:^1.2.9" + string.prototype.trimend: "npm:^1.0.8" + string.prototype.trimstart: "npm:^1.0.8" + typed-array-buffer: "npm:^1.0.2" + typed-array-byte-length: "npm:^1.0.1" + typed-array-byte-offset: "npm:^1.0.2" + typed-array-length: "npm:^1.0.6" unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.13" - checksum: 10/e1ea9738ece15f810733b7bd71d825b555e01bb8c860272560d7d901467a9db1265214d6cf44f3beeb5d73ae421a609b9ad93a39aa47bbcd8cde510d5e0aa875 + which-typed-array: "npm:^1.1.15" + checksum: 10/2da795a6a1ac5fc2c452799a409acc2e3692e06dc6440440b076908617188899caa562154d77263e3053bcd9389a07baa978ab10ac3b46acc399bd0c77be04cb languageName: node linkType: hard @@ -20907,32 +20941,49 @@ __metadata: languageName: node linkType: hard -"es-errors@npm:^1.3.0": +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": version: 1.3.0 resolution: "es-errors@npm:1.3.0" checksum: 10/96e65d640156f91b707517e8cdc454dd7d47c32833aa3e85d79f24f9eb7ea85f39b63e36216ef0114996581969b59fe609a94e30316b08f5f4df1d44134cf8d5 languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.12, es-iterator-helpers@npm:^1.0.15": - version: 1.0.15 - resolution: "es-iterator-helpers@npm:1.0.15" +"es-get-iterator@npm:^1.1.3": + version: 1.1.3 + resolution: "es-get-iterator@npm:1.1.3" dependencies: - asynciterator.prototype: "npm:^1.0.0" call-bind: "npm:^1.0.2" + get-intrinsic: "npm:^1.1.3" + has-symbols: "npm:^1.0.3" + is-arguments: "npm:^1.1.1" + is-map: "npm:^2.0.2" + is-set: "npm:^2.0.2" + is-string: "npm:^1.0.7" + isarray: "npm:^2.0.5" + stop-iteration-iterator: "npm:^1.0.0" + checksum: 10/bc2194befbe55725f9489098626479deee3c801eda7e83ce0dff2eb266a28dc808edb9b623ff01d31ebc1328f09d661333d86b601036692c2e3c1a6942319433 + languageName: node + linkType: hard + +"es-iterator-helpers@npm:^1.0.19": + version: 1.1.0 + resolution: "es-iterator-helpers@npm:1.1.0" + dependencies: + call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.22.1" - es-set-tostringtag: "npm:^2.0.1" - function-bind: "npm:^1.1.1" - get-intrinsic: "npm:^1.2.1" - globalthis: "npm:^1.0.3" - has-property-descriptors: "npm:^1.0.0" - has-proto: "npm:^1.0.1" + es-abstract: "npm:^1.23.3" + es-errors: "npm:^1.3.0" + es-set-tostringtag: "npm:^2.0.3" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.4" + globalthis: "npm:^1.0.4" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.0.3" has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.5" - iterator.prototype: "npm:^1.1.2" - safe-array-concat: "npm:^1.0.1" - checksum: 10/78535c00c49d81df603e650886d3806f3cd8d288e2c07703cfb145725753a3d2df19bff9feeb14cd1baed02252d1f85c4bbc922c8db02841722ab3ec02e78339 + internal-slot: "npm:^1.0.7" + iterator.prototype: "npm:^1.1.3" + safe-array-concat: "npm:^1.1.2" + checksum: 10/7aa8f17934abbebeb8cd3ba5135c1f107c568470f4c4b798f457f3d0039caaece1f9d7addbe1fc01079ea2f2ce8f922b736ee914c37ea99dbef22c86b006d338 languageName: node linkType: hard @@ -20943,18 +20994,27 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.2 - resolution: "es-set-tostringtag@npm:2.0.2" +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" dependencies: - get-intrinsic: "npm:^1.2.2" - has-tostringtag: "npm:^1.0.0" - hasown: "npm:^2.0.0" - checksum: 10/afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + es-errors: "npm:^1.3.0" + checksum: 10/f8910cf477e53c0615f685c5c96210591841850871b81924fcf256bfbaa68c254457d994a4308c60d15b20805e7f61ce6abc669375e01a5349391a8c1767584f + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.3": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: "npm:^1.2.4" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.1" + checksum: 10/7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0": +"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -21540,106 +21600,108 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" +"eslint-module-utils@npm:^2.12.0": + version: 2.12.0 + resolution: "eslint-module-utils@npm:2.12.0" dependencies: debug: "npm:^3.2.7" peerDependenciesMeta: eslint: optional: true - checksum: 10/a9a7ed93eb858092e3cdc797357d4ead2b3ea06959b0eada31ab13862d46a59eb064b9cb82302214232e547980ce33618c2992f6821138a4934e65710ed9cc29 + checksum: 10/dd27791147eca17366afcb83f47d6825b6ce164abb256681e5de4ec1d7e87d8605641eb869298a0dbc70665e2446dbcc2f40d3e1631a9475dd64dd23d4ca5dee languageName: node linkType: hard -"eslint-plugin-chai-friendly@npm:^0.7.4": - version: 0.7.4 - resolution: "eslint-plugin-chai-friendly@npm:0.7.4" +"eslint-plugin-chai-friendly@npm:^1.0.1": + version: 1.0.1 + resolution: "eslint-plugin-chai-friendly@npm:1.0.1" peerDependencies: eslint: ">=3.0.0" - checksum: 10/c7022be5f864dfc8a1a18494f0de357f245a37cf3f5ca0fec95b14bc3fb249e5ccfa01c3ab66a2203163b61272df495fa6b71b496467a49c131a35d1f8a0f9df + checksum: 10/459c0162b606d290bc6b10caa7bd7b67a3ce3d37d98ee1b9b91646842553d7282887858efd20cb6a6b8cbaa42746e83258244a32bce0e1d038ebe5559e747730 languageName: node linkType: hard -"eslint-plugin-cypress@npm:^2.15.1": - version: 2.15.1 - resolution: "eslint-plugin-cypress@npm:2.15.1" +"eslint-plugin-cypress@npm:^3.5.0": + version: 3.5.0 + resolution: "eslint-plugin-cypress@npm:3.5.0" dependencies: globals: "npm:^13.20.0" peerDependencies: - eslint: ">= 3.2.1" - checksum: 10/46344892f26e4f2c905a98e9d391bf1f930aa95e79f6678a1ca75ff466a6ca277fd51cde650fbcbc828068659acbad60601d239481402f443d177a1ef5934190 + eslint: ">=7" + checksum: 10/c7797902d76331e4b243f8c97c8ecde451e6959af6ec54c07faf54e095ad64e64a588dc3bb466cb172f63219ea07fd6efb2bcb6ae63a64dd9c067edbd222327e languageName: node linkType: hard -"eslint-plugin-import@npm:^2.29.1": - version: 2.29.1 - resolution: "eslint-plugin-import@npm:2.29.1" +"eslint-plugin-import@npm:^2.31.0": + version: 2.31.0 + resolution: "eslint-plugin-import@npm:2.31.0" dependencies: - array-includes: "npm:^3.1.7" - array.prototype.findlastindex: "npm:^1.2.3" + "@rtsao/scc": "npm:^1.1.0" + array-includes: "npm:^3.1.8" + array.prototype.findlastindex: "npm:^1.2.5" array.prototype.flat: "npm:^1.3.2" array.prototype.flatmap: "npm:^1.3.2" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.8.0" - hasown: "npm:^2.0.0" - is-core-module: "npm:^2.13.1" + eslint-module-utils: "npm:^2.12.0" + hasown: "npm:^2.0.2" + is-core-module: "npm:^2.15.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.7" - object.groupby: "npm:^1.0.1" - object.values: "npm:^1.1.7" + object.fromentries: "npm:^2.0.8" + object.groupby: "npm:^1.0.3" + object.values: "npm:^1.2.0" semver: "npm:^6.3.1" + string.prototype.trimend: "npm:^1.0.8" tsconfig-paths: "npm:^3.15.0" peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 10/5865f05c38552145423c535326ec9a7113ab2305c7614c8b896ff905cfabc859c8805cac21e979c9f6f742afa333e6f62f812eabf891a7e8f5f0b853a32593c1 + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + checksum: 10/6b76bd009ac2db0615d9019699d18e2a51a86cb8c1d0855a35fb1b418be23b40239e6debdc6e8c92c59f1468ed0ea8d7b85c817117a113d5cc225be8a02ad31c languageName: node linkType: hard -"eslint-plugin-jest@npm:^27.6.3": - version: 27.6.3 - resolution: "eslint-plugin-jest@npm:27.6.3" +"eslint-plugin-jest@npm:^28.8.3": + version: 28.8.3 + resolution: "eslint-plugin-jest@npm:28.8.3" dependencies: - "@typescript-eslint/utils": "npm:^5.10.0" + "@typescript-eslint/utils": "npm:^6.0.0 || ^7.0.0 || ^8.0.0" peerDependencies: - "@typescript-eslint/eslint-plugin": ^5.0.0 || ^6.0.0 - eslint: ^7.0.0 || ^8.0.0 + "@typescript-eslint/eslint-plugin": ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 jest: "*" peerDependenciesMeta: "@typescript-eslint/eslint-plugin": optional: true jest: optional: true - checksum: 10/a29319d5a090633e30658da7521f9fa0468f861403509538e0927175ab2a46a7f60bd7fd344b54f7fb5f8e8b6385d8db67c305502a4de1291f32191163e74725 + checksum: 10/3f1798c61e143981eefcfb2fbc4b2e5b329378ebaafdec6485f443c79ee0d3304e9409e8ea8ce089ac15abb4e700d8d838e0a1da29feb528d77a2b3cce6989ec languageName: node linkType: hard -"eslint-plugin-jsx-a11y@npm:^6.8.0": - version: 6.8.0 - resolution: "eslint-plugin-jsx-a11y@npm:6.8.0" +"eslint-plugin-jsx-a11y@npm:^6.10.0": + version: 6.10.0 + resolution: "eslint-plugin-jsx-a11y@npm:6.10.0" dependencies: - "@babel/runtime": "npm:^7.23.2" - aria-query: "npm:^5.3.0" - array-includes: "npm:^3.1.7" + aria-query: "npm:~5.1.3" + array-includes: "npm:^3.1.8" array.prototype.flatmap: "npm:^1.3.2" ast-types-flow: "npm:^0.0.8" - axe-core: "npm:=4.7.0" - axobject-query: "npm:^3.2.1" + axe-core: "npm:^4.10.0" + axobject-query: "npm:^4.1.0" damerau-levenshtein: "npm:^1.0.8" emoji-regex: "npm:^9.2.2" - es-iterator-helpers: "npm:^1.0.15" - hasown: "npm:^2.0.0" + es-iterator-helpers: "npm:^1.0.19" + hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^3.3.5" language-tags: "npm:^1.0.9" minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.7" - object.fromentries: "npm:^2.0.7" + object.fromentries: "npm:^2.0.8" + safe-regex-test: "npm:^1.0.3" + string.prototype.includes: "npm:^2.0.0" peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 10/7a8e4498531a43d988ce2f12502a3f5ce96eacfec13f956cf927f24bb041b724fb7fc0f0306ea19d143bfc79e138bf25e25acca0822847206ac6bf5ce095e846 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + checksum: 10/d66e5e541a5a747d8a7ffd6e45b79c9da416b42be5891c259f3d9af63ed8897b5ff67373b00682ecdfc04fe2a2bc9df9c23b2f1749a228221d2dae0914543303 languageName: node linkType: hard @@ -21679,42 +21741,44 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:^4.6.0": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" +"eslint-plugin-react-hooks@npm:^4.6.2": + version: 4.6.2 + resolution: "eslint-plugin-react-hooks@npm:4.6.2" peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 10/3c63134e056a6d98d66e2c475c81f904169db817e89316d14e36269919e31f4876a2588aa0e466ec8ef160465169c627fe823bfdaae7e213946584e4a165a3ac + checksum: 10/5a0680941f34e70cf505bcb6082df31a3e445d193ee95a88ff3483041eb944f4cefdaf7e81b0eb1feb4eeceee8c7c6ddb8a2a6e8c4c0388514a42e16ac7b7a69 languageName: node linkType: hard -"eslint-plugin-react@npm:^7.33.2": - version: 7.33.2 - resolution: "eslint-plugin-react@npm:7.33.2" +"eslint-plugin-react@npm:^7.37.1": + version: 7.37.1 + resolution: "eslint-plugin-react@npm:7.37.1" dependencies: - array-includes: "npm:^3.1.6" - array.prototype.flatmap: "npm:^1.3.1" - array.prototype.tosorted: "npm:^1.1.1" + array-includes: "npm:^3.1.8" + array.prototype.findlast: "npm:^1.2.5" + array.prototype.flatmap: "npm:^1.3.2" + array.prototype.tosorted: "npm:^1.1.4" doctrine: "npm:^2.1.0" - es-iterator-helpers: "npm:^1.0.12" + es-iterator-helpers: "npm:^1.0.19" estraverse: "npm:^5.3.0" + hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.6" - object.fromentries: "npm:^2.0.6" - object.hasown: "npm:^1.1.2" - object.values: "npm:^1.1.6" + object.entries: "npm:^1.1.8" + object.fromentries: "npm:^2.0.8" + object.values: "npm:^1.2.0" prop-types: "npm:^15.8.1" - resolve: "npm:^2.0.0-next.4" + resolve: "npm:^2.0.0-next.5" semver: "npm:^6.3.1" - string.prototype.matchall: "npm:^4.0.8" + string.prototype.matchall: "npm:^4.0.11" + string.prototype.repeat: "npm:^1.0.0" peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 10/cb8c5dd5859cace330e24b7d74b9c652c0d93ef1d87957261fe1ac2975c27c918d0d5dc607f25aba4972ce74d04456f4f93883a16ac10cd598680d047fc3495d + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + checksum: 10/a7b9cf2c43255844ad0c9d4e3758a8c2b687a2ce9a09f4161ab245581d5d2d91b37742e541c88aa9ce368ec6c860e23dc78c15117f3fc1cdc433847038e8346b languageName: node linkType: hard -"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1": +"eslint-scope@npm:5.1.1": version: 5.1.1 resolution: "eslint-scope@npm:5.1.1" dependencies: @@ -21741,15 +21805,15 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.56.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" +"eslint@npm:^8.57.1": + version: 8.57.1 + resolution: "eslint@npm:8.57.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.56.0" - "@humanwhocodes/config-array": "npm:^0.11.13" + "@eslint/js": "npm:8.57.1" + "@humanwhocodes/config-array": "npm:^0.13.0" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" "@ungap/structured-clone": "npm:^1.2.0" @@ -21785,7 +21849,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 10/ef6193c6e4cef20774b985a5cc2fd4bf6d3c4decd423117cbc4a0196617861745db291217ad3c537bc3a160650cca965bc818f55e1f3e446af1fcb293f9940a5 + checksum: 10/5504fa24879afdd9f9929b2fbfc2ee9b9441a3d464efd9790fbda5f05738858530182029f13323add68d19fec749d3ab4a70320ded091ca4432b1e9cc4ed104c languageName: node linkType: hard @@ -21840,11 +21904,11 @@ __metadata: linkType: hard "esquery@npm:^1.4.2": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" + version: 1.6.0 + resolution: "esquery@npm:1.6.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10/e65fcdfc1e0ff5effbf50fb4f31ea20143ae5df92bb2e4953653d8d40aa4bc148e0d06117a592ce4ea53eeab1dafdfded7ea7e22a5be87e82d73757329a1b01d + checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a languageName: node linkType: hard @@ -23957,7 +24021,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.4": +"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" dependencies: @@ -24065,13 +24129,14 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" +"get-symbol-description@npm:^1.0.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.1.1" - checksum: 10/7e5f298afe0f0872747dce4a949ce490ebc5d6dd6aefbbe5044543711c9b19a4dfaebdbc627aee99e1299d58a435b2fbfa083458c1d58be6dc03a3bada24d359 + call-bind: "npm:^1.0.5" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.4" + checksum: 10/e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 languageName: node linkType: hard @@ -24385,20 +24450,21 @@ __metadata: linkType: hard "globals@npm:^13.19.0, globals@npm:^13.20.0": - version: 13.23.0 - resolution: "globals@npm:13.23.0" + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: "npm:^0.20.2" - checksum: 10/bf6a8616f4a64959c0b9a8eb4dc8a02e7dd0082385f7f06bc9694d9fceabe39f83f83789322cfe0470914dc8b273b7a29af5570b9e1a0507d3fb7348a64703a3 + checksum: 10/62c5b1997d06674fc7191d3e01e324d3eda4d65ac9cc4e78329fa3b5c4fd42a0e1c8722822497a6964eee075255ce21ccf1eec2d83f92ef3f06653af4d0ee28e languageName: node linkType: hard -"globalthis@npm:^1.0.1, globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" +"globalthis@npm:^1.0.1, globalthis@npm:^1.0.3, globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: "npm:^1.1.3" - checksum: 10/45ae2f3b40a186600d0368f2a880ae257e8278b4c7704f0417d6024105ad7f7a393661c5c2fa1334669cd485ea44bc883a08fdd4516df2428aec40c99f52aa89 + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 10/1f1fd078fb2f7296306ef9dd51019491044ccf17a59ed49d375b576ca108ff37e47f3d29aead7add40763574a992f16a5367dd1e2173b8634ef18556ab719ac4 languageName: node linkType: hard @@ -24705,10 +24771,10 @@ __metadata: languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: 10/eab2ab0ed1eae6d058b9bbc4c1d99d2751b29717be80d02fd03ead8b62675488de0c7359bc1fdd4b87ef6fd11e796a9631ad4d7452d9324fdada70158c2e5be7 +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: 10/0b67c2c94e3bea37db3e412e3c41f79d59259875e636ba471e94c009cdfb1fa82bf045deeffafc7dbb9c148e36cae6b467055aaa5d9fad4316e11b41e3ba551a languageName: node linkType: hard @@ -24719,12 +24785,12 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" dependencies: - has-symbols: "npm:^1.0.2" - checksum: 10/95546e7132efc895a9ae64a8a7cf52588601fc3d52e0304ed228f336992cdf0baaba6f3519d2655e560467db35a1ed79f6420c286cc91a13aa0647a31ed92570 + has-symbols: "npm:^1.0.3" + checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe languageName: node linkType: hard @@ -24776,12 +24842,12 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: function-bind: "npm:^1.1.2" - checksum: 10/c330f8d93f9d23fe632c719d4db3d698ef7d7c367d51548b836069e06a90fa9151e868c8e67353cfe98d67865bf7354855db28fa36eb1b18fa5d4a3f4e7f1c90 + checksum: 10/7898a9c1788b2862cf0f9c345a6bec77ba4a0c0983c7f19d610c382343d4f98fa260686b225dfb1f88393a66679d2ec58ee310c1d6868c081eda7918f32cc70a languageName: node linkType: hard @@ -25880,14 +25946,14 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.3, internal-slot@npm:^1.0.5": - version: 1.0.6 - resolution: "internal-slot@npm:1.0.6" +"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" dependencies: - get-intrinsic: "npm:^1.2.2" + es-errors: "npm:^1.3.0" hasown: "npm:^2.0.0" side-channel: "npm:^1.0.4" - checksum: 10/bc2022eb1f277f2fcb2a60e7ced451c7ffc7a769b12e63c7a3fb247af8b5a1bed06428ce724046a8bca39ed6eb5b6832501a42f2e9a5ec4a9a7dc4e634431616 + checksum: 10/3e66720508831153ecf37d13def9f6856f9f2960989ec8a0a0476c98f887fca9eff0163127466485cb825c900c2d6fc601aa9117b7783b90ffce23a71ea5d053 languageName: node linkType: hard @@ -26048,7 +26114,7 @@ __metadata: languageName: node linkType: hard -"is-arguments@npm:^1.0.4": +"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1": version: 1.1.1 resolution: "is-arguments@npm:1.1.1" dependencies: @@ -26058,14 +26124,13 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": - version: 3.0.2 - resolution: "is-array-buffer@npm:3.0.2" +"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" dependencies: call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.0" - is-typed-array: "npm:^1.1.10" - checksum: 10/dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 + get-intrinsic: "npm:^1.2.1" + checksum: 10/34a26213d981d58b30724ef37a1e0682f4040d580fa9ff58fdfdd3cefcb2287921718c63971c1c404951e7b747c50fdc7caf6e867e951353fa71b369c04c969b languageName: node linkType: hard @@ -26161,12 +26226,21 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.12.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.9.0": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" +"is-core-module@npm:^2.12.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1": + version: 2.15.1 + resolution: "is-core-module@npm:2.15.1" dependencies: - hasown: "npm:^2.0.0" - checksum: 10/d53bd0cc24b0a0351fb4b206ee3908f71b9bbf1c47e9c9e14e5f06d292af1663704d2abd7e67700d6487b2b7864e0d0f6f10a1edf1892864bdffcb197d1845a2 + hasown: "npm:^2.0.2" + checksum: 10/77316d5891d5743854bcef2cd2f24c5458fb69fbc9705c12ca17d54a2017a67d0693bbf1ba8c77af376c0eef6bf6d1b27a4ab08e4db4e69914c3789bdf2ceec5 + languageName: node + linkType: hard + +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: "npm:^1.1.13" + checksum: 10/4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 languageName: node linkType: hard @@ -26389,10 +26463,10 @@ __metadata: languageName: node linkType: hard -"is-map@npm:^2.0.1": - version: 2.0.2 - resolution: "is-map@npm:2.0.2" - checksum: 10/60ba910f835f2eacb1fdf5b5a6c60fe1c702d012a7673e6546992bcc0c873f62ada6e13d327f9e48f1720d49c152d6cdecae1fa47a261ef3d247c3ce6f0e1d39 +"is-map@npm:^2.0.1, is-map@npm:^2.0.2": + version: 2.0.3 + resolution: "is-map@npm:2.0.3" + checksum: 10/8de7b41715b08bcb0e5edb0fb9384b80d2d5bcd10e142188f33247d19ff078abaf8e9b6f858e2302d8d05376a26a55cd23a3c9f8ab93292b02fcd2cc9e4e92bb languageName: node linkType: hard @@ -26406,10 +26480,10 @@ __metadata: languageName: node linkType: hard -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: 10/edbec1a9e6454d68bf595a114c3a72343d2d0be7761d8173dae46c0b73d05bb8fe9398c85d121e7794a66467d2f40b4a610b0be84cd804262d234fc634c86131 +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: 10/8fe5cffd8d4fb2ec7b49d657e1691889778d037494c6f40f4d1a524cadd658b4b53ad7b6b73a59bcb4b143ae9a3d15829af864b2c0f9d65ac1e678c4c80f17e5 languageName: node linkType: hard @@ -26548,19 +26622,19 @@ __metadata: languageName: node linkType: hard -"is-set@npm:^2.0.1": - version: 2.0.2 - resolution: "is-set@npm:2.0.2" - checksum: 10/d89e82acdc7760993474f529e043f9c4a1d63ed4774d21cc2e331d0e401e5c91c27743cd7c889137028f6a742234759a4bd602368fbdbf0b0321994aefd5603f +"is-set@npm:^2.0.1, is-set@npm:^2.0.2": + version: 2.0.3 + resolution: "is-set@npm:2.0.3" + checksum: 10/5685df33f0a4a6098a98c72d94d67cad81b2bc72f1fb2091f3d9283c4a1c582123cd709145b02a9745f0ce6b41e3e43f1c944496d1d74d4ea43358be61308669 languageName: node linkType: hard -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: - call-bind: "npm:^1.0.2" - checksum: 10/23d82259d6cd6dbb7c4ff3e4efeff0c30dbc6b7f88698498c17f9821cb3278d17d2b6303a5341cbd638ab925a28f3f086a6c79b3df70ac986cc526c725d43b4f + call-bind: "npm:^1.0.7" + checksum: 10/bc5402900dc62b96ebb2548bf5b0a0bcfacc2db122236fe3ab3b3e3c884293a0d5eb777e73f059bcbf8dc8563bb65eae972fee0fb97e38a9ae27c8678f62bcfe languageName: node linkType: hard @@ -26612,12 +26686,12 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": - version: 1.1.12 - resolution: "is-typed-array@npm:1.1.12" +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.3": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" dependencies: - which-typed-array: "npm:^1.1.11" - checksum: 10/d953adfd3c41618d5e01b2a10f21817e4cdc9572772fa17211100aebb3811b6e3c2e308a0558cc87d218a30504cb90154b833013437776551bfb70606fb088ca + which-typed-array: "npm:^1.1.14" + checksum: 10/f850ba08286358b9a11aee6d93d371a45e3c59b5953549ee1c1a9a55ba5c1dd1bd9952488ae194ad8f32a9cf5e79c8fa5f0cc4d78c00720aa0bbcf238b38062d languageName: node linkType: hard @@ -26858,16 +26932,16 @@ __metadata: languageName: node linkType: hard -"iterator.prototype@npm:^1.1.2": - version: 1.1.2 - resolution: "iterator.prototype@npm:1.1.2" +"iterator.prototype@npm:^1.1.3": + version: 1.1.3 + resolution: "iterator.prototype@npm:1.1.3" dependencies: define-properties: "npm:^1.2.1" get-intrinsic: "npm:^1.2.1" has-symbols: "npm:^1.0.3" reflect.getprototypeof: "npm:^1.0.4" set-function-name: "npm:^2.0.1" - checksum: 10/b5013967ad8f28c9ca1be8e159eb10f591b8e46deae87476fe39d668c04374fe9158c815e8b6d2f45885b0a3fd842a8ba13f497ec762b3a0eff49bec278670b1 + checksum: 10/1a2a508d3baac121b76c834404ff552d1bb96a173b1d74ff947b2c5763840c0b1e5be01be7e2183a19b08e99e38729812668ff1f23b35f6655a366017bc32519 languageName: node linkType: hard @@ -32948,7 +33022,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -32960,25 +33034,26 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.6, object.entries@npm:^1.1.7": - version: 1.1.7 - resolution: "object.entries@npm:1.1.7" +"object.entries@npm:^1.1.8": + version: 1.1.8 + resolution: "object.entries@npm:1.1.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/03f0bd0f23a8626c94429d15abf26ccda7723f08cd26be2c09c72d436765f8c7468605b5476ca58d4a7cec1ec7eca5be496dbd938fd4236b77ed6d05a8680048 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/2301918fbd1ee697cf6ff7cd94f060c738c0a7d92b22fd24c7c250e9b593642c9707ad2c44d339303c1439c5967d8964251cdfc855f7f6ec55db2dd79e8dc2a7 languageName: node linkType: hard -"object.fromentries@npm:^2.0.6, object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" +"object.fromentries@npm:^2.0.8": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/1bfbe42a51f8d84e417d193fae78e4b8eebb134514cdd44406480f8e8a0e075071e0717635d8e3eccd50fec08c1d555fe505c38804cbac0808397187653edd59 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + checksum: 10/5b2e80f7af1778b885e3d06aeb335dcc86965e39464671adb7167ab06ac3b0f5dd2e637a90d8ebd7426d69c6f135a4753ba3dd7d0fe2a7030cf718dcb910fd92 languageName: node linkType: hard @@ -32994,36 +33069,25 @@ __metadata: languageName: node linkType: hard -"object.groupby@npm:^1.0.1": - version: 1.0.1 - resolution: "object.groupby@npm:1.0.1" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" - checksum: 10/b7123d91403f95d63978513b23a6079c30f503311f64035fafc863c291c787f287b58df3b21ef002ce1d0b820958c9009dd5a8ab696e0eca325639d345e41524 - languageName: node - linkType: hard - -"object.hasown@npm:^1.1.2": - version: 1.1.2 - resolution: "object.hasown@npm:1.1.2" +"object.groupby@npm:^1.0.3": + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 10/94031022a2ba6006c15c6f1e0c4f51a7fa5b36aee64800192335b979fcc8bd823b18c35cb1a728af68fdfdbbe6d765f77a3c5437306c031f63654b8a34b9e639 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + checksum: 10/44cb86dd2c660434be65f7585c54b62f0425b0c96b5c948d2756be253ef06737da7e68d7106e35506ce4a44d16aa85a413d11c5034eb7ce5579ec28752eb42d0 languageName: node linkType: hard -"object.values@npm:^1.1.6, object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" +"object.values@npm:^1.1.6, object.values@npm:^1.2.0": + version: 1.2.0 + resolution: "object.values@npm:1.2.0" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/20ab42c0bbf984405c80e060114b18cf5d629a40a132c7eac4fb79c5d06deb97496311c19297dcf9c61f45c2539cd4c7f7c5d6230e51db360ff297bbc9910162 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/db2e498019c354428c5dd30d02980d920ac365b155fce4dcf63eb9433f98ccf0f72624309e182ce7cc227c95e45d474e1d483418e60de2293dd23fa3ebe34903 languageName: node linkType: hard @@ -34206,6 +34270,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: 10/8ed3e96dfeea1c5880c1f4c9cb707e5fb26e8be22f14f82ef92df20fd2004e635c62ba47fbe8f2bb63bfd80dac1474be2fb39798da8c2feba2815435d1f749af + languageName: node + linkType: hard + "postcss-calc@npm:^9.0.1": version: 9.0.1 resolution: "postcss-calc@npm:9.0.1" @@ -36680,14 +36751,15 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.4.3, regexp.prototype.flags@npm:^1.5.1": - version: 1.5.1 - resolution: "regexp.prototype.flags@npm:1.5.1" +"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": + version: 1.5.3 + resolution: "regexp.prototype.flags@npm:1.5.3" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - set-function-name: "npm:^2.0.0" - checksum: 10/3fa5610b8e411bbc3a43ddfd13162f3a817beb43155fbd8caa24d4fd0ce2f431a8197541808772a5a06e5946cebfb68464c827827115bde0d11720a92fe2981a + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-errors: "npm:^1.3.0" + set-function-name: "npm:^2.0.2" + checksum: 10/fe17bc4eebbc72945aaf9dd059eb7784a5ca453a67cc4b5b3e399ab08452c9a05befd92063e2c52e7b24d9238c60031656af32dd57c555d1ba6330dbf8c23b43 languageName: node linkType: hard @@ -37184,16 +37256,16 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^2.0.0-next.4": - version: 2.0.0-next.4 - resolution: "resolve@npm:2.0.0-next.4" +"resolve@npm:^2.0.0-next.5": + version: 2.0.0-next.5 + resolution: "resolve@npm:2.0.0-next.5" dependencies: - is-core-module: "npm:^2.9.0" + is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/20d5293f5015aa0b65c488ee365f9dfc30b954b04f9074425a6fb738d78fa63825a82ba8574b7ee200af7ebd5e98c41786831d1d4c1612da3cd063980dfa06a3 + checksum: 10/2d6fd28699f901744368e6f2032b4268b4c7b9185fd8beb64f68c93ac6b22e52ae13560ceefc96241a665b985edf9ffd393ae26d2946a7d3a07b7007b7d51e79 languageName: node linkType: hard @@ -37226,16 +37298,16 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^2.0.0-next.4#optional!builtin": - version: 2.0.0-next.4 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#optional!builtin::version=2.0.0-next.4&hash=c3c19d" +"resolve@patch:resolve@npm%3A^2.0.0-next.5#optional!builtin": + version: 2.0.0-next.5 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d" dependencies: - is-core-module: "npm:^2.9.0" + is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/27bff19d8219385bb1e271066317e553cff18daa2a19db9598d94ae444417ef3f5aec19e86927872d6cb241d02649cfb35a4c0d9d10ef2afa6325bce8bc8d903 + checksum: 10/05fa778de9d0347c8b889eb7a18f1f06bf0f801b0eb4610b4871a4b2f22e220900cf0ad525e94f990bb8d8921c07754ab2122c0c225ab4cdcea98f36e64fa4c2 languageName: node linkType: hard @@ -37661,15 +37733,15 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.1": - version: 1.0.1 - resolution: "safe-array-concat@npm:1.0.1" +"safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.1" + call-bind: "npm:^1.0.7" + get-intrinsic: "npm:^1.2.4" has-symbols: "npm:^1.0.3" isarray: "npm:^2.0.5" - checksum: 10/44f073d85ca12458138e6eff103ac63cec619c8261b6579bd2fa3ae7b6516cf153f02596d68e40c5bbe322a29c930017800efff652734ddcb8c0f33b2a71f89c + checksum: 10/a54f8040d7cb696a1ee38d19cc71ab3cfb654b9b81bae00c6459618cfad8214ece7e6666592f9c925aafef43d0a20c5e6fbb3413a2b618e1ce9d516a2e6dcfc5 languageName: node linkType: hard @@ -37694,14 +37766,14 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-regex-test@npm:1.0.0" +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.1.3" + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" is-regex: "npm:^1.1.4" - checksum: 10/c7248dfa07891aa634c8b9c55da696e246f8589ca50e7fd14b22b154a106e83209ddf061baf2fa45ebfbd485b094dc7297325acfc50724de6afe7138451b42a9 + checksum: 10/b04de61114b10274d92e25b6de7ccb5de07f11ea15637ff636de4b5190c0f5cd8823fe586dde718504cf78055437d70fd8804976894df502fcf5a210c970afb3 languageName: node linkType: hard @@ -38067,14 +38139,15 @@ __metadata: languageName: node linkType: hard -"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" +"set-function-name@npm:^2.0.1, set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: "npm:^1.0.1" + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" functions-have-names: "npm:^1.2.3" - has-property-descriptors: "npm:^1.0.0" - checksum: 10/4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + has-property-descriptors: "npm:^1.0.2" + checksum: 10/c7614154a53ebf8c0428a6c40a3b0b47dac30587c1a19703d1b75f003803f73cdfa6a93474a9ba678fa565ef5fbddc2fae79bca03b7d22ab5fd5163dbe571a74 languageName: node linkType: hard @@ -38930,6 +39003,15 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.0.0": + version: 1.0.0 + resolution: "stop-iteration-iterator@npm:1.0.0" + dependencies: + internal-slot: "npm:^1.0.4" + checksum: 10/2a23a36f4f6bfa63f46ae2d53a3f80fe8276110b95a55345d8ed3d92125413494033bc8697eb774e8f7aeb5725f70e3d69753caa2ecacdac6258c16fa8aa8b0f + languageName: node + linkType: hard + "store2@npm:^2.14.2": version: 2.14.2 resolution: "store2@npm:2.14.2" @@ -39142,52 +39224,77 @@ __metadata: languageName: node linkType: hard -"string.prototype.matchall@npm:^4.0.8": - version: 4.0.8 - resolution: "string.prototype.matchall@npm:4.0.8" +"string.prototype.includes@npm:^2.0.0": + version: 2.0.0 + resolution: "string.prototype.includes@npm:2.0.0" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - get-intrinsic: "npm:^1.1.3" + define-properties: "npm:^1.1.3" + es-abstract: "npm:^1.17.5" + checksum: 10/34c1e71ac5cab469bef52a4f3d983d141ca61c43b9fe8859574c8829822aad0a61fce1dddfaf8a48ad7ac5032a1730c19f1fb2d09715f57025cd138b1ad4b0e4 + languageName: node + linkType: hard + +"string.prototype.matchall@npm:^4.0.11": + version: 4.0.11 + resolution: "string.prototype.matchall@npm:4.0.11" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" + gopd: "npm:^1.0.1" has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.3" - regexp.prototype.flags: "npm:^1.4.3" - side-channel: "npm:^1.0.4" - checksum: 10/9de2e9e33344002e08c03c13533d88d0c557d5a3d9214a4f2cc8d63349f7c35af895804dec08e43224cc4c0345651c678e14260c5933967fd97aad4640a7e485 + internal-slot: "npm:^1.0.7" + regexp.prototype.flags: "npm:^1.5.2" + set-function-name: "npm:^2.0.2" + side-channel: "npm:^1.0.6" + checksum: 10/a902ff4500f909f2a08e55cc5ab1ffbbc905f603b36837674370ee3921058edd0392147e15891910db62a2f31ace2adaf065eaa3bc6e9810bdbc8ca48e05a7b5 languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.repeat@npm:^1.0.0": + version: 1.0.0 + resolution: "string.prototype.repeat@npm:1.0.0" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/9301f6cb2b6c44f069adde1b50f4048915985170a20a1d64cf7cb2dc53c5cd6b9525b92431f1257f894f94892d6c4ae19b5aa7f577c3589e7e51772dffc9d5a4 + define-properties: "npm:^1.1.3" + es-abstract: "npm:^1.17.5" + checksum: 10/4b1bd91b75fa8fdf0541625184ebe80e445a465ce4253c19c3bccd633898005dadae0f74b85ae72662a53aafb8035bf48f8f5c0755aec09bc106a7f13959d05e languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/3f0d3397ab9bd95cd98ae2fe0943bd3e7b63d333c2ab88f1875cf2e7c958c75dc3355f6fe19ee7c8fca28de6f39f2475e955e103821feb41299a2764a7463ffa + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.0" + es-object-atoms: "npm:^1.0.0" + checksum: 10/b2170903de6a2fb5a49bb8850052144e04b67329d49f1343cdc6a87cb24fb4e4b8ad00d3e273a399b8a3d8c32c89775d93a8f43cb42fbff303f25382079fb58a languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/6e594d3a61b127d243b8be1312e9f78683abe452cfe0bcafa3e0dc62ad6f030ccfb64d87ed3086fb7cb540fda62442c164d237cc5cc4d53c6e3eb659c29a0aeb + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/c2e862ae724f95771da9ea17c27559d4eeced9208b9c20f69bbfcd1b9bc92375adf8af63a103194dba17c4cc4a5cb08842d929f415ff9d89c062d44689c8761b + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/160167dfbd68e6f7cb9f51a16074eebfce1571656fc31d40c3738ca9e30e35496f2c046fe57b6ad49f65f238a152be8c86fd9a2dd58682b5eba39dad995b3674 languageName: node linkType: hard @@ -40555,19 +40662,19 @@ __metadata: "@types/prettier": "npm:^3.0.0" "@types/semver": "npm:^7.5.6" "@types/tar": "npm:^6.1.11" - "@typescript-eslint/eslint-plugin": "npm:^8.5.0" - "@typescript-eslint/parser": "npm:^8.5.0" + "@typescript-eslint/eslint-plugin": "npm:^8.8.1" + "@typescript-eslint/parser": "npm:^8.8.1" babel-jest: "npm:29.7.0" depcheck: "npm:^1.4.7" - eslint: "npm:^8.56.0" - eslint-plugin-chai-friendly: "npm:^0.7.4" - eslint-plugin-cypress: "npm:^2.15.1" - eslint-plugin-import: "npm:^2.29.1" - eslint-plugin-jest: "npm:^27.6.3" - eslint-plugin-jsx-a11y: "npm:^6.8.0" + eslint: "npm:^8.57.1" + eslint-plugin-chai-friendly: "npm:^1.0.1" + eslint-plugin-cypress: "npm:^3.5.0" + eslint-plugin-import: "npm:^2.31.0" + eslint-plugin-jest: "npm:^28.8.3" + eslint-plugin-jsx-a11y: "npm:^6.10.0" eslint-plugin-local-rules: "npm:^3.0.2" - eslint-plugin-react: "npm:^7.33.2" - eslint-plugin-react-hooks: "npm:^4.6.0" + eslint-plugin-react: "npm:^7.37.1" + eslint-plugin-react-hooks: "npm:^4.6.2" jest: "npm:29.7.0" jest-environment-jsdom: "npm:29.7.0" jest-expo: "npm:^50.0.2" @@ -40790,7 +40897,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.13.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0": +"tslib@npm:^1.13.0, tslib@npm:^1.9.0": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb @@ -40804,17 +40911,6 @@ __metadata: languageName: node linkType: hard -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: "npm:^1.8.1" - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 10/ea036bec1dd024e309939ffd49fda7a351c0e87a1b8eb049570dd119d447250e2c56e0e6c00554e8205760e7417793fdebff752a46e573fbe07d4f375502a5b2 - languageName: node - linkType: hard - "tsx@npm:^4.16.3": version: 4.16.3 resolution: "tsx@npm:4.16.3" @@ -40924,50 +41020,55 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-buffer@npm:1.0.0" +"typed-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.1" - is-typed-array: "npm:^1.1.10" - checksum: 10/3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + is-typed-array: "npm:^1.1.13" + checksum: 10/02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b languageName: node linkType: hard -"typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" +"typed-array-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" dependencies: - call-bind: "npm:^1.0.2" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" - has-proto: "npm:^1.0.1" - is-typed-array: "npm:^1.1.10" - checksum: 10/6f376bf5d988f00f98ccee41fd551cafc389095a2a307c18fab30f29da7d1464fc3697139cf254cda98b4128bbcb114f4b557bbabdc6d9c2e5039c515b31decf + gopd: "npm:^1.0.1" + has-proto: "npm:^1.0.3" + is-typed-array: "npm:^1.1.13" + checksum: 10/e4a38329736fe6a73b52a09222d4a9e8de14caaa4ff6ad8e55217f6705b017d9815b7284c85065b3b8a7704e226ccff1372a72b78c2a5b6b71b7bf662308c903 languageName: node linkType: hard -"typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" +"typed-array-byte-offset@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" - has-proto: "npm:^1.0.1" - is-typed-array: "npm:^1.1.10" - checksum: 10/2d81747faae31ca79f6c597dc18e15ae3d5b7e97f7aaebce3b31f46feeb2a6c1d6c92b9a634d901c83731ffb7ec0b74d05c6ff56076f5ae39db0cd19b16a3f92 + gopd: "npm:^1.0.1" + has-proto: "npm:^1.0.3" + is-typed-array: "npm:^1.1.13" + checksum: 10/ac26d720ebb2aacbc45e231347c359e6649f52e0cfe0e76e62005912f8030d68e4cb7b725b1754e8fdd48e433cb68df5a8620a3e420ad1457d666e8b29bf9150 languageName: node linkType: hard -"typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: - call-bind: "npm:^1.0.2" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" - is-typed-array: "npm:^1.1.9" - checksum: 10/0444658acc110b233176cb0b7689dcb828b0cfa099ab1d377da430e8553b6fdcdce882360b7ffe9ae085b6330e1d39383d7b2c61574d6cd8eef651d3e4a87822 + gopd: "npm:^1.0.1" + has-proto: "npm:^1.0.3" + is-typed-array: "npm:^1.1.13" + possible-typed-array-names: "npm:^1.0.0" + checksum: 10/05e96cf4ff836743ebfc593d86133b8c30e83172cb5d16c56814d7bacfed57ce97e87ada9c4b2156d9aaa59f75cdef01c25bd9081c7826e0b869afbefc3e8c39 languageName: node linkType: hard @@ -43305,16 +43406,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": - version: 1.1.13 - resolution: "which-typed-array@npm:1.1.13" +"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.4" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.0" - checksum: 10/605e3e10b7118af904a0e79d0d50b95275102f06ec902734024989cd71354929f7acee50de43529d3baf5858e2e4eb32c75e6ebd226c888ad976d8140e4a3e71 + has-tostringtag: "npm:^1.0.2" + checksum: 10/c3b6a99beadc971baa53c3ee5b749f2b9bdfa3b3b9a70650dd8511a48b61d877288b498d424712e9991d16019633086bd8b5923369460d93463c5825fa36c448 languageName: node linkType: hard From d7c8594311840661c5cc75645af34d2064f75325 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Wed, 16 Oct 2024 11:54:28 +0200 Subject: [PATCH 185/624] feat(suite-native): debug prefilled send form address button --- suite-native/accounts/src/selectors.ts | 10 ++++++++ suite-native/module-send/package.json | 1 + .../src/components/AddressInput.tsx | 25 ++++++++++++++++--- suite-native/module-send/tsconfig.json | 1 + yarn.lock | 1 + 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/suite-native/accounts/src/selectors.ts b/suite-native/accounts/src/selectors.ts index ada96607a17..0689e2543d4 100644 --- a/suite-native/accounts/src/selectors.ts +++ b/suite-native/accounts/src/selectors.ts @@ -143,3 +143,13 @@ export const selectAccountListSections = memoizeWithArgs( // Some reasonable number of accounts that could be in app { size: 40 }, ); + +export const selectFirstUnusedAccountAddress = ( + state: NativeAccountsRootState, + accountKey: AccountKey, +) => { + const account = selectAccountByKey(state, accountKey); + if (!account) return null; + + return account.addresses?.unused[0]?.address ?? null; +}; diff --git a/suite-native/module-send/package.json b/suite-native/module-send/package.json index e8734368a0e..630648ce8fb 100644 --- a/suite-native/module-send/package.json +++ b/suite-native/module-send/package.json @@ -28,6 +28,7 @@ "@suite-native/alerts": "workspace:*", "@suite-native/analytics": "workspace:*", "@suite-native/atoms": "workspace:*", + "@suite-native/config": "workspace:*", "@suite-native/device": "workspace:*", "@suite-native/device-mutex": "workspace:*", "@suite-native/formatters": "workspace:*", diff --git a/suite-native/module-send/src/components/AddressInput.tsx b/suite-native/module-send/src/components/AddressInput.tsx index 1e49caa78a0..2393327f493 100644 --- a/suite-native/module-send/src/components/AddressInput.tsx +++ b/suite-native/module-send/src/components/AddressInput.tsx @@ -2,13 +2,15 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { formInputsMaxLength } from '@suite-common/validators'; -import { VStack, Text } from '@suite-native/atoms'; +import { VStack, Text, HStack, Button } from '@suite-native/atoms'; import { TextInputField, useFormContext } from '@suite-native/forms'; import { Translation } from '@suite-native/intl'; import { analytics, EventType } from '@suite-native/analytics'; import { isAddressValid } from '@suite-common/wallet-utils'; import { AccountKey } from '@suite-common/wallet-types'; import { AccountsRootState, selectAccountNetworkSymbol } from '@suite-common/wallet-core'; +import { NativeAccountsRootState, selectFirstUnusedAccountAddress } from '@suite-native/accounts'; +import { isDebugEnv } from '@suite-native/config'; import { QrCodeBottomSheetIcon } from './QrCodeBottomSheetIcon'; import { getOutputFieldName } from '../utils'; @@ -24,6 +26,9 @@ export const AddressInput = ({ index, accountKey }: AddressInputProps) => { const networkSymbol = useSelector((state: AccountsRootState) => selectAccountNetworkSymbol(state, accountKey), ); + const unusedAccountAddress = useSelector((state: NativeAccountsRootState) => + selectFirstUnusedAccountAddress(state, accountKey), + ); const handleScanAddressQRCode = (qrCodeData: string) => { setValue(addressFieldName, qrCodeData, { shouldValidate: true }); @@ -38,11 +43,23 @@ export const AddressInput = ({ index, accountKey }: AddressInputProps) => { } }; + // Debug helper to fill opened account address. + const fillSelfAddress = () => { + setValue(addressFieldName, unusedAccountAddress, { shouldValidate: true }); + }; + return ( - - - + + + + + {isDebugEnv() && ( + + )} + Date: Thu, 10 Oct 2024 13:07:46 +0200 Subject: [PATCH 186/624] fix(protobuf): repo path in build script --- packages/protobuf/scripts/protobuf-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protobuf/scripts/protobuf-build.sh b/packages/protobuf/scripts/protobuf-build.sh index c42ec9e3d88..bb0da18482a 100755 --- a/packages/protobuf/scripts/protobuf-build.sh +++ b/packages/protobuf/scripts/protobuf-build.sh @@ -11,7 +11,7 @@ get_abs_path() { SCRIPTS_PATH=$(get_abs_path "${BASH_SOURCE[0]}") REPO_BRANCH="main" -REPO_PATH=$(get_abs_path "../../../trezor-firmware-probuf-update/.") +REPO_PATH=$(get_abs_path "$SCRIPTS_PATH/../../../../.")/trezor-firmware-probuf-update if [[ $# -ne 0 && $# -ne 1 ]] then From 85465be2555996633dbd77bd79abaeed68cb10ac Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Fri, 18 Oct 2024 16:13:09 +0200 Subject: [PATCH 187/624] fix(product-components): add back legacy coin icons --- .../AssetShareIndicator/AssetShareIndicator.tsx | 2 ++ .../src/components/CoinLogo/CoinLogo.tsx | 4 ++-- .../product-components/src/components/CoinLogo/coins.ts | 9 ++++++++- packages/product-components/src/images/coins/eos.svg | 4 ++++ packages/product-components/src/images/coins/nem.svg | 7 +++++++ packages/product-components/src/images/coins/xlm.svg | 5 +++++ packages/product-components/src/images/coins/xtz.svg | 4 ++++ 7 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 packages/product-components/src/images/coins/eos.svg create mode 100644 packages/product-components/src/images/coins/nem.svg create mode 100644 packages/product-components/src/images/coins/xlm.svg create mode 100644 packages/product-components/src/images/coins/xtz.svg diff --git a/packages/product-components/src/components/AssetShareIndicator/AssetShareIndicator.tsx b/packages/product-components/src/components/AssetShareIndicator/AssetShareIndicator.tsx index cfdbe8b60b4..83d2984c9c8 100644 --- a/packages/product-components/src/components/AssetShareIndicator/AssetShareIndicator.tsx +++ b/packages/product-components/src/components/AssetShareIndicator/AssetShareIndicator.tsx @@ -4,6 +4,7 @@ import styled, { useTheme } from 'styled-components'; import { coinsColors } from '@trezor/theme'; import { CoinLogo, CoinLogoProps } from '../CoinLogo/CoinLogo'; import { motionEasing } from '@trezor/components'; +import { NetworkSymbol } from '@suite-common/wallet-config'; const Container = styled.div` position: relative; @@ -16,6 +17,7 @@ const Container = styled.div` `; export interface AssetShareIndicatorProps extends CoinLogoProps { + symbol: NetworkSymbol; percentageShare?: number; } diff --git a/packages/product-components/src/components/CoinLogo/CoinLogo.tsx b/packages/product-components/src/components/CoinLogo/CoinLogo.tsx index c53954a0e0d..33d59b114d3 100644 --- a/packages/product-components/src/components/CoinLogo/CoinLogo.tsx +++ b/packages/product-components/src/components/CoinLogo/CoinLogo.tsx @@ -1,11 +1,11 @@ import { ImgHTMLAttributes } from 'react'; import { ReactSVG } from 'react-svg'; import styled from 'styled-components'; -import { COINS } from './coins'; +import { COINS, LegacyNetworkSymbol } from './coins'; import { NetworkSymbol } from '@suite-common/wallet-config'; export interface CoinLogoProps extends ImgHTMLAttributes { - symbol: NetworkSymbol; + symbol: NetworkSymbol | LegacyNetworkSymbol; className?: string; size?: number; index?: number; diff --git a/packages/product-components/src/components/CoinLogo/coins.ts b/packages/product-components/src/components/CoinLogo/coins.ts index 4dd3f3620f8..bdfd08e8425 100644 --- a/packages/product-components/src/components/CoinLogo/coins.ts +++ b/packages/product-components/src/components/CoinLogo/coins.ts @@ -1,6 +1,9 @@ import { NetworkSymbol } from '@suite-common/wallet-config'; -export const COINS: Record = { +// These coins are not supported in Suite, but exist in Trezor Connect +export type LegacyNetworkSymbol = 'eos' | 'nem' | 'xlm' | 'xtz'; + +export const COINS: Record = { ada: require('../../images/coins/ada.svg'), bch: require('../../images/coins/bch.svg'), bnb: require('../../images/coins/bnb.svg'), @@ -10,11 +13,13 @@ export const COINS: Record = { dgb: require('../../images/coins/dgb.svg'), doge: require('../../images/coins/doge.svg'), dsol: require('../../images/coins/dsol.svg'), + eos: require('../../images/coins/eos.svg'), etc: require('../../images/coins/etc.svg'), eth: require('../../images/coins/eth.svg'), ltc: require('../../images/coins/ltc.svg'), op: require('../../images/coins/op.svg'), pol: require('../../images/coins/pol.svg'), + nem: require('../../images/coins/nem.svg'), nmc: require('../../images/coins/nmc.svg'), regtest: require('../../images/coins/btc_test.svg'), sol: require('../../images/coins/sol.svg'), @@ -24,6 +29,8 @@ export const COINS: Record = { tsep: require('../../images/coins/tsep.svg'), txrp: require('../../images/coins/txrp.svg'), vtc: require('../../images/coins/vtc.svg'), + xlm: require('../../images/coins/xlm.svg'), xrp: require('../../images/coins/xrp.svg'), + xtz: require('../../images/coins/xtz.svg'), zec: require('../../images/coins/zec.svg'), }; diff --git a/packages/product-components/src/images/coins/eos.svg b/packages/product-components/src/images/coins/eos.svg new file mode 100644 index 00000000000..5254a1d097a --- /dev/null +++ b/packages/product-components/src/images/coins/eos.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/product-components/src/images/coins/nem.svg b/packages/product-components/src/images/coins/nem.svg new file mode 100644 index 00000000000..8d7d2141974 --- /dev/null +++ b/packages/product-components/src/images/coins/nem.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/product-components/src/images/coins/xlm.svg b/packages/product-components/src/images/coins/xlm.svg new file mode 100644 index 00000000000..df1e03b3c32 --- /dev/null +++ b/packages/product-components/src/images/coins/xlm.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/product-components/src/images/coins/xtz.svg b/packages/product-components/src/images/coins/xtz.svg new file mode 100644 index 00000000000..571321f0ef2 --- /dev/null +++ b/packages/product-components/src/images/coins/xtz.svg @@ -0,0 +1,4 @@ + + + + From 2cea609b868ea7a27c935ecf80ee19945745690b Mon Sep 17 00:00:00 2001 From: yanas Date: Fri, 18 Oct 2024 13:30:55 +0200 Subject: [PATCH 188/624] refactor(suite-native): create new module for device settings --- suite-native/app/package.json | 1 + .../app/src/navigation/RootStackNavigator.tsx | 3 +- suite-native/app/tsconfig.json | 1 + suite-native/device/package.json | 3 - suite-native/device/src/assets/t1b1.png | Bin 206087 -> 204533 bytes suite-native/device/src/assets/t2t1.png | Bin 80125 -> 78090 bytes suite-native/device/src/assets/t3b1.png | Bin 788864 -> 223907 bytes suite-native/device/src/assets/t3t1.png | Bin 1294289 -> 548288 bytes .../device/src/components/DeviceImage.tsx | 53 ++++++++++++++++++ suite-native/device/src/index.ts | 2 +- suite-native/device/tsconfig.json | 7 --- suite-native/intl/src/en.ts | 44 +++++++-------- .../module-device-settings/package.json | 29 ++++++++++ .../src/components/DeviceFirmwareCard.tsx | 16 +++--- .../src/components/DeviceSettingsCard.tsx | 2 +- .../src/components/HowToUpdateBottomSheet.tsx | 12 ++-- .../module-device-settings/src/index.ts | 1 + .../src/screens/DeviceInfoModalScreen.tsx | 36 +++++------- .../module-device-settings/tsconfig.json | 22 ++++++++ tsconfig.json | 3 + yarn.lock | 25 ++++++++- 21 files changed, 186 insertions(+), 74 deletions(-) create mode 100644 suite-native/device/src/components/DeviceImage.tsx create mode 100644 suite-native/module-device-settings/package.json rename suite-native/{device => module-device-settings}/src/components/DeviceFirmwareCard.tsx (83%) rename suite-native/{device => module-device-settings}/src/components/DeviceSettingsCard.tsx (95%) rename suite-native/{device => module-device-settings}/src/components/HowToUpdateBottomSheet.tsx (74%) create mode 100644 suite-native/module-device-settings/src/index.ts rename suite-native/{device => module-device-settings}/src/screens/DeviceInfoModalScreen.tsx (76%) create mode 100644 suite-native/module-device-settings/tsconfig.json diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 128152f5126..659fb0416f8 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -63,6 +63,7 @@ "@suite-native/module-authorize-device": "workspace:*", "@suite-native/module-connect-popup": "workspace:*", "@suite-native/module-dev-utils": "workspace:*", + "@suite-native/module-device-settings": "workspace:*", "@suite-native/module-home": "workspace:*", "@suite-native/module-onboarding": "workspace:*", "@suite-native/module-receive": "workspace:*", diff --git a/suite-native/app/src/navigation/RootStackNavigator.tsx b/suite-native/app/src/navigation/RootStackNavigator.tsx index 63080800c50..afb1a4b04a3 100644 --- a/suite-native/app/src/navigation/RootStackNavigator.tsx +++ b/suite-native/app/src/navigation/RootStackNavigator.tsx @@ -2,6 +2,7 @@ import { useSelector } from 'react-redux'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; +import { useHandleDeviceConnection } from '@suite-native/device'; import { AccountDetailScreen, AccountSettingsScreen, @@ -19,7 +20,7 @@ import { OnboardingStackNavigator } from '@suite-native/module-onboarding'; import { ReceiveModalScreen } from '@suite-native/receive'; import { AuthorizeDeviceStackNavigator } from '@suite-native/module-authorize-device'; import { AddCoinAccountStackNavigator } from '@suite-native/module-add-accounts'; -import { DeviceInfoModalScreen, useHandleDeviceConnection } from '@suite-native/device'; +import { DeviceInfoModalScreen } from '@suite-native/module-device-settings'; import { SendStackNavigator } from '@suite-native/module-send'; import { CoinEnablingInitScreen } from '@suite-native/coin-enabling'; import { ConnectPopupScreen, useConnectPopupNavigation } from '@suite-native/module-connect-popup'; diff --git a/suite-native/app/tsconfig.json b/suite-native/app/tsconfig.json index 788629957a7..c594e090cde 100644 --- a/suite-native/app/tsconfig.json +++ b/suite-native/app/tsconfig.json @@ -53,6 +53,7 @@ { "path": "../module-authorize-device" }, { "path": "../module-connect-popup" }, { "path": "../module-dev-utils" }, + { "path": "../module-device-settings" }, { "path": "../module-home" }, { "path": "../module-onboarding" }, { "path": "../module-receive" }, diff --git a/suite-native/device/package.json b/suite-native/device/package.json index e4cee8a2bbc..d0395e91129 100644 --- a/suite-native/device/package.json +++ b/suite-native/device/package.json @@ -15,9 +15,7 @@ "@react-navigation/native": "6.1.18", "@reduxjs/toolkit": "1.9.5", "@sentry/react-native": "5.33.0", - "@suite-common/icons-deprecated": "workspace:*", "@suite-common/redux-utils": "workspace:*", - "@suite-common/suite-utils": "workspace:*", "@suite-common/wallet-core": "workspace:*", "@suite-common/wallet-utils": "workspace:*", "@suite-native/alerts": "workspace:*", @@ -32,7 +30,6 @@ "@suite-native/navigation": "workspace:*", "@suite-native/settings": "workspace:*", "@trezor/connect": "workspace:*", - "@trezor/device-utils": "workspace:*", "@trezor/styles": "workspace:*", "lottie-react-native": "6.7.2", "proxy-memoize": "2.0.2", diff --git a/suite-native/device/src/assets/t1b1.png b/suite-native/device/src/assets/t1b1.png index ff410a39728e32edb6f3fc778658613cc9e06ac4..84ff3e6798278d57acc8f217cdecee63caa29be9 100644 GIT binary patch literal 204533 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

EWoUMw)X@Fw&}DhVv_ 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 z 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 Ndg_8p_22$C{~yS>V7veT literal 206087 zcmd3N^6)MupQp(7(BV|@DLu_+lDIgyO)x*iSH z)e4{I9^2Ii?VBer1IWlYg#Ww9pPJr1yjmm=FxA&4s~zXtzWPDouJuBTjI2J5{?dt( z?E2mOr;oMFL&*0Co};Imp~#Dsv%dK690%VO6KD0j>R$~XiviePuvC~ac-@gQzV+at z)MqZSzZ~1|sI-25xh7XIuWRz$p(WD9k;=p2ZX_#Kw~SR@&Od3YI+b-GmD6-euja0> zsomqJbK1wD8>+s@qCtnkZm~30QAIxh^_$g2A}K&^+~tCQFqCLynELMf9scbn`VXf+ z{r~?J_eH-<^uJpr*1hvtvFi%M{>uVxXBi4c9QMqJ7KW^y*dlRr+q(`VoB;;Oi#Uv% z;q`4>oeqZLS7!Wxn7k}s$Pvr{?f@eE7|D`$2s>!s{F%J#3niS+_<`_CaH$UYlUz7t ztHxj5?-?l&U?^JBA^|D!@|P0!;yHzI_AtkY31Ea;O?S9!2V?rU}zg+ zxnKr=*@Xcj<{Hle_qQ<<8laB*&<22Lm70~6y;b}iTC}QLvg)#Gx1p-)l5>uL303c| zBX)Ky0$mBGy_bqbn~~W4*g&*h`1*EP5zxs(4i0$f6S_LAQuDweR05lPt5S1E2aH`phugyp-OuioqV`&4Z_FvUqs=H{)v5a1 zr(|HiGD98U8XC_)Qq<3?OVwW2y)bY{qu7kjdnu|~(FY+9Q z0iB_VE89)*DQo3v$->k`(i6^4h8m~!X(`SS-_WH}&8*b6Ba2JK;wnU*z=iYI@GMba)zN~+8@J21m6_u%BNOowV zxEXhCLC_cpqwbR(G!cp8N+aYR$(Hy1!O)cz%8I}WFIEi3Ungtb7{8aWJs#lz)le#e z8`&+aqB8)o} z8Mcw*UTA+7aW>*WJPw8vCJ1ZN#5H=2vjB}?d6v|7PTS?@X(ysNwfLN(i<}Vy|K+-v zvyeYv0Pf-^_J6M*qxzxHAo0zmxiedMVCj&b!!^>^A0dF&nDa4%(B%doXkTL2Vz+}= z&oiw--AXU(8py#62yuQE*lqR;5I_(szetPX6;^&0IOGSwL=NYM$B8Xm*mnW*9(-*L zdwZj^=w2+gGupqlIDVr89kKbyoz6yOrmWq{;isBGPXPgZaFNnbb31510+4vLr|~R; zImWYZmWjO>vf`KglW_+Qz~+~-!U2n_B-!Ubp_oYZ-K-047iWZhDUnAox$?s209zzm z)QXXXz7^=^ig6b4c^{3gKEj{k_Lp{{qHwf}ylT6;Mk6phECng&Jz8XsO{+iL51dfq z>^Ll7H@q0H#D|Xzo%c9gNP^beUFDzaTK$LM8YTZd);QERIq-S3;N{;ygJMKo@q(3< z(dAcRbF_{2Me2{q13>S|>5q4aI$&oc?cvhbbf{}2)U^ubf1wwpe!s zT)QO?C5n&C^=VBzHjPgebT#Oh+uah5tps9KTut0`RDGU#BdVG*<>+2Rc1?~UCnn2M zd8@L+Sw}Ma1#q$6_F(aR?=v*wWLB%?4N)fCVb zWHOA&Rh+<|jAYBci{a;DR*(?G5GU%K*vj2u9t@=y>QHZ`(n>0-(!TRCcdA~9W#j~y zsIIgc6F7#ho?wkS->5__RV}+yKecXEYwp%i0sBSn+NRa`hkG4OqjvF);K+S%Xe55W z6+}AdL<60K==4kfJ^@w#uUe%)<+2HI5CJX?&c0wY_}k@1+YP@@uKEU7V~~w#kJ(u< z@aXoWooto=6$`^78)tgMu_|9G?Db6W{u~AI-NVj{#n8rRm#L!yBo0dRnIn? zU5R(%o9;B{Z2V?HZvj&O<|rC#`p3j5NEP*G(|gz}fn2-91Q$?)-=wUR?pLRK%l0Ru z$5<@i$kTHqW2_NQ6d&aJV^$P&g{qi~=ST36oUjxNFn^!RqKrA^sB!W8M}9hH0(W}& zcBJpR)aH<|{^dh-I?jsbi5-G&Ky9<$TP-ebz?m5*TcveQ!%gu64}&^R6%BuMG$b8 z9oP<^E`S`Zzrnmc;M&Q(8{;k;FPO&sFg)nIY3|C;f@=fgk+(t+{w}B*mjtEJ8R|hZ zBqGWou-yWveSm>O@Ev>A(#=|wMCI}Jwt=SDZ9R~`@wiJXCDQw zVN-mRWQJ(63f%UH+>)`)C1&bNVIA9uBP${HiC?B2c`@?7BXsxn?9F5=R`=ARcl4_eg@M9!e1J zbg>oOe{y_c1;Sc^p}V!6_oaIRX2Py^TI-`M=5P#)*ICU3+6L{{zTdKhXo~r_Zy*G5 z>w<>eI(r(GH;VcF+E#ln%M!n3sW!ihT`p@os6XSIN0y;OY^p}>ao1c2 zF+aX<1`oGB^}{BHzOj(kDLwCpZ=RVLs-jKEu)oBsOSJbEN4Cndq$6a|GY1t0c|8k~ zEfJQS!go#lhN->fZh0{rKGDMBbi@x3&9bF`Ph2u~W{fll-_FA_>xnNG7|2`}fQs+P zVy8s)@-JeZh=mVlq{+CBDa(>=bbAht9$jj{$NV3_?KTWNwl^b!)JRx$ZB4|*xoy9LIjYTYOufm4#D`pk`_!wZGvrk4;2ium+NEx@MdX-F0tHZbq9^G zn4aBx`3@a&Vz6qcz2fagzbN+Z*;|S=8UURO#oi<&x;mcbF7A7|>UU?CjfuXU7TF{yTGX%hXKtZm;HRmSzo2eznel~b)#beohfXekDH8%G3 zl?L%~6P}r`o_FN?I*qkhiDIy@g#f7^9fOzLX28<(g^QoOi zyccuI=X@2;Ab)A#v@e`VoVv2OOWo`o_H;bjJDGewI>n_t&CSnFl8hf$J%$7*2X>E%gw4u!5a&4jZF>>n< z&6RC0JB%^Ry2Ur1C4Kh(#-EVySn!}sy%&lo4--@Q4rTb%Ze+Vjnd1T7=;Ufhk0VBB zWSVT{_Dmh;od^4Tn_v`AG%c#);^utO?frmXw|tBZdwE0Z6a8czSuDJ*%bN$Sv}qQ+ z*|at0*>Y2{$)9FG=4=Ha_RjhFQ7KoXjv|}9ZYrmk3!zHO%`lcu&&ih8thUZLr8X|w zD_=qIo8H8j5;DSaFhiDVV6w>x&}Yk>v~WXZ=HY5Imbii?j#gr}El8*l&C9Fm0V9c` zRr?P1kp!FsK3E{~Wa_tQ$SUg<{9#1(!*r)ijvQWh9P|ki552z@ccK{mLi$z=td~30 zp+2;QXHr`JNF0#FBGP*AgTl)r_(#8Ekw`%yY5F{U{gOFb-c`k@L`~8D-FhoWiPEKw zyT&Hh*2dU4(ACCWib^oMa+?AQ9Q}f%w7>80TB!K-2=&=MKQ2y&s1lK`4@>KZsK7)1EU6!G^u5^$q;in;CY73Fd!8G?wLAR^55H`KQW zi?&H3t?Uv$V2P(#;)bvcRWEe=QZv_JEi*<|8eqqLS3Fuk{?R+&!)5fN4?$XQLhKxWS(2WV+{Qq&0o$`2EOf4#9vN>`*a>h4&i5BSNliy7hjoW>yNd3P40Xjn& zo$Gji%~3T@Oa*?JNZVi1agEi|l2ptesiJRy4*xno&<;Z9uC5{%-Dh?oJ6IO^ zPPh&?qwdAB3{#Ab{fc4x9gdAqqc*+=el6K8X$p0@E2*JqHzO5?S>8HVR5 zh_uz_t3KVvzQ1s*JoWYi!q{)#^XaValUbKEwbL=sNg8p=`o&=Whb-|c031mGu5tob zaYm6lX2DV=m%nV91nrW}t{e0~BfAg}(+T}3xUZeGKzwR2eVeO9#) z%VVZ;It~lDMKL^i5GgqPCQDPFOK~dceJ;t>nY9IXtHP*71688kY#iz`_<{>1b#N2` zxJfx{7tM2HOxp48pTAt+(g!s^+#y5Q!?_ZQvlhRkz zNbdyu)lRv&8=`P=p>lja_2UxS1b`mxUG=)>=cqK&u*9Y}XcK)|a8ptL&R^HZ`U51< z3|J}YpQwh){eI08KYRKkqZ&#a%D}qYyyAb4g>cKoneXB)%!ZC4k#;~pL!MnjJbA}x;i&GILf$2ZBuGtvCUPs>lxr1 z%*ts1kk@%&;R$rO(PdKh9w>10@!(h>n@JxXTSdKWtByi`?yr}3D#a50eQT+s2e?Xj zqBj;Ub4$lBGE^cKG0Z&bpQIZ$>kf%!$?bw+y)s^HRMNAKaKA|Bf7?jrSK|=z0Hc^{ z+1Gp3f-V}nU$tZ+WQ|_ryF!S0n?kBbV^^|LKvg%W4nPXQqE@9r7b6a8`V@taRHlop zug)tPPA4Tykz0R)5uuy5@F*7_BiWgd1E;!a{f{yX>ODt6crY-Q$i0TUa1O@F|*@#^Rn#6e<84ys*lXUzaef-=N&t9q8Z07{< zSKj{dw~{O_H$ucV_kriz!d*#^5XRU5^YO&hF)nkuM`; z=in?YeDK#}Qhb^^Zp$6CZUuCu+Q{ZS9Q+RfrL#9;AYdT2%Fls*XY-)z3<0gX)z~U6 ztg^XWG_K9-=SMNKH+BD?6{XJMdwkeA&3Ut>hVTYai200J_qpSo_tpaT#b_gAT{>~O zPpmj$xzFs4v~Xo=7|A$U#DSL5{NhpZPk&6r{thYXUFr_~_3xp~%a z3eQiE-1vYtit^QOcrwWlBN1a(LVyY%7(KNrLI zf&xvS&CDIMxGKLwX#Fj$rIwXB*kIC7x-@2^Vahq%h?05b_3rPcz_iZ7S-Nnj7~`k& zYJq?uWvRsX6L{M%s@$#$xMKHGJ5iD=P>!fjU4x1<% z*?jxRS!+;7mp+$F-t{!&L1Lvg%RfVL+50q`y+bb!zoqX`vVY_I#vo3KNcBH5%(nQ* z(v8K55A_y3m=Ya*U@T%ZA2?RSH7)I;^~M`~;XzxUUn;_HDzJWbn_u81p^C68pH2nUv)^882 zV{N$T)zHPL`F4-jNQL3$6ot#jdg+YzI>SY$D}iu(_a$m!+S=o8(v>z%=o=ISU7|*Q zUl<8oSsl`Rtk*~bQ-PxTxXov0NDxU19R}}I?^rtp?Z5B~n;|(%y=Ri5d^>~NefJXT zUZ~dgWt#8y$9I4XuHy*RR7lWJ}7sZ7yC|S5hm?@Jnei}< z@utLs++f!iT2$d z;V))j5EE)(fl(E${u8chC1gQ6$EtX+-u_Ka;MTf2YU!>C=3hl(GJtBh_U;I1QP|G8 zCMdOO!a8T-cps?+y7 zn+!;(RmAA(HdS6tiAOVgSAU5TsQe`$OnGg6ih1X6XQN)xm9f^c5+imr#lKV2`cS}J zZYT4%q-c8XtxX>I1)_R4OhT7tR>#SF!Hi5N28`!Yb$Ju|&?fd?$3y-n;JfmEtlS;bzyOLqw}N9tu5`ba|UVSItw>8_KDBa z-uK##tg4-&vW`U2i{~A+Fl)va5lChx;I{b3wR3IJ4aj6iAiP<4;=^>6zZ65y7RQ07 zDge(bGMP#+8QnRtW&AW8Q|Rw_$;HA(!m0$64(e6uhX(Rh`(s4pU!{5{zvc6y$r6M} z@=l0T3;G-WJUAj|y;jw^ZkY#GJ)L(cvUf@*z3C;}#dD^n2@*H;_0vdc*$6!13~_iz zZQT!D!O^d1b@G zqj3|>3QJ}ljx|QQ=rDkM0A z3Jh1SQL2W-T_1I59k}SaytUjU*;}|*HpZyG&|&kcmrsVdx<^Dx@xvrmq2VDD>?_1L zPNkgOqN$p+YnCE1v3?lNPDFs7(3B>t^7dmcpXQg*vv+ydlrVu?ARz9hiREx~R~qQF zv4}wY{fRjAA5bQEd_JAiZX^9CH8?mhTte-^Bm`gHBkH~620`iaqjtAn!JjNY*u1iM zr=G-WnyiyTt=MV1K*3B75MFxj`?cd(cuE;@P--^B$bt>29#Lxj>MVO2fPKO{ezWtZ=G|Ha0acp*rl))n zuyBuB-oAvXMT)^VcCS|!3rYfNkz7Ce-u&Rh2GALszxk$Ha%Y4#nKA2E0b)1y@Hoqjr;T1Vuo=2XooDFp%2?wH< zG=JL|57W|9jY)#!gnvfFe+7-gezLnH+*ONx{>yo9S8rh=>gYr^*{J-;@Sa!ih;!rQ zmFcP~ra0JFW=(MTQ0|L1yzPBJ#?>V2n^<1|#8P!#=KDc!;^Ks)_&bNT{5pOw-Vlei zi81N)L;BG^fZF^zJa-e`;?MR0v|{e^DO>ZA=jnk>MZ*hKLU~= z>a<8GswZnys_xW#F~!c_osJZsZ|5wT+?1$m$r1u|^L=iLclUnsu7>vu&jcgEI-X(X zn7iAJ#;Z{!oxxg}U!xfWtK53YIL=dr=a@Y81g!}nVp?8;UZn3scsqI67$SCEhwVJJ zf9D}ie$tu%BCia+ZrsqFw1~@!vO*k`Py@xbs)ODxUpv>=zQTi|4_Eejp_Q};sX$T> z3w59av78~Av(KmR?vLFrxjcT%UfNsr)Pj_@11w5+*}kk@6Fz7 zUi|4dC)C&8E~fjHYad3J`$0eXI?!_~YMPBomT6_U%mLP;`tINox;gfaQQV+?4%%!Q zT@9IW7i(e)3E1R6W1y2soxu^_l{{`m1TFb!w45L7XUQJ^TS5{~^))a#6MT&%68C>d zAihmNgGk<13?xuT^$ZCWbp~>KS*FBfu5ctl@0=ECDKpDkO;+Q4|1oq>B%Y`0&Lzz= zOM-C<6MajeqEVboy+vY_w}`y!%QgrV{Q!c1%Ah3w0iy7XbuW3GF6E@njF|@mB9Hp4 zX06cL8sd?N9b?uSuYAuW;3+=yF2dxN>i)Rjpf*T6L`;t{W(EIxDXClROBu5C744!B zO7tUGPm_`NSxQf=-=)>7Qe!#5j&f(M7>jx7!mdT7PhV=3jG|aD+^kxmgXh80W}%jK zKO;04SYx6p9a?)K3#(PRzcT}ZbYPwZT(1=CEUXa?umHC`&^-P(OPz~ck5XqpP-@j} z#FN*q_1sXIxC5^Br;dW8$X|4~GCGIc9uIziTeEk*BkU-0)T{bBa z`wP!qsib?sz)lQcVv1_0mUSwzH0I>E%P_08#jJTyRva((%kAg})<(P4A6im~5WQP3 zXgi$XByVzg>or})@249vM_ML_YdaUr<^_FU`c7j!tUal9#XBE(Q-Ujz6-{&ym{_4!;!d0B;zu6i{i zX3_ZZAQ*+HuVE>rsCgmwUhx}(I&*UTxcXvW<-8!goKDQH$a~20!e)sv`W;hO;E()` zg?Cvg*wnI1E5bV^j-I>E|YKWMCrM{$SD3KAlB5c z13PD{Q8(O0TJ7wzFib2EF6C>TLPAIX4Vlsy?Tw3vP$Y7_F6n^L$KUn*ZM^wO=KkG|kDHx^WGdf{#qZ$9Xrsb}TYB1C zCIPYJ>&x+t&sXsNZ5cvZcUKdfv|jF|5ei5HYFd+v&k{ltXa*+RT3ZxoD_rc(b8d-1 zI?md)^Wy)oGKa2UA9`C06&kV5WmtG12(j^@A9X02zUvgFB-OuvGG@m*w;~C+ADYq+%3i%P8lv zQIIEGdk+J?UQ^M_8QB$+xRpOIQ+DAMX$DWk6qQtX+uet*OZiqKME#92`pg zBn>=D(%&L6J-sR~^3ws7bd@wYN)3)UvD+ps4CH5RYSJN?e!L?8?Iv*hb%!oErz=JW zXZzdvDW9J^d%F;4Yms3|rr4f(QW&C^!PWYh6d%ci%z*^TTx-6mR z{z))phv*1SI32N8@gos zGZmCW3b{dAt54NU$+_@hyQl7TBavv$yHnX?6Byijt8am#;>aupmmk3l@t!8T`f4Q`njY7|-EXAPQSM9U$IN$2gy^2dD(T5^Nc`N( zKohmwA^$|adP-6hKYgVTv%_!Y!K1`1WmKkT*GEp#Ui}7Tp;P>(KGesT=7-s=3zJzw z#Unf2ykU4q`=!Dxv&pAYkqmBX)t^jkz2kyGeDa3AwH<}|&Sj$oq@z>?Q{kp~*U@ms zn|jn425K3q>YOZZq*3WT`P z$gPt2Zma?H#NevsjQ)?4$a3#?4_JddWf!20&Nx5neY3r0N7@1j!KE&`8P?R4F~uN# zF19#PnV^AZA#co4|A7g)1{t)O3y>G4T^Io)bIN@i#1bf|H8XJ3&S}Qv%rL zBFGevY-g`%HEl$10gJdIW_NA$B`q%K&U0jk1O7y153DcY?5g6mj(q( zSR>4+kD}lUPsV}!ydq>O1`t!0$ec0Zeb2TN2KLZT=`X1Oy*hm03kV$K557Fd5mKQS zN~Ddl|9bW^qtp}X>8t(7oNIQ@(L}Pk%6E)|&aN~l5Q^q+{rgTOD03O5?R@6pR_JD@ z=xdW>0FBVKQo7OJ!!{$VQfqNxIHhCkZE^=;Iq5f@__N3^c6n^ViG7iGPbWAjm&|kM z*L)y7=fM1Ki0fZySZ%RYpoKM8cw)CKs4$_WYS6#o#uWFp75Jf;Y4K$k20I?N6SaH0CJrrGjx`vp!-?umkQ|izOAMZ?A6pyS6XQE;l~K(^ z*~_}J@SggikwVx8Ka;ut$#b$u32BZ*@J$NmgQtwe7Q9=UxcKO^ZA?Y_>J zsNWARfnfq`Hy_H@wl2RNNik5@sDt78N1oy{;{}1|c~^V!zuc3w)|D$8?+18(%4wwv zI^9D0dOz*@QQ)*Y6+DtXpkpn+@S}HrO*s8hMBed};tiwu+3OXb%Vo;7=LG1}dj0KL z)HY!` zGSd#jA?3!tUBAUA0=Dv$-EO$6zMgUx!*$6<2KWs!399x0vB%;=`WJmw#jJ-LsqeFIpuZd@2Qt=$)nwf7PUlJ-+_C4h zcQHqOR5R+!R_I2PJkuthx*!=EBD(^+S{YQg-}C8t>S$QZXZQ!09MS`4Q&)=Ts89{O zoAzI{jqUp~x$UnHXM6ud<7_kPXwntG-%HmtG*R2qBDfLyMG|jP$w9+k+WVs(;jC8>S+J`L?gYq{=oVW{GFLmgrT@D` zvO?)XIa)*_I^M@;XqfBLj`MmI(F8`l>3)>koVe86T22u8y4}&;>J#(0LWmYM_O~RN zu8Z|~?6)Mq;dG+c?Dd_H4gg12ja7zwN}4uaVJEp2pZjDT7}+Za`<7mD;q_o8-HfnP zgJPwtob(E~e$qM_$hxGy{T~VI5x!Bv-SSX-{cu21ppzQ>uNYlp+8HpV-kBoE z_AUH8nf8@uC=p%*kK8>|0k{Ldp;2UGHr$Zd9c=7thQ3_a*I zg7`+1Fbf=$S2^dx$BbpY%Zm>PF7I!Mk7!9piZLJ#?cRSy6McL3WLtCx6Fq*vlr_>F z@_MIO(R`(zQrMW^y&?E#9-+e*GXIjKFjVt0kT={tUb8H@%i9Yw)>UX@J#YWbb4oF8 zrs;>V`r``krTO+?hAaWp$a}}xc1uzs6)lteKhuRi1q% z&p;mfz{64kB9{L__|@dp51Maq6^$*U)fjJjhNqOYcqc#i7R+^e9d}~n?4rZ}Z+jWa z&_83b@hD67jq3`Yshfxe3!Yv0T_I;l8t|l4qx}|<^!Gm=g5$!zc1>U;U96rm-ZUIT zY!0wmXLRXWXie!FS9RCfWwucchA)E`D5GP`43A!66>}aRbHc>gHDkEj79dI>&8`=( zCGHy0DE=#cvEfn<=d>x<#n+W+w*;(&T!mR+QT0{5)o1$v)b>9`f3E=ji;kjira*S2 z0E>4wnQ$F%!1))^!Mc8zf(g&GE`q(S0*nr%q#xbjWOuN7%ct~Ja*~2mAz#?5@f60{ zv7ojKaQxC=-i8k!jKBYEXMIa~`bx#cWrf=|;9yZe+-G!*d*Ep|JK+P+dWKCpXG$u1 zv6SCpa@b5i<%9b5-iM__V`iI8my7v7E)I@1C7{4uwP`FgR;($!9d_xC%SmD9opMb@C&Xgl%>nw${=8K3HgpQKwlb z481nzyiyb18z(y0xokombuF-GZdi132Wy95VZ??e{B@I;0d%+~l$~m`HQI?T7($O^1{|dA}4${WtP< zZ4N%-XMYAfxC#kvYLGq}MXa5_f(Bf<=(-@B5osGPElon&)t5k7rePc0FD&wqoz@~uFFatH^9W^5q)EQAA7lu6(Iw?tVzWN7W~EWNCy z@~)ASGe>Zy#wr=V*zhXQ<;hKU;^qqrZkAEZ(x{e@8{sw?Ow74jVX9&^p&}Ue{(X%* zV7^VyuH+AFP4ZHF)K~P?cQ)DiPj|K3@S~DkBb+hLgN$ji&cor1MO&r7TwaJH;INmN z7mB{wpi6o9?Yrr-wz!`3M#d(iBA#j4+KhnE$#d&6z-D+Scpzyc;JoFH8e;7x+CL1k z2EaIW9b4K4wHBESDZCQJ`cu|u+S!OqKEc>G)ws2G9$52Jjw9p*9Ul(?+^D68|BtS`Lq$GX8 z$dlh+uHuv?N7C)5|7rFl%#T~79p?sHs@$r>n`JHUPe;w+j4!QOeB*Z5SpghiN^6hK z#AYay#i7%s(6y3}_Bt~gTK6@}nv-8154V=n@&z&}Or`&^A28lJeXVI^qAQy0Q2(>^P)M^isC+w7wwtcgaSlP(`Zu z7oO08zi*%Qwr%0l@9K&fU8HKMrc0kV0^MJmAVOB!-rWzPG(}m5H!bDdC`K3dm>?d+ zX8`&fHX3b}b{`M@uD2X1lY;7V%V{^QJZw0v7J@NGJL`WtbQp{m`o@U2bT22n(-Y>| z>-9x5NqNqsd|5^ynbvy>q|jd`?ZQ@jHY2=*Y$A4If9Cn(CIrIw>Ro=4ew!Q>5py&! z?!Z@Cm!zx#<6!9x<;+lTli4bv&Ue@$K`5VWSo<1mnA=0X!!jn zMeQyXX13Oc10M;N1H+pCQcU(N;$W6V%YOGpmkzrMBoqWvvf4M)*6=)Co#cz8Lk;11 zNKRbB=#O|hZaIPil({-G#qKH1H(1%l&Q$`vxzl}5=Xew^5a*@An|oY@-E#yV(*Y$N zc>KKU>W^z>hqQ_aChLHgCMf7j5})YVDJcwH;2t@B$|F%Dh;Cj91iHPbJ>1{cCP%hu zzfX%;rFS^r7eD^TZV2`mAgwZi&JSEEiQ)8Xq#-ea`WyGNCdpzu)T6lj-#w>JDgfb8 zyfE}NA=O=iiFs^K$56(=9WirDSKIk?n~B`&3|2FeX$l~rV={0 z%zTW|Lh|K+H%qD%VF)MV{k<7pTH3j7hnXQ`58dS{V@EV}@1DN{hW(ZT z+mE;2cj4zem8&!Lvq6xL@w*pRpOlcZkMsahtG;StlOg;Le>;G zxMZdOz)Ip$y&$Mfk&S&l1%PLH)T%A;q`lmzvSkil zbWH2VEn$8e-+yg8@eYGJDmH4{t1zkG)@Hv)Hmh_8EjsDQ9N! z^j1PDO%Tkt-;MIUgu)nkDuI#UDbxO*wv%-6?*+TiM^<8IKP^r{m;J0pmk3I*X4rrP zkqLMh?bl8?T_W}UH=0)%3OSH*YjtK1s~k`>N9U(gYh57k8186wAox7=zIM7XZny{; zwW}rTHn6PUyXnEH$@bCOyURH0!!;qXP&*yQ9JbVI=U@)95>wY^NJ8TT3d8n?%}QZmCcVI)})6R$?u;XAVn-k$yby@n zHqyXtU8NEKu`^siZ?j)bq98#iwXUBb)+ zdt}{01sXH3cj!>aWqfcf`zQ4lVVLRJby5;0^SPvH+jOmcjJJ;evz8^eY?YvrN({gqzst{&sSZLo;sEcEo%6AUslYNT?X zDzVr4n#RMja~a$f!m^SMTr4OStOfT_k<0#^dwCI)FJUvq%p=eQYyQCJ5%Npww+nDL^sc!Mc?W;8W3DwtM*OM*)2@O4%QG)V?m>Plh*a`BbVhjdYLrR z9FHLr;Q?}s)EMu4?|XrrufFVfJ$Yw;(pW!}rM=dzakd;FJuKv5sF}j&V%nFi@0r3; zGDG}o)>oy^<}D~NeY#<7E;3)}W+!RpWv=+x;>0j=2VB48l3;Ju|4f6&vfrq-;zOyg z%lu(HY1RbbW-VVvX5rfm*j-ZnBpFE81P&PR2AjM`u0$Jk^0!iX7WLEv!&g4zk+|b5 z=w(q6M0=aP?0mB#Jb2lE(4p&Uz=w!WdU~Hx=Y4&=%qQK2@2&T%h3I470rXWlk=WYct8h*zX=UJU>xcOPsP}-& z~gj*yZLVEt^WJ;CY2LiHEHQJt@9C4Jo-8o z*Bo<(#V@KaV_IEg#u$N>_;U@~#V=t!)HirM=SFHED z=Cr#09A|Q=Mkg{fbbDKuUw8QPv@Ufs?9n?e9tE!C0N28H?_uN1^#h?I*)mxiX1xM|*r0SQ zYAJ+AAb>n|1vh|nCw-iZ*tcT83={UI!FCDO7(1gfsyXAE(L%0&T$=p4ErIO1BQsV- z^r&2Y>3X3fb7pQh6_p$6msp9vj8E5w9SFwve4Si+ z_St9Ow95Q@%jKwx4->gdj0EP|G!%c;ikz%oyFCYs)kVJ zFjdmEgfV9ime~br6RZ4RPmsb^Pa*AjmyxZ_$}BWnVNqkH7PC4j>0NR27Q21NeUzL9 zRy3rry3@7@#|rFvF4|Q^Jc6Jxzo913QA8c*A_SDbT?$UoV@UDfE8OjTC~7ifj4CAc znUJa?_FILZ?}V^1=Yh>{JUe_g3a{q@=m)+W>hmJ-Oi`8^3zAm5MUKa7th)8E{TnJI zE#a{+y)kIm#n>A6>$7#SXiIk$;6wNK%!L|INNj#bRe0Uq)qs~8W2U66ks2Z#fad&E znKrahglEWk9@ELlr_4XJIvq+@cvqf9k2H4ko#&pAj>Q#))YJmwr*uMHckOt_S_KNbQRs0vj7k z0>yhFaofR~!9T=nVaXFdgg{}wp?c0k>Z@l<7!Z;SDDzeL*sJqlEX>KY-IMQ%%=o`g zK^t;NP$6OhtIFOyRH#mwQ~qpw>|>M}L_BYvB_VH|3NaI=m$ndqYw?wOwH5MF6rx7b z+{+WcF8K=mjDHzDQ%BE=-@_?$-RykXVf3ODEnm3}1L>3TbnQ^XRyA_*Q0r2L`R0}S z-#Y2Kaeoak{BG{M9dyqD(7q9HmP@8MN@r`esEXF?h`q#gH_ImvB$4?%6?6H$MzhFLFoQL4gAE(eEZug6#?e@5*5G||w5HWJn{ zrW?+vp;3g4*VT1Y@3+Quq1}c+iY6WM4htRE!|yt2Qf6W78gKYr-?gzJx5^0pud=O@ zD#B*XHJn)Zn*+gnwdQLqm%kb===w5F#=B>fSYOt!|0@^kP&ma=|MjmcdtkXV(v_UJ2*W4wV{=0gOfw)b!o zM}2m&*VqC(Q|Qnb<7T|uXJgxa>bCnp7={QGf^=6fg|!_ZLO2&Cso`aAn_yM%r5)i>DFb3)&sb>rw+fkKS533NU5XIEl+!Kmu%4CSn=Vc_nDCtvs#cB1k$!q4M zhH{aeq9=HL1hMB=K*K!Ry5pvN#-B4AidgB3`D0u=Pven}R059Y#JwNAPVrR&iYJo0s~cAWbUs;K2$;8Z8i10 zT*n~5z?4=!+A0c=VfVC;A@K0S51)Mc)1N-`=(XLxVowqy2&b(U+t9RW42CD4{N1Nl zx{iRbs2bL&BBMwes&J?bfly`1Gpq0(s^>GW9@|=&S)Im=QA1f0to3dwQyyR2#iKFL zyd&+aw+U$>jE%MVtVc@tL4j&4RG2q057ppdbP>k-rSJMAjHR75EIV)JvwYPYhd$g! zIr?pUjUPUr?|V*%zEZB*P-CLrx3y8;F$RoH1?PxA}R zl{V?4ai~Jxb4-SMY<3+Ma-w}I%G0NLHgBj#lC~ECn7S9-|LRr7-&>B-V<)c=dPOMy z_rL%BKfV>kQTx3zHP)V zTC0-Nrz%j%PhGTyh<(;~UQ)evf&fxMpsKSrzP(TRFh z`sZ`w_5^1k`6}$8qC9xjcN%4QeF`SN~uPmepS(Hqq#ONLJd3Oh0oMcB{#&=q?CI`Lc=lmL4PRO-7uK> z6|eSxW766|;Wn&g9q2Rf8=so*B2&uk!A+Dl*<@U6?4lYCWLIUTK4?SNl=&vVI5xsc zMF)zELIfCtMHjTGISu|BzTL<0hMY8Nodm^v)e3t)yky=#Jb8s2<9p#1|3^OZk;{vz z{_@Q?-~2O+F)vdXlwV2=%2&Q}_TRu^JbXfOs9saO>Bbx>3=3k~GX}sIOR{;v@cKSf#KYO@3@7j$ z0oA_EZ+o127OipaoDhsqi+Wi@-Oo-@Xdi*?y#l2$VHI$ds&WWs!pj(GoBJyK%<&ju z<`U2N-#D0;j)(DP5Y>1xFI8T`AGu(BKt_g0)wJyT*=s zjZt~0D57@bmm0l3TRX-;2t~a$)c5tGUHaLC#5yn#l`80lGAbL3z6l$s2X9QsN}C+c zWNmd``YeMNlFQSbJ+0R~>|r<8oqxZy>VIy@s{dkzMxQ--1<-|8{3~XC=ki$p^~E4R zGBCewPZ+1lsIV8J@atjn2798K>v~=`PYI-Du@Gv!84I0K7F)&G^-RIzvpBx`)vunc zxYSuD>nPZHHIYcUMHA}b7E-P;U=cGK#<-XlPnfqiR4<4z;y2?pL?~2H`+Z-G1Y5rs za;(8Y2>HA#ICCX5Q!j>)G{2N(Jv8OlKw=aW)gfF8Eh1%>r@Rx!HI|f71fcwbZ>n^5 zgo(#&j_RQq+n0i3%M&#Qw9_2a0BS6kf@mlQUm9y`1do{~<5ESYzwL*yZn&ar&ioY> zt3umP$+UNNYe;wiv(N7&p%IE;mJ68un3s^9#r|<=1#L@A$F( zF8|gLD<3pBsdCc0HV@TcWTe$$Xb7#STn%pj;ZyC#S4BqKj>@?jTQznVs&N8OmwbE8 zs^>pnVa_j}yaMRLEB<%C``zzd-u}P7KHeq~stclCLKFEgje|+{tzU(Vn;|?TS)~R+ z?4ib-LUF)Q%?8f7L^%Kt#QP{o)s4Q=DrHl`Q5&E0(a`_6AR6O?}hTs zB}fzh=(qOnLU8|H=#d~N)VgoonCuXF1tw3>*tY+BLgD^@`H$C0d9^JKSEvhrYG>!7 z$QV>h8=Aqs&-;+JwT_}R{;$xkp}@H7`Z8xVdR$)*R=M7b2|~|C^In09|;+|G)zed}Jx_ z|H+!*>j_^1sb1$Whir3;V5kDzV!%vIN+ay%KgL3ZrjP;S0wWR>g-fe=2<0lWsfW^+ zeb2M#BB|G}Jr>rk=>3l>JS@a9oCb=&?Y7%qBn(fsQs;Ja>NYs?Q?GDK)v z_!a)@B)FeH&r%l~?9=#~K!p#gL@0K`h;Xm5)3H3{?X;Zk$0m>}a0?sP+il+(I$!`) zutJu0ey#GvBhw~ZqG}MxaxT9O**1mLsqfxO7)s-o!>lqyJ%JW>YlE%jyE}5 zBUpQT7#C-&#>BLH_{tiLk#gzV-~RS9Z+`Qe|KE>2_Sl7w^Ivquf4V&We`^Vm4=#p0 zoung-O}P?6Gx@_bJm(?*ji*}yDM6?LfM-EC5x5v~h=pE-J_2sqC4^v+5pWbl<65Ki zojlkrHMAY<9n}u@HxyHW2oGu7P@;`bY@jo1!b)Ly6mM%c(t0)kB&Cmxr7WxHeU@-YcuOo(x6ln$}`^`U^PgW_0~jEZIW+6xmIBf?V0%V zS!~-m7d6mqb8MK$y3jv$;B)fC38Z9Bl_aH#U-YL*laMSt*7$v$i-t(*p*Q5j;J_2z zDm+xDhJ2i{bX{dqjc@B%n}u5Oxr5glGU`q#^NuIhTwGpb_y76EH@@-A$pxnit@z*j z-uK@0hBv(77Z(G)PIkGI)(BmKgJ84BnjB=|V6J*|;!%{fMOnqP=Mgj>TJN(Se}#iK z&GoZQZxZ`FqOpB#r8p>F_wPn)A!Ta`B;B!W20k}SSSQLg=exJ=`j$`O;;9;|>St(lHw2!x2AT*= z7IBVtgv|Aox#k=C+OWus@q{y1zkX#Y{?D9TaJtZn|6T8T*E<(1{co)azJYg!VXHLv zxZ1A#hWy4d-o0gv$ZD<-XeIs=JR+5U--foUL@=&Y@6r&|@L!8eWZO)|10mRg{Q#Q)spDGXATg z>bz8`sfY2^m??y$WgGh%x6SOXalFrc+d>(1A2%W0P#7q^mM{;c~KNaowDrB2bogO798VMG+fH(J$+%JYR&fh+)wt z{8%TY24IaiZL=P`J=eS_Q-2tVJ3m^_HRg9&D<`K125DQJFypI?t`TzB+?}uSORLN; zEr;>H{NfkCc%k9`i>&xh@4x^4kKA#`9sk;z@Y80DVld1&RLHu*aQAS)QH4*%u!gFX z_C-`fqE>5Tt&N%aO}$S%@x<9aeafW=XQ-RNV{p9gb+0=+iI1Wm59sEbZ@zZ0&lmyY z5jqFFVTJbRY(V4n51csVHo=VWuCdU3hI#~`Z5{)KY;3w6iYHIeRe2N^AH%4^g(7lN zWBZ{U-ocuLL4}sND15#PjtV~lkl|4{l!Dw1DT1G{Hg4KmVQ#Dmz8a(2W$c?n(3q!k z+crX*vb07d`{8|cRKRL?`Pp1{ZPg&F*Vp`*=W=F3*N(PRBu#$gAvgb_h7<#=29?(# zgsq_!R6d|QlZj0^3;iL3tYPI@ug0nJVftGc!)xw(EMJ@dB1)W#9pNe(LY7gu zU4Pp9gFKMQczIWD!zJWYpU}BO@7l7*b1W&4vctni``D{QNr>)n|DcsAF{+6^)SSiKAl|F_LM+OdZR zsu=5u)d(qUj;HWJ5fO?M&sMotk!iPfG~TYyJ?7X8UmHJV$@?*G4W}5F&Yd>7uX9R4 z={K}bJw1+g2<%TT@bHa46a!BgYrof^DAcVD)Bd6)GXH&kK8b+k4MuIZ7pkL(rglyF zLKYM*WU2DE#$Fw*CXE)EEy84NdWYgvc6ANy20ngR4$ZgMJp4yX@qg>&0@H<6{I~ut z{iVf#4`A-0TJ!bzc%g+=E13G2RtunzewDieLzLTn?-;dL9|Ley9qB8X>upY4Q&cjx;E*r6WsQl(dK;`AIk zA7bbztKLCTg~mSXEmui&PU^++QYntY;;7!4a(Bg4__fgMkn%jCudrl8LKLr@1JHJb z5|7?|OZ+Org9r7CkoSKDA!_bGjm;{83gT&>N24-y@y`6u<1GR(gy*ZMj6F}%HF&ii zo619HMzP*+1uHEJq1%(1+x9&n{y z%7tv0JHPFSD~Cm0H9VEoFp1Yt*OtDW8#;pw&*1*YOV)nvb9IkQoJ;q+4XK_xu zdFVV3{i_ltxb?|cR4Fr*%y|U`A=mO42Yr|bg{}@Mj zvq^CC+l=|t->r@WZ@s7*BlSp&65wIG4DirgXKaf=FgnUV6a@pp8rWm5%}K#a3~6J9 zXN$s3ySk6QCr4JJGrNo24NW zvIDH&ghS4VaDlNcuT>6o%@n=C_fQ0VCxaLz%_T7w@)^oE4OJi^Gad}es?4)qx|YgYH86^RAO_kB3tn1K|1U3Dd!ZBjE~?@`T^{d`u9)`!Y)$-~ z<9QMo%{sSGD1jkL5mQ@GJds+=7}0_ls^Te(??1wzg2f`n;I*KKrp;gc;ul}!CA}0) zET7V+h$;k!crCmm%8OTQdlqZ{Y(O_Cjb}Lb-g)Pp*Mv+JE(50HTkE{1{5AYgWl5RT zQ!oY;A0y6OYK#Bt1-X|J(kB9GsGljuA_s-TjhlxhRiF^0^*9JACoR?>0Ew3Gj72?R zj|#3p!+*^UpxC-4iV(*G3>zNn?y)sIfOwD$klcP6nlOB|4^UH@*UcQ-)o4 zj3V<}XQF&oxE~LZM+}HT_Ik#IF@X|zGNpBJ$Ve-sufLSCd;nvDcRVnRe6h}X_++28 zQ(mZoH|7nA;g=e83^n6i!-hO2L)LYdS9!nj_~VaX=!1MNs^Y)&?svcYPc6p%3u}^J zV}bMH8k61Qw>$J*;W-RO=n~*VuBit$H09V!x_gH8jOzVfpZ%>Eb$*|uz8WN5(0zZ? zo8EK{x+K5|)jdu&uWh$HWsj1kdlva~E8N zSu4oRsWI0U<8AyJ;?dV468c&}Xbz3*p*VjPt~k4~?oJTpYGaK8^?Fy9a(P?Yth_?i zgfZdIldVAm=53N)1-d$_kSG-GRVQ9#oRoiuYRvHZs;u1K1VzHyL$!7zt@#(7Lws$% zghaXyD0%Z&53$CB?=>j#*43*oK9e5*XqVr2o+V2T9U|q3-o~wK-0rb(AtSs(p?6&| zI)<7A+KhgDZ_daw-n;qg{299{Z})4vah&f{4yb<*acL(*1|p$6;|-N5ku~O=(bD;} z7LBVl>0YvV-d7t>m)!f@6Hh$x|2?_DbRiZ0M?UhA>sE~YUs+K9&yEFG#>B*3lug9J z^g~q`n3b1?>6;`{%M^n(lbY3U5fd0g1dQveFs6Nz(Z74eZJ#pU{N^{GH=Lnhi%1IN5pz%w|897-}IKY-#Qw2LZHY#npu z5&XPg^_uT01#K>`*I*@tpCFj{sVo$KTY;2|NWq6{^{_BEkzV)RvB_0k*a za{qX`3?yr+c|a7YShK!bpXIfN61orHco%;5c}LDD9S^vI9%&23R__>+$3SlT7|u1` zgx=g!qnMILj<<$96y~o1U-X5{;DK8Y)+agB!=v=ycnviy(}x3T?|v|pby)teh9M8+ zuv`P{t>X*r8O6WG|670V&;7ao=R*%YboJzd(uGv~Z+qL@ZdlCwvr7T~nKhA@c6h8- zUSml03JP)ZFhAql4S@!i7wUc5P zB9ttI#(>p3{eSxDr(Yzn4=Mk-AJng}+Gf1#txUYj&mKwML~2;7;j#uI`z38tNY|P6qP7X`pjV9 zwbmH4{-IQi*oIk*m336bVm-QF&XBRavV~BZ^w%W69r4rNIwgk;+8z#7nE=MFlhH7o z@x&L_n>s4LI%f^%G#sZKW7+T}p1qRTdyObYX%n!!4jSH2Z;f=ek^>Gc z8lGPs|L=V6bD#UaKl|*nzZc)SV00lB|MGg5QTghhTgv~(m%uyaO<=eof{(((>^EBrBaMC$0-(l z*8jrlL-Sco);&cBD2Dd028wmU2sMuq)~q>omA|yDUULM@5D&?!qT|?$h9p_N{HRbHI%_cPBc}QI4g7sJ9#CUTCc3$poD|JsFZoBQa z|KO2F9{D}!<$}?LRQz*P?^;BEc}@5`yMMn-f)NOSp~8h#=eEr$XiNG7wtXRIIc_$hu{Z1jgW zZyX8vDzt_!c0pJ}Nxg(#VecWZrr&1HC64jBBzG0oEUJL&xz?-cQ{>#Q-AzQIkSP<2 z!Se6y{$1M;KRl7M8ElP#&YPyzE*^jWH!O(L5K(O%1w^ zF<$QOnL_eaYz*KgGU9i9Y21t#-Z1|D$9Lvxk5Lcl&koo3^V9 za?#k%f3^eH5vrq81FH{4BR7l8Nbs(~um276orguPKK}UQ|BvPPJbiLO>GH`1q&2zM zF9x`sQnAphIO}ElTIf6yccfNzP&9KqP!hS5I?mJ{bdC3c8pySqVj4z9SW*(djI=R zxixSp4T_?%+#Q{2C}4gQQ#GD@5+5Eh2VI9d$|3npy_9#6k@9EPU=g*32|CW&$b;RX z=o%e6O4bmGdd*$ocH^xaW3YSPMHAHBBxFXx9{y1;9+aqA#Ibx)G)I3O32bes+kNJ* zMx*hl0ii$r-(1%aQLiwKH9`TKJG^h5HD9SY7Ik3Sh8l{DIQdmI((!NS|9oCK4kG*?2TbIMm@yR=l$$`vq%f2>Sw8ftIt2Ex25dH0m0GwTA|W@46*W?poj>* z&Y|&~a|IX^`XPn~!sP|dwZkL4m5wi?Wr&b8&&uVU?T~Ykj(N@f>XDX^Scl;R)iFQyvg>KpfNPjUTU?`jiB>gSjQI{RE2n)keq9HQxO$(E ziYjO2;`b>-mVA|qF|5&E^vHKSz+kh^@HZuE9*p1ASqOYbMHull#=BF3fwLRu_^sbAtTtdepXcCyI7ilU?IvRb%$}04h-w2S009 zk(xtjZI4#>e|ht~Ki3@<|I3ipgpTHYjm0~R!=t23ES_4zgieKJ8J?i+f*ERp(onrK z-oyNFKQnKGfB zOR!P!#*Ps3*j96;%<^MV5BypWaYr0#Y{?nut_Jf%8ABC}X?G{oW1TVG2C z;iT@VV^E!*0Eh<*6B~~T{wg8FD>d&tJI2YL5N4ce99ZAlQ)ANnx)1*}xvhrtd`7>ly=4lc)I))#)!PGhmlfhy1%Prl=IGN`+E>>N<`Zp>L@*21B+Z(dx_+38LL zC?5k*JvG*f5_Qd}pK(xS-mqAYZf?l6=uHvVhGMke*lr2clNUCRw46dNWM=<`RQ!vf zZd{D=YC;CggL!#zBlMe@I@Fk{14ry-9ok{i#_4%dg_tR_Ap+TNjrmTZkOVM`r{xY2 zBo&4gE)@zBpPzb0fKNYr7W%yWFO#)iAT*$Yw?>EW_4+;bxKJk#WelFi0vSxrw5=B{ z4A4Y2UV$>_XyLhLav$tIFuyyrJM%Z=%P^=>Q24mYTjnC%r)~YiyE`j zpJ|Wp^H3+}R}3{&Q6r-U6vYK~D{^E`rVZ*d{&QZ1dGY&P$5?I%rO%+CP^M25&&(OG zfB2m@Uznaku(fg8Hgh@i*3h1LckTs6Ic>uijH(&CDSzJQHUG^!&wXgtrERw}7PB)( ze~TKL?;1LIn*nUB7>qSkD9&k{HN|k+v-D>?d(e(KR#w;jv|Tb{9Tl>uF;d_%+&_pHKvofn$voVdzoI+Bo$xX!WNFs&oJF$+_ck%gF^*`a>5|@h?W0?R=Mc z+0AZeA@_7C*5|G`{8re!XVMQ5v>38+sKzWU=plv(VLyuN)1UtIi%th)Z4XV`!Pi4w z{H3}7lb`(LHN{kKyijTile|T+=r)@v+6F+h7d;#>>V~?Hu=5PMyHLtHBsE(OF z;OEX;+gIbXaJKI|k}~6T|NZx$wQ1Iyd6WwTmqreGDA^AEOM)z^K8OU;gr!Pd@j#&%J1Um;V|*t88d^ z4!`X(XU1yUI6UakFyq=YQOLa+3y^=$j^Ncducy3dZOfbKI(H2;0IJ)B=AL=c`GSBj zO7YtHp=PI#KmPc{1dbm6%Zb(`&dR)QCerD1!yG-`$pUJ;i*O$*)JXX>eu+^m5CX7q zFP=cNZ|C|E3WW5OIosyIu7$k4gTS<_0@-ic2&NqdZ>(^raIi(`ejb~9dP0|byZF^< zadjb9@HZ2<3%lsYPz{SJIS28e>rTTDfuOh&YMUff{77o!T=am;;ge8Vgqs~SM4 z^MDu+o&OzHRc_?>X}tjaAPMC`@Wzrj0d_>KUuI#$1i6qDl3- z5A^|WSd*RehL{+`^)kC2%%S@CI*OE;-$Mw%zJ9>@40Xmxb1k$Pq`thuGvn)PU;Em% zP{fR9*XtpJ_Jt(c4UrLeXzG9Dkw?x#6>oj(TTkw}=bmdGHAF|U9~mPQVJs+4{HOm# zZ_4ZYx+zZ<&8v}xpQi3H00!NflS8M?vo0@Z7m9h1Q&Q)tXoEgDvC?>zgcvCQ8k_a( zi;mP_lUw5)h9+vqz`y?F0@Fp!>OWnRew7!o$MD4fn?!=a%1r&ea5QDQdlRhfVOVh| z7A5AYm1_Zjz8kyRJ^wCPvRn3PWki?K1@0cf3@iY&YV5m|WS{kl*k<o7uhOA+WIessy_Smr|W;#rV4@s)*1o z_>{XZ+@cT`c$JMdRjCqi%BW%mkL`+TZCih{+^1l1- zyJq0-+afP#JKA1%$CY8w@!i{TNC6klJ*2=ZbeZ z6R{v<4^ukL`mYihDuY?nJc1!!?J#qLIJ?(wr?#c@@S0V5yK#HxyLaZ?{ z^ism|hbd7DxM&JRUC57zN8mT{(PHgZv!Uh$bb)s)b|Kzf8-=H}wF=66A?42PKIiI_ znGK#~q_j<)OZD&Jq8&-u=l;^A7asz(hbiQO%(zYBm}Is2ZBQQYr!scr;}CDTPJ64E zJI?!9?PItb0JF~IMOdG_)0g78h7tBUlw0Vy_1DWTpEH8mAG|r#1kN$kN8x|zOJBMc zCOMS5QSWkZi_g|UJ#xHP*w^QTcF3 zW_H80ys^)LF&XH8X!vi8qakvq;aB`+y{NytI>>3pba!-+t#S&i#fEsgR{BV5Z82ZX zVK|@vV^;smiPpqj!AKRDyz-$g3d{gTk{Hu1H5i1&IK*N^Jt$*dVo8NF%UpZR`p_a9 z+CBQA-P2K~+yd8VCkwg)RlL0(n|gL3Sx>l1tHwdb|3%lTyZtv8;6RHX{Lh2XCMb-u zhIl&qN}$vjs8`#uuaelk_CrdpTZ*&?F{T(;MO5m6*0|VFoqbMsfvrvbuLjJOBL;;J7cqX2yN5O18wI%9@^PtO22pR_rA3b$KCq9j|*;}wWssc_I7S}o-|MU zI&DaU@z^H`X39bc*9aI7tQo5C=x>F?+U8xrW(;1Wq!HmodXC_jfC=t`zWObcb zsP)fds5ccxrEe-!o`y>n3=$@B&JXyGpRS`n+)Y%1O ziP${((ygr8Nx{o2k$lTguIxK+&xQ5&hc2YzUlTY={}hxgHrIvN#n~9tkVL5@dK}yW zRd}gh=rE#p7I_T>UbaQRbKRAYb`I^zW>@U~-xYNchh96>6S#(4zkAjd0${kkyhDO4 z^Knh6PG5~PkI{oYI#0%dG9nb@2<*zFUhyHJra!v^-$@u}r}npDjG=}tT2DQ$Qaz_# zz_-3461%b2IjbO6wmtHrAY_3Pu5H_1cRlU?z8fu9H=}aDw#vr1c24AO%;d& zy?H1*&$pi5uRr@d_H)O4#%#8w;W=Akr=0`uL#N6kO1IS5^Z6yH!4Jp;zVY8^EwEUdP2C`@^8NUXPWUX-Kd3zbYxnh$oNp^oMzW;tc0d< zFptK^eN%_{bCb||HibEv@+TgQ|MvOOUS(G4b*mx|_|Ul2m{OL{vv+=wk}1Q9eDmML z^&JSa$KaK{8@oezfSiEB%=a0;sbl5`Du{o}k9fs9k9O`I*nbi@9bF3@>-g;RT7#^- z=>VarzuV}@LkY=F0^HlU_xtqp_a2fnUjH0!_ul?v} zZGU0grNvm013-?EZPwEvWA38Sg;e}Qn2FNBEQGU%rZ5KVMX$mmsAi#AtV4U;h+-qi z)mL~D{6sPKtbko;C~qeVb>gG`ZjT3Kpkb02TCvy7`*xU;p~oUpugdvM53WmZexmfX_CpLu0yoT@#y> zk*qBQA^ze0N#HE{VB8NW(h6dqr#^~-aAOG73m-)>`^G`1yJBlyZEFQ$(W|Z(V_n5K z@AKQNkMV{ZA~LRx4Hw|DAE$OLN}LWl?Di^v<|{23DlsIjcmqd(_7dCcm6ITCM?ATsH*xCm($Xcc6W<0vea zDGRh#YqzI#+g{_9>aRCBM1fH%yC>1U3{ilTt5e1pB$R$b7#2vqT=i01pz10y?Ww@7 zp!I@gXk+0sLSf1z%=NDd#8`A25<|+ubh=iRmcBJfk$~;CAm=u?x8qvRXNd7f02NN{ zUg@68;B(8`AxEU&jdc=C__7|Xu!uH{=RMbra`P0u5~V>vPCuYcoxh?_^#%`xLU`kn zpr$+?`wcg|_<8p|T!n$hi^P}s7f*ThYzfyvSBzcD7b>t0Bs4l1b63(`1MS-=<~j6; zN6jFea^_S%vO{@?6tnWCAGhCr``MoRCLmg8__YY*c*A2@OyJ? zNMooTM^8OHX4w|Ou1WF$53KiNa^K61CdOYcq!unl+xIc=0=LXus0oA3bz*=+jXM`U zB)ADj@KWKjp>7r1y-!pj(stBSCM3nppcdL$k5W5Wxvb~LR%;1YSsj9+4=Fl*D~#_N z3ZUa#&%eS+8BM(FI1wmS?mPs_q~nMVc}9>FeJ7yz_7{TnUVhs>wju3QXN@5SoI1=y zkrD!Z45=Y?9P$o}ggCTBpBP!C9RcWELk=igYXnTq!%`3B+NkxEB4Gvc~&n*ziOdG~AIn`M#g?$<>d2>|-Yvl`f>>Z^mt( zJO@t1ynSNa5bvAdA&hpY5kvOmI44&Xa<9T60ETK9P$m@&yQeZl@rv`-$e{3fR|JbV z?@M`}ENKhcdy|8p236-tkg8N`m0C!cMkt_OgoRJY zvm_~{-P#@^yv4M%v7X@W@mATW%Yvzb^<4U)F5WKALui4r#31X@mAW8zZ+Rb+TKzpg z!CBh8!aa$x#tPv;SQcR^dQorF+!50HS1+9V)+uN9UstH!Ckt&_m6i8gdX7)Pub4dZ-M7?DU+2mbn}J`%Zw1NEcG^uf=n9 zP3-ARuE&lR_P2Mw7BM9`WI2V+um%HECzJkBR9!iW(ZycYHK_=1?JRp>T%Gw?r)o zpoPed`6&J2DNwz!u0hnfWn@nre!O)5Gq%Pcn0R|pjIP1Xxp9~{yF8XzKg~6f*xIAR zDI{n}mC?M9=RXKW*SEU#MVWR8*x@2Kh5XU>p&Enji~aF<&AhmVOsnxoah7-LT=*<> zVrPv1$Wrra=Y%j0L)Tn##I$|dF}&6}wWj5Z%=Z}^yIIJJ`F-X|f4VLr+b`^1{tK!2 zDT8h~vk-0X>mJeFTccbV3p~&sG(te~$japEBorw&@58L_=P~Y!W(dPq;MmSntKR~m z+;>mD3${YTHI0vt0M#y#Cq-I=s7g%VDg?BdF{BL^|4fj%iFF9PdXPE;r8me%#0Zaw3b6fEqe9v4l|%hv`Bbst~6fyC53JrDQQy zlWahu+R;7FjXxI(t8%IU8|qe@dRLge+358Q-G2xUBxsC{bHY1zAm?3iX?q0#1-XxX z1?T+Fcw*s$8@rQ$z+*U2UdF2ELHk5__rD6xj_oeIv|qpW-4H{BES@N=Tg6zTq6$O# zjGZC|pmbw90&?QHvoF6!Pz{M4WteM5iD)w=N6_xHL*n>CUI`v(9W_AvdyS0pE$@;6 zSVPcQ77Zidts!e`ke5;X`cot5kn-0*aeaK*gjj8Eh^q?M_x?BSm%rn?ev9K<=Pi$M zV=nRjTs!5BVK554b=Ha44K!sj)Lq;5R#_YGc^7&s-^lG??9Xcq&fz}_x?{2%eqQ7W zdFS1jGI|=m;QcFO5P%--t2~BnjrXoMW9z@Jfg$5m)al$|n2sGi{+AQY)A=Y@kD$dM zjrFi52^R~IAiz8rqcAAOahS#-&lS^yfLYRA=tC^oLT7tf2t3#m0SQ9FPrZ~CXp0ix zpLMPOHF7Audh5HPGgKvNOsd!|w&$~T3lh_0p|*!*S_6AQ0I;Ul+$vqO!LQHd?C!Fro`Scpz>7IM#@xYt6#DK5z=WG;;7ZyA;E<#S^U6Y@+uV`Km z=3*F3UoSFU*nRv%1hhp=0eB~b2vJERsNT5+EcS$fKu`<^3k5?{zgv{} zwu^AI8)a8??OW$z?is<$2&CY6aukNP?8aLSShOoX_3p;wuAqFE$z62ga<+U9@tVy8 z9=9e3Y91q~XDI9_&aS|w4hP=wikolKgt9|nkVAcG+_{FI|8@w!>!Z0q`<`?C>>TVo z+qOx#gIYGMQG>9kkl!wyhabBusdMc+{_C?wIyU9?0K`B$zphu$BGJE|07*tt#N>i; z7~(MT%8l0$8NYk@l>Ph$jgf5Kv8j>OuJH~NOPsa7dsN!5P2!sR1>@DWkT1KuQpfIHSDE#`-5}fzhbe2;H-oZ9dl3$6u&Bj8 z_q`WSPd>*`w+k|u%3In_b{5*N;{g#H!V??@YqVo+O%>&W$dHqst5THX@`cV(p?R6|1QEf20h={1Q@#SRi=hf*sLYIZZ>ulNJ8iZli`A@* z3TeWlUSbn#cnbs117wAGgv?}8&dv(RTIQv{)CEUxChfs^%v+MN}&vv|X z6;6$T-n$z>4U?2dyNklTc;*n&(RQ1!fsOmT3s8IGyT(So!@$u4@#FdCfM`o&xcWS( z$3Xn}uS!tg4vp`jG3_{LqcvB;%XX~ip+ODA*7UgpxI(bDM z>yzI-=jK8l+!Yd_L%<zANsXhYxv%+S+o<$54myzI!ShzEMt- zwje#9`OIftgna00jSYNcoew|HKKCZwG1A?Sul=@5(u)cS+uSUvz zA7g0Bn0aeLWyu(Ierkj(bLZ)oaxTS^_c3k{7*G*VuynXYb4xYC9iZT?X z5t1}s$$Mo`3CNGrAeCJr;BKR2VY* zHlKPL9jgi^i>ir7^_Hg|@%^C}wha6lSB+yfX;L16vg&2G?e!qEv+XsGJdP^4j$4z5 znmkv-s)DlrADY+Bt#Lf0oNH|E<0%Z^f@nWs4rXQ({VX9xIi2=ce1LFJbn(UL=h@Oj@m-V~Ab zNf|L*SYkZ|#RQtS=Bi z^Ny#x#`g8vG1z1K?e`d340Q(Nd6^eBzCUzfll#`Bo)!+qfZ(0NL=1q&cfiHnHf4b} z<9Z0gi&6T_sxABr&a_|%yP-n6eedF}ppf7K*4CFQ?_J=`b=`_X*%72wR@!518uQ;5 z`wm6cxY5RXJjhek=C?llW$GAsRyjOpTQzyy4hE6?Pyy0yn%Z^<-mX$ATc)cc)0k)#dj)lzJim{@ zIcQVIVu$dJK@I#N##tX0)-A^7Y<{!FPpGBnNqN0zJoKSbUF+q8^WUap$K<}36OGa@ zL)UBT79x{O@ztxU1v%7(UkI{`Vcun@4_Wy2j0gnAK`r$PtgBaF`tX-7@G`G^njln| z4aC~|c&`=8U}4$z5Daw~JG6TUyE1~JP$JzX*u#&67@UgdAQbIs`-d1iRc!S*o0Fgo z9ZzlEy~Lt06;!-BMn&VcQ-?ToGlXBt$T+~W*93ie_YkDsww5;s9tN*A3{t+Sms)QR zwfxSfL!(f`8C4v3yhup1=;wDvbrH8Ao}O!_%<=p^fCoQ!J!tcx-zJpc+(D zNDzf}2;rz9WZXx|j^`+cz&#X<5I}jL_mV-)R_|`4%9%ql$9zEaD9=MD_my^q?zQL5 z^!`HzNZT;{H-?tAYz@~iGB%yddg+y+6gZ@I>h@S)vZ;LM9dGU1M{U!i=s6Xfnpwk> z%so0}9@2AB&+EUi9)BUWdZ5i7Z|t}htN$rx$!9#15lVe}TLpC&&`_1^{MO_@minR4 z!tPzDqh2oNm1suj?0e4+zm$$O}^PdRBz6=}Vkz3mM<@Iq}R!e2cX0r6z3Jg*+`)_<4>S3cYm z&kjNDGnNBq_qp%j=L*}x(M~Kw1T)^(M`Jce$c{iSggWERv!uMtrTdXJWG?pv*ed2- zA%5vgU%Ga7y!tzK4Sy(W=48ShJa^+*IJm}1c?|MY#ozVZwJ0Ne&h?kGpx=e4dC~2E z=bXVaWz0RcEADwIZ3~)f7@hNyA5f3~kdad_T05-k9UU;nhxmBfHb)Yr%Ljum&kKc6hT7^J<$Um*NLIyyo7e^p9EnFDF_PdF`>h zT{!i!E!;vtJy?eK*tm9MyhA!Xh&eNI zEYv0#Rw1{1_Yt%fJ|$|r#LIT$rbbFVq6%jVzVW`IF6L{8ob|Z|T9X+^`HTlZ=yi{H zJx|C;%kG%Btwm6r|K8ZEy4{Bd3ZHjhcIl88)xHwA^&0hmFUQ!4S&zV{c<`%!7_)iJ zb+#w&eAjkW**QM|uTTGG+!;g^xpm`!l_s%O=r$7@9}xImO9Szb*WcY8H7c9`QN9~P zsL!p?*KSAc4uZyxopmAMPhAZ$)KHk;XScyTj@SC;c{d-SvPT%O4?3Fb$J?CudDi`* zb#%zvc5)zx#2j?@Lfc|9lA~WjOzh5j3aYz4fhcebL&6I#I;CToK-=u{{sx>3R0%rfbjK4A~Jgzm39UbRG)F zRe2YQ9He3RhjTLZ&shoj-+OixWcn}&#W*8_3^8c%O^sG_fe++N;aNykPuZLM<YbJYVM*I=S!C$ps`HUaeSOSUs|$0j{aXMWBFqoAJ9_ z?uF-BsH|K}Tp_Lui)^>*t8n}_q)qN2WZE}M-{PugLO}GPJ76`!QMs;D*S!89Pj)v} ze6ROV*kA0uarn7r1eo?xh}u_=%~(~T%$U!@Z*tErG~36v*W44VO-ypeyfH33Ngz`A z?rpg*MFi!<=119#0Oi5;ntil0*2E@))X;XFwh5dr^QYQ_6jm@{}u9I=>YW zE80?O4Bhy5CyF)6`sQxvzJ_%Q|BndD&Bhe z9UJ|A_~D1o=AhZ<%42}&KZk_k6P6sMKT5P=xXw@c-B>t$r;4__diFUef@kcep6Tz5 zpVRr~`)*`d=QU(`-_!0vEEvYtpYu4XbSo?OIc-R1sN3(%k#QUHP^CIulsp5=e3N13 zTgbM~-_*0@$A$LzFQnqH62w@uIGXU{>~R(!NUwsPFc~Ex-h_dxs4!qNzUO|zv9VQ_ zW%syOId_2%?a*(N+1y{{*7n!Cu*mDB_zz6Z^XQI*Dr5ENAHigiTFixi#e1*M>1E2_ z;b9*CyvEbeSDsPFu*%Depey8001Z{?9P*%dWo6v)fs^7GYsRMA(x!|ah@|WtX)(vf z*|;ln>KG4fZ|BaN=5$^Juknp17z>{nP2^7#5^EsNH8VbVziZJP7adC* zXW%ZZ*MA`ue<4Sf^azo{Lo7XB#xQ!l_$J*=;);7JoDt@v5Wq^T?poosb}cmC-Lyd_ zGAn-mbDEtx%e;lnDDEyY!ju4mbWq3=Z5(XT_BrDkgf?S1)MTY9v)zj>9LmemP6FLt z?YRy-Joh(QsfyK3gZ2R`Q;2zf^Jq^(p&8^AB8R+~3O0Mc>tR&!)HpDoO?=$TA0qTB zbd4QjaQNW1+itsdUxjYVoNH|h8;=p+jo>UFfKe$NZAQCc;`6Rdtc@DM46hU?j3?J>DUnQ`rS@9m?&rytXwd+)vXMQ4cY zJd2;nXS@0GM8iQjf);DHTKF?Pfy!IVt)lS#>+=bDksVYeI&a2z= zhN@7tlW^=a;G2}>v6?Ju?P(Z6|J$#QX*0SD^)j*wb6dFTHAniYJl?)KD#QpjO22{! z9a4bxJO~J0BVHP%(JgVjhbC~feC?~JRReNIg*s-VOh)iFhP#(-j)orxCZ|}?Y#$GyCGB^;sTsGQ{^_57Q8~P`@fd}Hw7qTH%k|&f`@|DZ zyy$o1h;}rpirDzP``z!p7NVMKW<8D93q7jg(RJ##KBjqgBg_l`G~6YmfTw1Tg#q_= zb__davx@*yS%Z<0=l(-uwvS(-fAUIy#&GGABX{GcJUI6~_~3(Q?UG=rJUJCZl7`8u zB53;wd=Omw_pO^6`85jbh>-J~hK2;}$|BRqLWzVInJ%Q_Cwv<>9kMVyZH_|6d>E%* zD#g;pQikf2?fhTsn)Rtn-Vw(1d!b=UyHq%MXt!D~C8k;{xBFWuR7Svj2Wb)*+Qhh+ zacV*zSa0a1gm8rcg9g0Z*qm~W@6_v1j>gXqg%oNe8E@kT{;P3yC_8>vUj3h^*pLo{ zq)*}N6ZHs{3f>CZT~HdI{?}ZRDZ|tCrVcqHJ9MiK2-SGL<8_U<33AmJ^W1}wl(`#6 zl%qMXH@Kra?b{(lqTvvVS^_5nYm}su9Cw9vX#AR`Elz%DT!*SC4k>@-v|r7Y7{xr^ zZ26|+Kh&^M4Ooa&x5D!5;88$`Rrq zLr#t-_r1J`M_TI-6N^(*Mih^OA%;P_FLh}5UM(u{RAWnBJhpyS2-Z3sA|%E`1EV(H zMnQJ*j({9Ew|mQF)+*EWJr0ymA|Psj=ySIr&3%ofF{Z>yEBK9*KJKx|KK%;hOi`)7 z4-y)(RnL6Yx-SAj!1j<22Q^7H>eC4idAWyvqr`hCi%?8M7u_Q)r=&{shk02wI4D3$ zM|(iX!bN=<4}8S1n(ckOF3O{xZFf5C^VhZxN!050DCO+)Uq!h08&5P-y-G_x`+VT3 zy^UQ%6lfJ?$EW;n?AmsG!#h>>@XyGFdB~6K@wQ_(B+Y}mng`J~HMzEH(*Nbdz5Hp< zs8IUl zFACnZ6nN*bYoXg2$!+CyhfB9oGH&UC^EG!ox$oshbAV3;lSNI@fOLkc)F~#+P%o*A zrIzjxK~11BD4ZVEee8v>DiG${QL+Swvg>VIJOic8g7P4iDhf)e@V>T-v+_n8@1-bt z^WEhz?Vm+I9*-E_cmNgPhYWzBdI83^a5%x*?MDnMkSXEA3uh!yL>9OA8cUu|cSt~& zM=D4NY;`j1%$au9@KTP%w;7|>S&!409a0{~-WUqNU+=ay6c6pFk~$=$h*IO zXui*yhkESo?|jU9ALnF3Ly|3pNo(LXl*rfu$2Tdr-afg|evp|?{1gf>m-2$@gpo_y z{X%vVoEwrCdOP2RRQzk=Pa6m77Pz5$j+lcIZoJ$zO$=diH>N8y-F<$mf~f&wn-$op z!VB&9`mSBG?PuV$QEVd!=HQGb$yr1^WASK)hVkin0EB@BY2lBso0qLgj)tw5Qh`;& zhEXDEX09bncn1Wlge>j1r+eDbEpmO-Z0AY+L-kG}4E54od&nSg&(PdALe|(dSx_5| zV~rQr?flj;+Q*Jz*26~3!(2D}(`U|`zp=NyS@h#|O_G(PWQUa3{_oyqy}_57*S2q0 z@UcgWLg8T+`H51-qXUIQ`d17a9nQ-^)+V^9^guUx6Y(t7$^ z`EED3+MeBr8a|x))W$j#yQ~^2^3d@z#+_Tn6?w@cul$@`hjCE!eJ@izJom{ngc+7ACK&PnbBgBvk9YY zyPeBonMrPf$+g z8zLyj>vy`?-Vg1!J$3l>v!DI!$&dZmkNrLmlEKwE)2)YHBi8q> zE#6%-+LhBeDj${q7!fs|cYfSG-(I84wyzI>v3Bhi7(;uG)WwH;{(!Rfy7X-iyLAk! z*lJizXm3y-{Hz>&r|;GU{?X?e$=Xxpjqe-YvMxCd^LgO=kqcKhRHcU6{O+Df)|@a^ z^Euj2h>HK_x{gl~Hf^&8h41d4^q&Fg`FGn^W~`cUrw}y?kR@B z5GI>Km-JQ!9J0_@rWmnsE@4BtFc?_6g{%nkA&k0jb?QTV>U9n69upyFk@057iv8T@ zK6kb##{lqHO#SoX@$DX|@AH}r?kUFuMn>56kf0rU-G%@DpYf{qRLF1l>S~nid-!WO zRA3R#`_2Q~@1QdBD4O`!wpKVRzXI5pSBdLSw_!TMcCSOb>&bV{3ECPq1k`*V=(PLu zJML9942Drq^P0@;Dg}a_k+B;j##MV8*R8^=@b7QNu*PwfASK^$T0=62lw*}l+q4^* zHE=p6H8>9`{~AxcL}x}gpTqMZCdNL-@g!1K!D?6Mq((@`VMjIep$5#%p=aCA-0N?R zsX7ZndWRJJK8`gW%Rin|pnS4wc*pkAF?#knuc1b!df?Fg_uv1bQ!drd39)X-*v?<& z1-V><&)jt@tuUb)K`ki!CLncj@5*QBkSE&vUU=d69unjEwvmBWA!q!Wl+~RXu4$qY zqu`M8+R=&jv4@b<1KH<{qUe^&8WmNLyYi`VNjdpVJa^tlfsZhiVcj+(JZQVp7r*$$ zGf%CFQ_8Qv-j!#SRNGlaR>ih^)@@69gO?2AZQ|QbyE3g&+nD2Xx zdDc$LCoh_nKL)@k%NlyxzAN@a20{7HTtIDR{X+2MzO;-UCZ(LVf0rTqI4h@X91<#g z)f^0GFgV*}pYx(>jPa2xVrm8V%$H{;siC=fPYF z2})kZv&ZdxFGB(oOLQB;JVO=-Axp_X2dY@@8&yVQP!)`qFTeO1)@9b7*ya0_=?s7& z*6bl=in@q>wrCg@(1hvB}N9o}lQ}W>expQ20giH(moe*k=B0-`?X)ZTJ%j?v zpY=NB>R0>SWX7%y_bW?#_kMS7{BAxV26n z;v0itl)>Z(@Umss*RvVg75pL3&KT^Fu)W4&kwfC~Q(u+)uIMd5p9$nD4}!8DbK&fH zpEk_@<8eT4lvj^zt{r}uIng#k$4PEOazu&*?5Fxo8^+*rGGjB1DP-fpNY$sghmnTY z>Vb^cKfgKouzXCILA9JbhgauXJ3B_X40>QZ@T#)rTE`DtAB4X;hV-R}WVxs4n%~m_ZS6J3+M#^&3Kf`pW{u77 zlHeM9FXD(8+6)M%_w5ELLzZId384)28aYA)yCKs!c~K|pw8jHR1lnK>B>MGe>KZ8S zX>6SwhQKxHPQS>FhA#TJ+#07stj$5uPDVqGZ#f5Kg0je^^2wArsOiZCj`3eei{_&r z{pg360QpbXNo7;1#fkJD?hZgyET+czLoEbR#YBB?8-0tQ)5tFm1SM$%ESZR&THM3r+ZI% zss?7)@NS^^9dh&auYdioJ^b*)|L5uM$pxhAPA(w5;~np~_vV{#{)=mJZ}5S}$)TBe+IORZK<0oN`?qS}&K^e;U4)0Vk8e{V`e zc*|X}7Q7e9LiL~#?~JguE1*Val|a{k&rN=;VK(zSVf#{#)@SRT z3{tkX?`2Es>zvj|8tS1*)>32hh4J^00B2x#9IW3%TdRxybXODu*nNlcaPXmWiZIq` zn{i*^v0q+Z|KC5kpkDulRQ&IG&wJjonEx-XiM>JgDZxXK?+H|x5mOa93VD`v)H8{@D9Ody0cA&`hvX;TtG615_2(yF0V z_un6B)mC!VN^QDDKlP7FQCl@_{z*xcbRh+s1Vh5U1OhdIuy4le*kEu1_MAT7XWq~8 z=Uns7c$RZ!&ikC}E4_NRXStvIzV2(kuN#I`&w*gm4iaecGNS`kLtbW`Ta!iLBV-Wv zj+rqDEcE$rnZgk;Suz2`%;GwZg-_{JCN9=|)yCPk+aZvE|2UWPe7=R66LVnDwiX#j zgpfTPC>*xb36mf+sxUUKz$h4FlAiEv;6b1dy_zELQA}|O(+>z_lm}>q&73TVP#Sp_ zggpPjm^l~PMmQlHOe3TNKa?}Ul${WKqQegn^qazk6;L)8LzA2_5?JwBDUR-QwD!Ry@L(7O}(pzG=# z@pa%?UQ+Gn1<73)=gV71?`sSGRl@%L`wxtk^Bcwi-3J3_;9-amm))%pEDQjGA~^)t z5ya>T#>7D2F!^2m&GAzN3`{TQd(C&iR=vciVM+i7NgJ?2?3S#;+wm|nHlGK~z^m{_ zL1ErHn1c0wa+dV0LU*`ePpGPvL(tnZlv>D4;?zxf`63| zSN|w1-!Km5z9eaQ*${+b&Dk(P1TYiF%YcOsi9Qyd6s_O9eR}W?=WPnH&?%@y6;c33xsy z)!B-5aiUzKPHu-TU|KacXcsHYm+#O9j2NpBWq~+5&+9&p_ro;AaWFcb*Gx9wqu`Nj z2h*}Ll4G%05d?wh(+m;ek^4Z4xj(V(>h5KmT08-SVZ0&(4@TPMtyE24C<+1NS9e#W z9XZEIV)>8X?Ln||gWK93BIw6V-{-l|4FcbZte!`CaZMCX`pH5QD;*^SuL#$3Y@GA0 zNYGa(E%c#EmXS$VGv$TVGF*-RvlA>QQ&RCN(s!g zti4w&i5Co$ap4`sflPi2U;56=2ptoxg1s^?JU%?9lj^t!OquJM@gmGa1Kh`68JHY& z>B1#ga5WZ=Qs((Ug)_z#df*xA@r z-)jzrUC@3`3nb>9H;zK-GW3U)dyb=T;I}qTcz50m zV}bXTK6CLlp3nJT0%_Ndbj6EI`6 zqTqg@Z)qRQn0qc0o_5F5mk8zng~E*8mJ-(^IgY+}eBa4(ZmX3wm_ZFS1Xa2QKeyMol}p zhnFi>*D=D{0urIg^FupMjI~vX(qjeRZ88mV586ii?NzfIo8vgA&N+J&JboO*^O=UM zY|>xAO0L65)xfaD>x5PdPlt!9^2WLLct8W>9C$wGJIn0qSXRY{L{_d{`6gZ>iWi|2 zb3J&q4F?->rsX;&ZZ~}d{ZKM{e2&}ZEcj=+jvp|nHG4Qj%0BaGeongbc8&axwPx)! zfXMlcP=PIbPnt@cw&*w?_bQrkVAmuQDgR|909$cpDPWSttm%5Pd1BK)W>B6Cd5@4s z*xM@tvqj6d^=o%qK;PRvO}_^8s|6(%Ds968&5JeYRcT`Fy)C!B3cWZM$n%@A+Et7q z0kfn}U{+>cWKi=g_LkTMioymRz>G`>2vZ9fTjkIW3ZMn9|K~hh+@=RxM!uf~p9PeK zEs2Jl&vmh~s9r}nAfKz--UU)DM7cl5N2#Sg0ah5}Z6(smwmmrXH?+qXKszW{DBF%h zGnYA!7vn_#_&fLJ8qC-H&I%&vh)tiE6ZX_N$v#eMj_Dh#G6o{PSrJyu$HUY^zA4m^I05p8FV+ORSmK&OPisCB}e zXWk#L2-6%eON;-y>#mzz{o`P6Wc8b2!eFW^6UGda@?^IrYT@hHqqW!SO6B_b4&m7v zbG*$0l=}qvOfCVgFxr>T6aewsYG8|nYrz2gIoFCXPl1l)6~x-N;I4TRH7g%?G{@Vm zYAe%>%Zw?gRy|3B^b;{;`Z@P@c*ac5mZVGe+S;&yb#*Tk8(TRZGkY3%rmD1MZWoVLJJss+nr&GSPyjqGC{hk} z(5@u+-GBf6E%;XnH{Ep8RKRB(;C(P6+>bRL578mSY#n%VLu_VhwtSo);6xf{8hf27 zOQUQh+sX(W`*U0u295_IumGflCpiFB0r2zW{0RHR@N+z+JDCIsWNX^CsD*h=TH;lOot2_$ z*;=`@0Ovc`Mqr!15RlxFeGiUz2xiZo%_W|#6e6%uJee;jIu`sMM?aG-SKzi(>(ib?1gH~4?UC~w zWDFQjXwh`TT8uk3*9G(%S z7B7jzLns3FidZ?fQ3F4)l47NRzGnV$ZIoZG>s12wNTF=d@9+&PX6|!nxO&W>7t+^)L2&0K8#+B0AmC}YKPFS{De{AoMmWTB3S1uM@9 zh5T>DiN3J)Ym1JyxeYbZj{5buA) zbP?dHM|tP^+&jmSyykMdj!ApGz0J3OXD(VHad?P+b49y4*3bvu7F*3I*M2tojY^aV zN6xhe(ux8!MY|jtwX)|vw)ZK37vddq&3#+?4y$;+GcI@^7#j>R_%4dND*Qfv zFj4MrHzw`ncP3q`>~T)OM6iq67O-9Vw#@mB{-W|A&&@MY^EY)uAsiQ1Cl zCDWd&Y8YWK`SZ7zY>pOq^CGw1 zR(@50?Ip=LEL{D)oNtwofw!Q*I>~2ZeoQ#DM7v>a9pe7R-3DRvZjBPg1fjv$VD4Be zRGso7TjPcSIdeG2&_{-aG)w`H1lMrv)iFcICTnFi z`o1RNxbTN9r`+3Cr9Crtar#<3w=H_F@wTh6E}g^@r=JnTY;I($#coR{&Cz!EPfgrn zt5Y*PGg8jWZy6t#k%fVpx!WT0e=dTMoqL3qePYjpu~JL-tVMPUaZ;g8s#tM*+g6Up;n=C&J8% zJTLf!`^t1md+0xVt;lyl@S*t79xHn_?BKc1J^2m|62gQ>S{bCTNmj1B1{yM7u3jdG z7ojtIW5^3K--Ui@5A)aFB-&2VBIiq3QRf`SXPD{kwZUvH{&A3hX8d?AWi-j?MG$%7 z5FbTY1h!@&QVVgri}M+w#{>>+y+d3OZnfr^CUddAC^EBV zVlQ(A!)zSev^B_o^oNhP5`{)?7aocVOptzH@&_nOww~xi+JGQHfO#bX{b-jr?J{E~ zsRt#D@pcG;{;)Rz=3zl*s~JWM?eK1I0AUK}9MDc^&6bM2Oja^j*@3InG|IWvLxJ$J zg_Y~GKSaJ$Bf;&@st=S`m+^(BOuJZoR!pD=#swNAHcQ`G*@oHI&2^Yd_R6Hq2ylBi zxGzeA$AWp!IaU%qXFaz(A4#OM^5f5TXEV<&$hnTk-t*h@nE%}_!VU;d<{-k^VUF4! zcvB6z@C^34SfONoo7eHoJd=g0Eo&dk|6GUrnSXgFPw0y0cl@4w1o#rq!(1mXhB^^= zE1~~v(lfr_*0uUq3A-@_}|u*l^-U&3yL5pxwkDw3%&q1u`LrO zw8zEX1;^@aiO^THh4Hc5k+F2F63dVC?UkV2^fgR~bL)mT0ppIqff*qfImS#rz};-Y zY!^JwVWrX58|OTtWG@TY+Nbtx*ea_6%?#MI#@JU2jpyQ-EZ{AG`9IetJj8R_Eo-aL zaeLzaUg<&GEfjoRo;^T`vC;M-HmmPDQ6>5)B^*}m|;Lwl_3HsL8#ZzGq7)k@E^UBJUy_@!$T1jBF0rX>|g>l4_ z2&@2dZRR<2Ln3Rii1EL*1^2t>2g2;k`d&3|pHJane z{I(#VpowFU4i(hU4DI6HrZxJLo#)I{t#I)fAx%Fx9`0BxeZ#onnV?@CW~df8G{ZPR ziymVaS3&66+hK))dqXeu5y_NRuwC)b%R)UyRw@F1BV=Gj!SmN4!DXQVD`>QzKK1xQ z2k-)i_qaauEXSCh0w;3vEO-NW2981LsNOETB30S5(rD}50zBU_AfN-&D%Z0@>F^!x zbG1!-pYR4+X`vm^f)!EoCbz{r1f{^w>4Zx7U;1TyzxCdG@9pHiRYC-R3iylzKUMBy z0zr@@1lbi8Ldvla5zNrbr4T4)!hw|lPka-l1r&sr|A_N?&1`;mT-FTPmIPKU=kjjr zp=$V?YZsdpi3-Ob`R++ddjoq2=s&LM@|ffa&>n{^=+_({ka>&tA6SSm9s$hQZssU+ zp6CJAGHb?RQZPFhD!-$k@XW*=tqjpOgbAP*3pXo}UQz^ufoMs71BR` zZhm)?AZ@Wljmwhua-72ob``o!Fg-I#1fGSsg&^nCPA73%p$d+5|G-un$9jc>+hV$M z7=iO(bXY|&b>fk(l4n81v$%c4`e~bKppKsvRXiKC&HYb15xkxUrdf`$V5G>B=LYvg zncz5w&+OKPPH2z4cn*6p-n6fV#ppN2!GeJPLby~V-d+KZMHCa3x7zBo!p3(irJi>j zV_xHN#zSd~9eVa$<~}3{q9|CwaiJ`D3S(s@7X2`xUjnD zAI2Zcux|8Yi=(LB*1N*h} zJT>P6wieapQ}XH~g^=4{nNvna_`dCRd;j9A%YuLNzu zn*?1uUxPkzoqUvD#?Q)zt#s%LuL7=g=#^)*(qVZe~3)-1oYa&NB!$}@fJVo;Ql#@m6AcRxGq ziuVVeVXrHzW^(<7#ovN|m2l&YH|`%N>g4K=E6Fk3Ws}YBM~K3)JkEi^SSUC<9R?6E zi328(UD|dXB8*@dOcr|}YT_15mQ@SZU;{H&{^ObQU(U4<&2JR+p}$Dm63Xx-bS?skjJfx83R}ZcK19UFTl}E(KhzYhNQZ9!T7@)#TmO7z4X|VS4U& z+Gh*W$#_;6+$IDk0?2eq@*C%PWrBsUl@Bv(+Q)byILSGv9v_#K&hOr0mEXNT155DC z@O{4NpWmQEXomm1vcdwCem8wHPOe+eeH?bOb?eP&>>@`<+U4(D66U%sU*@^p-q3~> zVgwi-r0P|3*wOr=D#8}x_7qsDGylQBu*K|q+sjh>wT`3vruHG%v64>P;SbdVX2EYI z$>WDH!Ack4>)E>kAM>2&dEimUqNgA{2G0_7olSZkc;JEe4l~7UOZJXd_(qJM*pCIL zHDoi$DrlF*9bqO27%UJoZNHo02N0rT$lN>N+Aw+AZ8yCwXC`b2cv(^m_h5pdJv*r@ zfXUfnwsk{a&@MA~CM$i3a5od>zK%WGTTvM!_X)VSEqX#CZnu>(n3FAz>Skmt?Mh|* z=@Ta^B5+_#%ajYw31FB!17lUK88#AOjL+2)O3tAlv9P(9-K_TP@O+FzwYs1qTiRBF z=^MgV(3EM*Zf~v!tw9sCi{r4&88g$e6#;08ImvxJC+x+r0)&@Fqb*T^PhVXM&jDE zopJZQF+OY**n@;+ZjY-o?%^S{-M`U)R<59F=mmwumHs?$&DY@xULMT7Q4FD{^uc(Y zTmRPI`djb2{r212;$Ia!=Q+=rYW0tUJHEZPoPYg8Y z{1RWYDqObg>=CggWbczb3)NN3SX;4lm$Tn#;3~ZHFh7J*aOq1(bIAY1LmfUpU@KP1T)zacKeeAG;`_2h> z2t&rF=1SP>WiOZCd0vO3%&ZwBXayyJRFs&;fXp8S@=1n_^?FP#fVrbDT6Kwg@ ze+W_MPy`PDLA$t+`D~AZX`Sb@(4swfdHAok4;rZongt>K;_wc%!(4^NQKn5Z^qJk^ z_Mp)&D->2bd3Gx(folnPOqVH|=25oJ0dteFbsSw~Ses4L#R9=S1b2Cg1&0!(&_XFt zZwLen?pmzD9f}l}qNP-E3GUWn2~gY#THK3&dB4B;vAM3jXJ>cLoO7l%rraLTW%?ic z19@5Fakw8c;MYJZ4vC-z=gqCu}8Dl<%v^f3iTQ40L|%!8_|wRzYbrI zR#kPZc4za@#3>J@=L+)$tn0a5GQY=YbYkoj{)_u%%60z6`gto$faQZHW^eGnf5dq0 zh^v>nt$bSb*>f%a(J17ei?Fkh`k1an#%p3gqE7bOTl3q;Ll}V3XsM}%=#1!qQ*a*SrY5A$-+mIgL(;9b!K>nAoU63s(GTiip9&aB52h#;^OeW)~2XA^XFp&ygR92dT>686H~;J{2ju2mzWUElZIUEod1rKsJsGM!;+ zQh_8c1jn_r3@b4`L*X_SMqQ7149)rBgxwB8EAX^Z3ZW?0L=yv!zGQLku5fZYmI?&R zGM$@R->Dc-#qeeYyuqT#I6EP7UU?cBv3&FmBH?&-B1P0e)qi6hqNV1^*(Xo@%q>-! z?in47O;4=vKC++O80Kc)zo&pWJ&{Q#4b3W9ZlAC`9X0PLWExc~YX!fHDD-rloH?)d za1|AWks2CW08*|z#Xu}I_JlxA9yfYBW8z0~|08b#t~PUiEMG8u{&LdR{qqu(Nzp);-9m4`^&ZJ@Pam?xo0UcNJN~hQ&kdM!24%=!^^cP2a4?Qmd?Y{<|o} zs};;x4h#k7d~xw)7Ke%4=YAIIB7r_7zaP31?l1Z`mp*2sdjd$oItQye3tF&BRXTOd zq&aTS^nDs1eL5`Vc~%LLy``l~HU6jwp^A0vI{ELt1NFR%R%T*;u~DH2IWU6Fpr#JL zeRYz0G8IQiLgzvUg->a~USOduAbKs?l-*gkBQ90yEWu)2G6{LMP<;Ew34}zha8i`&L{#+AQkNW*lh+eg+972gEq~jlMJdAp9ZXvoL44t1i@+(Jr8vc$Piwym;G?4o{Amx5L7b zmjPs530U=J+qTp))UC#v;J6gVr#CqvElZ3Gx9{k-PwcCT z^t&DgqqJqB^nA5s0%cm7ai2cBHs@foPU3!+KHnr^t6P$xKEB?g5VL_^8xf4q=j4iHod-Vb|0%R ziJLN=*Rn%26G725F-qT=JAT(5hQjGOrb-`9t$YeF4cuIjyN;~gsBaeU|Epsumh)LV z2mpJ%MQq%wl;9A?5$0BbwQW5T!*Y2pn$n3T<1c*F8%1d@*wJn-L3mC98KPxRO;iHf zr0~W=(KU-`9dov+?gKUJ?ei?Sw?3YEm}AM+wEXpoPlW zVnfqRR1*W5^ZEmd4)*&4eujTlyV)AMe|!4KgL|;FQHg$?Zi}nOkLM{R04P#{z(_c+ zJO|N$&On($OZ{{9`4Oox`TG+Eyl?ZE*PVW*Zb)lV?)=sE>;q^a>_i7UvKvj}K}+M# zLjgb6h6C)mZ*@b&*>p{itd0U}q03id7Yq);EYD z{~?X*=5OWy9KeNfwjR;w`u#mz%9q9tTjMG;eCK_931xbmENrh9(C_YLpfTgB<(!zt zOu}T+=fdexFa#~i=$)o~kupyd4vGa5#kSVJ0;SItlbDVp1Of@?QK|{qmMu0wD!Q zFOz?|e&i8T6V!0cemxP{xjlR9t9~$7v#QGp4h*JJvfphP6Dn z7HRy*Mp4gB2ISZpA`I=0-NvNLGIo(TF59iM!+8%^SHO8)?lMB8wU@{^Jqz#pA8ZXK zZ((l-&5@&dt03>aeKxI-i*`2-gW5>fI$`I?kjYRvJ^0>+pjv__3^{CiP(xkZ^IJVG zmo+bc9@Aml6zDf?5m7k(x01om;A=kP`#DpNym3DQST@jkqz^vI#ebP4Rk1=^YU!l} zec3l{`LOL{%vJW6wRWlb86TT#SWfA~gJG53T?pq&eAqCj>awAul55#ewPw-w_V&jg zZbq!(WCc!!zb#7s8lSt1xDB$93(mUgYUXbenXJJ ztN)c)c{;3*Fgv7b03yad)!XM&R6XSHMj7jN_iiXaaO@3GFepe&9ZTh zY%Szp&N2B;f37)UZM$b5rjzUe^2RdHhwe(LDO#MYcb5a47D0 zgy9Z1ZStpYf{tp?dv%8uxd0#$);R)n_vDa4G1N{e%!+L*L1nZ@i#}}IA$QbSB>K-D-C~btH?qig!!z`#v-Zt zE*pk96Ab_SZF5fLYuE}H7#ux>$=*QTd%y&(b5b7QT^i5Kx(vzKdm z(6BCbj*b54Th7S_nP12Lf7Z;&g-$}Htz9EjUZu{WM<3@)vFsRDej4PcP!QQbQM#1< z_8Zn*Vgo*|V|Sb$h&hC-LBn2S{+ zbHGd~=_}+YzmrMN;GU7pqY}Q1jWy39m)eMq>PBh_UyE%nn|+=A-$SmT$KEa3Qk^yR zl1dbiS~!`FQ-~(RwTpt{&Avd(^}Y$wP+Tbx`vnpt#?eG;uSS&VxRhS1F@|xKBp)0| zmy+EbF-3ncEJfl$a_|QxmSC$6}s7wRTao3V!79pzFqu>s&HmRc`(4&s6^g zw2ZnG?!K}hl7c1n5-8x!Bkt;c(#q^6O8iIT*WI#v9$87=vTt7BPa`m`=o$9uW%552 zOeV_QDl0GNoA#`6M^fOyyPzol0}8m*k>aWvlX+m6=>aw?@-SU04{A27Q+j)~-_~Y% z{WE;Kye;s@oB~5;{P>c_OMTuSyC|z6%_~C9x-~3a3 z3ux+TSv6VLj8dQG!BhG0?{0U&wiJUWJA2h@sXngK#AAg4-mX{KguAtTj}S;{H~~n2 zAjH^Y7_6*bEIw6-p$;k6K@K<=!$#);y{QqW7XVQ1hmSol3ZW^Zaw+D#Hk zVCVScYD0n4<=1yer?lxVYr)Ap!e&9xP8w*7mWhqhs%aE?jrQk^Jy3bhLH7+9{^Zyn zJv*Zlg16)a>CWM7*yQznB_1?+vyM&f5zlC_Fa5`*Ecyvs#eCm4wZ*$EZcE8rkkXa< z$)^o{<^tcBo9r{$+n%llGu1D37m4bs?6b+}t`=B(pE@}n6k0)_qO|%)zj9^^~4ZiiiF%F~-p<(sUnKG$3 zC|^i-&_n!boI;d$o?C9f7x@WY^xh$C?Y3Mb?`8wG>7s;zQl7S@v)MJ+3P*0rSSvNe zE&95G37MI8I8t|3Fm=D+Pie-wpO{@@{>N5Jj>@;@6Hv0a-cVvnik^N6583<@rc>j^eviq((#7m*8UfR7a_Xk8Ym#!M);H_VCN}XZVx?0QFGqm;)*z|4alK{ zF6338MIX+MOM7?bZKc1V00tr2;}e8^xeZfD45T70jC5FqGin`9X&lbMh&O37-yN5*$o$4QTN2?3oov@1 zxI42^jKL0$xOgK5auS!8IfOFi&md%FNFUkB@P=fwrAl12BlvYWF-H69$C~|-2vhho^0t!Q}&mzO8oWvJyQH|2OcAfP0?OSmN1oyNu2 zF8KDxf^5{QUF7nyG@+CA+>;tW6*Ca^7TSts>sRok7UT@vKGw6nQ1KTA-GPN%I@+Gp z?=^0JDYCqCVcYkan0Gsc*P{aD7oVF$gV zr(IB#8cpX+SVuT7bY`*P; z8fT$^+C}uX_h;_w&gRZ8=MZ21G{q229lj7{M6+Ea@SG~|7P$`6iIWWe6Thwq9>TZv zE__KeOk+AcoyYR$i%wVyX?y=r#4=VruJS;#rxNzIKPgQU7Nwq>JlRnV?@&%pVE*Ns zEpcEmb?RjFy+3q*Yf$AFFr$0ruYz)dY6a$bKJh@jkqB_T#guG=2@T=w+4sS^rN?pgZ}^+WOq4RWnak5yzLtrmwq zariSmrmvvl%(S2;6PQDyHppeseiWh3!z1$+oLl=?OhD#ZlY|?_|w~q9F-#3eAd8 zT&sms4zu(7fxU%mtt#4GIetKbC927c`ik-b$qTmlFnT|wt@H2LrPfI0L#QEO&)AX2A&v>ei>t( z;F#N5MIREXk^h?4P$gaNnrJsOsEV&!_Avt=2B;=?BNNrqU47Iw^Yx@9?Y|jXeNEjw z?ORMt>UHmFX~j_qWyjsb(>;U~2h{h#9{<*4=ul4B19xxdnI`jPmj@PKmNHdC*+Lwikq~`AE7J1ms@pfE)tcwa->=k7 z&A@$kNoipPZDP&MBS@Eno6z?>A&*rNSRUiuN9OP0qABRXo$1OoCiv#;r6u%*hawj( z879iy4NiJ+J@}n1Vfhv|_2LPK1JXaM$f_JAVdlFW!Cv!1eDMB0EB6eNmUck6r7$tE z`lZp<f?W?|(^W}&3Lf4JrI3nnP`!_N&*YU!yFsQl{2%aT zvmBQ$V&(wUTl#KqGpw;@0woM7Hv#^9CsPpATYHb;;L#ZIZUPic-CGw|c8e!_hQBxv z{&{DM7b7V+II|P)IGN17vn!_idj2RXri)4pylYg4B1f9XH}sbB%!%I|UR=_e8kp>KqBs#d$lb5B7*UzrAyZ-}AGfr#t>`e#XZPxi?1U%%?S$V>hxT=sV zCd%x^E#k{=4a{JYyt~QFpslC~+D1kKCbAP4K~pb(@^DtHphV2D9`=l?Z)QNVZMMHF z`C&|f3A%s?;RWQK+5a1PM)SaDjwRv`4oOQII!_Uz0_dxPILlpSWw8XKWb&z+Vhq<_ zD4>4Cf{t@lt3Gu=k0_{nGo)%hE^a`CcelRtlAwC)%QPKe9)-5-qHhR`pK&-WXZdqu z_=m}W=HZq3wWEy@GB-BoO#p>+^olbr9WV957W*+E6%@yHnH6q0vtC-2+5F(Q{%6-0%u$#6A2CMo9Ts~wk@>vAVGj6%rumHKSq9|pib_~x&&<4In$4U91E zBg(^>g!u;fz-rx<*HYngnp8Ob`CBci00RDHrEe5AHoxQw$tVq)*?{_&vq;XFBo@bg z(N`AiuZEF1^S2xWs>dQ;=vA=HW;-k~4U&gRm&94EjpGt}9Li~KI_fiFyR{bAh4Jm7 z%#Ae~ZkFSjV8wIS-Gx0rx)GIi7Qd8yaZ5U; zcl&R&4oqhLo*BBAQ0NE1dOvLMBsnhn_j~eB#twov4xIlt-)AwO7i<%4SdQZ+LnX&f zxbR}>0J=ybgopPctaRp~%RmIqS!Y^YYcL-*bIQ@azG|H^mn30hZLy9Tf0;JSAZM$$f9vr#(Y#JeN8^ zWpyW~3nZ+w5xuf;_$dIrPB-y|vo{_?Bj*RbF}oaklEYdNA^e1-V86ahTr`S)r?hgi zYf}3=KOrWL^HIOcdi%orzyG=CzZqa!->bkkZveK?wvrR+GZ9LzHiwADvyhDvX5n>~ z^IEbn&wv1E1eV6dTJrp@$os$|Oi3JKB-{*pE~gNK_Taorq>CuySSSB$N&y{{F3xj& zpjo?n;{1l7fEpFAI3f4aSAJ%-68+Lv^>4Rk{;Q3g+3g0Ll74GM*V`g&(DpZiK{V_x z5BbIX!-&iFsHp7AXMvP5CGIjr2z)Q259`(>&06wc_9mZYpn=G-XkiOOH4)mMtqh8? zjHZ(`s$q>RCWuVN;8g+32a73M;eK0`e-cR)*X+PK|GPr!8{ zmImO}Tc{bQt0=n*F;N7rK4bob!*x08QCOc45zoZu^Otp>2*gLD(DE|!0wU`^ssHsE zu*%GR#1=V@ebuM`gq3~UCG#Olog2~%eYN)@jo>m2L(FJ=A7%Pb~$&UcS4U@v5gFx)f@=W zf4^QlNX~9U<31x&%@XC_xR#EHY_KSsJ=(KHn975Y=Dc4BRzk>)+Ib!mMfavthK^^8 zGY;-aH}xZD{%q9AyKIldO%qMSD9#1)tVRFAK}1&{XLHw8D<4G@R0=uw^dSi;CsSXX z3e>Hbzn>WVYLp69#-W8WK3(ObuZ%B08|9-(bKdNuJxf%?2P{Ss-j6;Nrftv@*mrY?XdeE{S(E<7N}Z8URUv*;iFERUg(uuEY!$P38fuDivLIJW7-cZA(fzj`b#_w4yY zln@0F=S;rP!7@e1Sq{gc2_1#;Q?gfUEk>(!6}Tz18Yoc=`U6+hD-mzGv%fF zLIn|@%eUqJ8ME|mY@B?q>m6RLN^@NcQLXs&+;Mo!%zM!YUnL3o<i# zViKTDW|n273wKTUr%10VG}=$R?P?VH$>9;H(!wck^GK>D=#1$=Z;l(e>|1Fc+xitl zPclfH%6*@;z3cT1v`RDcx2(7=Cd8wU!tKt#dC> z-P)SMFN}LxN(A6^hCC01(ITYTn*@{sUx-h}0TP)3h@M@-eo>x=T z7y412Y{IEQH7@6FEK(q5+M3j}Zk)Em(@bVFTh_Let;2#4Pji>PXs{F3`!!LJCY=|u zu`~yz9ACzh!f;S6CQ^&4CR!({5uv#nIHLBhlxjNp^9`0oFKH+bPb!X&Op%jM-m^*kePlFnvbq2qj3VhA_k$)s?Az?aI;=aj&!M(D?jC zu!Z#u`A)-;G5;T=YmQ1#2&2Beu*Lv+Gd3*k>H5P{k^-v3>vckr=sE7hIK1<<#WIXp zNYownSghUGTXb>`bKD-wo^N=sekV&Da*^-X<@-Qcgku%nFlw1_=wY)C3Z3ss-Q;Fx z#6!;S%SUKX?4>*-HhD$&;?ATw?!VofctP%fFMR&LgdACeHe62g&wyT7Q zlvpZUv~{=F1#Pe6cHW}7)@?p|D%mE^F3SE>q}lbJJLQe!`wLAZUO(PP1I#aE# zrY_?rVfXuj(d+3^mY_31$Cj@m*OPLO_LQ{kl?L2xT+Hk+w6d7;W|gBe@FL#iKURgj z(~7yvJ(Ta)2yvWMd76r_NcUX6l0`?nhXnv+&9D~IuytEZTk`hx!V5~FX-9HujW$+H zWzfQXqwAIgy!eIUmN@1xF|2Vvgp6xyby)KoZ1TlYrsCk7URNgvGL+8SDaKLV?m@0P zx*pldVd>*A^JM7V9`Ze<&?;(bG(5yz!r5%yrAC>9@FDwA3D9X##;tiYpihPb{Z#zh zrZ7StQ~^!wVt}7|li?<`gDv9^#Jm#&5wjm=a-E7}P{&#FGvb?4T5kVLpSI(g0BOtw ziS$IkbBP@_WMpW)INP3qaIae6Tpf1d%i@relQpS#;&d)r%(O|* zw*W6+dHAcgWq>m-!l#oIl&YsyW*do&PmeL#H=Nwc)=_+w>v=KnVtDzxlU$cPL+Tvp z#5`tG{z2VOePqQ~=02D$odWZaw5rr0Tsb9Uocv7VkNdfoc(iXIB?V=BSCoPzt~wcB zy{NLsq`Ts`rH$w^PH}|)*V7pJ;sL)ebTe_rwI<$M9Rs^8Ae*tK{m}REICv{b%F>C@ zxfX!&xx_e@Zu#Vs?bcIciEeBivlfYr|K?Q#nMEOJw%xNY@ur=&iG;_~Z=bT~WcK?` zbn1Lz6n$QB&)O?cS*JXqHlo>nG?wyijO+LT^y2~XVjmYdJI{$YZov3QgSKzA-W{l0 zzPAM2V5T^HDhF+asg~xzW4_X6U47|_2=Ux*IbWD9!@Dtnart-}cbJmkx!+5~WARzz zuf01w_ZTz}5gQK>k#UzO!A`c%H75H$ zFR`c+=!qU2%3#A#LtGqve35uu8czn%xlCar^wz|)llgBL4(2$*4hpD2s(YGZ&b=`k zRAC*b&zi&@Ud%h9RZJ83yQmuE-x7IhXN8;%>r0~B z=kn1m_E7+CT;~zYu2hMggG|-T*Z(ca z(5$pNNLd=f-p?6s*t``oZ5lgLgRziwk^E8_(Q5cAr|W!jC$0cL{c{Z6lq5fON^beky`pDR01^dsy1?3|v6AF{o6El%!DC9k zbrtFlsv@5ua^YmhC7^HlBUE+L?@~n<@r18Kml?BC4w?KXUqR-C3+at>qg1BHJcAs_`kBR8zl;F=oVZR2$kVcj}*Zn^EnBG!yG#$cA^pRLFEZF zD4bKmp`=12sP%D zCBC^OdY`7?nPga@0CH!vAVtF7{s-oKXO{>WX7GP)v*T8T4njC^rq3^r!7-|+)$&re@Kdm*x>u(#))^ipgls zLOtg>N|*Rv|RSHS^!cD_1+Epv{sAb6J+hAX_MOQQ9^j_ z{{Lp~3N2G4`2{GXfR=Y+0F331?}j!j3y!nA*5NLCR3%-(@>5j`G8H`EiNH2iL_(`{ zQx-t;vk>9B#7a6K2e<5)Jpbyu@o~q|E%6^EZvB>!T%D zt@o?+JJk0=m0mJim+!95rrFM$5ep2$f3W5?9*NAy90k7&vsN1H z5);oo{}~o;{P^Imx-7_k|KN#TH}1s+wJBJ%Bkp7V$jt|q3kH`q73P{g%SRtQhelrc z&u;$R$4iDf@$wehhX;vaO_j>r4?k!?Sa<4mcuArMyP17g4uaxY0g!$NdrxX1;*?$x zq}#>D@*JF=q)86(G^nVWpwg_wt_3RfHg%7HCZ#J_J~xg8vo;EkOLv&tY~%z78v`>z zWfn6Ix(QcC?w%aeAX>egtHiRVc&~2Q+&xA#T{R$4FzK%IH3uqcONsY4CVYD~CXdgxVTeRSY97&F6$%B+Mf&Z zp~8dA$dUsFtyK<6+1?IQ3U(#f$q(%TT*uV9;nuVB#0XiOGjD&bN9$G}bX0cupCabB z&d(agnYTmay%-8F>Wl`}ke|V@9?1>yGag?@$qhUvtmtO0CWtcePLFXUs@$HN$gVyT z|K%L-E|E4uBqTDCHW}UZ?Kt1WEWx#_yX9jxfN9dh^nq8}A)+?i_;sZ13Tj5@!e}L< z!6xv1LA9KI)28MU2PsO}DOZL*>z|%#xllzx&rFS1f3=&6P&FMQkZfpxVU7Hf6Q_zQx24uKN8Dz?wurx_?1T)>?n=S zvjl=A0|s10XwGIvNG&dgn?lN18S@6X_(b0;MUp_-Sz$DGw3ZgGG?u#;nCeg0?ULW5 z4OJqs%z~I>XigMj-g&vPZ2wsT)vjhpnCk(GlY7P{k+u&}*un1jsN-$KQRpW-Ypl|9 zdD7=p+VAfs@H{v-H0VyLOK%yR$ZG$*R0OdBWB`VMzsng?@_^~%Cez;wi<5vusj5$s zS)kb5cnr62=~{?rkAo&gFFIO8QzJVr{!=2Ocqj6J`b0DL+BY; zrp<1bl4h7(;pDuMJcKgQVR*(VYa=*yJoEACG=SSG!O*Xr-vEEu6#~{9R;})bSDI|? zWXB}CBqm)|lzpx9aNHh8inmrLB}L@75QfAv)v4Xs8sY7#zN#3)MveDoj#FBzEQY=O z&i+1%;Nl4Uu}uFjSmmL-9>+Um+3aJS>G*b7Csn@e;twuK6x9p9=6Ci9nZ--o?AAJd9shf22im*gF2Eh{1IMSrPvhC6r62 zN7taYxQm^_0~I7F(B_g7*)LZa$xpXC9Iiwr5Cpi8q>9<*XMzg3WcW;J*v$->ubYRM zi^eS~W$dGQO5GH723*ud5oc6}-z#;~TI-5kCW}nUY%Io$S=*gjoKiNz^Pmgf@!7o6 z6M?Gd!V83m>piv06xE}butahq^ex7A47g@7uQjF`Oml1&F55S{@FVybdTLBb-P?a+ z?)b+uRjI4t?A`c*$)*5>{(6KxJE85f=$0sSLW9k{#PwV#R}?9jxcpap_M_$6PLiPu zIOQbA_R6z8+Qg&{g`0jU*taERFciuTQnuW=uuu*DMA(KbDcxLle#GmsOUT5)BxnkT z4>Ka03&(mkh9rhqk?Em}W&Q}AkolE`W|Gh!dfehuhtf<$LX;$y3U$J7OZ%e$DLx2i zJvJFx$4jrTvd@5wO%aKVVHIaNgjAYU!d-(QXYJ~()gtFQQ=Kk)2qG?G#6O7Y%=YbB z6Cf+Aq(w1s1OwqflzUTWBj3;x!vrb{ssKZ^Id5DAJ2#ZC&3{hw0w`@;%ggarDlgkY z7B6T4RK;DDPGH#$&$2XrQO#>J(duc+9)^2))3A5#IiVnA33^lPkBUKNip_ORN9fdX zJc~vWHn?v(9TGsTU&J%I?>&oI^{ss=ge*TS@_g!jhHew6Tlz`(c+9XCs}vI z!-wA@0hXI!=m2C(lARLvZC7xq(U>^o?`~gio#q;b!**cClU|Y-7n2lGWf!<)y8*Qu zjpf??I)9RHK$0mDmDP9=W=L@xQDGJplakB(ktY}zMcOsT%)y$?1V*6HM-qH&%? zl0@hEvWAvB)Szjy9-HQK^2pYcIffwbJ&j)WI~tamig$fRz?c&gYQ8?B2cFsXwaxWK zZw|`dOR-q-a7J|cO5Yo+O6#das}nT~d-uQ`#{in#TBTKC|Gp~#YPgFJ)%BKjw@Q>v)TWA=<9?}mFO6`TQ011D=r6kt1>x*uv zYC^EY%L2ZSsW}ZR0B`7#&86_Jk2@;naVB3TojZRnIU2?kal*`v5623rqF!vxHmA77 z5os_KwSb;}ij+Ul_{3q*`aEsuS{qom4s@GaVVzmQ)8NADhJ$D0Qx|^`M2I*&nw(0R ze_@w&oyfzZwN+w`D2054=#i)qwiGCXE_rS{`c9+4XRu1ry#HS=p; zE-_1q0o5zT4fb|1C--S$i*0uOIZV6P#F|iDRA+#>=$|sf-uSBv)kpy8WX&5SZB%|& zrLK(D$f}TNPsN*lKiEs>w98hQteCk|NR}Ue&W%~EaRW&9<*ea+*BR)-(CPO(j(N$} z#J#eHD zn)||kp|$398v7e-GY8UR-xD7kOm4`FOVjT3$h0h}^vs5NVSZ5gmS@2r`S}I7FCkw6%y0o_Y||x9F%C%YtuUg2jze{ z#nLFpa%Dwhw_8A$JwH=bAjO^d?acQt?ddhU?s-AeDgl3Sx!en!N6JMvzR4Jp39ri- z4$l(Xei?34wT6v==36D3*{6qwiSK(dRZOq!J@e$MZwjMYrTo|4n@ugHE$8~>2Hjq; zLmBsN!~JhH8$1j>qToMP)a1&233K;DIt*0afzHDJ<-CW~{0ypvQ2aZkl&Ck?+}0$R zWqt<5?%j7RrJq&HFf33-PGUN zKVxT$?;Y;5&M=lWRvw;=-oOtg@u|OSy^3-T++O~j;{IDO!zq=GCJ0|03TqSox)b2A z7()H#Y0kywdgku9zx@@7g_}Pk`Wb)FILukibd3vkfnUSVLoCaz7AD}*x?2DC25pRk z#;xt^l%^Z#PwEfcf3BfO+NwL)g`@D-|G_tb?^;Ebp7ior1RZG^X7a}F)7D*@MfB-@ z*J+Xg?)96W-bW7fF0Od>@O0T7yxBwh4Xe7Slot zua8)t6E!FIMSL4cYF5``ZT|b$ z_rSz<$?%HfxxzfjQtjgFA->9S4V`T6#gB3~wx;HkL8`iYY=|&D|MEIl zS+<`sD*PW?EvN{07K6%3C z&xZ=XeZ)VW^I}bQA~?UhwY~a7WF71fP#el3i1LeqA8^qL$6~d+oSbM^On5K8;-f{C z&mMzXVT}B$vfF;}b@6ui#YZQkZ;~D7Qv4~Y`hjhUpMjM%j;pirbyj%P&u>#DS?6Ma zwx8z9!@S-p;VpEbbv2K4PZ(62iJJL;{r8B1*8|$O`Y&NCpVi95P1GR1x4FW{s*Ak%$w)Gcg}4dd-mYHV1kR^356Q5=ldp| z!+qkSMw8A+3uGUX^K{AfX>00xJh9!+XZ;L})|8FcvgA_S*Leo!V!d#XzG)E^aqfHx z0!5^zHSPv^%L36VF0yRL4<4SpF)&ksR^7t+7OKR(TMm=Y;qG=Ug6*gm6|x`Zi7xii z2sCX^%Rz4E6;2rTC%)$p+XzytkSb%U!r=zG*vZ)B7i^Adq2DGm@|8Z9 zT3g6`$s)b+`v5O@RiMevRhZ(Xq7&2IG&l3{{=m0DJMuw+;Dy{U4d1_w*8e3*#9?>9 zMnd5qSAD2Lb0*u(>T6_XGlB;I zKX;K>9@n8eAl*t(PI!dm{fFYb`$4!pzrE{z{LpgHRg9SO0i80Rlt5dtx6Jf4{GTaX z{otEFipr1gz7E<7!{phHyIVam)9{YtRbe$hO?Y({?KQikIP0~5>#M>v0oDE=ug00X z5fwn;?x96IKu#oxD!pm=(i#(PdBpycPy<*Wl3e;snp=XuET%44oR{5})^LCJQ3_kU zA75zy@ocT3NUqEBuoMCA8R#Z*g^q`;bD!mR0ABn{Ju(r!_J>II_5N|-aChV<9SvDJ ziegT8_Cg*viP#6Y9lpI=_znI91ZKvT?xI$NaPQL$vaXi5{F1CpG7zY7TGY4asE9d< zW?+L$U=zL-Z?mnDv*yw2elXb*C8NV7@UMYGa{4wkvYUBT5amr@nXp)P=Pk8Q_1R%1 z&A_xlXAGa>WZD&rCs`!?g)bT&CsI~b9`*P5)7>7tWg=+qSU)Xtf^!3c5O`XY)4+DI zziA)~bs{zAR7F(nl?cH?7psMP5^&{Wq5Z4-8U4O)#(}f!dK5o{Z$Rv^WzVZe%$82~ zE$Anx;pnI(+C^JUuKjU_hgzBWn3iCS7(flc2Hh;1V+w7Lc=jUCC^o~Nz&0WIap%7H zfe%Q!vbv_cuNeQyX(Sm=uRE{)j&1=x|0#y%;7po@NxA#z_RB?y)}yCwPRZ&oT1X^2 z7uHaQy&+9`;5KnT>8m1+CF!FtH1WA1aV!YF{{?$TdV}sihIeZUD1w94m93uKeUF`s zLHYLKt!z=7tGDnqrX}7l&(>{ClC`PwS={r3a|mR$BoDX$-41I^9NSK|Y86Szh#V#q zPlC+}iB#|UiW4=0C(|o}MQh*n!PEmM!8q>q*lCH4W1~RHW%XC#cF$>kozXh&qSS0f zDX&RKHnq~fraM~huP2fVVZS25(fIhF zvf8h9ry)_NB0E=o6afF!=gt(Zm_7jB9YH}AylJXR%0>Ufhi_+|iX(e7`||GY+nC*I zc2OiD8d;Z-PV(USF~R)?R{(uHq&oz`r4MNn4D7mp%|kpqN;k3hYUKB!fF$lX`_}t( zA8MtC!sTgMnzldg(m2l!wB6c}@iVo$!*L$OipAbec@DUgQ5KbF9G5b<9isdq&)tM5 z|7dU`pMFux=JUFlj*D_5Jhy)zWcx{B&t7&N;QC{|crtZb(1%hr(K>M?(txL}Pm!wJ zrxmm|>7xnsL8o2iB+@@SWn@H!bs<0e~7~lX}^wClqyVHi$1#!1%{23CfElO9Nv8aKb*=yM`GPEH(mM&NyBuGwk=fgOMX~Y z-LH?;o|yeS8%w)#%D>H>$5lj2h>_msY0jr869M6`yZnTX0Ulw}hmoo}TxEmWA>0<~ z0)!goc2S2MzAbliF_z;=m6+_?_Y#eEQ>FC>os>~up=l%ASk0s(-nceK>uR+xR-sT43R(yXX8&;E- zV@1ortsAIT+y4n^qkfh(I@JGLdH+@QU@s+@`soT$d@@r<{!oJI#qVcN%a!+=J$*L| zqwZ%EyHB|PJD?{_Jl&%R0KYBiI8RoY^gw=BI2qJZ(Jl+}{XdefI-sfcZPN@vS{eqD zN=bvn2n7{EF#x3`6kcf%7&St=Lq#PfqN0)m>Cr6+7<7!$y}^KOFt+dP_x%ssIcLxF zocq4wzDm+C0x|`4Wqtrgu@7eW;i=m)C)uC<)xCjpKO%tU2D^XI*NlCP*ENsc@9AUt z@?Bpq?!YOebq?jwL30^rxWln>h^AR~iAWT~VL# zZ`M;bhR1SB;d@OwI%>suyDqjdgz2D0%sj+>cG9-zUi|J18q}Lk{Y5y@l zsgUi33F-0+;(IEUTXt%uLFBQeph*WU0>yrOLPRJyFOPU;n+si`Q3Vc1UQ zMAPNl&Z7(Z`OlAdGVx!$NNb;VKKP8Xg8S<-^RyO>j9W~AL!D7`wX=)E{wuA_O}Xfq z(d6u~|3HX~bEYKr^1JH6N;R%dGB1|q$};r2Ssk&lXxXR(Sy|@@nO4hpHltw^wF&gh z>}*=72pralvK=LAfNvTNQhltp^n3vq z(^>%@#h4*fKq@W^Q+d*(B0;nG)6x+?7y>g{UTID*%uJh|Y&))d%||M32hG_M{dY}J z?j@p4czMVDlyCa&ypbY zDc1k-4mXZdMo>iE`+8BbpvbIHKjLa02juK8M4$Az{V?y#N|&kYY_)+`oZaqL2#b?D zUYD2E*G%c37g>&Z#WQuA0&{ekm%v+9IC&7WjH~Ic3paNL4+2RwTc@1`AlN?I0p9ddRm>ytQ zjoBJ=2k(%Dk~*~s^V=vTVH$AZc1oB8Lx7Dr>SMl z4BbxZH5-`p4nhzRb415&Xx3CBI&WKtCE`M0j3ra8l5S%4vve8350wM!#s&}eB)4;) ziZ4v+GZ<;pEIlu0ulW*H$`5C;poXqZJ<#_Zf6mdf3yzmAPA(Eouejz=v>UM1bNH>o zSdQP(lAV7--;?kNlj%Mg4@+2h6LR##6H?7+TxXDh>(j4XPs6%LLars`jM?g6E4w4z zUYK&_u|w`^rP?xCIZd3k6R^p{EWm$F@6A|H908=YIdVNGskQ z(W3CZ35ACNvVJN_6MF(Ls#c}e?j%6+^%dlC!kqG3e?FJRrv*MAb6W+*%E5Z&?FQQzX-M#yqe6fn!@sv`gGLUKe%Wa|B1RwqIi`e7A-U3<14 zd$#V>A*B8K3{*&Cm+6Y`Dp|L)68+dokaZofI8%(4hn*MsFJpu?%eUrhY+x7XE8lwh z|Fj`<-u8q=WuZ(&BtS{&IxDB9-*0%6@_PPmJuaRs0m5H|O^ht6Tqq%wI)*)sm+0-;aKl8*F1 zkMo`HrQOrtnXnfGAkp@Ux=`uMK)#~KX-dWo<;@>IaCD(&_f$*24)=#})A-~1|HukP zY^=16cYWQg2)`+2eyF;^cKIlOx>}-I13u~;y|Br0k-l)Hq4`EEDp_f=?Xmh8NKbPbir?2}_$Y-M5o&}oh zp1l_Y&tl@+w)b@RN0IYP!sy4ig9t~3_3fP2vN)B57RzASBO*Oh;V9>|=-?ZUh9eRZ zSLkA&MsxBZz5o>-k6=p+rY(Hx(hWqB?P+Q3*v{z!z73rR+symoK6C3m=?q0VL+3>i z^Af4Wi1r1k0@_mRuaaT^} z!U<(8(Lfz}w(AS|-1ajfc^rt)5H3wM1MBAuVrED^D_kVfTBNPl>itA`;X}zom5p05 z@XEP{=K`*{M76h$vFq0|q7|a-$RZ{eN;!dGm>d2SS$Pp-!15Tx)d@%F%_iBY>|yWU z)MPu84kXiq2_5zEg~m9_I)w!PPiJxPV<_UOR*y0@0FvK!iF!DvmdYkc5wHi ziIKZmqqE!xHHYX`Rwgncs4fg=k&ZexF9mT;4{^;n-NegxJQ7!EvO3(ii)u2AK#Dh` z?5hyX1BCv^2D70;#lHcd=)clycP<%`DnnX5C0T-6vc_p|{?UDnOmef4HLCutExPzI z@lI|roWG@F=_IkijOkTeYl$BHg4g+%{*h~Z^9s^7Z*avdGliI(G>HUG&gJdKw&m+V z#G;UG$;=Ok=0*znbTll-X+z0}e82d!E!y3sFk-EjoNT9BQ0!H1q*03|D8>8cK{A3fMuv3`J>MoVsFA`aP+QKy{b8ekUrX&ZV13O znjdM3cGJVV-dYB=lGY&<;ZmGMBl~68TbMwvu*C8)Q@`pagxbe|7y-Jjb;SD)1DEojw z-Ipm_Z#Vnem-BNCOJ3^Mg5i9FRgD;WYwvx#wE#j*o*nLD0tY2nyJMUbFxO==$49v= z@#w6w_qGV+$tBQ)p1*{;zA|ngREbrP)8;3ooEv~Fm-bK@blL#=;aLqMAf%^3-ocBK zl}_@9p&$vPoT?)^sYzdDR=RORxDWXiLL+?h$%jg3b{FztPCIG(- zaaj+2`45d!P^`nhpROF_rqgq{}ok6baa2kda$3mvrbqA^7|ErL&6 zns-pQ1NhGwlHIo*dFhb!B9nuWIHNu-=?H2E_qTF1y4U|=iiFtb`<+F-+@)$<0aptR zbfz!owLUJk^51JRQ-J=&b(Ib-hH!($76iORfceHu`XDlt2x82|>W2U|CG*H1HqJks zMgrynGLKFgQx0^}-mXS8o?arEJd0`}tS3WXe%(0||0AdO?Rd@w$S86@{gMN^e(*wcML;Q??29TpL;i&Li59x$)*Mrwz-noA* zT?!ZnECG)`v#vh*wzd`Pv%=K4f}yJoS|0)G+t_eXZ}wlD6&Wj>c?ajkh19;-ch8he zW-zsqJYgUQw>zh}QAm`w=v)NuS9d0bkjXKdJoewKRAlf~Al!NVJnC#771`C_zMt;v z)rp#7SUTWE7ayChJ%|1Xv47fBH%~NLyZ!yf8sQc3Gau`0T`qrC`a*)BD?pA&Mc4U@ zPuk~$JJVZ=BHv1U1nsj${J74OY<|3SF5uvaE9?df3Q#c>y|F0`glKl_+82RlN+!N0 zm4TPpM$1{ttsbODC>l2&ABJs;t+)7bFwPx|NOU;%x8E9&(GQhqytJ{X{WULQ<*n37 zXum##eotIodn4Jjygd*1i=#MC4Y6-g@>|+GuGPjJsA&w!Gr04xmOq783aS z?4kO__Lv`LauZ^61w2)i4TnKpn#GH_5nbi9R`cUZA={#uao^%!Cot9*Rk*|EvB!t~ zGgAAX`bb%XfbT>NAplpC!cX5%HAjg(=HFNG4gM`w9%W1;5J!ToIOckJ*Z@1+2L=qJ zQxcP>FaMjVB`)-2oX?7Bhx@?&RdUAl5uQgsLp4KoJk^CRYzvD$cEOKeLw-dngt2K8 zj{9EoG1+&dC{{7#w-{-ee|w#FJFZs#V4R@@w0DJo>~A)isx2?EjxZjp%?D3<408x# z%Bg!vm);hq&|5FQ9taI&(~)OX*bm$cM$#$#GR+o;dphsq0|3d{M)RYFA=#HVSM}xT zJW`T5;;)RIlb~}C%~3XV=1VG3Boi<4MdifTz*>KM6gWWX#rWr)8}#RnfesG9&k-szS0 z`qz7($Ad1_57p&vSR@B?H@Wh%Y}#FVLQlw<((7;8Z^iJ? zw%URFLtFa$kp2Mgo6ZfVvTn}a-lL|Wp7y8M&_vpTg59wS^MfUpFCx0_P0_PdJt9yt zu_W)SeUP9@Irwmf{^Ne?$TahiD9-KM)2%TEYVCD(Edr#zZ8Ki=OcF?+M&+^M^H zwK|cn_>OHfNulc8B4eg(E&QWTV4s33z?4FS5_XRWMohTkM6sEqaTCK8y2WNK2}aI% z*OQ1n0SdCSPoLi@!e4pbOMT?x@t!_+SFfuuG_qS z(S+siAD=mB36%mVc~C#a!)Yk?&_C| z__b)3<^CV|+Cvuk_7bU;#+|Qx($V_Gz@gKp-$i-vSt&TeYd}JCaDYjR%!v=_C&q;r zunGUEy)tzzGVeGcp|e1u9fVaZ5eN@lQ71 z1IBqfNdhJ4megU**PlhaX$)TX-|Zv$uNQ_`&Z3IG?PrWpFqE_QDmS|S-tKQZ;+y$M z>57c8O+x;0K9BzNYi@%gF+YX=T~(;0ZV!g+Ed$Ej+` zLw$r@VGccw?sP71$%x>>hiQX!f`>1rHvr&24cqK;`?YfJj*?GctFd&4o;qx<#qj`buU z_@y_CR#fm%h+b@WWKW{T@X-kWGj<7o1s_sl6!Jk&D7{gOTL?!@5v7wEECPVI@0gP( z%71g%ev9YtxL}9=r846+SIqlF#6>Pl{&*lphk9m<^whZ>*A{duh1%;Vtt>MbT-G)+ zT!_!y4$WV9=om1rt#jC?pWZi39}D)J4?5l-PKe4+Y>_dCg@{J6nP3jhw4X>2bb;Ym zhTX2)4k^2a0RHa>Ypgvg`(9gae&-G_ z8yV_Va`ukg6#*^>Bq}w6k|;7=9$vzt&9q+MG5cD=pk2Ub-#&&F*=}CVLPx~F6pjpB}b=1WgVAh#|eim?bwtOA6=uI@HaIPV?S|edwmj0&08co^!?0!I+8eSqp zjwZz(qZNV(ti%LX`-91c^5mlF&aRGcIIf*SjDOQZ7Cin~EH0 z#J>kFip>T6F)=axod(jtP^Tk&dljaH_9@D67q9AdRN$fmKIr>EhfHqnlAcT~O=nT3 zjOK#|k2u3uyG>SfjSgom{Qmfm)jr_nI>w0uRmO|U^=8ogC}t@fLKyterd1@X?hL)n zs%-o}3hj@HOet*k6#}zmDM*4c?r<$eu!eKrNZMV0?7fe1l4M9bQghvAFH2QsH=IjE?v=N&c zE;OLwBj|2oymU1CX%4bgZnMqc96%;jam!6~|It<6G+Yk!cAs33b!Kn@ap_oP-KE_x z2Fjk6eE>o63$yMH z@6v3O(5qhE=C2Kq%$4Lk0m>EE;Q)!SId!F(MF#y~_m3$~9rqw}r?h(#m9B~^2nW#T z+7scMSXK+SqZ=i^r^FW5LRQJyV4wlSKCOz=}Qf1419Q#@9-}zqxlR0$#-x{__ikI9rKBG5wTVsN!0=deEI0xzQPR_8%8DWmTZ zqt+FjXSuY!@tL|1zd6Tu1^Lf4N{n1qO$;md=MeLz*mU0rS6AE@fVV%Y=HmARD=XC5 zF804#J6}y;Szp>p?9bh1ydtn}kmuf#0Y(=zpK->OX)j9HUvOVf~4Q(2@ zQ-$_nX!XBSf@sBBhWD&)hr!+)g*six!P8m0HGN5~C9`n3g-km40dqRr-cN55*sWpn z$;n}79yyNN@APOu?4Iqvuj~OxPcU9fXcm;F$z6s<2d!S{hkCc^*DLJ~1vO19A?LmV z9HdZAdA7FR5N3?dpM`7ENd6j5^7rUq!~`grGFg+EZW?fdI!qr>NqOlX?}U2w>*v&G zlG@xQf0(;8m>_f#d-fi0a?p9y97|3P3IA|D>+V3KUC$Rh+Csjy=vU5Kk^RqmRCzE;Wc|Wp=*xc8$EU*+ zg}UaQ?Y21$8CT4(?$NH_?w2!9a%zx%laRC=$r2*n8WkFvLZ%*NRPMK)Poa+eAcMw? ztHZ?3=Gmi0Nm3aAc(gw)YX!J^8T`JEPgGKm4~1mPo#z3B2{}Jq)xt}TyCL;Iwr2>yHI*XoJl#zU*V9Z)7xa^>4YeI zQd$S=lPaGLYsWb%$;}DsDv0BlBg2~RfsMhtTp`?SZ!uEDpl4C8y4Wq7_OQma_nrx} zzU`5OseS{^IY7y#`+lN`v?9yF%r5f(Y%X-r+);Hm8`u@nR~oDTB;)Nmm>rMT-;?5) zvzS*xA7Q&^U9XH#WmL(lP630`!jB~|ZcvxOTtXh(j_u{fqi?iNJd4iYf!K0nTLi#~$T z4S*ZOkq~w`@E{Ts#lkkqV6NQy0@wk<0#7YR`YL>tt1?-z z8%&kBQQw8SpzM7(51=Qy>}(b4d!AM7BdB_gXc>EB@m`xph7l~4?*@p*Pw-8~1D;T>zlRW&Z9px5$!#Q^%!hK-ugx$?(%yUkxF zTE*0d&nG;fs(SBHVrDdcB$9MT6+VfvW3ja*0pmn98v6`h3U8z07O$Sgqac`zy;c{@ycF9eO6qANyqTrS0P!1$XA){ z{u(1P1$ozV#3BkV*g{|6bj|Av33)vLV&zY_xba_p(8RHqB8*#Gbg*Co66QI77q;<^0yOu zbLAn9339@`KY-#xZzA(?4*!Rps}bAYn-*IN{Seh}&r z;074yo^kGS{L225r662v@M6S43MNt)dZ)x+lk=nnP$0;57T8BqzbKb~QPDSaXodC$ zV`uIlJ!n_f5$tOm2dflJZ3midZI@x`7gZRoz2Yt^K z+cJ@DfYKvD3eQ!_A#rW-em=x-YMI=51YTtP0Oio3rJa!q*Iz#Gp&m?UoC@d+M2;~i zNGM$m+m$lf9FDBj=>GdO#&|%$IseI!)WJdOaGQ7X>tytv*9vBvNbIjiOPip~e;^3x zS*aJ{P8WD%1pLdHl0Jm^bog`tvZooxw}Nod+!v;$4tgF5<>#LkZqx)(8Ue-F(+{@) zrfoSyPHykRrIsR5_(;?WEtGPKf>eN#=&~*-jQMvl4i1mX_kRhdQTbC#+vV>dQ0CA3 zDw;Wx8&)Ed_!#u3@_-BS^(My;s(f69h-hb!=4_BC7i$R5$Q$D9m8k_ai^rN3<7 z5p3;ev+eqienCjx5G11h?6#zO*zfE77A&Fu)0BNMWgnZJ8R2$7=O*1zTXa;u*^W6| zz=&2hZ+)-zneRVn2H>JZd@CmMevxsBbKH1Xi3YSvYl-EfS0cV;?rMKFW%ZMHuv3s@ z$MoAOckbGtqjgc!gs00v#GX9~26t>rk8=C{wQQWH_l9XVbh2eZBVsQQE)3h9gn2`M zc{-{gseGLMrh?Jczo0WSf-KjSH<2!%5PSEfHoR1uhO2-X<=fr*_&GIc8PiL|pEhl( z(kq%meG9Fb-ubCPd!J`O0ck(tJO(FI(9DaNl^}l$8}D5@1NkH=yu??vBox4&Y2H$+ zITbSoOIR+!_33CI6*Y3d|={%;WoCKn(bvM^D3_HZ0Xw|4`)1&cFFj?Nc)$_=>P9b z=Ynj!jJI)Z!;atir{aG!_9e()itF?Bcr5}6$-BFJ$aOU}^^6~e=Kr$N1ScfJ1z;;? zFgNOuW}O|=p03R5Oq-QuFoi&M0`L*i`x!ltrUNEdL(n*=_ob3zxKFW!D?=73>e@+j|V&D{zpdZ;>Y3myl z|B;(^LX}kUbSLNQPDD9s&G~f$`)Yc~QL~~yGoU%8_|tGI)l%?XlGB;O9ED~6i#J_< zvACk2riT21U61~=Ba#{$9S_GXVitaliY@N9A5FHCk34xKJU7f$mhi#T(sT z=+wWMPwW{_%@;(>hnbB=gASs|FW-jgI4!$zHE0R;_EB{@gN)>2j!2K6jL=S2$1AI} zQj$>@c!!7cZE=?b4%f8WLkT62lafo$Rlldsi5QTkR1IXGCTiVJQ^cJ!82RI+5I(sY zwe#K#N$5xaif<_k9OOj~;0#x2o&7JA=2fqy^M^*9Z~NKt%}^aXJ0`6)R{qt_ zFxleK2_T{qdb2^E+;ngm?YPddf~$p}?HmEM321N&%nYsAtIRVhB~>~=^aBOx3Or*sCbZ24}{PQhIi|RvZ`d_+!NkGPShYmyg^3f9zDfba=m! zy*uZl{^WdvCzoy{^(%=bB?gg=Mpz^iG<~P0c*3;CgMGXdm*P|G^n`cx#4bJoBwQ3f zs!B|sM8;6a4;;0cXsnow+uc>!vYK8s3$U2ag>6@Kn?V2WQ* z8xej$+ovhnMY#9VlvOKi+>#_k@APG zX$r}vzWQvTgW_S~j~`hw$o!E0x^N!SPH&JvYmq;6;T5s_<2Y06bz ztkD|sUgGtMJ?QIi?F-kk5{Xiw7&p$VX|D?zn#)s1EhF}6R?gh2j-UhfH;+13M0;kj zgLhyxtb6Js=dK{9+?eIXd=(dzyQ(!8?SW}?M6gY}4eS@SDirMCWZuR(-&1NazsNih z@g_vu4qOa&`H5+KIn~9rv>ilBzkl81(!(9&@Y0Wl2}Gl3 zLCCxje)vh&+iPPDS*hb%UkPi8EeC*Yi58yNn-4W^X?2Z6lG;+9W}sKkeQ(?xoOH?4pV$t61b&f$UYjAO&Q;jPhW-jL z9uC%lYd~H*&)wJ%XYT0N1qfO0%|zNsKygLup%40LEPQIykC z#hCk?a(LGeWO;i(Zro$X-pjE+b9^t-c4tDCw?lWmV~Fdd^7ltN9{?164$xkW(4A)Y zYGM^%P_@hk^lr4~=B>N0XnoWznYo&iE1Y1&)$U-4AMeA6gO>(!I>rLK=qegDtr?+D zJgw@50_qYcRU+ARku;SPTeo3VOhCK*?w#ql+7BZpaPjWv$bY*b(`Eq-+8M6m>Q#ac z*1>hZwFTqqU5?-^5+XvDmPR$lb{ksOEUy4zT#G;;2pF9KZ3uZ&NW|{UfPU~hTXneC zQ*Fr_%|~vk|HCBB_mg(Rc@j98lp?FvrE1~d?;y4LstkE!gR?d3>5_3gVb9ft%v@1z zfm(5)uWU3|5vrVIi-F;rGl&D6SW^e3avf7p9Z!ca7;a1glg~a)~Pptp!zx3rS;u92h`kM0!w?jk#`xqn7oim$0f{dB^EFoNc?t-j(CN zRoFQd^KaMbnD;{G$iI)}etDXMFN(unQIL=5*LhS2bT}PZ$$i#npv8aQf)Y+&?nn-c zbMG!0>?EIcw^(Gvs2<8$glb}>ETwf`!CE;*qUQKy-j_t;GE35zDB z_M1?X-NHNNqykV?Y4i5Q&=%?_5RcU=1aBst0j==viY~qA2j0emTu&XGWer?wXFB7# zXZn2V*yH0?fSSCponId0g16mxbMRrP>;4wDRroYnU!oX%S!>ojSj6W&ZCRr z?lN=wjuYs@_sCXdA`SGsc!8;_eD>4G7Uw%y(`C2lCmft>F(#F^+w6k}vF*%Kp*BPC z(ZKa>;E47bO7(j-Xtsz_T+C%P9F~jAl?D^Vs%U242PjTL_XMI`%eYR4*K`0LQN_*9 zF^7O{ZuZN>KQ!`ddCPI(v>NN#J0X(Vsf|x5udO4rPW;uyDwg3yTx!ha+CO_K3tjYw zi^GW=9|4$0=n{ICD4Cv6eLPk39Qh+I@aEzOr4mrW!h7~;%)y@}D2NMHdQH^u)t;r% zmSm}c#lEnR+j8_G#w=THBb@gptnD5pY0>P~xRTO$4P^mJIUmii-H`xr!R5hlled#~ zr)boxgX_sye-l}J1)t0QEaRO&VwGVzdS5$iv<{7|KBV05P$^jV76r7Irf(mW13Si_ zA$;OkL7m+!Cf>hh?>YfF3C$ZN!nMAY^Red|(_Tq*haeR{o z$>RRZI!2#DD>s9NnvVA=01%q4#0;7ra0z!9F1`5>FW zk4q5ICXLW%^xOz5nxti(2Ig1Z{eG@Zn(N|{cZC4M$=-;KV&G-1M`e=PnKlXvzFj6h zhKgsxS^w5GJ^=DaNzapZK%dAC_{W&H_tDGf--sEmKej}vZN{NEZPm_}Q-6zq=0#j! zuL2`QJ1aN2=bizRL9FP~elv{e-SbF=v)UY*?8X)4$>-|zti=s(1g%1iVBO=r`C4ZW z#OLO8^*4K=U_ST5-1gPosn$@A$%C5qCYOmJqBz?e?$J;8RIykUuEzH~<|iVMns}5F zr7u|WFbLC%4{lBBt4ze->Ub=!U0n4yO z^mXQJO@k+d5>Ij6v3i}kOj|_H2GOGj;25Jc`i2q9u*NVs?Bc!j#*n1xa0@vGw=#ns zlXyAxZa#9lS`2{qdta$Cbq#UxzF!e3>)D;Sdy<$5P!cW%w9a$sWuE^zt#m0i%&7v( zr3apUopw0Y^B~$-S`c2uQw!2BvFI?(AsxLP9P_%O-_z-I27TIwIn_LSgMhB%$ct6%bQ=b^e25`fMf3m>*3^~ePWxiy|Ftz@1Jyr<(FFY_~xl^Oz z{F{IxZ)ozy=Ev^a>GL2=N(zFnIsu|bbDf5R#uy%m; zMI3SOC%t$%X{n0`YuA2cCw!P6*<~_YykCDT+`{7N8LpY8qYz$x5`9Df1szoToprCP z5TO0NzLGwBO!L705}<$lQeY~&(^JQxdD7=%6_IUBq_q|-^rdRrqd;!qs4~O?h##W% z{f>Y!2P{pXK00>F2KcPxQj>C$>IrgPze?XC-68Sl2uL8eO6vEADGwd{mUjTQhyD*T zOwYC2kFIkyI*v5l5@5z&Nz0ZFo!F!MaUJuM*CpW5K=d%ocU9nn!jG1t;f~q=lmhc6 zZ>453%N`Qy9`?f(GC~wtiBNcrr&9@H79gzFeP%oq4QZo&TNcRKftvl~G6@0Bh4Xyq zIgON#Ul(eB-7W!futb8Q>>&~f4-QHgl+z~dG>z}-7)ZQqv}^qfmnYTHRkz-Nv;&}| z2zkco)bsBY2@NKr6ILUD7=ZH-!b^yDx`{RYgR-V2s(6e%3@57P9(nadlJnb%`Q6l* znoWEf9!|kU!5X)|mua4fO)lv!>}R0W;KX4;VanKxa!TW=vrlNo|IjI==8caf8I*ZI z^7U<@J-cmqE0&7N{>8jwrozCbHoa8$OsJ40FV%^M1={e9uk-SMCv1>Q7czBCWn-zA z^fpIRzKA&NZmABe0svpX8vo?Ey%x(yKo4J*an(Tn8dWvo3w1VxUfWPEQ@*@_E5g4} zO!(U~6B{*oW(~!EuXsO~XR}t;+7gqBlpyi{yv9m?__EeO?Jd_y&xr-+kSfyZ9Fk$| z+R`Tj&1ewM_HJkc|K|1;G!DmI$$t|TGmWuTE6QjXF<=lo!TF4HlFUa*kR#J zGW%_dE&o;^2Y+X*e8Q_xAy#lKBe?`-J|bN(6vVGXM{NegV>mn)-kr+4x?(A#`=-_0 zFhGwb3dB2c5_tX%L8G4EYGLXE;^IwTSt0z0zw@8*CCGvjRB$Qkm)&Gim;8%f;PIDdU=2=XSY}~zaA83ZaKEnO$&RHJ8oUHH8 zXqLLZkNP9-Cdpf&ba?c-E?VCf@LwL5upXyMdNu@?gPy!*fa3MMv!% zF)(~f=H==KT)sU(Pg%X$pcjG!*^c=C#(7cUE5F^kNlO&Z8ybL4$x8s7Jb`8o5XYQ# zAnN+>x_o7$%dPTZQbxmi3HWS-MN#zppFCv%Yx+`esxlm?RZm+2T4-^{t?6QcBKgj7 z{nkPnvvOq!#`V7jt<6pog*$$LT!E?nKPesMf$(x^mqXAQAaUZ|HguSn>}P6Bsy2KC z2}5?NrdM1~A+6NeWizyo9V9momwakNpZ9$mKx@fMoj0gX+8HJ9d_ftX0&>sO1i%19 zp0_f81a#w~DmbYjp8Gd04g8F2Cu&jFqz+4}Nw_HTC>Xy$AwnqYB@9t(lfcnS@&3N( z;l@th$Ruw(;6hxE9_%EnI+0gPDk(X6NH;>S6RCGIFo3Qm;39$04>2I+MjhNq0G6OH z&{X|>wT=YrK#6_FXkAI=HYnO5U3Jr9l5_5#Q;ZW2JJx!~k#3{Qz>U1F7C)0PvgM@j zrtkE&uuRv8SImRweB3ossZ0j63A}FlpLP*zGf*M+9KiI%3z7p3#E^PNwi=f+RvmOE zFm|6gbKP3l`k!wjx@h|!Cxl-t7G6L5=K#r!4?colRlT^moTh)~?OFI|2l`^$GI9Z$ zj-_#Zv+OYVdV9Flv`;~i+!$eM)HWhsvg-Uh7Y+W$l6G;ii=+Pd+Y+AB(Jwz4h7 zOMj=0`;>0J@K7hTweUK8uw7c(!IEC9(hCo$#5J z$C;^mKF6*S!z0NlLvc^mjEva;!{kr~cRdSp!T0FYn!^1wM$sp`r566mLnYRx;40XI_WvcrtnxXJ(&x-Br_Z;>wWWf;}sA`#~2_^UZ)=sllzHPP1W)_I1K6& zS7tqPn{e;FJyYa9ck@QR0l@v;x%sU8frl4|m}uz{@lIG*Uk!3h<%gT(F#1tI6P-eM znwIi*!uo7UnGlV{-t_ykTE)fMB%H6%-MHp5t!y@93Ff6YoM|DOCVxu}3}KQ^;#KBK zO>W$r$?Ln|AvXzc_>%VKPqbx4ZQ|?bz#(Crsb5FgCZd-{2VWU+OZC#mtcZ&|YEN==T_^5pl~k z(LHAzK29Sz37RU5Td^i>Rgt%_{ZXX;`|SqU4tf*UZ55%@Zk=$v*G_^^5&N&~uj}?= zdW{hYsP3VCu}+LPsTjn`CrrG`M^O+Y0<h3((xVBh`01b1raiR$Xf%oBIf%y!G#-texy8ohk-UP z=})B;UMlfY#C^H;PUl@PSU#L$>zMpE8U2Oh-ue9pr*->;q%q3K4JVs49ALrH>+0^V zz1h|0(M`h&mrYB}Z|7Z}ezhXH$WmG7$X&1hV&iVhiOqTEMSx+|(&vw|y-zgL412O0 z)fU*+O&>>N+m)y#ep~z|jHv(gNjLB8YP--tW1n}Vp7cf6qG3YCSIq`d@w}&HT;{r~ z|GgXw;hh!ly4o9%Axp5*{%#{4sOGt#hRWd#FK62tF6lQ?NPM8TU^oVjDfP8#^E>n;sG?Y_K+zEhkafnmg>-3CW$Z z121&!H__xdDWx33gV)a3JK+Wa(8djtWXdyw&#S8p?J3({ADXv*HPGv|_7GL*rdKon z04fv}hV`^*->r1I=+wl{Ud1>w8azjAp^F5k;H{T=ky8!=v|t(j$td3FSNp^49)YqS zb~{x0Yis>7nfu(QHSPp`n?}rS$j*G>=|s!~mm90ehLNqE{r;j)9e&4p7q5EZ2Lj>_K-z*-MI~@G+23WE7gBrgYUr=|+{Z2&AmNC8T z-wD@>&O4`h4zm52A939e&7K8)IVRpQ@O|(3E{}`AQj%kH9i-*QIFZJ4frR{3Il0?S z*-oK(x__rVcd^j36xL&}VqSMd^|G3qEj0y+U}a@t+Zyk=dKNxviR-?K$**l_7i6d_09Lo83fmv}_o=e6h|*6X zfcq=zid51Wxx)saeXEhP-VGMJNgW2`QYMmgx|P3X_O8^*3HFBWq@o256tnPi({hj@_<^Y-G9Ig1>f`BV;vlfIfO&)>x^-*kOf+5LlW z<=}~AbbTt_3;@KPiR8qwtiwZD39hlFySiyrsh*!P28n?2hNnU@(-e=A`Dgv0!BH838P_?`q_;xMJ8m+-|wDPpb7nuc0 zmEC+h%X%D=nAHei97yzJQY!aQzp7dIj~2Lh(DpV-e_QHF2`+IWyP0Y9GKI;Yk z@)F6lnX~=I%^%|Bk_ae}!Yw@#>j3xOxfv&-eAH@O=IGnKf9Gv%C-|-hYI&*uvDNPx zTL|21bEdquxlIR`4t{6zE_I*jIw7|>bHB&&GWG$i#N!Tm$QRwu&e(-ATA?eloAl5r z_l_uu?tzLtOPjXdb5(>f{q`4E2vi?@TwN*?{uYZYP>wSVGW^jyCx0_)g@=J_$6t3% zzmn2O>V8{msq>EF{I4CS+g_VJZ~)z(>zlZkwn9~HUE!DdKaS2SuF1EL!-RlRqN225 z{OOJ%qeVnIrBfKW(W6JIs30Mo193E?2ZE$Z!{{+uL1HjKDcKmj^F7$%PWF7B-S;oP z*Ts0ldY&ndRW3-Scd$??tf=tsr^D9)C(2H(fBuv)W=Tk&$ecc|swiOTWHYo@@?^JM zz7-2I7oF~~hf9j*ozyMPgD`Oi5G9%)E7b)5i#ueM67ph(dRT@^Rzda)Me)A%xdCT| z)wxT`V?FyDMyH`cdhZS>LAuUjrA5ywGrl9zg^g8@O;zP?IPt5!=wE&lJ07P&9}~bZ znb{irHaPUOXYtl|no)U3Qfx1+hI>y=;6u$Ho`=G;O}?s)n2v^Tv_9|F-1Gpo4Fip! z`#)n7etrw8PQw4zizr=U#@3xr&a`>fy#BJuA=LeZV?n7gLrvoN2**rd75Qi$^X>lc zD5bo$cOi-STD`v$Z)=8HLRM8)BSjsk&hj_4{c^|eoF@1G8SqOMsvS$A6%W9^&>v zI2{k^bCN=nzwI|>D0`6|dnu4+G$<9GZ2eRBW-cZre0ZO!X3O+6ycQd#<0;B}>3uUb4u|IvU> zsgD@pZ@y+1WcSmf$$_*xuhC7cz+dC1g)+9%!o{2KH>ELOcgUapKkpiF?_2byuAb*J zNR-r)^|*?wU6d>Oo8pIFk@(5op)=2a2{1BwUKXs8d&)0uf$Qr z_EQ(OHd4?wN_A3?|y=u$s6UO4!uZ2Zj1Y$ zl$+jPV_oGxbSaLCU`mP~Oc~$WEZtwc-c6O_tdy$VSurz}Uq1|^+{B8kebl#&!bV9N zvr)#}P&{{T`)y(z9$)#wBWA1Gg@IyhO;y685~daPc{F}_)JZhxYFP4U88-DMlinlI;w@}Te-TRiVEX}W8C)cah0pQh_ zmW6&kng{)2Ts?4f{eh)e_ruuoCE9Af?Ay2QJaqzn^RgH{0>=a_xz7m7DJ1JB4p>PZ z0yOHlm^GvK&#pWDoToGR&?NAm+K(S+6XzUSA}Wh%ZuPH5rBK;U5!^nmHd&{u-z5)^ z%}0-fU@omI9_=|dA@tlPf8O0<;A6O+EYakautZPS+f83`o6bGni$%D^uJi^ko29S6 zK9VjCijZZ{WRRPuEePnmt?j;yu1ET9e7*=&_Zeo5LTjPDrry0$aDH>sTY`zco(4&S z$oNWO{l|PTe{+r0e*1~Y$PWt$8?>5^@rUY#KC!24Je9xBJ$cb&mG>?adAZ#Rp|p^VckkNy7@-lezLRAH!H0 z%Xzg&SN?k|)gq_Km9y)S_v-5A{JVzd&wlkKnl_KSQ^O#b&h2<2?bQb=0s4h$k<9`W zwC1)cTtk^P0foa&&jkCM^xCT(54gMulAvC|XXfyNP4@6Mc2(Ay{C=2T@R8w`Vt9j~e#TsxpwlL}O&j6Y|;PS(j-J$4>Pi2dmVJ6*_7<0Bk6Fq>H7Wl# zwg*qN*y<>S7TTYGxNEPc1GkxHc@Ce=1ffP zb89Uz_^a>EA|$feC^0d8m358Mzd|*6=O3>xkI*nc-FvG-s{^gxBA4mYAIy8mtHKf` zf2oEKE|x{ABqMHn^$puUQ}sdI7Gdi|DHo0NkzCgJ>Y}T41e?&@C^e)GxOwu%&$Gn3 z<6+pEm!BHBPQsfw*G@DWvO%TljX!uI+PXb|ry~8A zZq@64QCs~w!uClZdd8->=Y-3-_QtzQ4ONSW^)mPxYLv{G{*IBv?Q?=`1%NKMe%zEd;v8w)z5tJ01u}=3Ux-8v3sNLp_6xJq;e2}(Izm}brkE0Y1Go{OvPa_}B~Qg7=i z!ESBQjJq)80JkYt$2}@t51QW_pi^LR72V51V(=Ul$K=?3R*FG(IrlKvTi1(TkFJD3j76Q(+t7{v2-TafQlD7#`i z-nJw1ns_YNJ1n_JbGDv(#x8Lt?a17@t4m`FWo(c0y%~h5%MXE%LUFtb|tN|H}J%!~qBM7>{^& zjM}V=6$#5Gbp0GMu;bqcNbz6F=9`WUpD!AEMxDj*{5roP{?scCMqX-GYt+RSYa#{i$6 z40Lln#Iw6FGNsCmjc>31xmH}2SPWs4pxj3jK$v9YQ4?#uf~2R~_TSlOFyjoIuSIFA zdbTuwpMMOus0xW>BRO!9J*Ntn*Ux)0RPKH663_fX3eHAtO4N#{Y610zirPu4uMRfAm&!c?#j(@@rx&uX#y8Y>cQY!TzTIn{pWCECb> zsCio1zN^JM4CWYitq1pVcWl-jnjEXpWh#orewP81st<8L_lAfl3vD57=}$J|JFb2C zIy5N(RA8h#`=Ac(`8yehyR96ke@hfCE-0!P+UGyCtV~9vq3x&^hO>G)RTrL}Acx4L(j(sI=iZjyZ9e8408!b>2zE^1D-R;hWdzSDg z4~8G{q2F9)^w;s&vDZ~WOv(Qj-;q)wx3-flIhkZpkgM{cW#)X8U$?~Ihu*-e5zebk zQ*--jYxAyYH2)Rop7M}PYaOSSZb2GyKY|}CGT>T}}_>Sw0i_Yn^ zwng3*aFB+)n zFYd}wMj^V%;Lgq>iHONemVZ?+D(1Uy>sTDl^25|85* z)(k0G_gn_g1NT`IkY|ygzGYm!KX)(kM(5c^32^|XN>g6Zv)>IwOq<8(7TElnUX_0J z0LvN~=d_u|&@>de8)^j2e2ZmHc_62M-!f%_RRUWPH!Hzhyy|FJzvaA%YALD6Kf2wz zC7Y^e$Gbel`WRYa%9s&M9nwGE%KC)R-t(;^-=2DZ55wF>Q4W28yJsUkzSkg5A;@v6 z&)zYHQ2GOeLswEQZR_2XsMl7*b zLgB`Wq6@}w?+74dKsBv^ZzT%_E$Fp>!m|=F|D06Dcy3zBZTe17Ad@t09S#Zd4W-7-f6%`vU4CpvXi&9!v zND(4@hN)6;BY6cGe}b00P2+t7_i@Ar;pf`O(A zsZJH<&N}7+?@Lnh?DnIBrh{Qep*)c?+xqhIJM-!_hh26f{T>aJYj*uBBPq7@W4U6% z5%iW-iZ~D6-0$=_*lWONBwuk`y*jw;KhD6)TTD-8>SG(JZowL}3i40ynFSsQDr{Sx zTqf}lX8{d>3woQDjpCToXFd$ebI*dWmOCdqkkoHc9lOhKypBw>C|gisE20Dp(6KZG zd_)V?tb|o*90vz3$c)(=d@k6R_C3XoCzTublpk)f#-@ohKaI&PhVnLihP*RSP~0TD zY6_MBC8rVZwsYkE+>JGHo0vI*3Xl4OOoqmQB=0-Zk+-vV6>uiY`Q7OzBV2)2W}2CH zdFm)wWNH*P)-@a22PK$-5mg$VrQ0CgPBz;?ZKHi9zgo> zb25J5xM4kpBz00+I1Wz#Ffn++YxlheMxTeWUs}zMdn@rxZ11cC(Svy05gSqcR8^aJmA|$r+ds>^-+E@=vy{DccrJeQ^9w;{>{iAcjn9QZKu=TP2J`X;ZU`ud zvX{F>Wjn2UEF0i4>p^MS2*&95P^G(;$>4{KaYybBqt}%mKh2*_B-(n%&j@+6NihnE8Xc{qR$}XPI>fs zJB^-YT#uZNDyjGItyK(0?kirrVAM$F@zv%ooSGGVq$82-_=SM{oUcB$jKUOAJZQmG zmB+AM>!{g(`~J9r$hL#Jg;i?oMyzVsbv>VM+oy?3sW;kpGM_}}M@(CkK2ap?CHqON zhI%dc2LALP`VNyI?==Nv>1~k@f%bjJ%#Y~FIMxz|8lBVKj*Y#V2jDvvO;v#)f2J1Z zK4mSzl}1j>V8<6B3(>Zi>PilnMcu5E^Z;-MC|ADJm=`K5auShl*X5Nta{^6l6VvAc zfS8ot$Eke}zJOvz-{KR$bSFe`j^zGFrr&%$u%RdnuVa8dp^3tk7ee(mWOBf9PbrOh zK1e%O?F&du6`{jpD!XQ`fz1R4->Pi2WNeOl-d404Q1k6oo`HIw(+5W zmP8Rr{$bh`S|4Yll&7b{QP*Cbq_Wv8lD4Le)6zG?8&7r)UW)2fO?;ntG zZhI4b^Y8t(VuuOpc-jzLaANa%T*TIAqEcgI4QcPb4FqG4c>!sv2r>hFJPE2GX8emD zdh?PG00}bssWGcNs-rT>o^fKPnl>j^mfAbhRya(D8ef|7ZZbjCi;)#hW%1c=il94a z8lp*ZH#?n;=K6*!$EDn*dvWgjg3F2RitJof@^3c%@TUbV@yoj%_`Fzup9SD`EQML6 z73x8^0p&ybm%0TpSx#~B_nT}g3-+)>LAGrLsn<8@_%8O4v#!1BX9 znt~2*H}|79;CR=?^?qOqL7~=FMfz{UtnL9jaOqQuWET^MDLF0hjvtWu&1mJt3bA8_*!T}@+sSa= zf*1+vWMDe`^9xNpyqW(IGv;Lw!x;=vLG+EWSIXL5F|lS0+o%75ikXmqmhLg9W7kI3 z48))krj@FCny@tSHUdpDtw1Q+td>aR5!mL)(4-FRiNEj#fJ`?EuT^GfSiNOx3*v2A zRKSTpuBr}-cJFHH>hD&u+%>d_^kS=<_N(R&e;w;)6*5EqfrC`rv7aJOh)kl1cv_qJ zEugd?DZTI(<+nSsD0qe&btOR7{nTeAm|oAOjqDDU9o|`#BSY^a!?}GaC4&xr+g*y^ zwqNiX7oh+=rLgVMNK1`PIOClw5h&EMs5~UJAGedXn$$53=KBo56G zOaC(JIhDEEa*>^b)k$<@P(*VD)YFh;M>5`_d@O;6{W82*H{6rHSTG}lP(Qn^kk{wz z=q^G}4<-BqL2>Bxk7St}+E4zf!Px-SKP zf<)Ji*I3UL7G0m&#ji#kr=rjKhnYCSPp`cVbEZ$pCZv~nt0@Ni`n3Y7~$ZF zkc`pCe0}BuD-^Xb{BY1bzH!wi4w*JPD+Fzt$L+@^m~64Mpw1X!7AG&AMTQS%KcW>f zkV1~p;l~P&voot&4G<4sRnE=WEV~sIZDf*1Ex-5c#Ud;L_@5fG+(e>of>v6nt}<=j zOb|Pcec*}pJTIW}kYQxy)_81}XnT~$2k zTxKrZ!^?7y{8}1ghC}A~=RLUaD-411?l|!)Z7q-rm^;e49p?sd3x=orEnd4Z{_tMI zYBQhf0%3ulPXS));8QgN8ErK=Ck(<7IGpbf?RvrR3x%^t&qCam6Zz{7M zvmDboc0m7jxcH(PzN9b%yrGU%kKod4Y{Z+99f16PEcdojrTrG=7d4o0Y{(u#iEv=)k6NOpw&wF zI&wgeEM7WlxKFS*`ou$%(r1{LNc6sR{m*4*Xzg4bU%;5_CxSSX7Zi5{*O_Vccbx`R z7854dzpga=A$Xl0XyGPb6H4YSa^jIhzm9FTqW5E$|2BAB&ZB~$TE{De(lM9YW$?%| z>8;aEe1x3i&{H9uV}sv3-^G5l6*92Q2b^H8u{U zeb~MTzOp%DEI$`ufcrTULCbr6tpb{BO?DU56UDwCjbClIg5kLu6^~7yul%Pwj+O z{H6;h@f+P$77%z)igsDr5yY*8tCfO_ra!}Z#ly&PT(1i?`CIszJ3Q}puJDUndt%)l zEM@zO&I0|e-)&lUbaU@b^$7H`?rnG0s4{gn>qGYbHYJT(3fr|)=CitI8XwwGLvPiW z$k9ct6=pic9dd9zl!>xvVYu>?jbV4N8C6A+>A%EP)fSQq^AETcfz=G_+!e$+C<2O1 zZ{RRShZdTwaJ3YDB`gs!Inxu#2t>s~stvOkt#CS3MHK zIVpBhIGeb3JzM3TR7Hzyx;}nK$o(u60>gWSg|B;AMZ4-b@19Hrcg|fZI#V*@-08(R z^Ko0=4KL%J&sz0zA|FlYcP*mtg$8j?Jb*w~jTbx?=gB=C=xxE-Z8=j{UM*}1pejK$ zNU~b5s*DM|H1-@d@S>mTS&LYO2H>ICC{?`odWpGkO=3& zp=krQ8o#ll+HP+*YrK4iX*^K3MSkk^WT-)Ih67SIHKPg3h_Q$lzExCd>fT&H+f0cq zXcyPjyxW(cd~G=cCUX+&O`0nLC;RA9uimvF`4uYL)fn#F?-FAAbnbLZtj$TO?y;$7 zurlMDYMf%8t*SM@`W^E z4^F+i$ekrqZ=(a3S!!QV7y1$KNf~}3t8l|1FjGNNvL3%(MoZCa}r0h*O`UQJex)%uVWQo55S1+sPB*DiAb?vofzJo z=~dJ=s($KefpiX4br9p+GxhK3gnFD0N53>H`Gt*-`Wqj-aOQ0q`ujUuE!(O7>g7L{ z$yLIqZ;aH+bNfNj)s4B*L;jR^d={iufnDv=EtFjbA1L?qa^rjpL)5>Wi%mgL%W7RY z@9w{t=5Q9KKLIDCU#Z}H_Wn7RGHU42qIa;UH2frh#dIY2h(QAk6Z(Y{BTZ{u*Q?g*3;Hkl*i(U$w ze^SAqG}tMTSGm8{R@zzTPMw6LdxUc%x!^OCw$@lxI*+UJl!W)s&i6DAXo54(0AoV=)UUv5`O;>pi2Qw}ct1I=Utb=z8TV2$7Y-_fZm>R8YQI_P zYZO3wG!eXURgdzM6@5`m%z>RnaqwPCjzfX|`*$(2&+fnse|+QgRcbk%i=C>rbl`|I zG<=Xp`^Pn*ubQ$chH`Eqvvbp~UH8@prqvhciB47-c3K5CGCY6sMVru*@-ab*a#-7A zOk+%}c*rfmQ+D<;*M&x8(Pn$HJ-u4@O1eRsFS1Y`Iz0tAOuI3*9gPr99?42lAE-(lj>%i+4EY(R;0eZ))tO!u{p zWqGHngFqxIisvLR|DSXrdtIP_OFtNg1W7!aKdYhYu)yN> zVRBv%#pC4N_1$0T9GCxK)@~B-!pJpM(k{MoU)YjuLT}stSieQ4NW3X;GI4NI*&))+ zis?yuGsD!ob;Wo=M?8g1$!mLM}#I(+T`K^x2t$G1ZT)ZM0*Qoj!3Wg54siz#bC)Ra^e6Fw9Gj zfg;hl(FeU_>vxQl_Kx@d+d~HjOmrPWD#fv_NBE?15|Hl z)iG9T7(kkz!_}FJb_iRcX&0j7PAy;pr)=4Ef`AF@+Jx772N8Z>&CVJXChtl0oqWJ| z`RDL=E{p}|4biFo?b%5qipPa3_dEQzS2@ecNwfNiYd811fe^lHC%g9t>mylHaZ^b| z51Vx}1sKT@=coE#O@L3z0X3S*w-uz^4to3!BpWPz5 zyI1*UKF^u#n?v^@Fr*knZ@F_P-`Og|6_8=oC^_af)kvcoZT;)H6?OJPg2GOi`OdTndYj0~W3akD900uQ_O(NsAJcXuox>BGDvK>zJ6NlLI&Lv|mzClkZ$ z;?zOrzJ_=0zRZRXq09sZkdAEtBZs2o!!Es`;gk#3x#rP%C$MnByk^DuDC+rTZfez3 zb}PKFty7@b{3N3UC7-qzXb;!rCE*qD@O_3|2EHnd!e&y_$%mPV*ysLTb;(f?Z+U_R zPM1pkr7FW|LmQIsFSr6UBUtNSPlG#qg7UFf*6d9`DSvmv9qCv=efs;0irvv*NiWwW z(IRZ-rt!fZ(9~z~XKITzh4;1AEOZ{J6I5 zSD9JsJ_zhGK9afz&iquZOB|n>imeC>Gb!q}>}L)+`J@e;KMMxVggU~UTR^&=@p}(M zqy<;0CAT;@!vFK#-W*DKkMpuB5GV{GIyv_F(MJ`D(cA)Qrq{6bwX98k_WUD*oSEq` zFENv+=b1P?13zYslQT(Sb!!ohbkm9CX>d1Us5(4n(#^ z_4)5D+bOrP%>zD+#iRGn7Jo3OFD`a<-&d2blYMZI@46BDkf!u+dXP>*IOUtrM-1oe zvNZknday&r7$}`K^V?MFtC|M|QQ$ty6UPhQI%gPV&b-Q;%KYK*90doWr?F=?n^kla z8n6f8V6$Ab0e^FqOw?i{`s&@$=S%=<{1N&(m8hZETyYs}yThvJ!^B$drD#aXs}7}$ z`Xkb@AAlDvpUL!Yrh5JUaEwBP;bgL{ zRoeifd%R5Ip+oNls{iV}7~mB|^0ZrUEnN>x^GdtkP~F8cor`Cyo<=e}^J<}DQ^fr+ zp<#^fadl~$u#PUItWys=u2!>CB)05(w&>gvJ)M!537(Ai_S&0Rm?<#Oo$cE7voP%W zqbYv9lT7?s#IJSf|9Zt{A97JqR!I0WGpZX_I^8oHa`LeYn0_r#Gy6Gs$Xa8;ig&Yf z$Amqp6|GpfLoLVw?wnQTc)d4Yq3(|Xh+3hO!+EpI1(l0^r6uL6=9FSk^JK6`kwy4+P+3VBys&F6AG{cBY`xnw9Wh z0W#gd*}_FkGfnvUK)BB4;c??wr^xnkmsRd0xQk8`PiPzJL|2h^qcP2LJVcx}J_p9S zYC-D)v8C^w3+^%6JSg*-mqbv~2dpYlRKEkrw$Ek~?!v&)OVejJ;*7#guNPFn!VAMP z2!b%->nd_+sd7cwOaO>P|}NH0bm&sgvddM78=y*3kgUZxpS)mqaCmD=qeBF1(1?Lx?^URyy26>LAT_G z<;d9#@SoqYqH%=`Pq0IZeq5#|hjH3c*qPNl7T796-ToWuO6dcsf+;lEpnH}x?v<0$ zf6|_u#9~ewFQSpMQ$dC+7RJOStI%U32gT>(KrEY`a8ZrVhbv$bPR?{Aw^J%Lks@<6 zWjv2xp|ch~@fw$^!ZwFvEAZyBGi2T^i7toC!0|g z+ZHr|5eojk&^p$7=8mT$F|x!PlEl}Yv2@3*#ei_HzSywEO&bv?ZN8Bq%b{|7w^NwG zihvq+GYXqPtof3mK6ac3bzGnSb$RCDDC|4FLAulSIWoxJvei7u(QOSSV*+oYk#xJ2Vr;(|;S8dv@Ggrj}_WQiu6fB}cmhnE+0 zBBRwt#XIGzao7JNp%90T|J$E^?lcan>Qhc!DZ@af(>6HPEVY#8=4t# z{AIFs@B)7CHrX`^OtdX30y8~I{}`A)srP9sEynkP7428Ztw<+_!1`x|O@U3@D9Wq` zpMHyt588I)K}2S}&hW^jEiiFwvsg4xpl1xgr+L*p&dEr9TS9iC+C>1MCluV2mT;vK zi3uUTs^S0^&5OfeE0#aLwZE~B$gxhVe%6Hw981SxvDP9$cR8jzn_H~hAJ(#W`w>nT zeO0VzICoY+9|uTK5+fAt($x5CJfWs~l+!MgfM`CvJ#xMhD%&MyuO5 zAJ6}!HJnHIkUD!B{Y69e(o;9RxnA`1NWhaj%x1Op)ZjMQU_vZ-qmc44PkB!C3FuSp z!XCq$X0QE%TJM9j`Pp!JQ>z1Y*N7v7u{psrRwFZmCE+FKcW6t4&#krTc2V*ojcPSH z{BAPevqihCm{ z1p0{pu5ODg0zcWb;abn@c^<`;NZ+UAM%VO!&*)B3j5^#}i)g)sEKD_q|L5M$R%6p| zGfp(CcTh4LY+$Q<9W;loNX)2OXG1R?&2Se7fb6ymgE z)M45r2*~&{68e+vNKZj*#s{JB%GnG7Q-se&Yo*%u$LM=(tX>w>tD(}r(A&P;&Ix#7 z7uS3Kh!r~UN8hch=b5XLfSl4|cZ)e-$rH1M zuGyxXl1FcAzBJEOoV1_RbT)`hnfKpgbJUwa(juu|iW`+Q9y2k`sx?s9<;)}p4t>lK zgYn70dhX}aK6=6OkXgk?a%Io}YM8gsC3MWSZuS~%$hPMeRDIkyb@jtXoVyhbVBF;C zJGkuA!qJr@Us-Kz&ae>MDU6JL4B30piV-*+{i&jLXkIMHTsAalLQ6Y~m&|KhbSt;W z5d`i0ig@>_<(3y<|8VxJAFCK!tDcbON&bBwm|%Hos^4QA#m&V=q3<7Y_fK5kjJnb& z8|ZJ#C0hFCHZ)GoTAYcDdg~H}6sz{27b^^TI+TErzq~0a&qFRETp@A4e`JSSug}Ie zXfj!jn(LTmcDVCZc!Pm$4b^*7IR$nlxEd0LiZGqOSc(5P)(pFe+A%qs0lYD5st=}e#5a+r(`gMs6;#JNwUWAzf(eMuQm>yR*V37Ragh+4# z(c9`X<9b}l?TuLV&E`CsMVo1Rw)1JLfojl7c#_S@c<6`_M2n3%2VivltE0OeVsU1S zFj@4Rz82#z%5~;>>-7uMI(#tCtHjQ+sngN0L~6I`)sL!-Sm0G=ms)=D0B2!WT){}E zRcq0tS5v&f$ff-+`fsVtDxMZ)kb$4il81VI|IB+EI7Ca|W$IPSua_^h3z!%QZlqJW zm9Co>Bo`d#actMcaD-#0X(e01SjL)_ryOYQ?Iy(4KykGVfi#peP~c?6y|(4uhP7v> zoZSo|oY9=wN>hJZeW-_%GAAYx4|4Wi&$rlj|Jc5 z7bN%|YOGy8+Mwmbnb9ili!%Yuqc%U&P=i>*lTVz@tKbAFY5WgWq?4A*7~AOO@(7Q2NbxgbM#zNu8{WJ`tK3y(0B6MO#F?omv?|?W|d|==UXfzpAm^ zf8oXSnIvTyrRzn|-P3bbtK_&iVN*ns5A`+a@ywxTzGU<{XYMaY_tF}I#n=5Wc5GFC z!a*WeAAx8qdFR!ybBZe5S8rUKQ!$i+NnvbqYIzY|3SC3#ro42uOQ38p?+z?O!y~GJ zB^y$c=e6mhXjDnYX@1@|8k-Dh3+~Koa|K`da936nP2+Q6ZpEG${M9#>m6Z%%7jItsqgC#&4a!yRx>1e%UDojsiLuI}`j zkJm7bwDPM)Q`f#Ku%!%M`ZiZxduKy=O_j6GajnmPP2Cw1RlF?G?`_K1IY-*xG@^44^?6D(EyvpPrzIlz3L3Xq1ujbpKpRgH8#Dy$oxPMyU88@`)NG zIjk14vCH@`#}v5#kAgD8F)T!V339B}YNAA@&z>vi(7!9M-M~jYr+&8M9HLnHlyOrQv`L7(m_V3gP=3Gk$H zZHn3iRbpx189C>(d zsX}%vI9X;uQJ1zW9(OTNpn)pa)=(vDK06m?90CNu(F6fgTX30`OrD5uez?@FBV>Z( zvDZ#_ozP*mGG?E{Wm<^Ov=XElEyMT8+2N^+4F8_frv55wKmSq!quP3fG=)4+6q_+L zrh$)rmtk3vZ}d#TuOK9YpMLX@9hd5)Z5Mx-{P>PRf8B@+$`W%AUP7Vsv3+AuVS7a~uaZ93kOql5O z)crLzV&TC>q0sFg>B3b?mk5h%QZW}$ZZTC_x5S0fJ=h)FD?t$}l+EI4u96kkRIfEs zzEVJDqdP*L9@n&AtMhW<>o!agq{f6UTylb1y?Wu20pOiSBr3rP zw|m7VX($-_krf$l{5J?597KiSyzB@H{Jz`irnncI(61cs zK!lrKJc#*OzHIU#xqV|rq%R`SgL{fj-7FyD zlS-1wtj1|sc4X0JU(ZJ^4v)>S1@Y)o4l8wSRl10_zZr|0Zo8ASeJW*Wk${JaP12n- z&pd@3qf&%oOb+H3!|2}tn_tFMO3c|D4sllm!(U%x<+xsLyfE{5ho7c9OKPv}CDj?^ zmOkg!bLdBGNZC!Csl4Q@0kA&pWdmf{*K@)vr%l?Fn4f|BN_*M&35_Y_e{QGv)w}I4 z;8#=lnIXqtiMWgIX!%2#)x-d|8T)4Ki84uB<^&TzAmaPZYD7{)KHP8i@X$dq?z6}x zOn381*ClD+fo|d-3>c%D-}y=lTDg$w7es8u2-&^dY->=8RoJu>&OLPDRW@kBnnE;u z1#4_K5bE|eS6Id}*VxLZ6{@pD9f-PYyi#_Ad9etWjrpZMS^;SAUhBxSG67UA%lh!c z49cnNaJe+OF`9c!o*+1oJn?_n*JbKBZ_Yur#`O%sU#YWq)vwlA`2Z zeTR>sDWaYF|5++krAf|WdSw>>Id^}Yw9rpGn+CnV$x_U_lsa>=x4qPuX1MX5N=`o?jhF!=$zbkMf2udU(vK<>?B9`;FC1cU6uQJA1=@xrBADr zl7fO^J4<8hDPe1ZA?c3@mLfAq(P3l=#7YDUSO`f4`IKp2%(kREAiM^Ws@@_g-nJ^Q>QEP~8aK7M0ozCUjs<1ySL zXQK)j5bn;7w&eeQYMPuTR7SFwoblj3okjt_H|4~k0%Ry?cyUPkK;fop4N8XbP5C=_ z7GwwqJ!Cj=8~P3lXZ+-G>Gw8hi(@I;jW_#dq7IC{og&@mj$AU||5q@opT%=0Fp8D7 zTXp{)_<3`h=RvWh+`~7|`+m)jZKCA_r;N7-UGHZ7GF1L2R;_L9Nsc@!!5rGJIkL-X z#_Jh>8NHb?`6_S7`6%Db!Y7Z)&xdD4ssCrc_}Dy_k{r0-5x;yLS#Z^9RmraU1f#h*?Ec3zB8K@!Yniz-X%Y(bcyDCllnceQC{?} z@pR$yXwAE^RYgX1>IMk2!B0>xL(o^L$uonc^fpyb2Mc?yfUz*0ihY5Gxg7!3v%v=> zpYa@NQaBmHOH%fiPt61HS1z|LT0~Gw=h0okHuNl51CXWBxas-8g=^KCtrE|f z1YD8C+nOJg)D@%eDyzu?;R8o!Ku`5N=pPV0T@h-v(9+tDllfzEPWwuGfmXdd zKla>5Uftv)G+Z@+x>eYXn8#^WoTwDJal2D%Pz#zR^50?{iK{RL3{F^IFc~?5m4Gud2mSYtSE?kV37ISK(TI?SHkFABo0MB>=yN@rvH_reN#Na1EB>gdqHmX$Qa<@Z%jwXZ$lH$^ z*}|kX`K#2Z=i6RnC)34Ez2NlB%Un)ERcptiFL+5TgKo!f9ZH{;hIvVU0%M&Zs?KS>$PR$0%wMqoyO#X0E}<`uDg7yLYZ!J^HBX?Cd97SIF@{0XXg- zBV`7Du?<&QG$_~0>m;KB?OU81=KO$bqT7%-HDVJ;22o4LzhkmzSz{1x=5UfvUjCXH z-%ODKbaT@9i>V!crl?8$$}9QBiWOb3d+`qpEyrHyMj{KQ+cReddamRTEl~YboQ&(v8K?+Byw>d50xr5J=ggW{6*P;NCcyn>-)Y< zmnuev*RQf}im~dY`)7SQNY2iqq*^;wIU6*zC*fBv@NyLFs#XhMuC-ypqzQ6rI!lGh zm|#148xVCMD>Vu`7|W%nvGz40h*GhPiC{`@TuCHtyd9=kuJU8MVX#f5n$+=B6)`kX zWNOW8(o7%Bee0c9mT~VUd8Z8bFTC?6vA@1psl6syrb@%Zu{N%v#9Ixr>Q)WiTYF;U zgIFlLpnSln!<$zTyqx(pd!$?O*Qu>dqh(c)e$|LF(*RFds|46ras;Ws9RVDpk18nx(MpFSGi+pugIC$aU`*2l?h)RgUr zpRhXh4AQc5J@N@_cXI^8F>!5`w~nt7&7KfwDGshh6cb&!wJzgn*t_Hzv2%TkhyUP$ zm??^aTDY{c3Ow0R=vG^q_PpEbmsMnUZM~xodSR={83dj6AIdtirP`5UizoaVE?VY& zf~~GOR2~IB8WtiUbD}EnV;24&Om|0p_+>!p7ys~X&~e^h-2EryTg84Z^U272dwDqw z__GySoH6?5KE+5e9yUKJnx}2X&rS2yJLtJ}jX?!|cM-;u=6BFVK{K~yv8k)T3x#^+ z)nm;(7Z7-Y#n2S{{^w<}fNDlJ%8`kf;;ML>>>bzYDz-kChDZbZ?m7cRb;61HYqj#A zt;=+(`_9u4hrIuO+i)dDHQKMH9xgR_)s1UO-_?p-H=?usax|%nIg!GUSzRj~v|sOh z12Bl$OjKtz?x#P-)(+JNncFpu8lBh_>}Gz!>8)Iuqu3?zvvrna&D?{C9xSSS3jwPc zuS)%5Q-}?v^FdgJEx?|{x4;%?6B)2mjiY0uu(b#M;;y!IPe$6_=b*EqTgS2!FAP@u zuLk96cO2X3dk0-c-4^t882I%u`0zuaYCBM9DQc)YY7kY}e&u4Ph54Fz3ak4JY|w7zrBUe?|(8MD;}N&EV+c;;iIyAsPiOHIU*K zFoLh5Z)_DH_@|l^-1DmKcJvFk>~-t@`b`8ekxBR@@G0glxaeLUR%QsrJ(DiT3RGvW#ET<$8ep73|!T!DAW-Uc!eKTcoJW*hhjUz@77XiU3&2@ zjD>aVR9@%0La`kF-`PHU2WI}qo!7E13#tR=KF-zna`CqFw8%S+m zRkrktA|gqAWWV@Q>$2Z4ISCvs8>S!{6Kol%2aps}t4Pw@PQRm&PIJg%(>m}!n$E+U zt^e`=w$|!Wo9ZNX&DvDa+QcSkNl;>x*dZt#6nz`55rW1RBSeiD9X7E?f@rA`t2ROX ze7@)W{(*bWz2}~L?&~=o&xK@ZXjXevFC2c+$>0{*S$8}A6x}M_M|^KrSWc_3w(-)O zl|fRX^cUL;BtiKk!`wC?V_{LG@7Db-t`Y#c%`jCEJk7obT|h0|*-+umGuH0AN&AV` zjG=2IvHJ2XZB57J&@d*0YK||5J?%lL3Ewj)IimCV3l&Opbt)8Cqmqgz@)F-48oN$WrA3P&r8lt2bC~UY+g;Czxh*0Q@B8p+!|m2Y4@$ zv4zG?9YIx{`bQV=%YrUr2SUgddc}(FZkO5!wkakIGBWcVOdQzJ?*#2Bw=Fk~w2hlW zeVJ?<0|lRA|4>94eIRI+-?_vm8zi3eu&vKQ4(Od918=3w5_a`P{Tf?#X`#_oy=pSw+57<{Ln09!5`jwWc zbsK4*axq+T%dYg_vef&X9fp7A4>-O=qdTI3YXZ*f=)vgJUq)lE(OBF=~ua}vNTe3P@IHmNfHk8-6u zvk)PR&>TnLSr1F%VS#yD7wu$BTXQqasr;vsoGW;R!LM2{8wcH_P3a6Bs1N7Qjt7=P^}IeZ&BpK&XHWgepuGj zGXV~{1z5toSr7$>9Jjuk!1B~Wt@93#Hr?r6z;_gN($aUXz`WjbyVf)|&T(emTF|tM z;-2KHkWZDK8Yat@Zs-?xX8kp4T=^~jDR0!`%+wKCy~kOMiQlqDLBJk=0PqjK^hGG= zMbbDX=@&G!vCrRoS0Yo0{%Qy%*q1ZAcb-Xd!A>R~r86RaW6)yX8HSyv;pva&zeyE*~EKU81ZpILup zADEp!miyqb14P{w1-vAewCmdI<^D@f5%k(fNk!7utW1*Bl`aT&W!$chHUza%8R{II zOft8lE?8tC{|dAw6HXqGRticX-EOO9hHX5X8HT%v^FVO ztpzW4D&noF2H^$|U*5Pc#b`sVn0|uoWPX0BDKEP}DBjk->8uQkdsH+1U2h^6D<`=j zRX^u{I~BS}ED_8;@bzm5o(vE(oP<4pj;%#L7tcv(9gqGnx*soVl=j=QZFA`J$-2SN zo1_hhrAj{r%iqQ{ars-h3JYq@;H6M{y0C7GU}2Ai z!A(^tSl>qbH35;|cjk;=*#LD$W%uf43dwMW?-(xk+Iv0aPw#Uvz-F+xu7HdtWiw|h z>;=2jfi$=ZL0-u>(^RD6IP?vA$RLzDyPjDa5D3;R3aq(SC;5oI5qI}&ZL@13 z2axyL%KL&JXn^Ie3>*aO4GY`Q0R8S}^BixmRSZ^|gt1r`Y@KttsWs2*9>}B5es_11 z&v9WU)|%7CeRZJ%bJbRiS2o87eMZ&j?g(OqAWx(j)FlkGYrJSwf=0J!E~_xmj41CM z%q8G}nUaavDSx8OjwsL?B$GsA3w_eo@|(C@PIeF(zn={?%g=-7sSDPF&6|7KN+!1` zxco!}-JXNz-T?o6`z^EkM!MsbQEKT*GJ?db2d@tz6Kh~sX@TtadAMbzvU!yrh{A!U~-T^l8?)g7T165b1 z-r(GLhCETmL!QrtOn6_!3lFqQQa5ZX#cYjNal+z-YazVGhjTy+y}9|x_2QGVV)?hh zNxtt}xsD0v9H7jTnNgajLZT!1jT#PZGjHML?mgYBv{G5OOUbqe$8PPJieKqfv&$Aw zvl>5U9|#x&#&{Kg^qhtrljbIw)Qx9(ULr>uveQ+Oujbgz=w5+`Zjmp?1H+DnnR3`g z-CWqlOu2h`_n=VN#<{V9&S5wOjU_ve$Urx{%-U^@}LoP9X5e zUR5-zLa5pAJ=z_rhl-w&`@k(+!<{`IL1T6Q;|;XTA-sMV2eq~KHWtMnd49`3~g`!?TfxSk1i z7A*(n)a1zib!OUh`VeCQpK4RPu(-OVzV_kBI4)y{p)pTq6{ET!?eHXMvYOeD%&=iL^ z@Fo^|rZKHWPHb<<#}USs=TzR|g?k_0p5F6Oos}ie+EBzyd?XmBE1KI_C(5{iTh+$x z_R$Vx1ru%qP{UqzZlO_aTHx}#V2DRl5L5?O)yA$zBq63GYP6d(L!--=z2QC+Y%8S= z+Jn2f5j(?B82IyndhV>;qa#+~R7}dTiK5tvEM2Z0>cV>-`u2~>He<(nMXn8)Jycxl zkJ)N^9YbJmS#9`c0&+E~!zX@GX)3`|7oU0rk?$4F_Z@NPe7f(y_jS99AbMAEpiRY7 z89cv*I%(eX5Y+up9(e!B6q^Ujeagoav}SSte(Jbe>q`DZ7)MKYGgEhnvShq9VklC6 z#aNpc=d|G=oMX}SSzF--X0$@5;vuw&)Vmjn*#bMi3;`Z|mA?xB&q!38)X!zDnD($crDDv1?;9SF|cF&RawgW}~XMXwrgNLtR8(+%b*%i zB{W`CkG{xPgylIq$R_QQ#4D86w3sMUYszA*t`$*10-*{jW)6Puwz1s@6@SvA&t<>* znt$UPPOHpe4}n#X-e#Exo(I#T>E0z>SDnC)oeWNZe+{%|)p*m-*v(%nTdqT`vInY| zc4pfBvUmR(LS*8|xKRQGOuhI^DGx{&6dj0U4HR=AY&Un5MW+~n9o?L}41G2?EaTW( zNx4A><{~rRI-L|{SVpUeVW$3mfpE=kk}9jb&!~@fE87Ty1*kbtp#oaK9`pN6Ibe!B zm}O!aUqar(UJ85rl|dgB@bE8%?mA?bC$O8X7XYnb2NSnLaO8opi`|RTnU&(E^1R)% zeg)r&ShZ;(&`6bFn&TwGd7h~7Z2#KS&5Pqt?#OEC!Qmy8mk7MdlrAU7)jWIY*6|QE z1_zEkMZ$e)Kr-4=IEti7JO%Xn28|^a>W$Z4$@CPKNEn8yVy1&U1`bnTzv!C1L4!gZRLr!?;){XX0BF8Hz(qG`(PhSKP2 zA+_ng+V?WkZK1jV2MT-i<$9mEps|K{E2`Yf{O_{UcqnBOsCqw2olW)~-Bi+-P$P4AZ z>g@KZ>=CK^?NXatIM;`h|rYoJ-JVUZ`eOeLJXpm!9B zK=}({+#9x>b_x;quu0MfDh9&xDqY}&0rv}g11iQ1{%W%TMHNZt_M9bMg!m>_VQbgl zguA&ZyyPtk3hXe&P5_b}B5Yi$v2!ZEwAleKPwI*t&SuDL7fmWsu}nehQiz-o_)<}t zHo$OxtM*Efu_N{*QAOm2Yu9vR)nMgCxl5H&0iKHa&haYnxh#X1^l9MxMNyJiWd%lx z=LKQ=4&TC|xc>^H|^8cnZGJa9ps(fF}EhL3b*)Vj21pOS)I^iik6_Jo0n4H}OvncH zK}|8*YhGQW0m@A0+!13PfjRZAF`;q`OrM!v4VH!78R~s(_Ddk3m^16L;P5B*fqhb+!r=sQ?{lxqF=QeH)cmY_0MJ^DVOez~* zzD@tngiTA3oz145JBi3|0g%2%Y`I|}n(R64ba7&_GI7uQfa z&TsQ{LfG~F9MmP%Gq3|_7%QS|v^~T0`S@X!MD=tOd{M2LzCgR)uENNg-?2)lT^kPL zI0L!7@b+sVyVW%dvyLr0&(3k9a+bS&-T&wZw(@p*2>qC*ApVilBSk zuPQMq#vNBdij$`2iRlW=)CuSZ#%$OSqlVm1D#an%fxGNMfoq~Z*U!sn4xL*88pWAT-d@O|Z*^r8Ha zS;PiZ>+!=i*P9dj=$bwA=U0g<(*rC`Z4GH4B&un~Aw}4%d4giw0hzRWGtxhPei5-E zCpv}Gu$--h(hQ(_^p`vK^Jpz*b6FGxFOYkVP#sYPk> zTYIg?-phe~4F=I5RZElcH;{u|t56>O+Tq|=IplWPl<9+}C@pJx7ZNHGy8oT&fSN&k zocWWe`$xB{8+6jp8noW?E^mX*YqUz0Ry4pRM}=Kp_HRrb^0lS=6cmcnc+$LLA5<`7 ze%4Ux$mDB%h#!|Y6&=$0DC??caM@4<`eSuZI=bQ_Nk^kZPYDv!tG)7N)txGXW|~4d zicD*qL@}2$t*RI&J?4M;7TQ(xO9^J(MKY>338Md$^g(gG^6e0QD`9RqbD&_)zt2RI z&qz52QVts%cydUqKVGkbA5>BtQeuT_UtvuGi>v&p>l($=<)8+J6=hfvi+2p=A+Rr) zwYv8>D<7f^RKVS_di=3_@KvArrHbhSEi1gVq=U-~wPqj2Zq$`^OhvTUDseBr38-Z* zJV77M*IstWo~ycc7`0D&?kGr}aBX4uMkgDU>YsTXffYv6po0wO&YVk4%Z&NDl8m+W zVF(E?L(J+gd&$o0cVCeFNERtzJSV<%V83y(=4|#N2X>K;;MfjZe3UnG3gihFZ1Vo( zf9VlrI&(+h0;D(_cLN*K=27R77h4b_NeYq7EsK%O8BjEH+_i)8p*wMMFHk3MXPF*$ zHp;~?Efj1>ez*83NWTE|tDb%>D~;w+W*~<{JfB2Y+vQT54`_GDv}RF!A*4e{yejY- zXVZgu4=YX7WYa9Uloq;@mhN@Zpps~~52t^!JHn6RS)*f$X66APKB8IX!ucwUKF^m% z%~Aj!bOC3MC-q*;1mcreZTjqoa&vUe7G~rMkc_9ympqWTo8yW#yq#&Xcj9(yxxOg( z)Vfg%nlS1NMKZ?Uw z_Utm|0|M|?RqD0{Ok?u|9x!{l4*g@2!!mIV_Z-GCw0n4`Bs`y9X+^l%B6eU#`9v@+ z`mIW)N&%B|?Mp3gVTxM!1a|+qLGt+*{Uqd9z(!>8x#O-=>V;>9-0eY8RYrLRgD6UH~_n4ncYe6cm=XJYd*xuDpZ{c5(i z|6b|e4S#r`6_ym!Zz)msDmzh=a3_vdGqI|v4!Nv?chMN)~c_B9<+rw^g8G2(A! znMh0f4b!0;|7}|1_ORZwX~;@$6jzQ-veMJ)j8bn~dMTHmk?AJOA9YT2$f_UOTR#M7 zOP>8rjA_2BxM}pKt~x&Trk2;=A$J?s$yJLfriwc&0Q57Zn>cJc1czka)V|C9lxP`- z6GjbsyAME9<3iXI1?;$2#t`HB+lE+Kv!v*2uOgwr*dJ%7tvewGv6q&sj6q)}*Lqx~ zU#0#uo|bmJ-M9H@C4>^|GVWs5Ygx@V&Br=cs0gcM;#Eq>`hBm4E4ohlKYszNJNMTW zUwV$ei=iihb3}J{;gQS%-a3>oLvfbyI(rjW>W;S&d2dBq`9}0mqt^DR{Jm{8o zsRI|rA6JHdyGdMm&3NP3!!#$!Ui75_grm(*Pd&M~>ply_t`$YmO^LcoRw2)8~Y8+`9ne2@iDpJ7?k`=Kp zAti0$zw&4vc<}Pm)O6I^Rh;Y#g67-Y*XsP$~7>P$-nqj?pFPz49 zyYr(%Rd<+Hd$mYwufbb$V$YJ5L=^`+3teg@#>`7Ghp#(?YQp5JFq+}S_Rn=l!DXQx zg=X88{#Fc4OTt3d6OT{ZfE0;@(F$ukT|}23y=D6aZjVLBxd*Rx>u7r>=F*1OfkO(8 zHV0+TREL{WVHw-UqtNR{YXuGLRQ@_xmLBbyvR6!R1 zNeSP*2xGSzH`2W$ zFPiA9LhwmyN}`r3>Xzzm;@*>_zfG5XnBUbtg3S=eLqP=Lyy;xCM6sZt>56c?h4arpTK|N3-{e&#|;B&osNC^v;Kz zW@`(lsH15-l@i>iGNIVZ5OSb48pz&=9Y1dS*Css3L;P8ACEz?FV|A=K^~A@^v&ezD z)@FS2ud7`*Hv_p;ZzyFM_#QE?sk>xHNt0EQ`xQ}VdInUKbZiXdACQ*Q zbY}h${Yr1QQJqAwDvk{LSLsmYxD2ZZ09{dAJ=5KVW#!uS9*e4apq4qak-WQfv`H8O zK3GRC>u`n^)sdK^g5%otpJRuR8ppQ*>Nh%eRjfPTN_C@FgG&EFo~hqOLAADVNq{MS zJION!$OD@6A}eQDYwf;39&4JG5w>Q+ieG|f&Qd`+Bxq7?%%t~ab>(1Bc;_ijv4h9T zefhlgdM0~Dso0U^U7!{^uw|x?8D>zzDiqC_H=J23y#Ek!UvvI%f#j{)U;OpZK5XLC z;^ZdQ=T)%jwMR)M|0D?%R+mc6{hNUm!i5q~!NZG-JBcE#7o)VZj2FNVslj7fcgck` z#wn86rTm6szaZW8v*ziHCV^i>SpwG>16z`3qyR=vSIfKlYXAGwVy#M0+M_(>uzFUH zqL7>ZHiiK^APGy6GGF!)Fmrc7chjH;3;l9CuV1l2Scn0AQTq&AE7WyHAXg(eC#y6i zPVuq@qc7Fd-mMDxc}+$UeU0CvF4?=jo&y6nbEa2ADojwWPa%Iy9hiCs=`b;BI7ztn zv;5Az2qL^WQyc&f&g?ELgZ7=@H_yB5*{8_0Vr+thz1vsDGQ(L$vg$v5@Kgsy=r1wy zvo|p^#WW~GQJ4Ng&e@-W|E}D2k@>lM6ByFwxW=88;&B%**GkzvrJFO!uJM265x=$7 zyLgH1dB#iWMMo~ohVSh40*o9j1JP7-p>0KMXq;w_uEa*~^r_t&_TPPCW6SB!hCgNh z?C`zd3^=PwlB0;9_R-3U=gDp~9$KAViVUCA zFe@562-+c%h20!mZev_ZdCm8A$t(+ zJlC_o?9Kko@hG7DiE;#8sP*z5S#H{SqX4Hnx$^YPe_GmQU@yj#_7&hW?H9z3Iy@Zr z%D${kUchzbU*OZKJ*S&c=25{Fx5u1CKkq#3om1KY`ZAivgmg*fIZ5vHLBWU>2 zYzB2e*mAMvN1RNSZlFETvJ*mgbK~xURHb86jfsC`Ky{3sr_tG}Z5l^K;kJ^98FSz5 zuf@>ZZx02{3m8G*@Fr;G8&%I@uf4{>@>kG|Wp_$uMaiB<lDZjVmD zYTysOUwORRUl8N`hazc;Gc7mD)=fK}cX_hRmP=Htt(U&3mLDbe|A25rI1f#Q)phg+ z(AFA_Fs*1zN^4K@95$CueqKL(cjOSxVt)}-8oGyaDNG>V(}JFJ3_*3G4se6L#qctW zO|Ex;KzMc9j}oY;tCgnXttXgMdOPl;q1c${V}R&PtpM);hCaFRfAV5y6z?MQfB~DD z{;)S*yQJg_^~nG%T(FRm@s%r2;mCI^Swq2Hk+A*hx=Cz6)F1f2 z>XhYY5Etb6h73L!|Ei{Z^<6y2=~}^lfUAYtHpG`+vHxPq6S=C++6gw-RM< z%}Z}&SXq{auk;t4u|CEPAA$IqI5666B;>)_1&MWv_WG-Audu|wLA}5xnTjzfSE+GR zsR1(_*6l0ZV9=MCiscPqjX!VMg-7u`qlc<*y(e@9fsl2>Lfj+O{C)%Mqp-R^A@YM% zyQN-VsDv$4hRiz(N!_crt3PmHH;L*K8voUB7W0KXAm%_xDOUojG_-c*6Ur~PJp{*a z|CGwrMusWx@?wT$pD~`g5tvkO(pJFMS>==5CchMDaqw(d8%I7-O|+u*>oUqNVfs_}ry~hhGvUe$`^~;|CwEI@gi&@G1g@6hzu9Z?EyTiN1Vm_N(9B*yf+` zhEn+y{;9!TYD=ca>Hs7yV57oC-~2d|`9}uC&_GTssjx#EdDa$SWwmJGK*2osvjn~j z(I{TYp)Ury+Z0kbqu0QrddM{0|Bgre86lgReh^Wj>?5%sgTAg;)E3 zRZ7H@3C0H`z-2LwwXkT2kLDi1Pu zx9ggL@e_Yfj|Vp;9DA;Y0M6QQ+Ym0FAoq96W#vGzdhP{hMNekjtTddQ85ny$HYu6P zj^HR3^D8Br8^rM!67wD&9!EOEx!Ykg(XZ)tD0ffH)yiF~m)lq^n-XHz$8?;|Fs`m* zF%m(DgO+2VlhO^wo0Qp(R+oYxqhwZ@o=^juQ)zr#-;pn{1|3f~;KFg=UMykv;=Rb4 zOjBuNV%&X40YJy;jI)v@Sdg-Zo`pa4teW^9X$`Gw^A~Z7s$JU0IhPWtS&|R$bPj1W z530oV7I$1V7A>LWqK;4{XLJH6hRBY(aQ7tvU;4~{e0J(r67LA%$Du{UxmPNxie`es-A2iTzw(``p5l18sKB zw*l#Pul`GnAi!S5SicX7g0qUu9AC&vcSd~t%L}(>BXK8T7pqnt))RV$kqUFP|z!SFwQ)I?GYn|O|pni?b4KI4Z ztAT;EAu}L{XwT4ZK)N=D|pwtPF8T%jf{g4?kFM4aqAnD#zEngPlFpdD?G?Phq<|-zu)O|FMB2&_?)+%Z^cmP%J`3wiln?( zy@}_t)uxV2e>F>y|ukDS0)yEC#-hUR8X!qnr=n&Kmqe7GL% zN+Od)vGh~6j`ph1?6WFNl8A%I8U>E^-|>v0|9YvDYB5XsMm(sWoYYVv2}gSs)Y4A= zpAz)517CmBkn8^6#2W&!E;9l=-~yEDqk$`Ypp=>S7Vp!w13%Exi}DYloZ|NJgzRCT ztgHppDZj1~>7_c6fhYa<-5Yum&9|oO{}~UA*97;Xrg@kjG5%CO9LRbPAeHtf>v%t^ z&ZSy0I~BhrZrQ?W(pnY7w;K+EBd-m8E)Yb9c|z=%iYx=LM!J3znmgN3v_`yT6L#&d zess#WucIzZYXCZ_ym`ZY|Kj%NTznkIfbCD+PwZ%&H?Ht_p5bvSk0yQLBPN5b4%hlt zcpPfQVQeY#GF*ShF#L&GH1afxeXisAsiLap(wMweSq-E<9abC_T*Yv z9Q;Eyi{*Vz;p~q>0M)yYJyq3t&Mfr|Cri^(Dx{8`uay*S$e*_17SYy#-uU@3ob+2U zgXtrm9X%pw!V`eR=3I;koQ6XMe{FsWPqfM#H>xk5f&CJASz{O3#r1Y(XYI3%qU;vL z=j3WhrD|p2w3i)!*oYiolTssfywa@GYb`FZPOHkBc2>-9!4^)g$tCBKmQ!l{0S=4B z9Z0nZYu*(8qIP^II)PVd;ZG)*1JUM$wc~>_@zv4WDk^R`WF}LQG0$J^*l8Dj$=9fK zc^A3DiuZjmd-H_7j!2Yf!Hu=`G*Rui%<@baxLQ7WVpYuJ890@Ao<8TigK8DlfO@ z0iV5^9hfl3d`HJo#o4`LCX)p#dpi(y#$^jEJHT1*AS^2x{bE_7Im6BUdtk>Hqn)Bl zux@bdr^nK)k;;Pr_A<9xxpAgz3oo=?V8qXxN?i&=>p0p^_5AQ_DNUjuTl%Vb+n5A5 zHmF&-*Y)E;&9aOk!%0GrFOq=;?_z{!OI3FMI48z7U4$|MvFrm8tRvko%n5cLqa}&+!t|kF-Hf%W++oE zj;io_Pcy>Y+7*@yy>6v2&XfI1XDuAKXZm;T=+gB8o|=0g8nM18uZRAT!BlPBOb`JZ z{uHRKUR1Oo+Rpce;y`Z!4aaJ;*CJklougg|Bo(ExXh|;S$hH~B(q7ptSGQa~`b5Rj zrL!A|CD-0Lr3)7qpU*^c6p&BNc<*}Y_e$*r^CtIVT6^WPJ8W9h7t$!mu!C$S@;$8}5mj$wa7oF8a zJCL$wC$FkEXk$5@0X>jqs&T=A%J4WFxj~qvn!qCrGNmajLECkyC$zc2uI66hxMFO0| zpOfh#U?#!^a^SXJA?v)e$~pWl8mL}xs6s-#7c8mR&?v?1ojj1-RT{FmYHxPlXB0Z@ zjO)-3!uRB=h}~UM219U0<>ia+Y~xmE+vgk<%5R$nvP5_j?OX1gk5|s7q@7e9F3v`p zXan#2QHKcx${O#f&}BnA-s?|{Z#UsLS4xb3E&~;fNn3pPipE44Wx>qV{$B@98ALOY zCl{RBp^r?rygRd}W5$hQ3&mnPQnJktZsrq7wY1;ry0}zeiYH<`+cPRtgU9}kIgjP; zM#n6aI6h)=?Y0Z#b8)|gFQP4;evTxbYO?k}iW3{ME7c}Qphq3@petn`V+a^>vq%>MwvAJ<{brYfVK6w}8GZbgo^(M?F1 zh--Zzwe_c6%hQsohq~VyV_JQ!5ymmiYshB1QK`}lbrd8%iaNaibe49wO)0=UrA$Mm zrUTl+O`Z(mVxz@hJhu;uHOh1dBxKmP?V*3}_+sDS%^jb|--QxSuBi&!6)?Lh8LRQ# z#cVDe`Pu;D916Wsz-a?%YXWO(UTitRa;tpfX(O{306Qg=J!POZ`yHpeA4}pZ)60AH z9YE@J)TXTH{Z2&Z>bUJ*&slcT6WB?cNyq+xD9P#EmnE~puo)IX@h~iY#WFBsSfyAk zd^0F&IctD+Gl(uzXy7MYCEE6-+1+zWaPUB zgQt3ZhW-$J>Hj(;AS(n<@>Mrdo7MtW$~5Zpn%V1l6Dbfcc+^7q|DF}FG&;@Tx5OjW z%puOC-kkgQ253~c+0a?CE@~|IPnM(pEx+mTPpp!!H0r@~rrh~7AqDN^Ihax9oI`X! z9M|^01WNf*H4uMRRW&hy-_z_0`m>vPR3#)^J`4X`Q7kJ;7)uzy9nqNZmRkAcJ)CujxVNOmT zY}d$7>K%u&IXjvnb>hQ3!o|;LvFw^-D0qZS5l0lZ1%7n8sfE2*&gT3aWW-vuqQTGK zm^{lB7^wYg&)02jsE8@Mu%d}3|6gpPVV*BnDe8ltgu&A!WRV(G0fceNM_Sb9Ync#kyw z&C_Jiy0<@AX2?6)Vbq>4fDht^J>+tT%!-p&75J%ezvC!5u^^x-CWzF&%{3d`N8}6` z%`O!+^Qgx5Hfr1Fh2<=db-6HP0R+Ah_}9g%m||i+slfJaj}*b~-3lv^P}TAo6svGV z&hE#3KgvK_{r7sLSc$8|?rp54*e8f~IxT25T3$Wxh3_oISEOL-WpiL*|ba9w^GSpSD>3f{79FFnk1y3vSWwUqVMU3VBx>_?TM{3O- zyPccxkdbDpBP@1>=sBH2ouCtt__Qkd>Ta@7tkbz2jYa$T@i}GQt`8vhuMeexdSnKc z>xVqqZ63Q1&i|`Brr~>aX4f6)9RQ31Gy>4|2Cz+G<`Vhu6|QBsn;X(1k(4wQ{|iY2 zz2|^@QhIUJiILUDauo5}Ht>)4D0uWC3_4&^euYN`hfD#yQ0;ULdL>XjdEJ)Z>nL^D z&e3XiRZSJ?K_hWQ`K$^7E(}sYrQsHkz7AUOR0$z zYOd37o$haN#)U|h4Awp4UyW@ztakaqrlgPT0!6KnOSDGNb)(6r14*6*jH4VunB4!E zxysv%Xo~xFyWp6-pYZkD@JPQKa+`A(P(T(PJ=J_9K)!I})J;xV@5e7QikKgLpVXk& zmZ6{Miw~u=Xm1_CaIEg6!lkAvf@k|@i^9#U*DBxnbeA_sT=8$pEQ5zN?Qpq}OZ+qP zH#T27)vop)O9=tr{PTI^_k(Hdp;GwP#53W1yPV}ZN$L}uy0%Q;D_W(%`&;T=riXky zS=wPH$Q@4BwWfcC3l=VhOQWV27Q(x3$6Eqkl}?D-AUz*2GbPX=31^=^FjN&&0coqh zydgUXRPl9EU+qvdfSL&IRgBWo#DyybC~6{ui1XjviB`>GU!{(QTA8*eT@c%#j7p8e zq2LAUTiS#5<_C4DX-G8pJZFoCjcLDx7QNHaA~E?NtiSkg)aES8l)RSLt1)q<=3On@ zJMP2WqbOBB`_}XSg%(q;hzc}eXkV~^xlesI!|%xuf1_C z1;XWiGnFJ&on+lsS}ViQsdcs{(g;eelmVsWMm21boBzYZCp%3pH@+F9zwl)BPQDdU zg0Y=3r@gTeObgLA13QH} z)3STX7zQTSTX)7vqv5tD9X?>4AXWPEL72+Z zOlsu6-8@YOUpM=CrB~C4i(d-@*U*^MMNQvMt3`YA6dLB@UKInnvg_GKTRmtM9&Zyg z+7Tmw$j@wPbzx~1U+gSar>l-|f=g9P{#^;Yqs;Z?<8xZBW-_AWU8*Gx3a>Nb7hF?T`YFk7<%lz0|YghWW8)eA}wuv?qND zVZ5uy&ywieYY0c)B8>^s+%6vzqNNw6wYV6q3RXlBD1Ma>C1?OA7Ddku0DX{)Tr2w% z>cl?%S!>gRr0J0GV&cclHN@L-%Km@cezgbq#7Z+P-Cq3r|cWGxF~pk7tLb``OD zoU_e@c6+EREOGTtFsoZnAVttjjcgjlpSHS&04H2(DD-{c3)PeBp?gcQ<&D8rX~p>L z<aZiR*_98E0XK)1>l^j#_#9W0jeVHs$E?ais4f`2-d@ckT!uBp~)FZqZn=s+CG1(VU(_Pu6_e6l;=WUZ9Q0r?`}q^YI2x0@&Mx|8M#Q z%BSb|aNvLw8?GP5LZ5${61u!NbC-UjWh6q0qaq+CV8BgbG|B%(4jVnh4MrzBY5kz3k6Mf4WQ*E(k-ls+1q(+wJ|2qfnmFxO{=&Z;iBez6yL$=sNO= zH(f|lu%+1Zbhba~E;?DA8R5FYN3-LJqDf!0{bjwN3c-X` zs6O4q_v+;NbddH%O)v9nZCJMMZC2=x9k>0&Kg1I)U1Yepe}@D8R~pCAK)BXMTYIke zN&;ePQR`qpf1+yxCJt=U&=+JZueWkFQ+!P*ZBgBjX{w1{3@4w=y#cc0C%@h@29F1+ zDA;H|?xc>uSZ#vKslGOiJ@XqN9N=t$x1UH4}0fDcz4Ojjvz1fi(oeO<6M*=1hCE*K09bXIBIJw(S9%N#)3 z;nql@<0JfX-?+#{Q(vW^=Y|YB4FUi>&EncWKrh3+OWyOK}4$gP|i>!}u<(7E6jmebfjhq=uZ8E-orun1iMWpnE@L%>;9IBj z%w$~m*8e*G7`gKv$DvOOKXUz@?vZ}JNCUc5#?0;QUn|DZD~d<}-KWBJBjtFQln)Q? z-y)h=b4iEAD}KUsvdO2$%qU5g;N1p)nfOpTavoooF&OGpga`PEy68@K8@LE<(y0TKCF$M_!7mj(zG+-|w1`Ss$FGsF9vbxD! zakFIBXmeNp#t}wW1{7mFK;n&$2ZLJ!W^Kak8o9jJqM|1`ycr?mXvjXgV%3g2YIXV4 zS2B(e+}Ujs;Ume+zcSH*8J&{V2;1L^NcvEbo9emoBj))#Hk4JoadtBe4#)tO9-j?P zQ_Bq9la=;~8k@eVV=Bm-;_pJ{BrC?a%l#9sH~Kj}&i-h$$1(Pi+68@ z@^~u+48g81GC#7H)^e9L6ZmW9QjF=H`)rE5Eo!qVe z@f|ei+*lpU`uJ_xT~=&OS7~h+X~6q@0*G%h(J{kxKVweezY7r~E~Bf8TE?19OkaZV zyh72HO{95BQ>}W8<9-#cg20|KZvN`C1uqwa%~o`7uVFLIZNm5`A|x}V5z<+&pN-Al z&YpvPYx}%4IZ20?MU4YC%zHCDoCEj9c2A3)W|o;HFWnEmA1>$K$)@|t1DUB=u@ZQSN2GQS$NXov(mJ#j$sj@#IDFbb450`I}Y#N#>~-y8?y|V69*&mbYWl zuGkdJn>D|g+;NHNN0;m&nvJ5m6ql602g%D!mU4Uac1Ih)E0StA zkjGr8&GGr%V$%!amo48VxO<0RS5uQnhbYns57D2J>CyXNQ*HcZ_?ed<=HJ(3^`X0y zg2ucPK{$4wshg5SAOzQY!K&3#|uUm|xfPwad&lFOc#dlR27P@f} zXx=&aj6UpOrZnK*QkIG7M(7a^naE5NxDCq8BXawV!FRx)axbmfOdCy0XN_pGAyC>v zM3W*=qKzUt$o#mx3Q>h~2<1s;FNii*{6hGAft{}6t%CF{I)|pw?s6m%4~Ekc+$S-8 zs6?ny%-EtKzb17!*-3r3Uv4swK>W=9x~#39*+G&P_OJGt@tHw!NO5igruEhK!o}*% z2xH_05x z=pul~~|A0H+ zy;O{A50fW5OlzzL!_s^6U0*{1e}6qG!azO0 zQJK%?$5ff;&OP0IQ|h`wl1>S-f>9ZcP8SKt4S4SFXG()|b)j43T94pc8Eh7$S zIYECw@mx1Pv~siVr+N!~^?99oF*O1B_qyuUzkYQW_-{}7xFH&rlv-jZH<|7qf8I?Fc0;qO{JoG+~|~M zo{Bbi3t^pY0YMG0M$=-#vm#Y2Yqm(uU6Y&pki;+0U-^uYrV|C!4wG>h(R7?e|r~ zoqEs~?KG`m^}9l61>(7HPc8KnMTgLo9ciB(Y*XN%pMd9HAXmz`fNz5O{LE*Q`S+fw z4^vjK)AKh9M5^}!y<+-eXRJN^g{+zlx4z1hT)d83oedi9v;INbUF-V>m)cpUO!Tqe z7qr)|>!Zq6^l%#2^gJHpdyz0{Ia2eZ} z=~LJC5VIx=WytCm$f>Mp0j|Hh#WLF(U%5QYw26bTR-!=Dg7=g|?lgbMvR~9ol~mYC%^joc08UzT(tk6wi0GXEWD2cn*uR)h>(7IBkJ~47%+I z=qOld>Ab7JCc~DA1wAe0+HonUGR@Jgqn%5p z>m1|mn>sBL)W-%U_mnAV5PtK`N6&UJh67&5Cgx}QH~R0|7E=N}bf)VyI&CA+>eF6d z!1fAw%dokx*`ys2Q~ExM2AKvp{Vq6gPq)Lmt_vvviK*9$cKvj(_6n}_w(B=AGzB?i zXnZ;iC-Jajq|*dbEc)~e3pfRRK-K3P%ycY(fRWFP`PfGRe-~*ELv=~q#)n_~B@1Fb zufX@}#z&T^GR9?X*)`u%7L%^feTmY~fBy4VE;2f8#{Z716PISkU7$9FA$6{J3I(EA z*n$QphDT|qaKxji12#q>KlZVYUH$Iw{_fSE|M{O^ed}A_dc^RwZwz66WZV?5hQUA?#f2rAB6Q$cOCKL$~c|TiBEm%Q`dhF&1o8-LB3RF0g4Q+fTiq3 z8IP`un9nVQD`47kRG*;Zb8YWSnLNKh0w`t|0H|!$X@$dfeDRB4y#DSV|M4FmPKnjF z1TJq!1Zb+WN5IA3^r$vhrlR9*i~(UfS-mXa>=__*y5m>os)2m#t2(M%t_22-;bu_W zr{3CU$8mmaH?A$&ZLl-r>UaCoU|JBh``mHZ;HUm-XZo1Z=bn4+I%%5r3^OX|A59M$ zi}qhX_;$e`80*>p>Zsl&Q91Rh{!<2iXDvgWRW`-8K8oMDG|qyf?Ml{WHiJ&LGOK$| zCL4wQ{O3P^^*g`wJ6C`6H-B^Wjcy{O?`p#jNRg{`u#xo!aQr z1pUeOO*0jYbzYStDmA~eR?bjB+fG~%-PcxUkLXhi?f`}cvI4#aKg>=S4bI=DDW>0Z z?VMXM!GE%Uc2QuZAD%h)cTw67hL4kdzyJ5Hca1hwUJZsDFzldHS#F@(XP~-w-2y9} z*kDxY6ve)#Q&>lBnS1%0qoD2g2GyPZZ2dvo z2Rw!1mqjRZATt@G8ai#z_BgkfUV7QCH$!WdvsdGnDcjj}Gd|2r7pUzsA*RTtr=W)C zXBKeHu7+9Uh%MWT1^c(MgLzAtl1@9d-z_pvvfZb+HLwXRWNC3|<~2dTUW2yeNm709_dD>-?~~~n}8m^uktTDN~fw@!0-h7&wlo^*ETY1 zKt@l-HfG&RnS%P(vJ~2^58VdZDTJP?N@jh%ar-^xqKkKn`)*sgWL3{zGL@GvN_~G6 zNG2ll*b99aXkV8}c{w?TP_)QlsGs6=+uH>HL9X-nP+8;XM%gC_pojMwfV*;g%Z&2` z`=KmnfByW;-!sm$plO2s1h{5Jo#*7>tuL9=kW zOUqX_&H6X%(%(w&YrUOwe-QefEcSIr^*0zcsPF4Gu-dZo{m$~sglGc>RsSm!^-Tbt z?0#(G3t#xc^;(x%^D_60P7Dh+KMqPOXli>qRRvVC0b|oCuTE`lx%O?TURQmYM%8ntDZhm{8}-iTL-o7Y3RXyz0y-6L>Yn+`ac&d% zf9tn?>-uLtpZWhe|MLp66^(2&^HET z`rWNeo$qD9WbJXhzb-)yYhX0 zCW9H>oBjx#lf8WRyWhPI`nEJSEAFcHE_&RVY8TAOtbNycO__|WY=9?OdRDgqS{&6m z{gHz+(H)Pfl%f@Q=!=#Aeovd(VyRkVKXMsHZfs(*|4)DV)7QXwfbvY0&F={U7E5-q zSao~P``hgRz?2Tx-U6@I;~6~!$33oPpV&M4-zgANiCqKKDa0L+%Lb5Z!PstVcNDN$ zx=}spXY9sU6y(%C%W(Gj?9#MNS&EJUyOM0p7z~|12b@h-Khs^_yg1`JV?1L$Hev;T z$7xT+j{ewQJ#DGKpKIoRzPX?lBfxK#z1jfkQs3Pi|7|OmL3^SLdzz^<5H`SXYL4B;K4mR64_dlv zw8)#L4fU#vV`!l4USrgvap{3Hb(&;ug|Z-~_+9`jWw+-byTGT}pwH)??w*)3 z^#X2WppK9-0>%0N+u#27!xhOh<`$`OVxH4QhRv8d?tq=XcMrP18|e0!cRN_; z$Bk|KY0R1d`A#tEc+-XMVAyQMUaP=4&u{V?r$06_3;zZL%-Vu((RA>SI<=wt&(0g@ z$%x%_E_m-__pCB~&1h=_rt@6WdHMRBvI6YRJhbtuJPW9vSZgSN*4i8XqP^v>{(5#`AZW;xoc$E3(nGd%;mDZf!mLAdMq!eA*)sz@aq(&$lB^aorYFNz)@5tN?C<61XDKsx9LJMe-O&g z|J^@6MaC%$X1G%XGuOLj90kW&db9wdM$Oq7ld==^pevUP6a?wY#CWLNNo2NmskgzS z&ZdE2o+*3uSwR^GO>jzu%PDcy2fx)o>;II7>B@ATYF2RC5uxo1-r+G$+pxpo#b z=*<7Nc+Irj0AZkbz?B#L%x}-9N9?NsPH<>@oJwaLb`Wi_)u+DPsWyg9n``>QBBf(i z8!=A&hHSVtzS)R^G-Fe{Z=JQZf=jw=3_HzJ-Ej?h&@XjqU#E@gCwhOu3jb?*OTeE+ zp7UdS`R?67wQOb>&(mi8r{2!DDXLPY`}8l_hoA~! z`d-lNf+5BrJ1u(lSrrm}$T?sED7#>@p$70w59`8dy1lG6I!l$EQKmIFJj+->kp1p3l(F+hG*+)ZrN~ zPG_HFRSqk0NF z=oXpwz#-qweL$W?uk-ic{oUVP2Yc_g@D|2SQMi_^G(Z;kHDllYL4DP=DcxEn(xdtw!Rv%0A3krbF=Q! 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%0DT%@!@DsN3Oe=NQNdxfks;KRD!>@2>KV zpKia|8GszjsfzI?DwnXLl z;!}~iyxQq$rxvzTt&IXVjeOU7!er+|xG=MOjTi$?PAkPbosDVroTkpQHVUA02Ciig zglu4J)GWYt&$;p<$c`VC=?)XeR)7>A%KmIQOV?|+wrBI!wphO4#Vn8aq)R=H*g5P| zQzbd@%23w4u56GxZ`5yF%;0U=77PfgHXw3b{og>XvaO?W@}$D-S^e4BN96KC&+%VK z$A1XK`A{jJ8Q=y#qvQghBJG4RL!r~pI3F;=9)VHTi;(PzOWm3lw zAB^;JSe2iFcbqZ~8uq?x)aKQyV)@tHeNkw37lrJ4^BxK4Q}V<6A2p^ z$J(fN&*QoUo2nHET-Q#$g>+8`ns(b*Y|n)=PT2_$l28vRJe?iz@A zC+JVd&HA*ktgMpLQ-U)i()!i^wIe$u01>nW8l38hPGx2cZt73^Z&0(dmx2qO_?}vD zhmmb*Y+WZ*osLsBwZ+o4vw8)l@!oN*z3#AyZ!IeAUO__{3V~q18w?7-kKaFkc7f@l z&hgKx{x@?9M$ZX-n`O%27PF! z^LKRKXVGuv>kM3}J^xL_tuhS>l2Q)m^r}k-(EmE9R@aurP=R$urLX%xLuEbw@1m!G zQEk?c*Z&N-QLrx&zVol94+UZIAwwjvYOI_B$WRI}+6^wGP3F@7d{g0#k>-;A;= zueAjl{SAK1I+zI(?E1`xq2$yEQo!~e4p&JAcmKOyr=(+S4Nh{gBg}a2oVj4CcIx1g zuiX%uzNSjc9YmaM7l3B~!8IK&OaueTm=-uP_9gTB+aeanz zlU@jns@Wns_ZZ|SUU=b!`xJi9U8OK8VCYnXox*9XMAaIy>KhU?47uP+M=aW| z`~tc5I0aD1O@DO;yzOvr?54K12~={dZXeXx_g#m3o#~F0Jg4Y=8Ka^o)6=_u z8voi}S*GWk5-8i?6u|~Y@}TiFN~mw~eBOtDty9=jDP5!C)3J2jj`r$z(X!d0`r9Ld zjm#u@HurmKrN=hyGZvM-b+mGmKeIN2fF52!Tnia7p zL@H>`FlVH}ja(V8GZ^F1D%c!PZOM5wmlv7F(z&<=tak4RLhz!YbMerW@$kbBzgbh&)>ai#<6OIamU>3S-3=OBA4pQ09M_^9dAV2o4>et4TGLeLK2*gB)@Zy4-{`)w zOhdMM-6$=YbTzt}hGb|@2h=yGbShh8ZRBR%&2c6Nwc(UO9{KaSz=eiYXI%g1_mNl6 zV~Fp9X;+BXpPg;Var+42c+$I>iu#=M-SyXx^s;eo`~?8rpX>xEb<$=hDrb+ESq*ir zHVH_3FXb=DsQpf7ReodB7$ld1^ni9*Dc60-n{=msZ{QTqqozdE7pG6VrZ%fO;b6M1VGhxbT84Ts4Htek96nF6CLPz`;@&KRr{G$gfyftt;?U^E$nm0n#;b=q^ zDkI_k&v=R&i{cYnugMu3nWy9$1%Jy4JLgzRH6T!1G(v)$lrBS@K`8?v+E2mie@Ym? zYLiaF`vgTkg)E+H0II`wSEnoVUCgEq5)PGX#Z#=|n^-bq6j zP3OQ&x92cDHF8JrW}NCva@uw!BQ;5R6j!`8W zi@_u#MrGB7W{$aiDN1$AqWYpt=8#J_&o$|!4nv04Wvuqj%hY@KI4@rxH~+ie&&l(A9^G+Foc`?Pw$9{H{>#hC*R~}y zJL|H6o3^HVwGZ(txvw2Z`#yJef$2h~`akrc4?S`S-@kqc+=pIy<(0S5UIQK_fX#s= z7%j+BAVkuU!fq;aNF%pXcN)#1?lHCQoLp#B#no6O+$lo!<=j$^+P7CGS7(4i=aFHs z-1_Vzg9S?UX-D)LL{q-?$y9zX=YIuW8MPvG)4N}Ymr?icNJ3+-!8m0ohI|U5##o>c zUjlCe64TH9SO4Nu4sL@O)137=hqtp9wNIy)T;))dN6Rp6?{tdC*2WW^LVRxA<(m;E>8#_gBkeiy8_Wq1?8}Nq?~}7+ z+Rr-Z9lQj<_V3BokU@!#+CJ59+ob%&8*N+d3TSWsJ6*ALHQTiRcg)O)X}_{z%H!tO zvd!m5s{aRW-@g6JXBU(%WUBudxLMZ!W)7nR8cK<618#aN$2fFq9^8mO!_s|5Kst`k za~fKX+PTBpQuJ)}WrWebQw@W2f+7jGLU!D-j@cw8NM|8HmEfi=l-V{*PyrR@sY2QL*(H%_jLah*U5voKQbwbhnx2FgN6J>AW+fe-2vod#ElH;b7>chOIjq1N?et}o~t)BE=d47|X{ACcQy!WhwbLw}zFvB4D z^)cGYN!bDWT%T&MQ+w4XaL)#o!PYnST57sY0F`5&Q=6Hwywk>`(-g_Ze4$I$?Kco1e_@u+= zHUAATXk1T4!exj0oa0gso37BY3V3s78C~U6uqFuAsl*Gj29BR#E}+^NrIWSQH2Us` zQ&T!Y0jj{(KD$%J#gb+s9(?frQzPqJ3q7lQXyiO_Y#VoGBp@XKkKguxz86%uexfl= zXIVECQ)IGYS9O(3|E1A!ZCU5GC_p5`)>-=cLRjU6V zH~Pp&K62R08^7xirjLL6)1Q7Dxn5rjT2iWvh!KE>*mP# zlUE($Q1Z7U*lCN$t3J3^;_vK`5nhHr88NdW*zCQ2rd#$w@DYC;_xL7=3_!VvO@NS2 zDF548D%;7SU`-iK2I`++>7j=ndPlpJ!P=LM2^!2mxMSy3l$nh%%I`PVASv6~8i9Or zXZFnB>aYJv8-Q-W*O?L1^;KW>-a~Q!jS+026%Y z@Iv$&9TBaHm?2Hza#*{J6n#fy8kBi?jI1d^6;vl+ByHk#J_K^=N5-_@Q{1AF#zKRh0my;ey?g)a@~$u1K9yeXyOEJVZKsSg zwC#63kydPP1WV3bH+obA8pO%;%1t7K{yPCmS>QW*?Nv^gDj< zu~X*DSi1Jez9tI>Eb7D5b#E=hXJ2~hr9XJ+seWz#3%UXZ z?m`i;$csMrzJaNc^RC;7GM*??jeBLaRc}Y9wk&t1h&mAVDgpTnLP^tG&cQS zc}{`l%$*u5>#(ydj+?r(0Y=jjI(Gry2G5ZWT96kHbDr590Yv&$JCrTuG2SIV23_$m zJ6a#KQ(;GnreH)*(Scf}Y@3j?rCp)W#fN>B6!TLp$>B_YBXD(EC3@ubzJE z^Elih-P(0e5#IW4|N7tgxSVUst6_Cj?>4OQMMq_%ol(yiXaF*7r8uSTGXjZ4{PFyj(zL)?~=-mm8b~O!{w+i|ZtGpx&RHrB4F3D89K+ue#HncwzRUcGV95+dAsv z*#dcO?U!6!d%o$|YmeW=|ap0Sba6xF-dr!uxa3lJLT4fxDTbZ`A~ z^}mN+?L~XarMASiI9=B@+A=d&$<7`N?aQfkJ@@#1`^Xf3|8eiFvkOWW((yn0?6Y5S zApC#nczwgGufBTi_U+sErM-r7q#J=Ja6=w}s`EF>(+L?BCfuefHGCgWmA@JLqRaZ8!*edwHfG$nLsXfJw(N&}aiLKBGxeR}*qH-U*p{h-=szP@ z$D%RJpvFrdZ7P2&L&I0Q%@}1!Ts2&~cBH7WY^*eBf&$wTz|_bKWHoFVzSd4ueikRwgPVz!t9?f47J=US5}T z3~&iH%J>K@3<9=eQr0#I-oVfHTbBT3mm`Q4un8=c-GH37ED+V0nk~~#m__Jb!B_HQ z-yBbE)%lug*mgla*;jdWYC7bUeJ-=GWl{M#3gGeBhR7*l``X&LUm7$ zPGl@H4`KVeh9u?RhE^k4`!`@I6{x|seMTM`rwpJxvOQ))hAOvn8tQL=$ER|2eNlEt zw|ZcR#?P^K%|VWCkFiF28?X3g#$X#Y9dBbSXcZI;b+C|a^U04oeF2rb1)>f!s^6}o zXlln)d~IwegX<^KA;)mqYD5~~2|&1FUZ++HzWV3Y0!rIt`aHhpy!Z5ipt&rIvey`u z`Dwg;h?5RAUE6Z)lPS{`vjBps9m%`sc02ycG>c)Nv%x@i&WwY7sGP=o+o!G-q<62n z?H0OzYg{T%8uP5XW@ulVhH3Yi&)o?D+k&$M>tV`u}mGC!c)s!NUlA z$MO2s7hinwTB}SG_R_gSIZ0R14tbPgio7G%=AuKr3BD2UkdcXzlgcDrha=Sg|IZ3# zq?AoknaRpHJ2@#?N0Qmc9%r7tDP-@+b~wV3ak5uAdvos2%E-ENMx1>=eSiPL`~7;q zU(d&QJ|2>3mZhBPZ%V$!&zSm720R5Fm0uUB}6rtnID>f=v`}10|h9cJp%=7VK^FB zr54{>rN=A)IxaN@`c=xgp_smk@y|KI+Hdl(Bx}Qhdg#PyA-61JP9Ce?V`Wj+%JaU{ zlsdYB+I+ZG}j2_lUVRZsrL?u z*p3acd1CTdSK^=+X_(~Li&S}OnJ+3-LB@(jkmUll4+p+`eJM|4G096$-tyvgv*Gc+ z_+)XCZgHZ<_v(MgZn@ofN`{GKl9KGMd5jRBini4{9X4>Wp&yp6%I$sfjnh%5>E^JM zz8Zi|uSW0~-xqh}-P$~lQ(LWZ9BR~dR2sjcN#NZ}Q$7uLXHqw{2H8~(UU zAxZR9=8aVat~a_5#N1zXtLv49APYtaqPGt)asD^^rS=EflHcM5C${bv!ohJXg&>Y_ zhcz*_8go_mW-H3g1JO8dpDWw!i z;bez(ZX}jT0!CMb@*3tRLp8rv>Y#qc?o4uH7QxC}#BxOWiVb+Zj+%`2k5C1%C`gi; zc&sRx~a2#;=#U*u(3mE#0IOIV3fd{Bbxf#yj? z2m93@X~C>mZpuIMZ#zjSgksd1mo1SR*d{8nt<>cqkkd=)3z>IY#jN5>2{KD= zt2j|RT?b;O;MH%iBRs_6xl4H-6aTP{E9}dt+7i6d8}F)=v)|z+yGHFg-|S@(K_gOfIVB6<2M)B~&rt{P1+k=W*hET)%WOqEwRGafT#SrtSk4sRV<9k<-!l5$K z3wt-LcO-I{@Go9&lq-0JdQ`OLpd%@PlyxO%ERAdMTtxQN1QGwa81gg+M_;d0>OZP~ zvhmeP;+tYg)%LSK!4=cRq8euRm&n}k5*2Q4YdOJKhLMd9X@O(*ImFeozrM1j zi(w&xF3|}G>gJ_aeRXG_(EMAC|6!>wT&8A}9SBo#+%8X_2A;pE%IqH(WLVRE@BEMy zbL5r6E<5>yje)1C@`Ge5#BSKt#qCkYGgEfQ$#(VOfMK;sPHfi=PMi$8u#$wuQ zbd*QWo6L;TDw~f*7jRmt0IRp^ojIIGX7YDNslFWcf9lfKyK78rL5LemU_{3pTT`aD zDi@r?w_&9@_h>5;5pvgNLom!;_V|&J9~D7aTj3TV zbi1xfNmwK8pZT56e>20a`|h%W&VUMX>?}0jIOQVn3J=nMZj7d{3cl-Y`SngnGX~pC zzCHXdHj{!}UShYM?&T}OT)lSn8SzLC%SDPAYSw_k`G%UN+OMT)gfjfnIkPRs4hr~d z*d+v5Ii@)(OR4~@Px3+Z25(`>#^+wz;=wz6v*R{+mr9O1EUNT|#3?>Fs z&0APq<8W&3A0z=iu1_)fUE||B8}HT3OkxZomo;Mql4?wOe%$WxuKzF1@!_ques4*x zsN^4!kJ-c|P~UezH(Fpv8)e(s*M&5em29!O&@ovIX<|mrGndKTb4#u2B{7SF{Y{gi}T)mD;?+A-=dMbo1=*g9DaKdf`teMGOhG=c>Fe$bxC0NwI`}!(k zV+m#*Fj}kKz0pdN^ez>>W6#&rwy#)tH;1m|WzdW?oqS@#| zZE_K!c!Bj7(Y+0^y}4?{&+xcMy)oWUdRPvZW6qr4+#aXfL5)c9tK*Navw1`UZd_MA zveDSHSxI|?#dK@nExb`M4dVFpsGvHv{nxGR2%v+tD3z8*wZCHU)9am`xGNdvsV^qRrMM76Vh zKvr-DF$ih6vZ-s@MtDQ)AL5$skUh%H)bTxdpIfvJ-Z*yBS>X(Ulmh4EPZb}L+P>Vq z5)i0(JF6FPQP;-&)6HNC&D!!-Z+U~ie$)O_XL9I3P##svnW!o|9g@z>+VE6h(PA4j zc`q?UhRGn{T z*<6-D!u=E3PE`gw@T`5r#a6!qC5_)V&N+=4+{)~oZw51T`MFM>sjinK# z$68zTz01-ZiK}iBx(IPTJ^$&xO2k&E#BCvWVE=f%WGa>HiKXfofoBp<{ylK-^U(A9?+WXXTRcb6W+k`JzNpRFa2 z+eX9%p6PTh6Xb3)N^JqiA_YC5I`p;Y@HW_~V`-OGii+X-#`}*iLqQhHA)$ip4oll- zt%*v~PxOr&G;d)J18&re+CBsVr{-I%!_pF0|08^mSuw)SC)i~?Y-w{E$_@G5+g{VOYvFD;>6nclr&+e|SF$f^3OWbCKwL>HJsKPYuk{ z*Z$f-0+p3Z14(ngB`=TARHZk!kMsThWbyMaD_=jX_@{Q9r9CP{M}^2LZ>T9s{RfC; zo`95fBf28UGs0$R=BBD{X2#KdLrU2&07{g-9+sZLy-tBU0T|wPYi5s!Rm`a0Z2kAv zPUHNlW%$NI4o~LwH`$rC`+uXfxsrsFwztRX4WkH{XeGOM6`ni!wQ=tx0_7FobHv}? z*0^w*lL;-iIBXKHsNAX`G{{rnI9*nB(Ua>8Pxh{?RY$a(I_f310;_%(G`n6pOYb9a z8Omgak$@)VvTr(@$zZw-!%^J?!)s>7c#QmLa9<()BNUh=Q7c5{k-4^i)(-5XkWP=F44swk%mAqddTsD5`B0tND zAL=PbLVdtCI+k6YJW3(5mpsa)&cRza^2twL=N1>!78n1^$XyJkTh%ZRK3QwLE<=$M zn&u&OkpUH}a)zwW&1y$Ev`WsVi>J98c7j^XQ<4kN;km$ykvJ3LOhQ_h;5Dukw$E{f zp+IEqpzK}MZ;HmKz4-WBk@eiT~Sff{c2F8_W6;6lKmw*-Iw~%`Lciikz zUAo|T!OdQIr0nWccY9@?67&Ag6zF2M@+&I z%1;Bq*Faok-2qmX$WGJx0=Ff7ui$zW z6o&x?)Pt7vbIdwG1Rh(KL z1a_ZGuGQ8YvwLj4g9p^n?{(}elnGM1N`XRPaiv9w-|^J!JHA$1QOr4T+HA9tO^Xi5E7st!Wl8X4-lkXWWQ7$S)!Vt9TZA^A zgzzhQ4Bi@W9I z?v67rC2c6G<%o;VKeQaHvD@$cuF~U2Sm^J&^<4ePd;UR%4IY za^ebOs3XNMNztXJhdWrtQ?51&bSR-_a=Y(oy-V0c(r%s~ z5fVoKxGU@i9G2bO>$C)Neb=#N4qVI%oe{%r$lprK#h{BY$$7Jv)?z0Mp=wG$>wGBu z$cA#+_L>8ZPG^|#q_N~3Qq;e@cgwro{cpbFgIVl|@md<@hGcQ)Y9L4ydZ2I3&X~NX zOT7_2<|8F(-%6qEZOqOM<-PkHlG`H`vOMogDnEi;!NA^Xm@Q49K&wK6%j!i zc|4TG&3cI=5i%MF^#AXz)#X(kUG5q8m$xwF@P5gv?dhsY7lb*4@-*ky{Sg{T;<~2}g1V;IjW`ZK32_$t7Rg zIMsm_-m<&KH)%S;QxN)a=ZEv6HCnrx|60OAm?IGqAh z(AGW1ut?G#oLn*N`Em~~Nxzdmt^ZRq-d)+yy8r1J)a?hXL$0}o7gkGmyFZrvx_`re zpa`m6rk1J(q!sGd9no8Nt2T2bDS3W@KVH0VWiA)F1=7ux?z^%O!Y2ILO`)Lp8ts{( z=cveLKCU>ga-13<_PAa3Wvh^|Lr?FaAuNQ9y-5y9cw=Y4jDT9ww_5gYj8}aHMwh0<%X$^5*=nU|?*`DlNK6|?d8#TFxyw97y-v_+P&0XW zT#kF<zh{Ew;YAz!}4djSM2XRjHWqaNo5q6qFg%_`MT!@O*E zq;Hl|YBm_n|6ORh+`W^ZL;aVN)aH9-$mj-KR$pMM+q{SNLbjRqLe_CB`F9$mif(8E zMKmUbj6eo*9h5E1tqzUa4=0=KWD)y}=||bnaP?yLk7?S-ts7=2QG+PK8oHoEwlEuO z$W}@u@BR9&R0X$m?==Tz$Hd9I9GtXTrfe?2`&-IkufbB;ck*R)cWFOhH}D&?W$&V9 zp8+8M+rMj!?p-NtcYUFezburtvKCn01>!n7fF5@F9 zpqQGd?Kt|G>!!kYPbjwB#`?wJ@EJQ;wj_xO(FS+`3YH6w-@h(adJ#7fsqYId&*@I+ zj(_2ObuFF-aTxHOc~0c9xgaYf@GY&IU+F?Y3W6<+3&}?MOpV$h9I-_w$D79F{h>^y z*X>|BR183EfG}a)9^UB+kH{hCy^`&p7vwiHSzw#vceamQ#&Nw;%b-rA8naN6j%)*6 zLxUSH)pD$=MDzLX1BT^XDBib}KH*ZZey`XAo-&>3d=f}@+ej>+MjH%vH@Vp!X$ls8 z`I)B*R5pLnPNZXG^ePTo(2EFiRj6nrEnn!y2E{?v`@_P%<$lie-#TkucIthNY+`vJ z-40G=E@o9{dosOa-DyzL@=z!M6a32C`??AR`q=ix`kJczp;JgABcRD!ATwy%x|UIOsA$W$7bbek=R>9CytkK* z)tEs%0K_qE!Gp|66`?TpyMB8QRZiwZW;ntikal&kh)n^TXk>SpI*8IgdyBaA=Z%hv z#W66|8{B`sA^?EAesf~eA>?JKehViI8kdb!bj>kyYp!7;ja_}MIJbu#>uxTnKezIE z8yg>q(fZvCgnS(y_7{jv{(F8jrpDNY$K^&;4&|6d2XIK!S4BU2G`(vZXb?OeV&h!A zZ91=uDqSt*G?d8Qzsfz+_r3cD`EBATsPEvWhseH*#%Fd|oX%pr_XGMDLFj`R08j2W z2Rr1iGftz;u7+^zhTRvaXnd=@-|%g+R!s_2odl6{1AZHDm%KLG(TI) zqZW|-!Nv$^Cp8tN`1nXpe)$+LSiUjk`DkKP#X#a)4z7u)5|lq#UaAknYg7H?>&mur zp6L>KwNh?Qo8bgCF6cDEw-B-OeDde1NThN=@tN}fENJqV{CU31n8%Tw`E-+JVA#mN$w0-z|=PXQAeZFY^V>9Z!gZ?F$iT6tLNGl9ZuWK)M28sZM zgHUB?n4is1eBc|i(on&SMXw3DQ2Ym&4A^u= zuv+39qB_|AW6Rr#jT@!xM9jekG_n1OFyQi3uy1xn4;}BMFrk@w;-<9{vgXenirPGu zr+8otY8PJoREC&__!vJ}ci|v_P7Bm#JrKDCR(cn2E?ARW%4F6b-@p9=pxB5+ImAF_ zq}o)(VU-69U8)M2=Br=@Ou0K*&Hb^;A;ET8#NqrVcR9&9aokJ7##YSOC$J7|bD!$_ z2p(Gs?x_DjZa`*vIA1sF!=St;!xM78m+!mxi)GQTeUGZ>CjL18DvS!bKx`*ooFVU9 zxF#$@+{lYPJs7>Zi`?h+>~7{r708=qB(XhlPJ>&b5_q}dg&jTLbL&c`r8tW*-F3j0 znpxmq`}tVc@%^f@7PM%sG%G##SHAlu?<;0Z%;qII?+%D(zm8YQn2so8o(NHnn8gL7I6KLhPztF$v1tc=y@bMo<-?3m}iJn4#VCUA#BvQI@dF}UEF*A)x|hli@76(j%M34&qqAO!v@sS zeKDi_ov`mRiMU;hvriVspE>}}vMrsE)R{?1sicIgACA`K?W(_GZe{yTf2Qc=#Eh0le**j;Qu5Ny(sb2GiV zbkAb~xW=};RTY@K1SE3QSie{)7xahD)4BBeC_nnXE~#Z)LLw$moUKFN=$R@^cRpiT z6mA!a04=tD4R&ycQ3HqH$Bl5>@A!;@m5c3^Ce z(5Fky-jNfF-{l{r&fFek{eigvY^zU5a#>$I6aMcZ)>r6t1Bgp=)a-SgUrv?VNMNtr zCH~hZJyZZETvY@8k>167Y1|Gxo+MGF8;oF?U65mU;tABnxV zwWn)&6Q^#eABX<>^i~MS@k$)p3rX>{vD8_|L395wdu_{lsF<6`jl?zzywWJ%ZxPU3 z^9}}mdV1I4RJ>%SJUe6h2Z07`#}@NYX!4WFzD2~UpdI_idoImyp#hZd6235qL!ou9 zIFkeMn+#r$`esVRx$(+kvJ37k1>$ge_1;d85r4DQvEZUF_6lYQ?Za;@+!*GovTHIX@X&+h1Fsq<*vyu!j<0_=ue8}N#G>QM0+q-aHbn~X?%I4VfB7%)dj}OX zkGkN9QakJ8#0H!l;m^|e)*Njvfmw1{g$Rr+EK_g7k8rY?v%uO(X|bkf-&o7`S)lXG zb8RXg4~g=4!9K*b2~IPYpCgAx+V3VdbRkKr%CS|-H(gI2Yy{ro zrr*=W_IcdjmxxIE?W%?SiV7kB3HSQ_rBk3Og;9Q>9LE_q?iV!F@82FeZXOiJl3^T@ zUXE#=T<;G!2XRyB%cbQB%tFC~mBZ@{n%@WmV}D>)k88e%kf$r!pd_c?WCxVCTze-+ zx0R(RgCbE|yG&CaF% zP59q|VJ4%5f`axRyPz7;9~GP@y!JXkPGnHEC8*P;Wp!K;N!n-HBQ5cEbU^++z|p<@ zwvwCcPdN!b{9nQOXVTJ2Wi~gB!vA{}qA?0Y(xT_EF?&pyKQ{4~Qox-x`p<-uqqx!Y zKjF`Fw}Ep9iW+wQTCm>=U#_dWEtR{6r%w!cUepU-vMSm}$J0r~9e6AlX?){5@H`ib z5pYVS@YMU@aL(D&BFBy_@%Fi}j*S6epieBLN!p{c-qq!aRPS-F_Lp%< zsNtE2vU~>KL4<>v>pbC4{PJWA{R`726v4%{k`N}1d}IPzr1ZfQuUedx&tax7_7deT zN4ba=8+Xo%ZgTDMK!{h`_X&dUE9np4Cr@yk&xXXKX}8g(#w6F#61xI|*!tIfS=SOi zP1X0uQ0R_1{cKX~??^|B4z|sl2hh;dbqWuOk&Kl?TLs7~wn0u41NkR1ok_P{`KB-4 z@EO2IYCNFKZE&;EUJBJ%rBGIPCIb>33UvmJz0VVqgC_X*;E}YssLLcVQ@Cl0}ZSD-aou%Gh$yq7t1kBaMzO`ibo1 zX)q4qM7}Vz2AGjnrm})`6N`=o7kzqb{Nq|1IOg*!W$9tT@{gxc%QN56o2rNL+|F2s z$1jpLW;u?h%)ul*)YE^W1tSl>HR$R%7Rg`A)salNgO7g`WGBv1e>N6)@0#-?Kwxzy z+VZThw)?|>^EWTyT>82cRC4U}Ho&J*V+3FbZR1s-!P|5_>ct?lIuP!#gydbkW@@Kr zb6tSqHX#xc9dH@Q(U|j5MK$yuL2C`4_G17ZCfLk{VajB3UzzZFk}&o8CvxV6y+TZZ zunvX2|BwABiDmicw-tH=_^#5NP@-q^7wpRe-`aPwN8x)l`FqoQ^Sv|D21d1L)}50x z5W~zR9#Ur<3&Nw&i%p)S)U{==PMuurie87OQh3(E!5K@Vcc?bQ^iY9^Xy#%dCSl4< zI$ZZeAG@t#?T8f#J%0aHJr*bdndIH0x&xj3{4$~d7axk)(Azf#je_M@-j*TsDfX3T?gyQTkAlM`W? z!LJ0}sYN)_}?>#BO zZSA%*PA8oH_QfDi4bgkm>M6ia@(-LA46Wc1b))1;px=mLA2Of~TRiRK74;>}TYUM@ z)9E9FwFZPMdO;gV&AYo{o=Y&_eJiKkm5Gl<_9tNl2j3Yc?5CTuPCMQllJ+%iSpQ68 zI!r!O+L=bJoh4Y7Xyf0k!vQ_VFO}drN0x9Z#qG4t%gNiJDOsmbtC{PX>5s%ve;haf zcfTVJT{=tXvk_cfzjcECNamlULQDVMz^yB!e??Q{J*pv#;!76dCa1T7Eac^twiJ*7 zwFldjCa~EH`B$Sa4HGJYat8-3V>~3axmDk{v3=*9iomhzmYcqN*AlD!KJLqZJ~{~n ze#fW0tYSBld&Z(SlRQ!;?}6&&N^_2+xq;M2f_ZY0?B4N_dfp>1cgK#mKfe03L*vik z5nt=@3nS>-vM4gh^@p&Qo8WHF#r4D&ZK;b)5pn6XeeY*SyM>y=T2*c*wk}@S$8?|k zfqRL(-qQfsta}k}>XvZc#0F=|hL*;3)gr^gS3h zGS!1wmVJjn51a&Bew_1bgcGPY}MX7uYR4XaH9~IXu zWy|h5IYw*vyaW0qy>0Pf`mC?s#5XnLG6d_9p&SgXT3LH zzG=MI&uZ8|suF%P<=d!tCMMR7$pc1CLD-J25y7Py@-8J5e9NQRdHWrSXc4$kH_3BVn(H~@S52*Z zX?p7`S1f98ObN+>$6fz|R+6N}v{}#mLNyc$!ZA-5r%&Ui{KYxa^NoVLs z1+ne9uKF2`qoi@@y~XcI57+a=b_`mgm3cV}A?fbj8Dvf!KH=Nru=G?F@2Zi>C$fO{ z+^?R1!Y5jQ2)gyqlpV<%WgQt!(2}B>v>zv!9TwHm3PCDH*jX$$`aids0KyHXGxBf z1g~i$@8>mzd({fLt{3%B!V@<0?FMCLY;QoK2b{fF`ya`}v)#MODlVp>n28IQr}J6O zJ1F-Yb}J*Sj1G6TV`^ysAs|_0^vbKc7T=si|8j=P{nGYDUR$k#pLxEB#!1;#;_uCz zNgtN;rVDYj;lk-o>Khpvg3Q`VppC#b%s(IZqrFp5%*Wl}i-#T1bx3@gI%RyW`gBq+MuAVvE5!er5;%wRo*G48b)ho6 zD@b1YdKF8N?BSh`|NV4cd1{36uIHJb2NiyWDTQ|?ZDnu;o8P| zqwDAi=*q0#2R$dI%%yMcS>Gk~zjeSywdp4VB*a=F+rcBCK4^oLu|BlL@`i2BnAx zW^Y0o?(QQ6sbPXct(hgdM$-o%bkYp{^tuyjXA~nS+#j+c{B$R;FU20((jom*vd$C1 zhZfp+)v<$~GfF(UP!6VyAuZu<<$EUP(+>H0*K4T)U@Tl`Z}^mus-)(gS$|;PM!%m zk3#x+JY@kZ`iw4sbO?{QN4L%D)EEmQ%F@Pgg1X!Tcl_6M?AB**=x>8;N`=D(8f*Hq zai0KC(Hm*tFCz#EC#(I+N|%dmVySN$uh$IjrPm|1ezl`MF4YFCyS6msxM46ZZrp!K z#(0M)!9ymqEne}%W;18V$v8*Q%GcuxgjvX0Z$>d9Lw@VvIhuD9NG2VJChK^423}Gr zpGTl2=Zf~ztkXO5!hLE$PC&qd_4NnfT~JBA71GWt zE#s}R0WVPO>RfdK?EtB{{RTpSfxEOOKE-WL(c6mclIZg|7_@q=q_thaKBK>)_dmr13$6fEeY&W{}b}ZfE2%&Ec zy4{DTORTN(L}%4*d1$5N_v&3M7?E4wA#ABX#hQ~8Eqb7kl`uAywU=3UA^qzhldEsj z%P20@AqK;Xgld~^c2{H&1$jh{Z)uJL(NWFH zV*vQpB9#A@)FNZYE-}&lELrX7sd_W1TmJH@*6vQ~4hfbB*>+WU&_it(W>IDuQJ`jE zua%r1gS)-U6~_2Um9f^f6z_0@al>b8*=uL5X|SAUz_t za8~6%jka_L>v}$nZ@Ou-w~E?VNug7w0!LXqh#=3^!r~xEJq-%+R5%>OeW{%e*_-fo z?Q~frvf3=AXZdcvdkGxfDz)M(+vX;78?V0@XP_Z>^t72~S$kAqXi@>&_e9wK*0Lfv z)DKMmW~ZDT$^C?t9&>WE1M5d2MzGvuj;*uakjCM~DQX*sK8FnF!;#jwRvz?HzQPu1 zuV-&jp@kCin}x^)38vfNPb7|(xB-%w!ix$%Gn@T#`Q|Eb6(1P=mXG&zF0#AcfL!F| z?DZ?@nm5fjHa_QKp{SS6etpR2^2c=$UqvCegwWeP(A(!YBLzB%1QKvG_NO31(GZT8m!dqdUG! zm*B$d=!&UNWuHu6T)+B2)S8Vdu`Ks!LF3Q8!9O@aATIBbohKqKH%az0e zd55CBo!5~hI^~1q>(g`*w!?m=hYu-bfyDyeX9e)b$bY6Z)Mz1a+XSDoR-i^jY0ZwK zLpGw17fJ2JHo{qgYP)#UappeP02!`NLM`7i``+t!X0x`GsYNBl?5#y^ES~h6OP-j9 zo=+xnm|C*Z6!o6cWg@3XzGoRA{%U(IkA%H?{SEYE(mvI&cJ$8af+G8CzF|5Q>dNTV z?bNgUC!n4nA^mSU$$IYz>{OE_fGj*S+#+QCl|PI&Qpipo->XK!V-c73wcSl`^7@AZ z#ijRI35`zIkN)agVP|EziuhhB=?uqeT>iP?wcai~Np+PU94q4m6fLcI8vYF1bn-=; z`eU2-fk$7H4OxoEdcv3aVC2jq6vM3ps1j4T+cCG7L_uhFex=~(EOcNXT}%YoIncOO zjB15@*KT{k!zbIMksHdFWjq5Vhgov3WTf3{%(luTT;!&eQH$6^$a?1W%hyj^ce_c_ zMIPR?8~U>UlO%e7ACnr?Sh)lK@$GN(INhErr7dM2N&m<0sM@Eke3$D_Qj}D&9B?v! zxIf$fZb{3M*so_r*#xL{okt)?bX;hRr%;h**Fa#-SM9M(l#5=+D{mq4v@gIdV17eC zBqv$7l|f6k`khG-J#8Q4J-~>Mr^^VR9tAtL|MODhq$efo~`(R|yB+wYex7+eO!5zs}SpY!XT-V!U9UQjEtI2EOZY`mLt z2Usk$PYErG*Fp)KY<)NGc6KE0P&FbH{b-AwbE}?`S1NkVuySP1E}npKf1-c>+W>$i zN|6@X@8y`0H!~-YdajCH=X>@@c|FF;hnrVjTUCovnQEx4YR(Bk`bVa0N_;oDI!{hc zxoUDo%_svbe#69CywwA7a0#GL%e=g`~t$0D5KZV zI#vkDCEAL`0hirTgZXp?0dQeuiYtu)1r=7CZ)0{< z9caF8|5%$1%K%3Vt`vEy;{G&(G^wZnp2%9IUJj#_Y=;UL7K7`iRIKTR=UZj;0z#8i zWi#n6$U*yj307r}RNvLMEwuSNR-RfO#BlRud|@t^Kn1ADoM(~B);79!m}3Y}*H?~H z0hgIIx-JIe%Sbw$gb>2jbXVeb9_2Q7u|%zW+`_A0p({+I$^=tOC1%0WSHk`Wme?3&4#Uwze-7HigxB1_TT=I=cgYqvYcPY+ldH zY}#Sd|%^y0z_<&#f5zwKKrwD}*2w&h== zx)G^goTm9n`-fK`TOgH1RQl~%IEMLjp;zx=MP0QL7gl#*W__&1p*0S179`0`{y2X0 z@LA(*HzG}OWr_Ab&w1G(=;{N$Ix%2{I-R-?JH;ZE{E{Ohna=l4l_h;emrwFcndHYn-=D_ z8(aP~Ub#8!ce0d}GwSWjZYjyG2KYWO{dtE*iyN!~222XLzD%-dHVn2A8-zGV*)acT z9NrXTcRi~Nel`=|lkhyd{WcEJ0L8KGz2SMolAoWy_+>zQgvv65|0RgTNeJzj^hwC> z4AdwhSMx$PJR*NKh}r)hg7v~s+YB8E`&eJ@w2p{Vg01hyL(%oi4xryaxlqMQWFrncb?-)d|w(&Cy`i zvzuytyYQ2T>$kM88upz}NMNHm*T;iIAOWr@P**d^CL{qig=DamgGFNfB~{qGc;a*J zpzoK{xN6+rtKEaU!cnt{IvE!7;H;dT%FvY-7I?2Rj32?5xOk-$RSILj4=24xXt%jf z(dLl9pU!5;$$u#>jNPjYMp7L908F7E9)mDILs!T74tpI9N2WjF`eA8(>YJ0=la@NU z3%evK$hgcmA0n(cg}|-!a2hFz z_>%4)5B%kCb0v^}U2z|TjI|N@fjsHmH-vEnl6X%ie+DwbpwhhI2--rh% zApf2vEDe99nL0X++l=be&ho63`pQ1BNyNK4#pxfKP1gyc~#LUY<%7iOA`0rIhB*V?I=$&2T@ffoC(^$*Ote zW%D*wl$p;}q?p3Iwm@fjn;Gi)+p~L#sZUV@*2-JRjLqSLzpt_qgpl8F8+_@XdJD<* zw``$cnNAPrJ5+s}?~TLYd!}hz^TIqq9sDRC zhWuSpu2~8=aJqrIaQIH8C!mD6~K7u%`8%by8s~ zsjq(9(Te0G`(8JbSASfqf_>bHwNdiT$&1+)OUR{ADmF!AGFp<)F{?rKBOLnKPQDqU ztshkjicFt>=k(WW_0SmBJV|P>i__x&?w6^*^qT*_nEFL;jH2=2@0X1XS)b8BaX*X%f0>)e6)++yL{u?uC7^SyHK=o#WcGD<9KSfdLvU{B<_4n! zjTWRk&akeH;2x;u<&hL zTM?x6i}-Xqj-Ne+5~gGB!L>+b1rOU&LgR#x>O16b#;o~xAy;jg2b`!psD+P7S z{9J0v*TwFsZVU@x?iB7>`=l*rOFZDJ2X)x;=YtJ2lW|~`BD-Lt+@^gBI`?$JNeMCo zpv)boD0Vr+UD)u(omWmCebxI8P6%0Xt``=2W$`D7F31WLGTC*aL{P8T4~UpAgp_`Y zZ>S5#IkfID*+X*CH(waFmlg4sF-gZ9lFDjK<-ht9i{)ziyz zl@AIz-NVsAiAtv%SgiTCo}d*q`LhBmi1=_)MY-2|TR_e_p%If-G{X%AL-&JR198q* zMRCNz11_`aw@@Y3L8Y15?=)hx8BV%%)P{(1*l>cx5v?B)d}O#@Pqv^N}$ zLELm()p6L(O+l$<8J6YSW-qtgqy=kuQD=JnH}IcT@m{_lf)li2W&23!pRgM5rGP{a72sR!^mG%SdWDT&wV#?@>^JtpadtL0{zfVMF-~guKbFoqs_FOr|Fnpt zg~SL!38j0q$UtH=h)5{iIl58s4UCYG4vEnn!hnG&4WkE)Q0W**4o2)dKfmAKJ7?#- z?(=#*@9Vzq=k<7^pMR?E3es7UMa$M_y@&JcDh9kg?oV719F@6N`Od_4A9*#>p?y; znCdxMD$&mdJ)<5knSHsMa77d1u4TV>%wtOL%`#B7_`Ekakq7Ox*bWQ~Ttaw3Hiwm| zei+w92}!1mzA9e(#6fV(Gw+snuo9g#SAGMI0_!-fd8{aNoC(Nj2=0nO#MdcxQ+I=Z zXF)Y){a$t=zkl+5_;UG6O%1!<9#}Q@6y|$rRhXlLa94O{0*#ZKDJ-+xImvcb1FcNS z_g~y+hrV%5wC*B)7YF5vO7Wj@CB6a4u?PVddNH zm#OR#u_3m8%+ExT|>zFY7O>R_A|* zly*?ko@uED#pFjqg!No^KfK6w@D9YDA0|v&QqAFy;fZN8BIQ=4Zy_)FHzjkD(Um*- zuFoU4f*{Dt=faZ{d9iPz!K3KDl#Kuhet|6K4!^b6Cvt`-cj=rg6I87$7(}ht7GcTI z1pm;=ym*@qh%$;oda9K8J(HDkVRXyx+sw}Xw=meMrUF08p%y=#zrgHDuPbw8cFaykmT?eNZzmU1ab(4PHto^JE+fRs5m^(5q*a-npRIs;aJT?*xx zi^3FrG9TY~#&7D#pH5>5D>o6KVF~7ncqnr4=_xqNX1OuJUIMr``a#td(g$Dv~F z7^Wq=zokUVH$G>;mH@H6Gwqw-O1xaaqtcb%F&8q{iFyjaB^hu4Q8sou;!Hs{0BmE<`?u+DC$uZ6GWGY*F8m9 zEaGO?4}BLYMPIAE-O%8~VWlK-EvK|!%es0Q^<_K$W~)KwM%MCJ!t&TPQSN9!O3TK3 zWVb_r+jV~Uk;FPk-KQ zI*b@k+ldKGE~UNm5YWW7lN%^VO4VLfI?puP@ofq(Gf zY~lG|%}+U8BS|ds4n+Eo*ngLQe-dB%0AdV$&1Ls-^1eHjFI9Qv+?bd#DIcePikAQg6(C(QACs!e^Q(ukT5ev6D3oq^-G@o zGh>ggbo%S7Ex9uzF+SM0RpIa4A4ohF;~$}vZD!DQ{-SP+Fbg8dLVM1F0bin9o!c$c zo)_$dv0JQP1G)Rvf3eQE?`9oDcK226l6_}7twA$ooH!g;`867YhbasG7@Y18%~h6?bq=7~hRIrg zK6+h~CWr-(gVb;#jli5bW20E4cvNao;Au+!)f!LO*7>%+z#dDx3t=)?g&j8@l=um6 zDNnZdZ1Yu!%54)JUCq}Iq-mz#e)&B(&>pzFH854K@d{?h{NY1DddhW_WjkrbMV3QM-3q|qSF30uC zNW2dFZfm?{{%TKNqr_*_f6Plv$up8-j}9bfnOeL2es~~Si+-rW4BVzjO8LookEAT_ zGucnehqfuqZT4A587RNKKCHsl{M!XIcv44CI6Vq(_Vzwrd)Ks7n+iNdXU2ql&b~ed z+Umm|>n2Q_9^^U)2ii}6gM1sK$XCgGH7>n+EHfhcLdi>FxV#Js( zm0hQ z0*Awa^?)iElPI>w|K)mt2B`)V`EqJD= z4}xM^ae^njnU9r1hf0FYjHekH)!8~^5CO*Sjy=>yA_&{xN@T_{_xrgGn)|K`^(9N=Uv}H z1jz-M1!xS<)a)F)gr^3v)W?^1%+O{j z8h&Jb)e4(Z$;c2Rz!3BB+-Yw~`*SdN5Yt(M`)4JsJc)IEpJ(0r8y!L#C{}Ocyj4tu zc#zQb>FzDyLcdrpp(al@{_89+q66*QzCrdvzUjbh1v;FvnkQUwRN8qHL z_6N_jF1JH=BlJ^L9`B`=1aNJ_<3C~LO1&LRQeq5&TptS;lIqU#hirG+@PSgyj1O3t zoa!ozfKYW`cB!wmiFOk0CZt^kl_by|ZBOq=^Dl>|xLc?f!~Qj#4_zo*c8Vsp66WF` zIm7SJuQ!JeQcipQ`H!|IsG?}(rL_nD3=_NGTFD62)3f1iy8cO*mmTi=p=t&#=DlxZ z$$!Guyh&?zQ7acOzb(9P`XYvYc3jk5N`TXQ%8H}y;3N9tGn40(9OUlMwvN>NL47Nu zY`y#-6U)@x>eiuN--bvnE~|c%UwKdum$;4;Q`_pmu}qLO`C1jc-Vi)#FJ>qxEYV$N zv0mqO*||$1d~E5QzE&?M?XoWWynIZO zqBPiq$1&FL*%y%fx<}mW@40m>)y1i$V&-*4%2P6o)!Wa5g}#qF?n+-)V|OO3UZxqW zmFj0@DVF4@n7eD3Y`zn3=DK|W2y1WM?Fb#pI6FIE+z9jo>Tedko1z2*Y92B2+RBm0 zo$B$tJ1MiC;N0QG^d|`V4SCht%qq{B*p?3fb(2{kwM=)4lmWjs{7};?@(@CPfs>^A zXGN7}qxt()G?{|NeIqs)!wzTSD#cI}3sd?*=glmeqD}Gve2o+r_m*(fT&KLL+pepU zzk<%$;NgOmWItbBnYOIK`fC>!>-oWWCiZ?~nd5K~vG);<5vdJLm>A3!u(9aKb~uqZ z+*H7}u3>kx)9Zjud1Xb;BJ90FzWIxGpMXK+L$@(f2z-i!pyrF+Ha71t6TpOpol^f<|a7;!jsqU#dSQMXQt23p@cliR+El4G}&Ki}ny+zyTcRk}J4ZsW?y0I87U{h8;V5v_wTe z`4Kk}aujll=5TbILpc?=?Qerkb&VoPl+fAtIcg@j@1TX%<$y@`b?)xZ@of1A9cK&9 zilH4hJM&LUG`G(c&wJ=B6zNZ~Y!q9S8(S9ahh-_Av@Wp!#7b4%_^3`xZTQEM^0k9( ziE`O%*d81KkK-fB2}sa()#{^oN*@XpP%X0)&3|LvsiCOMqviP+YG|zUH4uBg!D=^T zmfylzpV%T1RR+AaYzzT8Guh^TX0UTb6>d{k6yedet{>if=zvu^`Pr-q zWIWI<@oP3BO4TxnPVlt9vkMC^_6iy*utM&|&-axzfZSG7FlETYDVH3M&YSkf78UIK zB=iNtQ}U+`jdui>7Y!6GHupKB>UXB?V2nd8qEgt78{BR!+r&-2oXt9HOpwo9qaQzK zok%zg5HM+B=f7jZmR$5$Hr+qeab4e6FY2PHiD@W)yI+Z#JHzWnW{qz)wIlH_uJ~S_ z2CW_FMjLVg+P*ipO!JtWpzu3LUK<-yz_AQ>=uoDu5A@`+=ABPr>KKw&NM--elT9Xg zpH{4^sOYr%qrsO6ADL*2Hq@gsITw`bC3hUw-gS6siMlXp6Td^vKICHQ(Fk#7#c9uv zm-7XgjX}2Ps;XwYy1YVGXyK<~*IzpLtd}hD-Y$ntp@hDw;;__aQ)PeI4AOk{^}-i{ zpk=gl*1X6YKaFuudfxdj80lw?<$~)|hbA>-R5P&WMk^LkO;H~(CpxO<%_ymG5_|Ar2@#0h zw@nm*Ilkp<)Wg2yoSRlZd8e#g`S@OS6kxv6$> z`sV5-N@gz_PsleR>Cn^pnRx?H<}JVr(0d0R+Y!H3)j`Ihfr0k3yuZ}1Tq~*lSbv!H zd#JB&7k%KmEM}-gkjMcHtyyZFQ|^3z`y2BnYDl96JldA+IT{nJxfR=y zWe9=RYGTmsj=jmb|v zY>feqCUv<4h(x7}c{R5y82}s?A$tZl3>_UyZn^oH@X}Wsffx{~WH$_Em*XNjAfQWMoY5X-Y!kzeEZ`FC+_q#cg)1|AA#fnb!}*%Wr+<)+7P; zWH6XCypJ`!nLao-#aAGoe>4>l6SIqt{tTnJKf*kCxp1IyjFUzoNxsoM<+naxUH-eX zl-b&*pk{Nj{k50oAtBqY!#CG47=WkXs96!YSLjA3Q}Xx|K-7v?W&5iML?Ylm5oI*? z{B;e^n2Cai1bL!y!GFmY(9sgkDa=SWop!!^vbFIl*n4cnKKPO< zSh=bgL?A6$Do$SGmpLEN{WCuYu*mR_9JkH1QknFPew1Pc6^-T!-V+Hb(CL#?X-*R< zD*cVzarvUf#{BFUpCAx6+?udyWc<3Ih zAH{Ijeidl_i|M$hBn8V42YXxHG*r1$G(#Q@=4m5%V|w_&CIQ zoO|#nDtOdghI+k`&^2Ssr7=g`jL9E=#TAl`7`E`Ok$I+6q0zMnt+IjdoAy>m7p9IsrvrWf*9n@%(e{tSqCDUvDK<|tO_*66KQTXvj zt$*i_P+K*~EG=Q_^-nhVjE6#+ramv(f2bmDK!O(1Y){s9+|USs1$OSKK^ds{8i5Mf z(k<$nX-|z<$V*{-IcH3FGLgXuZC7~0)-T04qwu%;`q>yJ2JB^@7C+{iZN(kngVW&X zB!+_U%L@B^KljX|@=yn7vb#Vy!M+SWHDCIV9ke_zf{DzOfrVYwEKO37 zb?3B;g)dCqC)QZ6!UOPqi@v~RGui~cWmLk*LYUWF7lG{{Vm>5u6XauW3}GX|Zg3I0 z9kX;}F<;KuG;ZfkX*f#Musq3@5WYKpe&?>nsjqpT&IehZoit{{@^{>GHA*-NL1C(GH816!y$Emz%yV9(_30{P2d6J)RY!b@(1%+aU{TekEMo z>xbjc+xKzDc(FRE>{|H6OU)_KEFd3Qqj@d7kWg9u=)}h8n!hFx>6z7VPf(X^b=Pgls|*i{@x9S zqCvk(8+?lyAJLB*=S}o3?k?Kco48L~gz$YzuHr$t(tqVzS}%TCb0w9+=>+~AH~nU_ z;NBeH*wPse$c^xEd+bevPwhBmAxf!~>>{L#|(-2y?lWhazUcNqF zP9>0HYcvyIgkA7Mt4G^Lu&KMy?I>qd)OGE1gAT&*t*+Udsx7X}-Tsa8Us7!ln(tA2 z!1<$Og&$J}1}~s7rfIx+zTc8vXMSf#_)Ez&?k#+ln}0}LrRN162Ikz|4Hdh88G88u z;aAFa!y7hegnF|=`i#X0jT~EUOLI@0Dt8J0wVAr~id|qz#AG?`$*IXa(!yv%zT5w1 z!MXPOC)W<%!2U~)VDoAiZX1R;`X6sa#a}^MXU93=HBa?#LGyLFoFO2I$q%C}C!r3i z^*f@`!H+<(X54=sr_sB=sAe!8U&7WXr^bGd&lq{JXwJ~7XYYu>O<%0pX*(U4547UM zBoAw40yd*JvFE1O35n681DdO@*^8xZ(0Ybe+R>(ON|g#b8Q#H1=0zLgk>#^AxDCW0 zs5yLC#D}g)>FXKh;?Um)&)Prq>gjckR>nIIIq?yU)?Ysq<6f%AomaVUyge(f)$Q8- zbY?Qz6I$tNmY9dWnt9BeF7Xf-um2D`tqTf%Z{_N_w-aY;9L*tU%0M}jpPOJJL`L3H z+ajy_aQmCzQ{`}OdiwkPF|sNpE@p|=-c-dVT@ZegAV6e89Wky@&7F0sJ?!KW7Qegq zd8)+s>R&tdLWNHL1j*L7i2|tqt-ijJ(FM%r^$IP`Nz{1xc4?%_6^jkGX$Pcqq2{@( z_!g78IX^mL!ogjEOOWwDPa5y@>nCX4(vwk1gLAd0la51Vt6?INxQXs;TPEhNlQ3FM zYa>(QX13BMnvZ=!QO!BY^9(flA#)Qk`QFCBQ-3+k*dd1cQ-^@O=|j~5!eUa`ntAEj=_TG4&buz4+YreuQJ z;8OV~g7$5*e^Zsf-IKbdui=Jr{GJWD;C`4{guLTM@#%(ep7ZDY-l?9I!} z1q@tuXxV{VP%>CD{>uAWas-}ik!b zD+-u}vHd7o*rW<#$+lTt98sj^H)s0CdsLuSYPi{#5z5;Pl%fnT5!}$GoE0eIE zZ^BR6F-r2n+c%hS2@2UKz~Z8eFJ`@>pGTq2Bm6?jQk~`Rq)P0>YZxSt43wSxG~D_M zcjGOf2_#B0^<2bUWDmknwZzH!vuWRV!ec*+Wt^^j60{chvm)okkkSXot!9IY+E#GR zEk8XM^$^x@Xkmi0J(!F!;nk`I+V4!6%d*WjIo?I=o5KClu16yCPjlZiv~UHYE2HM3 zr9`hgxq^l#GEBly?&0r4pgq#AsL`C1fQ2b*y@tt0w3)7DY-lqUdA_md=}O%S{FkLi z*)Jw$@7wUAcXZ^YL2`AX9?)Kjmx3CL;5HHdMh4!rTO=+z=Hk}xZP@5YO57XnIg(m% z`D3zszK{L5J+?j}uNxd{LxvyuXMRK^@czH$3ftl$WQ<}6JcdsE8K*E^;;PPHLpFog zOe6QT4AIUkjC#%96;zIV7p(RqOPkf_ocs6rc`(yTkP6`-&Nt;pkHN5eWaNBrD88k> zr7{U>;o4_|b|u3SbbB)<%7tzeQ;$dMAt4kmH{BGOQ41~X2hJzDnF_>O{=eog5;Cp45ZM6?)I%vW4m+(BaFfNp{*Uy}qTOBrs3;tx4a< z37v5a)y||2%CA=EeRMl`zb0BJOPFA8>Doc$; znej=EOYsX=``czrB*ZUc3zIhgzGbQ|WYx$dV@W$$%m!(}43|J#X#W{YE&`vHPhQy| zbwawN+wRF($9~d;Gi1-fOxVaQc7vQUP2ixi*AQENvDW7v>O88{x{`UsaQT zHzbK6d)Ahxgj}a~XL>HL%kQ?Y%QIvyv{&Q*ZTHBi!k2FMT(LspAe>LR>Ceqg`Djk!ts(1PtVJrEBp3+ERIQ~%y%YS#O z0GcR)z4%mc@Nl-5M}=k3wVK!I(6ibrXzvBSetT^G0Rh%qNWi2zu}xhrNx3chuMo~h z{wsgl3R7DL{MDP}nsTi`5Y|$PAs>H-KwcHA528&)f2f6xv8vYq@cpE}dGgf^b>-mo0rk2T(BYCVOEWIW`u&NWDRinSNHN}C z?VFjq=sC0}!KpKpRJUkrp>67FDED-GVEV~=Pf_V8IM-?TD*fgss!yW7^Yn3uCug0h z7-_=3cc5BKTSTdu?kLBW1F3)oN^=RqjPzwHyaU2@t=HUOLS;ZpDF&^bk@U*7zxMo> zWO8oU75e@VV6qctKI`Xnz{fXIiM(58v=R7ru0M$M9_sCfqaQ8I4r@N|(5u2#_%jX2 zkMYI3UKyoS=2qgx$}7i-W7vZWIj-44Xm@89@Y3z!*RzdJ;#DA75_)JA-)m^Q92)OT z)M=@5H;ij|j<)?~Q){hJuOc~$0~EEN3SOro(@ta#$2vmf*NJ)#(!@wBugi zC@@Wg*fm7xjS<^wNkNzIes9;GdKAC6?4MS^(KD|-$xjACQgsU`Okfp~qbQUdG&O_c z{&i2h&FyPo?%2HK*Pz_5JD~@fbO|dKfu}Pj_$g}_!R!A*Cel_Fx02P^F7`MJ*n{@! z`@62`6LuS`-9MC{bd|$7KL$7;kDvI1x|!|qEDQDrvaJr>rb}a<*rhF$sx|XwuJIE3 zqofu6UIy--$4MJ$aJwI`&GKVW#z{=-+h-NkW|M!niCTNc`NSU-h*Wn*R^zw}G9_E* z^tv3X;$1{Vp|%P0yrC@L3i}2|#(i@@GqX~LouyWnOS!jUqRi;qi~cI~`~40+gC(DYpY0Huz-ng5G{Ik>pcK?b_0UH0`WNJoacbhOw4U*snTV z`lKF?LhkO9l?nDEeCOSWmGGknHFwHcNn=l3WIefpl%YgsF*|J(={y-VNISqYG=S!; zGqe>1DsV(&jww1$kIzG~%_xgYSv4~}S|va1^zAQA@IQh2$LF|G$0`OAg@>)vC)7Tt zLU#Y>qp22`Ao0577bG1`pZR85$v*YvIP*98#L~v)I~4GiGe{!gLWdRC`O|u-H8&Ok zZ|o+xFqeIc?f4sF{3t!NdfZg}oXBgzYHIIr^JU9omwrt)(*?&zZvatN<>gela3UpA zmxrYdmli>Lm9}m~jxXI=M3X>YWOF;X-dv#O?x=g|18MMBEDh+hQLZ|kFQ(Z5R<+79 zlu7CGtX7iwv{W-_5t9$rCMsg<8f+uKt~vG$4jjA}@a~O#_*}-fn-?&ifl0TK1L6^- z&!X$ErD%s{DfmlQSF^A8nK;1JZF7ydX1bl!_LiPVSA9EdnXR$Dhs-*nfFuPOMv1e|7$z9d8?10cw(~z)tGqj}{!utA8=y zV3OJ`dppqvA)Ffu_8(e$D{`pE#-ts7kcr$vEDLfGh!0h}Y>6v}uT23e#lI=21E28FFeUiE>E(<@=*Wr+@D;a=_Kb4axeMU4YdH3_yCmxXx3^s%cFO z%CeTt-pM1(9h6PY1NGn|E;8wEeiCLJl#an`I$rmc=tr_FYHw`1e*H)d>Ja@)Nxv1o zJ~+L5K__na#&Z#hO_<=RwZ9ZW z%7ab_;vRhV54h3Sn;bF~L0vn#bMu%d_v7~`N63tGh3}hUf4rlCq!W8dpyCGcp@=xv zD9k)x54DcXiQO9)AzZ}`b-rFAK3l^T7FEF6n=_H<>m=0`Sn%n15NO9G8+OcQfN}4- z7~?s?Z1E{%PPzsv)fEv>mG$-Ri^;qC6j{&f{TkCc$)-zm(u$w^v!d{-{*uMp*2KD! zG(HC<`Eelwi9hRXfC^Sh5j7J>cv--Q#WCu$N9!00?dHnR09>&e{T-*b)U&v>!6T*s zbm@?0{%FH#K8l+WY&)}2GZB!L+?Xo^X$(8`-d*yIW+5^L|C$mA-_}QA@w0dX)KKjj z^4>ib9asau<_*PGtHnU8f~@M-D|=EmLV19tHM@yP@N8e`yG2+o%M!Sb!o`}2+|}P+ zLi2PqsP9md&$v7o@ZVTp3L;)hi!|GJDLF2dZQVbf>^e*h!aqvEc%ApctYzD>Xb?bi ziXSt6Bw+Wq&vW~#easMcHF+B?sn>;aVkHq~BHgUQ8h!-z--i?o@>bT*95Vm3=OEWV z4#{~j)`mZuj;I}ab|euyk7-;1Kfs8r&{o}KgIW|>)-YSofMH+m2SGB+MHj?Li{qcR zvhZ#%{z-{*T-8C`;g6A{=4E?Rn`{?@D_$jeQe=fb@YN^&y6c;Y^mp$o2tAYOYzjR+ zGVJT|omc3A*&Y!7+i3iWVhECgf_t<^eAeO_@7(H}+`;duw&P9fCNd+m+*mp8-Ti-M z`IiKx{V+K=u=+ru-Ro+6N=Na!56U9db)ar9KfxEua%lhd?#A*1yR`Rbo6McqwoMna z7_47sav4J;mIktc&r1=f`Bp@kw$v`p8X|NwJNJ^M$%X5!d^&~{B`U7;=Nh={;d8K|=Q{qE3JmS?&22Ui?X`kW^F$ao*&4$Tx#gKGjk1G=nNb$t(XAht znD%=I@G*hb=8NExlC<0F$}sn6rC%Hzl1CD8JUUH)$+6`<2tQn*UtP9o*NY%HG8;o% zvxh^-nkS?zpUPMUMsm6S zt+D6_j&bEJ$3u7Dr$2C*sEH`V7f_CRX431l*OoY%SrKKDknQ?gVKhq5(H5#m6bt2o#$cY`f)={$D=nYj( z=$&<6e~zAb6Gpz&g}y{qN<0DPC_QL)N(119k`m?@P|-mNI&HP$S>RiP=ZZU&U!c5+Jbm z27T1(C}tU$64jM1)mo87%w7MqMM||>$%Vr0-kk5^DmJn@J-|gNk)= z3HOz4eq6ueKY`RX=MIQ@r_jtsTz$V+f@T@|f!aNquCZStOIVdpZ+~N60Tl8}jgB&M z_G|X5@_eaxR%k!#rz19!tI36?C0iXmaL-CXdd`^GY7@O<(gW(lr@z3T4c9gD0l)g! zP&58#0xnRVPuV2lu+?4?&Ms^`{Kc7@GDQJBh9B~>QGF-d>XNb`zONh{B46?>GPW8E zT^)Nw^)+n;caO;DW~Hpt6GbfB*BQUyilR8OQ=cT=ykUWb&+ye1Y6BIJl3n@I3#TgX z9fy7P|9{c2Q%nEh=%TK&X@6gISM7zZrg)U* z{tDVw)16O#rNxquX3z?@BbUA_EmIRrshm3qoA)}h>o#8(Qs2_LpGjP^3&|yq6GApK zv*o*hIDmO+ehrP@#vcQ-U_Zsw+-uAAjB4pL;yE-AdFCl+_tyDYKHY8uo;cG6CfXXB zwxq!WUskfwnb`J8iRhj$*Lvfs0V2Caf*V4^xhFkcQzdp6#liTq$4F_F1Um9VDhQ&rsrYbWFZxkESwHnP=13oT8+WF z+b`Zqr|Y|mSO1d46r2FM5}`E<9;l75dhhK9=`#>BME1ebM@@CH8yo z*SP@P`Z=P{X20Ch(h6U(^A8T#qZjtTPWj^z`snQ8@9)oMp+CE}vx}JUq$N%!g7-iwf2z#IE zzwycAZGwyN=wI=U=||mqx|B~}I(^$WXh1AgRT`wM>H#7dW1@o+9V`*41c9|)F2x>F z_vlineW?D?$8vY4FFSpkcLHIT)OUyYpkr?{(TbB#b_n0ouR@OeDp71046Sl->mOO7|G1-~y0YXS~T}Jk? zvHe?C;MTI^9Zk7q%#I?OUZ?4fT`;p{E4YFYc!sm*2DtvsELxstn>w7?eE<6*?BwSX z(_rQlUvp>Ig=y0E>*<>zFv++#{R-b;i{caT7@P@2B!= zCpd!NEk=~&c2hZIY7x|qo`~((To~lYSnx)+B?yaG5({gLSrv;5I8;{26B6&+9%&UF zyCsh&RW?K8wKUz-CJ%tO8C`63Me~@+z=w z{8^!ZG0^A$vgg`3RwmQl-}pI ze!t_X=D!>^#IYxCt&u+N+!TalaM<&S=XdcgVXnWy{t)6?21HPoOplpXp361}k(B9x zR!()S^Yw(uE!(o$34{eGdd%1#T2O+O-*gCRuDvl+JFWvxP+w4}wUit&XXmyFL*Rfc zIhLUdDrTS1Y@U|>2Cql3Wh~^qXHuD!+9wQR#lb zXz1hoj%w&>O50#Z*FmE#itOsB$C1=BVR^J^W$V?Rx<)w zUH~$ihXmzDVt*tGnCvXk76i9e9|Id&{x=SD4t!1Ij-7biKM9wgC$p&ulSt#}L1@%IB(*)EVJ4l8EN5nCfnS+(dejy^g#zCag*Os}* z%fQS&WQ$7(pRl9cI(mNoT8%;0*ew0hJdeLQvtFw9ieXI)1w^N?ONg zG?Pc2@Aw@M;?7YAFz6GoH^iHtn$I&AvRYdg{NBfZeZ@t~WkCE1)Cu%{G-i^ufht=# z8_jYEA0T%3}*pKdl-`+yqb z&AyYpnx6wf#Boo_ZuYLH8E|d8K(u6+lnp>Sn@?7lO-@D7;}>_g`^TQj*rp%f<0Y_A z?j2eW`39#Q;$8y;M14*}uJzc+X3|!fX%8fX=K|k7Eaq$4#{w;{*}_H9O)wRh`xJ~z zHt0A5jYra%or>9;oYW8`YULxX^5vp+qWl?zPVwrmq9Uz(%h{7A;7OsYgDOU)G!SlK zyM>?hWbWwN6~|e$za`(v8>3&*SWC}veYAgiiIKF;F*+f775(i}9yHf55$GJKhczOid&rx0oKs)_Je&M!zP;b+FTc`8j#x=-bW;?r=@3n2NV<}d2t2CO+xI(7h<;rQT6k-KdhLJAgbe=Ys?}1p(vDkfPS5wQ z5`@;C%3?7jwF}AjmKg#wg<$eNl0caN4g`NKo&`VTd*#D%*mGcRub~(^+s6twlY|5w z%|>}h@{ZbNZ0LaGo!^lP66>ta_}L1{QzhNb=qUB`JCW|3a#lNnR>#FkZP6>0HSYXZ zpv{81&J${Ib+q=c#pnMcc7&bOEro6D?YP_ssS}PucgFAO$ax-nTp=!X$FYfz?_ZaC z$P57_5|tj7KVYCK7iS(zRqcgOv?hH0()X_R!8p;ZF*MgSDqh#oYj?(U&uH(ka91n? z_&5#zg-GRQTh8$B&;l*L*S;~==i`yB^8hu`77>mO9CSz0;A;fk+McJ_=US~q(HSc= zlDgi2SoX1C1@)d!^=cF2=TQi$)o9HL+?mYhyIpn`$dkCzS%c&@{D9;~U#UnfzL#;c z$rbC%jH>B87XKD1+nl81VHf?go-rO}x30r9`|iNOXMj8)S=4z}^`frpt5Zb#d}KAt zHL50k$1`C`q?z?{A`+%rnS(swv!!DvZ0YTseF`{@mrQhy&_W;=A z!i7r?vu>~V{~qeL&8*o@?a~86BGNSfu4}3UH~NwDUJzRV#h9V9b?b%D0526Zeo@?~ z#Ym;b`uOFKuRr|rk4G}cW+#ZsnP~b4%1mPRB$inIHqqI!uQ}s>b+}-GbnfYoVM$u# zS(BV%qBTf$JEt#Rj5n-M6QBjR0n`SM0FeS@82kXs{yuWRLkfS68Ev8nt zB^tci22(6S}hoTJLsgQ{{Dn}R15UuovipeXimI>SQj%B z@dt*Xgq`>;r$)VvHi&0fx`sFvj_O`W-V$|2h#}*&JB(85TdO>}C!5^6 zgA6qTXN;m~Ap0C?DJG3wINM+$905uDcWd*^t2gjp2}+Kj1iT2_rT<3A*~O#SUYsgz z_QFRUd7lW!YD;TcW|8Pz#9j%g{jAlR@J6+D*X)W0gAVwrj}vq2B$}owngyZ?NMgUa zu7YV;e%h_QZM0fIsn_`xIfgY}J!H&$3`Hvw1s^=fx|!Y~nn zj_&fqpElDLE0`vBlnZWtUj3q^x13$gP*p6OP(<4x*)-rwN{6oOZC(P+wkYQ9J=ZvT zs$Pc)TF_XY#drSc@>+*q>sd-tdTYU#Ljy7rCDm@)#v3HD9dxA7UP1ig;U&AY%ZVaE zzJ)Xh$`m*L?^?8taBsCU_%CM&PP={{J3p1rX~cOs>d-yX%~v8qFt5)W?XZO8dqwI~ zJRzm`l9bO-Ml+G^mOlr)c3q}g-YiUAym%F%G%az8c9<#?(p}55xD0mE{s5Zx-R2Ot z2@3guneVf-a1Bq@+S7`iNNo6Z-3;3$(I6(tjhtBU6}JuX8nAnk^ZhTkVoy;>3W|jT z)tK7U&MFo3UbA@M!8@qIsrIE1#&Hk=~OD1~oX6~EeyJgH? z3xy)U{WkBpb%c*J!I?MI6+-x+QvZEWFnGTlem6!m1j$+EE^w6HcC*o<1$X^8{;8zH zoiPx*A7U1z&$}tR*|qU|323ko0JGOoO+;sm24||p#NI%nWlMPGMD*{@iL>*xOOY6x zZZ_%}1UFe2v>bj{M;yhpkj_jHoDAO=jwe*_0aYS&<(xaCj$86K>w9D#VB--gWe>OJ ze*LV9+TLAg+w3M!KP>SggEhnAjZT?d`R=(rgXX&t`(XZ~btkRiWOU72;M0{EjP!y> zcpsIjcvk(Hs2ZGOD4(aj6v~*LcPX$|#9gQEm22+1{Y9|mW2rMo>p~;cdm=*ohImcW z-EFz0lI99F{*9uCeXSp)^?@=yK|4i%zvXxPE7@@5i{U)H+(DsB#d;^f%#H;3ZYHvg z;oV0)a?K|g|J4Cc#%r&e5obSD#zT7v5n!b%12xSsOVX?!(Fzu2*Tc_Lxec<3Oty8g z4x$QXuVM@xikLQeG%sZ(l0{{Cs$Xb=;LOd`qhL#B0b~$i+O1L%)@D$3_KH-X7Obkt zWI|IPGW^S@^EjL7dG1=?aTP1TpkuU$x{cyJY44CnS7Yc&8^(j=Q)g~D?`(tABL}S< zYjEeb$!k!g_W${r`t#H~~no)0n-0=p2v*nn-q7ROEK|5}nL>uN&;=@L_yBH?4c`BgxakBn2`%a=bs|x7D z1PI&d*S;cI7AmQ|U2_XM30~S&BGJ$FEt?RB3Q!7HOowm3-o&2Su>`oNn6EXIcO5hX zfcJ^DtbgAdXBLYn(yP0~VOA+34_BruD`z2*r2&;NNuR)XkokR@N08vi$m=kIl9eKd zOgMye=`H>2xWgAApc*q;k_Bkz0qn6W@p`F2gQH>X;+>N}s#YUB^D{!53#78?sDzyE z9|;Z42J=lcl+2cpt`TKx5wHE%Pg`L`sj@FWm-ltINIa!rmpx|qw44d0`P?iqmBTfO zFC@ehdJ~4Caa}h5mgw=)H_z2|t|k0wO!sw`3UN*5J~MI7y#-v&U6<5-Q=;3geb30X zI8}$4S1#l-W8$NRwjXEhED zqp{#u#x-CewtfTjdz`+S^BcLS#>RU!Z-j~py-{=dZ+>uxjXXaOQCpaCPJKJQ-=x!2 zG}akc(2(nvj6E7Zdb=xfkPvV!L~6XUjvXJUK8DY@7Gr$jvvH5)sfgnD$%E~HXVY)- z+Z^_89UrZOM&90`QJ^w19@ON<1Q(keScxKZ91h7Tb-9#{AY&c^(I%AHBj zr!VUNqHOK|@wn;Oh<-@{NU*bcH-)LTWRv}MSsSyCyNl8K75gGUlR>Yn&Pt+Dp=@6% zquCcVg|5=Eayhlbya%bC3BpA(REuwmZ0^^J%w;C|d4GaeFPqJiq{T-%uDW{cMtL8= zzTS;U#7HnBZ)1h;UUUVx%*$%KQgBTP~a{oV$uEMVg_v;ce zq*a=cA_5|fBS(mWG>8I9w@8EJ7$FKuO9+#e{z{MT5Jrxa8ZdhF$c^UR@BJ5^&wcJa z_uO;OMUTH*2WJ&g;k>i&8<@xWRPQDCW<_Z(3ZXoo9lvc(s-;P6De^48o&(yOK_nUU zlE^M|b@b`de`?ZRC_&adn`fghR+C46E|Ac!yONXPdsp^_Dq4C>iOaaRq`1CXg?Ygop0fD} zhZzEDSNC)?(Mq>&7l!sjXKQcjxGZ#MzfQrP7EN!)9giHMW5R6VyqoNyTPxeM_$Tu6pUbW}U;I1!Ls$4O6M0VnheCGs zcW3@I#;qbarB%$7_b0b;%HJkPi4{82U1d{bB?mt!{h6q$H~0o zZUh1ZP4V%#7O$D*TN~PaSwb8||1XYI{zvu-5u}`>((DGe(wxuz${2T53wb23WE+Cf zdQfk@hTh^yf-iNF#yi7DhA{cJV1{wf#grAWXJ^vTh&MWSN^#tPz*l*1Rf{}cJ(lo9r$`w!aK@(0zN355Hnrr50|s% zIJ1yq9Rb}Fm$wa=BT;F!m-%V1CpMQ7`BSumQR*&9iX|4Ftu_lRl?@S9Mp+qM`}svH z3wcb`Hbd~t*mcS<+k7|1=6szZQ9ga5B6KwhG6Z%~n)R~(VY zA=p0^Z5Oz3$QwW`;_kNR9u&}hvXt(=c*~vDx}>@0E``Oj=N{*(ZQ4KnZ$h>==4u|b z`~vcd%Cr7xb?~OvzKiz$#BBzShGXjV^`HV?BzYWo&Vxme?H_lk5XKGU%vDa z+j39r-v)cex}H=S+_%}tcFX(z@0j;3;=`g#lCir%)$!PW_g(o7l~zL9$rN4Gy{kV9 z7*{vH4q4;35@30)+u~QR@ebw8w0110F7m;nNXN@s)_ypq23WK?HvJr2bDNHki+!9duOC-EjSj_vrS*HtV*m4Eh^; z=LGrQvw32e;@D{Bq4c2P*uy+prRKDXz(6(&ynW2abgDC7RLq$c-kuxZmEKx?{pP(X zX{y0T+POC$b*sEc>Etq~yRW2m9UY(7fza(V7NUPxyZLaSL`KA&sQzLhxv+b2ld3oNPV%X>#PSK z0DPM2F>OF9=7oQe%8ANdUgjMoPbnJyGghvaeANuCExKTr_j#xI*K%TO!0gDLLw+0d z1TPH-iL5X-JX2KL|LF)!#4s%d#!CEwdY0eG5?d#adFnSdJwQA=zslf zQrx%Ot9ySVX;;q{B8h@~@-KbvDTeZ?<`Ky&fe0)lduIJK(}H#;@aequSHE@|*;cD3 z^>;(mscNfKKR=8OLCtNn8JVIY7^ZtX1e+n_JATT~my!)w$hQIx1cTqv@{T_|I9vJr z!uY?PE2&M9oJpDO{1(v7KTI_+fdu}N3ABYiHxsd;&!K)~_JHjE z4xp*r=uf68{u6%aqhHbGuxuV)^5VoVOKp7LEYKmiXuAxLQ)tKdL6GDY1#v}a2II5oDsg30Kbzias&jzF z%#1zfx&?sZ-j>E3@9DhHZTfp@s+Be|)n&d4x4cUf;2~5E7!)%0Q?U1Q+w8)^f-Qr$ zIUYjtaDAM1MtI<0Lu-*?2%pmG4kT&g7l^O(yq)EK7Z*e{Aoa)TaaRO2o)o(2`_?>= z0*#%##?v|4c4uK8k)E}`aB8~kBaGoN@Y zQRQki^Q}5n16I>-k-;eVrl$2rj5M%st2yYV1so8=d%IEfa#kKsT3HwQ0Xx!5x&B(I z1yub0BEh#QWK(PVRWTyR;ibzG$aKxqt_9qil`X3-S?Ihv65-uDHcWfw|FihK39!!u zcr4YmqDP01GGP+(@3LHZg37# zQQksxU(QX#NKWf-X(Q(Kpt(Jl2K4(3xb12nDBZl9a`Z;AyxgZy;impAYEc?^lwn77 z>z$C=eznd_b-?vxDMVGLw;=A+l$g)|x1B;`8Fj1g&*QRJdttvGtZiWIN7AcbEmfbo z*nU2eEJqCX5>3esq@W99D3ildQc?gms#cmMO(G|Gsm?IuGl8a%@#tzl>!u%ymH406 zHV5$gc6ogkCTx}f-I%EP96)%FYf+|d)Jd(2oqnM)Q;vdb#yG}-K^tp&c(E*8^EF`k zF#Oaj_+>xxatblo=g_&v-^^<=cmMTTHF_bE!nH4%Sns2WOp# z4+@*NT{fTWVN=`!95bbTw;^#7p|`THuxoz1Gga|rrKMN=KDMQ&TnE;nLu`Jp8)N^U(+gSCq2>5Ec^|}>Q`~8x7&yCuA2Kc2epUxFR}N+FH;Yz zUgHUC-<0*JL4X+Ou8UNI=!DQogFzNy5V?VAJ2qQwn!I1d(>ueaEp9~Jhie%2I8y*} zo54fe0o^%HOGWz}b)PAgygz4miw|jqSHft}ylu=wV*2Feh}Kl+Tc>ucXe6JDhlj!i zaRCN{P_`#}=59FOvA@^T=^7Q4bh(lWlWDGUY`Z*A z{uJ!U+HuQX@EDDYwmA7+Ay{$yw!n(k({_nfR`weZk<&Zu=JDmVI&q*=;xXw(Z*{7} zd*DlJ_x`BGfkZDF%DNW#zQA$}%|jz5!VR9!CH6oN?)L}d=vGsRxqkFF=`Z3`D+*-W zuNM5($7bl^RXu)+hK|%+^|KW5Mm2?R#s5pVLmRH+_HQ>ZP;o5lO^$=&2ltW8pbjmG zr;~$Fho)2oI?@KryJ{v*)86spxkVoDPFYqr{?p^A``cR=Gn-))V&Ola4s(mW{CMZU zp~=}?&XGntm!S9t_USMQ2wwtB82HsKd_)!N&#x}pFS)*d{(-y)kmwV=<3Qfst6RxBtECxQ3M|g#r_J(x_MTXec~~gEZ!-up(>{v z6}IBF;K*uNn^;*b-E3p!TtES_86p0vP_R^}KqoYPM@D&YU_vuK*gjGz-kZu3+WX~5 z>@Ky*H^g`6V|_Lu(+y(oUKTOh$sRRr2^LN|45gS+OqdfylGBiy;q-SK&cbyj|Im6A zQ(vNR7p*t%K4dt;&%%PAHjBBZ#s^#kFcY z#ffd{vswCV2?6a}Q&tuk0p3`S`hIb(@B~3cQn$eWKoM5vn~u|8^Z6KZwmyUtLCGND z52O!f^Rka-g7)%<8p~-^V&n$YKiIy;vjhb^h3-|=HY_TNhM_&ZA;A{HD^*epZVuf` zjuroozXTfA56-np(5L_A*E`x*^e-B}{xX>zI4illv9|Gy+u&zUmV)cav(l5&(rZ@x zY|UXJ=gR(d6}MEdKwK^Jpbs_Eq%exiT!SkhX18Z{73nE;HVOiQ+_-K{JDZg@ckXBa zO={?Q2ag}`^!iW-?+Z;&52b*OZnRW8r~4XL&PNpTsN<>HiN86t28F=Lyl>By3`aTL z_xXT{pag+P9OPy$GzXf6a?pApHep&XQl+Av?&9K+Db-Uxr%6=KZ2KZr8oaZvvp4mq$u^gxsQ#pLF$6LTRd_y}J5H8Eq#J1mSM8F6}72 zGroeOalrOjaAuVyg}tX{v54R0bIl-qJ6PLb-TH>^P>~q-K^w24!asv|w*$$C4ZL}% zHFohe5{3AYZ@)oIwgTcmm@$+_+2lD#fjwFm&_r?4$`bdQ+Q&&HfX^*W1Ae^|x0*@o zWKk(WDd)xQ)6K2#{0a~swDS1M+V7!RP4Oj-x~pHxAS4)0zIk)RUKFAbVs25*3jo!_ z9!Xq$Z#q|ioWLZXXNpH8s!7|byer&rHCdAd^_I}JTYIo555JzdAIeb`=D4uBx}ctQ z9AFs`QyiUo_i=MqgGuT1ks{t?5GVG8I7zO4o*jJ9 zNpAcEc{}$j887wfbPd{x`ix|61^E(c>Ju44Srp<5*^9%T)t0uwgBrmBqN zFbh>abB;_MlwoKIYvJj1Z|L0Kdc>9vi~eCmZf{x3)#TqdiovW5PI<&#n6Y*N!8kYx z(pjvKRmu0(&g+BL?bPxkA+LBosFmtSR@?MD{)Rade-P)+?o16PD^?Vru4-HuTLPSh z6K}|NH9+?LD?&5=7^)ew+2dZp9NG1NX0(Vv>ZI+Wvhwg)*80qI^-B)9nTngc$1|cp z?(6nghREI^tlW#Pv$?YzOR;YY4l`^!yvQPO8&{AEGHfznNOF3_y8mVK#wiMG*5I*R zw7s(kEss>-XYB~#SUWph%`VZnJY7F+w{v#h8R&-Wh6O&zJ1|WI;b;~(ZAtPOqik31 zO1Gpc=f2YMlWT@yuNSpEOQp2k>GKM~f0_GLD-mJF+cB<^Y-aQYHXaCPiL--6HC?KK z5lRF%m8sQgFCf9`1w_xnK5YDm*R{1OVes>Mt}f^oHGuVfrFiG5@FlB>(G=+9%4BnW z-PunC{#$LxWOSo34G4S-VsRllqEr&v_CI+znOFKE>RiUD$}wSQ%hj zq)Wz_(Zp^|f4q#vgY?flOFKy+cD6q+yGkkW*;sxr;g)1cR+Wv%&=Kf+pLxZQn=5qb z?V=LU%bbvSd=hGFYqfm5l}xbi0u?SW=uDEDYNuzoDMG3IZfzcrU)(%1kSV{ZPG>ygvd>dLymIV{270&jTp8)n8q|sfiqLH$3iL{Mo7u zsl%?=2+(&@ZXS}FDvqU=O#308o}}Sc<4rl=nC;cg6KS>4 zNzGT_9zH)pv-InvfW{2?7&IAl>nICi60>o#jGkp3IQ~ey4+cUP3r3G0VTxjz@fEN; zku+W}2cJ742W2ku0&ih~uEP;#%>N6f{L-;ZlIzpgchGO?Z^&GGj!V7W?zwfG2Vt9x zl~}q%r#cXlJNJ>W_a6~Db1Uf*j2xdC<8wP{b{58Dkf$HFuq+RaSXiiVg$v~+%+ntZ zo9sv*PuKjg{^~x*P{GXGL$qH#Pgnj2ymQl^7(kCKlM8}t+2JcY0H8M{=WC{6> zJk4UbTkn=LbWQ!`gjznPENpO52qPZvk~6z0iL#y= z5_g{tc-P3HTj|qU9C>)9Dd7pm58*i(2x*S$|gHctLEbGY(gvU-E%XGY3s z`&b9j_xdkj(^jMu5j{&b|4nj6Gu9K&FKvl?-_Ft3)Z1g}K|R+?!Cvo@$FeyzH7gQ) zXG{*%p2swf_0rcC3?DQ zwZ5q zL~`MQuEV1lh-vQu?U!8MTjK?{^%l3#Oo#($t%(3~b{_qYq1!JpEJAXC15Y4>yq0^{ zmzgbJpZ9AZMLr4}4Hz-Cc}{c_%@}l;oD`~+eY;%vLzMBtLH}?=VQb6E%0D2km3KRV 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


N zB~o6$6RJw!i)Fpl=knFkUs|^fpXhC;EhX63tPN)X3XM2n$ zZvyvTPQdnO|LS}i(kPUyp|jLuZ>@zoYnte^UB3sFZrULy=jri!WI%Fo1br}1-vsrM zt;;Oaw{E2oa%spzgf^gH`&q$`O0_uO2p%EF68s@DCrRG_=R1e|;q`fz9^(`UW#8{a zVgK!yB7plr#7^f^-hP7q8wIJoU-LQTbIeWB1;0wRO}YFf=9>QSt#euIuBS71Sox{s zL8?!b*wAv~rSLGRm7}CWJ;Mg|9>ZEpv&|amDS_s-R#aNt3VFZPaXR+*X`~tbYh*Lm zN!L6hysjc}AenFPGE00NvwiB8H7mmGy72GpQ|A8s`4ju)UZ5OLU&={zV|{)7x|Kuu zN0_r-ds+=BR|Ws=-A>*?*7nqLbpqCDKTtYDDpyiy=MLf?QhT&G$w|I#{XPpt*MOG7 zMO!YU4hq$t^7Rs};}oSMwl$7Fi~B`YSoql@P#8BCf+*g$XA?xnsu zq7h`~D!ig*6?Y%JZ*?h>z)=|}MLMev_Z%HtVd*oG9xI~i|NAaf-2VF{>=dkkYZ`=B znMjIT$Od|o+;U^=484rNW>#&U&n;CIn)s+D# z@CrBUD=^KpRv*Hg2!d7Gm^FZ+^#O=N?nellLjC6Cj0%8jsX?s*fe_l&hYpWOyMsY-W{ zP=f7Owd_PSzNg0tI|M7+i{9>>)shYr88c%qd;A=MgZUSA ziV-G2te**UDb!KNnU<`1P!mJbIa2i9wD-R9RZG){|P&!%Lo10D3i?j7bH z78y^*nD@sLr)9OF2}2fwP2ULuujxPT_F8K?`CxPH(OyI67OyAn{_#BBK;Jp};Gp($ z$E~E?tZboH(}g;ID~nl7Ri`|1d(ZiK&id&(lpZbwAllajaQI?LLB&BBQ?9M&ezW$s zLNb6Z|3yDRWtVR+nN1i(_z*D&zyQMOBGa7U^v}3)p zQO{;eZ4Fa573JGKPG@E7*864xeFU} z7MY%O&O>sS#KnKiGY;xZwn$%paEkSv7A`bagPo*`(mQTLEV)z(re-&lT2CMk2U{#D8A+!%ZzEBho$8U> z(gxW#jRg6_-@T~=oD(nMIlFv~x?nG5-s2_z+gjr|!MlASEQV6b>q_Df5ug(y=VI3~ z>x$+wTTOO(MLyoV zCg#7aFOh;F7UqU5S6|EegHpkjQO#o|`PG|lmBfX?QWH}$NKG8;`ZTT8laZV~hTzfc z@P^BCsWri$4b=9NU+zfQO+0S4tnK_sE}sbuJ8$=xrCNg%cGXfcYubiAqFv#S*!^|c zQgMfz_KSVY<+El4){g2qOn#_w;R`1%GpALYeU${~a1KG_B3*5~D1y!-0HoAORKCha z%ZY^0{z3@t=zOzlb(w=U5OcvxyndIBZvS+P@3#yZPd<#ImkyDR2|!SZlq7jR5?%hn znTEA5O2v^^xCBk*S$G?g3^&VEKniszb6!sNp_O8f55d1g>*-r(8Z*#mdp^T2M1T8# z0Ga(~kBTtJ+^`PrxCXyIaWbY^uc=cx6I}ij3U(Hy?%;4-jtVVE5ofYc~N(a+7r=Z)Dh>kZ!B@T8p)^H23yAp3OofI7tt!_2L(Pry9g zZB^AlBduJb4cTRY!jVdWztJ~GSIe(%f*EOI-}`Q`DKq!PYzoT^Oqj-v2vmJu(Ot`3 zSH%VnXmbrcqP1M>a_c|NvMb_Tso!SFK03+aj>WhBCx<3*mplnAK0GnvG_WSAeUqRP ztDIMVI+?hEA^K(OTl$&*J?s9Afbk~w;D`YGlmlqE@A6L5qdsYVYXv$Wev z@FmJ`Qul!k?>yLk7}m zOP~00b`y^MZ^5qi0#AjoBc*t_^k$*B_5mr2&B}JfqP!`o1*ds6Uof0;lSK z9|!U~np#%mtN|1j{`wUq9N@4uLuRX^uU%#L@jofvEpv_DtX_?Lq=GLOKa~VvYu*Qa zy|8O`jfhNHnKIwru1F*A8!6WbmXV+uHMTLmAYl@{>@$(u=#X`gU3&i7+q5u}krpvO zFZn1(PL_E?XN3 z-f1d(Q>&?6>J$Bk{Y&NH+1BJ3;l>vbZak#GvB6qBTk`y-K@fi(ahhYZu+LoiWqoL9 zp5Gr*xEYierXkBe1S-RX7i}6%?zD@>P{Vx2m?dp)ydL>zjpOp0q?{?phx;(d-`$U4 zcbX7W-*^V-x9rHD3a9=0wEGPBk^A*n@5z0S>Y^O~0XM=wMx_YVFbrhx#2Zn`QyjOG zMIo8iA7m^QG1Sx<8!`~`!p6C~9@@)hkr4u~U>Q?4=XQJIM`bMP_9J%N#p_+zvuiar z4e$;8v=b%OrR0S#{pxEJ&CFUgh8{7|No5EEWBnVqqpX5B+y8 zDjM=|x>MeO0&KS3@tMM@_zasKO?o(6^Dq9te7&k=^E+q{-L|@FXz-_p+pMzCk&GZgXIAW-KYW|xUiO7)X*F{E51aTnPuoI`S(x+g zwb>q6Z)_dPNY;W|VfAhQrXJiW1_FQMi(O~iQTy$Z=;C}i#*2O+9jaJiA1lZ7VUM|l zY_h=+6+4&0k|AFVc{bGhR~VDuv@>&{br!{IS&tumeT<*wy`g+}3GH+BZUg7-OI^eq zI=3Pu?T06!E>eb8A$bG8U4F)<^%<4L_hi0@)*h4lUt4wI0xPKeKM<-mLbqC5I)Is& zfa~b!w3IJhQ=bm@3fHTW)x6`Z5zV`0;%rYB3w}6ECO`NHYLXZGt49;ct<@ACh4>m( zjC%8xp>6S#6vplGNnGD7d4d-mU+f!?dgRBu_uXA7kT2)NvT+Tis=(TXSJuWPU`;0K zo&cmtY({`m12)%odP*^sF~OzTP*)&S*n2YAlG0aKHj22ZKRH{We*a^qwjtpU&7Y=3 z?d|Lsy8VO<6Tf6GV4Ob?b(Zw_ExIec@kzY9_bf_}4SjcO883?Byn8WfPlc&+$pX8U zbT}h~b3V1K-ne-8H_A6WndRkwW(|)>yV(Em1ixtCapBP6NmP2Goa_q`>JiZ{F8RT zyNgW7VBkau`|he>DQ;rdWk#bz*zPbdxL#JVWzAWV@};SnQ9!$+zv_j`YEF1?{qJ90Cw%L!Z1Pc4i9F~5 zr1+mFtvm6W3}e5o1XV7l!@lwtmWp-DhXW;^V=S3vB^}4x-FQ>_R%a{QZ8*&D7oB(; z?cePEA+pljP#(L`ZnL&(Gv6uy#uBBrr62}ngFXjH_wS8o5O%RugadOC&2kC?$aluszSthyX7vX<>R9(YSoO<^o|pW-j;LEiTivzDrz z9c08sqQm>A&)8fL8tEs&JZ2Y2Y2bs~ya9+@T!#THDk0*T-7pdF*e>o=alTT4jJsat z>{okIL%lzXlM8p-c!M5W?61o<#2irOF=sM@mJ|Z7;`s^GHF517pHRSsCVsu&lg>j6aW#@%6->K^*113F3 z!fQ|J*?Pc#R6f3h3ruLcy^wFB@a{pEyxWfg_2zym??j~-C);|0xcbVwjQ0ZYTs`m3 zU89;6C99L)sCm2Mb`rK!OA~kBk2x;}whbTpB9y=y!ST^_H?^U?PQ&ABDkuK|YGZG{ z$^cw3LFM=M_9&fxGj2hd=ShKb9L>6CVy%tR<6?SuYCjVe^%-~vVfbQ&Z;wj%bq$vX zjU_PePQqLWdrZu_ZYlE^DKHmV*}tRNG@lc(;`*C8b(T%4z4NX@yKthO-i?GHeT(uH z|GiLdp7?MJup4W-?6UxG))e1omD7_UmA3e0& z5^mnP$*H-}tl{^|Aw7+8{e4h&uePFv3w|XCFgP@`_vSTZHe>|nN)@7}0H{WotBSCQ zH(v3YM(D7?O_w}U*=2PX|T(+2*8EQBi`aQ3%q1C8RXRi7m9@xF z@`W-nabwi^Fta*u<2>2edGr!~W5|WK>Kt|ph6{5YE5^h5?D;b898b<5E$5nORizxO zM)*?Ki}j?iKYRpWIQWUf&f5%6@{`N*Mtpu`Dx}_=&{DHL;8M%Ic@#wI4jp& z!d}W(JdwW#Nd~{<<)Nb>r>17JYB$!3yn6>L+&hTOdh-KvM|%;;j#(40KW2?0QHnFS zznz!4D>xk~ZvxtJiB~s4r%MO>ig-gUOr^Q|!D&(oTT7n%@;lh&*Vig{3xaX9Fdr&&U#Zo}G*bjX7V6XTuQgh`|yqVAOCDFQkDr^zinB zuf+U2(6~&Qz?)5ieF??td237U(Js^xk*u@TMCqtAptCV=_D5-w?0F#;STbNy==b1m zV{`tSOr)J}vb2aEcwaoELoN7s`Ch(%qJE*FFjK(z&rW8wCZ%*Xjx(KZcpD}0iQw*j z`O_}-_il!mP;2_SU9eQ>>)XrQ65nhaoW<~hvg5RxR zSL3nnsP)9oC$`=VYycbSdm_<=^unxRx?QQ^3$yeusH|p35&PzPk2dlRV@?g-rmWcf zsHgts?F-$+YQ9nH)Y**jvUhN}?w=y)bX^FQBUNI9t$NC6KpnD`eZlSFM9#Q_uhqGX zaV?Meet(WJND0OEfug(Z4Pk~(%mEm#C+=M&<|SD2vL=*xCL}!X=$3tK)7QVBWF2=P z7v$;biQ6HGV{4XreHN(~vNJPlI@I>rWtpo4xIvf>Gy=l{jzuLT<}oCq#q9k&{dG;` zuW?sJP@=IOKvvFq93RnX{{EOoUO*JZn??vF`j7`um~|Ol-bq!sEhW9;0K-W>!gLEC z_b=Ok?oHiVtMAX@wOBB}c=h5(r}4mk@wwCezC30Did}qdZEav{8-CYg*4j#LPn1wp zgen5BD_2i*elVYx{xi&Yx4-CQ`6=N*`V>H7<_X9xPlxBkz%(-^Ycb!AhTh)z)d9u0u_{Zbc+O*e%@Z`RK%q=9_%r@a=kY0?XkSaCgExSEeVB5!5rFPH+Bi6QDv=Yundyf(&Uvr`YuUA zcyP>pW)+P9{=!)Y7SZ;&WyIW+SC2eazYFoTM7G8`@ z6$ONis;_l|zihs{h{M}7%0V1K=CbEQ2RI=S=68-cn;$AcQ53BbeC>Ysut<3MOP7en z_63*bzpRVmWa-E($fM9lJ6U7u1GX1D(NE8WuN}X2g*?Gn&!#fWOQ$1{1Yawy7&#|6 z-3B$pH^uT79yZUismkmddKYqMhRca@;=k%j(!t4EYg{;In%@_=ju(bytCra*z`W4o^La6U+IJwr9k5qADZ)>Jt30ZgwZBUmK8DOcSo^(eYkDl!ZfFq-`Up0E!wOr|c zrod{xm&s`s`@bkI8QAW=u?WJy=YMtP%oG3cdj~xV!OyKFy{zi9i~rKG>X4T@2+j4Y z3z3YFGOi3_eJ-{-1`@v0XY7ri==;-8FfIBm^XqAGPA3zX3NWa*UHFz~rmr%#{|^<} zkRd6uO9J;KVt(bb5I`UbXpQ6&1$;pA^xxS3BoIDDo)@%wVMRC5Zp3mu=1$A)A*stl zLk_u;Lup5ji6mu*rv)@ur%iUwsiOIfnxxaV?Jc+ zxW8Mlk(_9p3NxIdHtNo7NX=~2!d2{r*U7%2y-V+>{N*%gDo#S5Kz?o4GQqoR5@z+H zYhFn-Ev1_QW;wsYDA{y6xP5{p%#gwkVM|MjRyrMTLn&CLyf&`%6xi@a;3ezW9c3b_Ynr$$proEG0WF&o^WDmj= z$q0fOE1z1BEy6H~ic5DU{iDIwYfujlnFeEiD>rU|H2(c^v?2U*O@pvo9TNI9#-I99 z|82_LhyBLdnwlHb)VmfhR6ik_4VCJpG(~W_41ZgjlG-@G8=wj`a|@Z8f1|Q%?pE6# zpG5q8@GD>F{%pBAuQBg?#1G`#z2}bV{R1+_$=3COnANSS*)NBtxC0%DvFrLA6#5q7etybWR?pbi{+jjRCecKt+$A*3^dfUUXnt# zyL?kq{DIlG!Eu>&Q^|92E2au8WC6FOYTYOU)H(YCOssDcg}yn=udkW0xF32k3Xjc! z2+q5`4eRQTgqXd9uDLKxKN&l_AL8?9?Vi=jXq_< zOgmXYb0Ji%%w_g%3+Jhi6h^eNi_Ir*mufBewTy*2Qt!^7<%GQ(o3FCf1qXgQFiR8$ zDe~o`ZMo)~rLGEp@pQ&A!FN@zRlhZ|?HTWudRuDaJ32P1bgOK*}p1ppP8)f;V+E4rs-mR0N%^VzpZT}9oTa&jB) zpChjr3FJ-*A2IHL+TJ=(#~JqWZs2W#6DJBOBPiu8xPNy8nSq>EN<#I6vWgju*i7|o z(v#w|j05O!fIz7-`RuAirbK&O!-Zg9)r`8|R|4 z%FSJ!rOV5oGjc<;a8YiGG-ggrtD9LX+$s3nxHE(Qx(|(q*4`D%0XJEv5h&R*Ar

z6iv!%V4rm-6Eg+w#!u2DSR@09F6Z`&qQUgP@ZV6sIXk^QhUbSPxp}9kD+RL_UOx$X zE*fK>Y*fW+v=QP>-k#+fNy+q zEpg6NxEF8nctgDpm+2)T=tq#;c#tlC0gLcb{@wEfV%f_`-k!}7=uUwKi*4*B%Jzg| z!81b1`y~FKC;ikBTlPGS@I(;0rD=WIF|&ER+HMm zx^fp}+9;lfgTR@nM#ixG7~%M+6rKR5lI4QPsy|}js%X0@(Xaer5D;p!*>ip|llaxN zL(NA!-@C--dw*Njf#z*KC8gV0i+5~Xu%tJ!hgoJ8lofyqUH)OUz5@QL`>1$3)!sKy z&Q7ucnG`(_ab35qU#B;y%JOIXMg;!n{=M@(0&sOq*i|^`=#z>y7Qr_+*Ha)ZUrl_} zsz6zP{+M82E_B!^e55KRo}B)M+a8JeJ`*X@l}Yzw`PdNaLp=1`Q8D-vEg0Y!!8DYh9vHNXWuPL zeU>X_t0C?_DsaS9K^fbM>JKTL>3SwLBR>0CKq@ELGb&ffB}xi>C&z zaSJ_O%pq_!lSc`KXckhqfooRt<4#Q8e#OwO?%3#8!Y{oyGq=UymL^1H+98FBM#tHv zKW*7f?+Y8UA<(AG0ecc$$!h$yCx!?9D;MGqh6%i8p$h@JL3|zpe64)0v2FyfhD&`#_ca8$QsjUoS6SYt9vUY>?$nzu?b;Xcf)58(US^i|>FL}0 z=UlIsAmx@YjD6blo346@B>A%(TUmtuRSpD7un73GK9#!20sy-hI6Qp_P4KR*dV1}A zuTO~I@xMvq;{Kvt+Y`|il_|%>846L?pSF%A89O0q%mDQIgZt+6;nD<7iee29L=-O{ z=;pwji5uOtYn_31{gun)T`bRQF%*ub!HiMTANL>k4$v*{B4Whdo3{e?KefDnJRG=g zZ$IItOQ>5L)z<{P+bM>UXuS1&u1h<%RX#AT&W2kLW55o)dc02aKx#TWtrf6haF(s! z*cjL}Dd(;Sg_3CH)UP-LjRwB^%lhLZY;$z9CS|bHdneWu*?b;lT5t|cdbYI7nWXX{ zf(aVlu2(f+HXy*->(xH_x{qw*8RD@K#c6GA8e5s05VVz8lZN41X1-#*h%kDrrd6Ml zM+3VtPwS-uQ4{Ao^+C5|%p^9OsJid(mY1)IW%)3$^%uJgh}p_@$ltb99h~tU{4vko z;(fR@v-LN2AY}H-znqd(X^jr3q3c{$h-JHGK5Zx!uD`y`P8Zq?rs;p3pp1sBu1g(i zih?DAbDp=`t%*$_gRO@o+S(}81uN4HdiKdHthiP5t zK=@ZN%)rO!h=y+AyEAywKR7Q87UQTawo*c%%y<>Q@!KDxmON;qpm@+y(=tD%G@K+5 zF=|}b%nwT4bdViV)I-MKZ4DZ!s*NUT_gzYeh;OkNgQmGm0kQ+^~<}l#kgNJ ztbMgUJ1m+V`Du=KJK00CiUFPFnr2$9n-<4r!^tWaizCBJRs%vZhpJt^i1_ zPaOy+F2P4I|E7u=0fT8%EQ~ltg_hRnpI1}F}uF!K@v#{ zv)KOGgyfo!&%CEDD+Enp9)t-!z1A{>Gov9wxh|n7)C1Rzep@MZ?SK-S!xvMTA|T(u7%xf)o1VU)fM0o z`pZe5a65Y05#BEE#Pl$^Nd{)+*SeN4^{PJOPfIPv{{~T6u7@@vjEwfp#QZN#tRuE^ z*u`8|40z`QWf(iT)e!#t-0-BR<~n*VUd9F0b|M>Yoq+y25xo(XF(T;H@u#i5eSfNm z$#S1QkB>~oV&(22*m_AxiE%+zB^#V6Ghe*`D?M-6bBF1 zsp?-O$Ue(Y-k|u0L!<(pi1t^fRzslXO~G$5vyJFseoFAb6}KpG0T&- z4}|ut96W;z>E|AWx<&+#`FTuEy#9IBq)d?`>#o~(zIj&NA2|2{OE|Fv=` zsu33eix%NhjO{*r8_c`vYt(YLrdf?wGwF%T{>@-4WuYO;LDdwY&4|d?8O1GKy_Dd# zYa0gN=}rvFy78P7bet6dzu~Id#ZZG^Pb>StU)zV(y@x6cb>2PztDfXcLHq1E-*k95 z01AL@{hSoPjqNLLIZ|_E=aEw0L#m z0#Ifemr<1a4iaL#?ErJ!+~2Lfhr|74=ODKK9xC-;J_2$NdRylcf0AVZmP55sXas%v zb;d+6*TVqjK5F1)IA?-xoC3>ECe@nHvMhT-Q+GyY;ue~&qQzH|dsyVyYld-8iYCAQ z;80@yE`TnsJv2qGh-}66KX7;naE4RTAm^l0X_>#lpKREjiCI24?v#Al^94q0)%^gn z*c1=~bsa)P`R}hb|5;s?CT|*Bk3@;?J32bH{MbA7dK;e;n2wHXB(SfkHyiuf9jt|Ev7J8)?4yRR9 zra}D{wKsF&;ZR~ElJ-nvNbP~US>`bXH)x-qk$4L!de)YKne-N1$S65`HrOKSm=p4R zbg}TlHa41d8nZA=^EQG?oG;

sTP0Jpo@KDDJ{k;WS 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 diff --git a/suite-native/device/src/assets/t2t1.png b/suite-native/device/src/assets/t2t1.png index 1d747dde1cbbcffa6e1dab0727c3bfd26fb234b8..fe98c3f0121a4a1a9eee85d9d4814209bd12f7b6 100644 GIT binary patch literal 78090 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 literal 80125 zcmb?>Wmg+quyrX=+}(@2rnq~H2Y0t3rC2Evg1fc21}VkeHAvA0f~U9@cPIqsKKH(V z;r%dc)|pQ;>#VcSUbA&zlgwm^IwIr3Ek?yg!TEo ziTA5lI3)iYD6ewzDE}*>cLcbU8p?{$mR88G z5E}V=>@Xi5RIIu8DZfx&V}5>B=76FSfr-T<9%3KSpakSuV^+R2Xp`D|oVRp!47N+~ zsP#y0n)LQr2bbDyz`S3&s#ltKPPByX+~T9;|}yOlYbrj z@>Dl(3cdR~mg+Hi^*D5NbX4^*=iaF0T4)L6=?OeNJ5ztDF}JX2Szca_LmqWz1Vb$1 z;Ws}if|4c9>5)j+xaXuZdV2cti?7Z17c@Av;*1QCf2cK>0W;k%(Emo&K4S0BJ?f{J2f)}2*3M|{M zDYpCfHl#;Fu16@1pW5-yF2)77{Mwt_mX|^Te5x-B5L@DznVBVtlhM2$b4QKQ||^$J4f7r=`!MnAVdAOxdc$kYX>!eabiH=wTfM z-7PVyvwX67dB}%e8a?(F^(sX+T(D?FIR!&rnAp@6pS)^>&66U%B$@KXy~@A zilgwsJ!AXu&mR)L?p)uS2aWXp{o?v`UvT}=B4~0A@CSpju*vB{Mu>-4>LCv@7+`y` z+(Rq5^83tt^*D3V!4~GU-QQbZ*InSg*>o#CY=J;Ko4?zYmM~m$>{XrKJFJ={8p*I5 zmf62On;$wmr$Vl+tTa#ZSgx(EK4m_go%MXZ*pj`wX@fq2Uvj}$9=%*I#J{0Fju#Zq z16H>I?3Lgq^-*wLNetwEivsFQj2^L2TA@k)gFOqK6_1@Hl0@yb;xy9yytBSOMMst* zL#tfPN28nAfz2>|I9tG%=yL-%>Jl?P>-*lrD-#BYrb-4dRK_W}-`Na_sk{8^%V&+T zgu4ez$XCe1w}(nN9EA9&RweTIk zPBuUjTa)$r1y3`^`@?Vo84iZv+fAhG-QU!gD+2KC;LG*;Ee&`Z`5PK>$)9Kv^5Ngu zJ%bhWfAAV(d&+VL85G|au$OMWd)rN z$`vKB2%PLlxctMS44-wn0*9IpSH)r(%#HLzJ%2XkWf&Y5hHwVaO7a;uC!-bnIywFd z9JNNqq`^TX+c0;7-8@!_c%fGFn_7c+KfFtQp|P6>)Z^v0b-Yw$UP1b!&K9&zwX($| z*nB~!m?e*!49}Yr$X;a63y5LwW!~!L2>j&t8`>w73C7yte=3FkqmUqaiq2QKZ3sh~5|AmtlyKW|fFX{h~;JkDx{-?7h?ljQbo74-2p^l=dS zf_!J^y3{^aerrd}@raG?$B<6(L19+OfJ18E4ahWcN

fr(ABf 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 z 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 literal 788864 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 fxX);^RM>?!}+`#s{bLg~Yh}-UU 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 z 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�@AkIx1tER! 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 z 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%0A0w=s8Ju@>nnp^H`N_ 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