chore(suite): name model R to model T2B1

This commit is contained in:
tomasklim
2023-04-24 19:10:00 +02:00
committed by Tomáš Klíma
parent c51a7840f2
commit abe486b471
25 changed files with 55 additions and 54 deletions

View File

@@ -137,7 +137,7 @@ Active sub step of firmware step is stored in `status` field. Explanation of eac
### Note about normal and bootloader mode
Device can be connected in “normal” mode or in “bootloader" mode which you access through pressing left button on T1/TR (both buttons on old T1 fw) or swiping on touchscreen in case of TT during connecting usb cable to the device. Before starting the installation process, user needs to disconnect the device and reconnect it in bootloader mode.
Device can be connected in “normal” mode or in “bootloader" mode which you access through pressing left button on T1/T2B1 (both buttons on old T1 fw) or swiping on touchscreen in case of TT during connecting usb cable to the device. Before starting the installation process, user needs to disconnect the device and reconnect it in bootloader mode.
From the technical perspective, these two modes are seen as 2 different devices and there is no way we can tell that the device, which was reconnected in bootloader mode is indeed the same device which was before connected in normal mode. This basically means that if you are updating a firmware with a device connected via webUSB you will need to do pairing process twice.
When device is in bootloader mode `device.features.major_version`, `device.features.minor_version`, `device.features.patch_version` is version of a bootloader, not a firmware.
@@ -188,7 +188,7 @@ After the device is reconnected we show a button to trigger an update process. T
#### Device with no firmware installed
User proceeds by clicking "Install firmware" CTA. Since the device without firmware is always in bootloader mode we don't need any cooperation from the user. Device doesn't ask for confirming the installation of the fw. When firmware installation is completed `firmware.status` is set to `unplug` in case of T1, for TT/TR it it set to `wait-for-reboot`. User of T1 is prompted to disconnect the device and reconnect it in normal mode. TT/TR automatically restarts itself. Then we continue to the next step ([Generating seed](##Generating-seed))
User proceeds by clicking "Install firmware" CTA. Since the device without firmware is always in bootloader mode we don't need any cooperation from the user. Device doesn't ask for confirming the installation of the fw. When firmware installation is completed `firmware.status` is set to `unplug` in case of T1, for TT/T2B1 it it set to `wait-for-reboot`. User of T1 is prompted to disconnect the device and reconnect it in normal mode. TT/T2B1 automatically restarts itself. Then we continue to the next step ([Generating seed](##Generating-seed))
![reconnect in normal T1](./assets/welcome/reconnect_normal.png)
![firmware completed](./assets/welcome/firmware_completed.png)
@@ -213,11 +213,11 @@ Support for the WebUSB came pretty late for Trezor One (bootloader [1.6.0](https
- Devices wont dispatch any event after the user confirms the installation on a device. We only detect that the installation has started when we receive `UI.FIRMWARE_PROGRESS` which is triggered about 10 seconds too late.
- T1 sends `UI.FIRMWARE_PROGRESS` only twice, at 0% and then at 100%. However progress bar runs smoothly, that is because we are faking a progress. There are carefully set durations of fake progress bar. When fake progress reaches certain barrier (eg. 90%) it will stop and wait for progress report from `UI.FIRMWARE_PROGRESS`. Also when this event reports greater progress than the fake one, it will take the precedence.
- Faking a progress is also used on TT/TR because, on device without any firmware installed, first `UI.FIRMWARE_PROGRESS` is received too late. (Only variant where we rely completely on a real progress is when we are upgrading TT from older firmware).
- Faking a progress is also used on TT/T2B1 because, on device without any firmware installed, first `UI.FIRMWARE_PROGRESS` is received too late. (Only variant where we rely completely on a real progress is when we are upgrading TT from older firmware).
##### Remembered wallet, multiple devices
The onboarding inherited few bugs from its predecessor. After the installation of a firmware user is asked to reconnect his device (T1) or the device is auto restarted (TT/TR). To prevent Suite from selecting another device while the one we use was disconnected, we force remembering the device (and storing it to persistent storage).
The onboarding inherited few bugs from its predecessor. After the installation of a firmware user is asked to reconnect his device (T1) or the device is auto restarted (TT/T2B1). To prevent Suite from selecting another device while the one we use was disconnected, we force remembering the device (and storing it to persistent storage).
However this doesn't work in case of freshly unpacked device (or device with wiped fw), which are in bootloader mode from the start and cannot be "remembered".
When this happens Suite will try to select another available device, which will be the other connected device or remembered wallet and there is no way ho to switch the device back unless you restart the app/refresh the page.
@@ -231,13 +231,13 @@ User chooses between generating a new seed or seed recovery.
### Generating new seed
- Single seed
- Shamir (only available on TT/TR)
- Shamir (only available on TT/T2B1)
At first it might seems that both options are doing exactly the same, real difference between these two will present itself in [Backup seed step](##Backup-seed)
### Recovery from mnemonic
#### TT/TR
#### TT/T2B1
The entire process is done on device. All we need to do in Suite UI is to show generic "Confirm on your Trezor" bubble.
@@ -252,7 +252,7 @@ For Trezor model 1 there are two things the user needs to decide:
User needs to confirm that the seed will be safe, there will be no digital copy of it. Then he can start the process on a device.
#### TT/TR
#### TT/T2B1
The entire process is done on device. All we need to do in Suite UI is to show generic "Confirm on your Trezor" bubble.
@@ -264,7 +264,7 @@ This step is optional and can be skipped and finished later from Suite settings.
## PIN Setup
After the user hits CTA button “Create PIN” we need to show confirmation prompt. It is handled by checking `device.buttonRequests` to see if there is `ButtonRequest_Other` (T1) or `ButtonRequest_ProtectCall` (TT/TR). Yes, it is hacky. But thanks to clearing `buttonRequests` array in each step of the onboarding it should be safe and presence of these requests should indeed indicate that a device is asking for a confirmation.
After the user hits CTA button “Create PIN” we need to show confirmation prompt. It is handled by checking `device.buttonRequests` to see if there is `ButtonRequest_Other` (T1) or `ButtonRequest_ProtectCall` (TT/T2B1). Yes, it is hacky. But thanks to clearing `buttonRequests` array in each step of the onboarding it should be safe and presence of these requests should indeed indicate that a device is asking for a confirmation.
When the user hits cancel on a device, `@SUITE/lock-device` is fired, `buttonRequestsMiddleware` will intercept it and fire `removeButtonRequests` action which clears the array resulting in cancelling confirmation prompt in the Onboarding UI.
@@ -276,7 +276,7 @@ After the user confirms setting new PIN on the device we'll receive `UI.REQUEST_
The user enters PIN twice, if there is a mismatch, process is stopped and an error shown with a button to try again.
#### TT/TR
#### TT/T2B1
The entire process is done on device (including handling of mismatched pins). All we need to do in Suite UI is to show generic "Confirm on your Trezor" bubble.

View File

@@ -27,7 +27,7 @@ export default {
},
tests: [
{
description: 'TT/TR features',
description: 'TT/T2B1 features',
skip: ['1'],
params: {},
result: {

View File

@@ -3,7 +3,7 @@ import { PartialDevice } from './types';
export enum DeviceModel {
T1 = '1',
TT = 'T',
TR = 'R',
T2B1 = 'R',
UNKNOWN = '',
}
@@ -23,7 +23,7 @@ export const pickByDeviceModel = <Type>(
default: Type;
[DeviceModel.T1]?: Type;
[DeviceModel.TT]?: Type;
[DeviceModel.TR]?: Type;
[DeviceModel.T2B1]?: Type;
},
): Type => {
if (!deviceModel || typeof options[deviceModel] === 'undefined') {

View File

@@ -170,7 +170,7 @@
"model": {
"title": "Model",
"type": "string",
"enum": ["T", "1", "R"]
"enum": ["T", "1", "T2B1"]
},
"firmwareRevision": {
"title": "Firmware Revision",

View File

@@ -24,7 +24,7 @@ const acceptAnalyticsConsentOnInitializedDevice = () => {
describe('Onboarding - analytics consent', () => {
const startEmuOpts = {
url: 'https://gitlab.com/satoshilabs/trezor/trezor-firmware/-/jobs/3104755066/artifacts/raw/core/build/unix/trezor-emu-core',
model: DeviceModel.TR,
model: DeviceModel.T2B1,
wipe: true,
};
@@ -53,7 +53,7 @@ describe('Onboarding - analytics consent', () => {
cy.getTestElement('@onboarding-layout/body').should('be.visible');
});
it('shows analytics consent when going to settings and back on non-initialized TR device', () => {
it('shows analytics consent when going to settings and back on non-initialized T2B1 device', () => {
cy.task('startEmuFromUrl', startEmuOpts);
cy.prefixedVisit('/');
@@ -91,7 +91,7 @@ describe('Onboarding - analytics consent', () => {
cy.getTestElement('@settings/menu/close').should('be.visible');
});
it('shows analytics consent when going to settings and back on initialized TR device', () => {
it('shows analytics consent when going to settings and back on initialized T2B1 device', () => {
cy.task('startEmuFromUrl', startEmuOpts);
cy.task('setupEmu', {
needs_backup: false,
@@ -131,7 +131,7 @@ describe('Onboarding - analytics consent', () => {
cy.getTestElement('@wallet/menu/wallet-send');
});
it('shows analytics consent and then goes to /accounts on initialized TR device', () => {
it('shows analytics consent and then goes to /accounts on initialized T2B1 device', () => {
cy.task('startEmuFromUrl', startEmuOpts);
cy.task('setupEmu', {
needs_backup: false,

View File

@@ -10,10 +10,10 @@
import { DeviceModel } from '@trezor/device-utils';
describe('TR - Device settings', () => {
describe('T2B1 - Device settings', () => {
const startEmuOpts = {
url: 'https://gitlab.com/satoshilabs/trezor/trezor-firmware/-/jobs/3104755066/artifacts/raw/core/build/unix/trezor-emu-core',
model: DeviceModel.TR,
model: DeviceModel.T2B1,
wipe: true,
};

View File

@@ -178,7 +178,7 @@ const ReconnectLabel = ({
const switchToNormalModeMessage = pickByDeviceModel(deviceModel, {
default: 'FIRMWARE_CONNECT_IN_NORMAL_MODEL_NO_BUTTON',
[DeviceModel.TR]: 'FIRMWARE_CONNECT_IN_NORMAL_MODEL_NO_TOUCH',
[DeviceModel.T2B1]: 'FIRMWARE_CONNECT_IN_NORMAL_MODEL_NO_TOUCH',
} as const);
return <Translation id={switchToNormalModeMessage} />;

View File

@@ -71,7 +71,7 @@ export const HomescreenGallery = ({ onConfirm }: HomescreenGalleryProps) => {
return (
<Wrapper>
{[DeviceModel.T1, DeviceModel.TR].includes(deviceModel) && (
{[DeviceModel.T1, DeviceModel.T2B1].includes(deviceModel) && (
<BackgroundGalleryWrapper64x128>
{homescreensBW64x128.map(image => (
<BackgroundImageBW64x128

View File

@@ -52,8 +52,8 @@ interface CriticalCoinjoinPhaseProps {
}
export const CriticalCoinjoinPhase = ({ relatedAccountKey }: CriticalCoinjoinPhaseProps) => {
// coinjoin available only on T and R
const deviceModel = useDeviceModel() as DeviceModel.TR | DeviceModel.TT;
// coinjoin available only on T and T2B1
const deviceModel = useDeviceModel() as DeviceModel.T2B1 | DeviceModel.TT;
const relatedCoinjoinAccount = useSelector(state =>
selectCoinjoinAccountByKey(state, relatedAccountKey),
);

View File

@@ -3,6 +3,7 @@ import React from 'react';
import { Modal, Translation } from '@suite-components';
import styled from 'styled-components';
import type { Deferred } from '@trezor/utils';
import { DeviceModel } from '@trezor/device-utils';
const ContentWrapper = styled.div`
text-align: left;

View File

@@ -8,5 +8,5 @@ export const DEFAULT_SKIP_BACKUP = true;
export const DEFAULT_STRENGTH = {
[DeviceModel.T1]: 256,
[DeviceModel.TT]: 128,
[DeviceModel.TR]: 128,
[DeviceModel.T2B1]: 128,
};

View File

@@ -40,7 +40,7 @@ export type FirmwareStatus =
| 'waiting-for-confirmation' // progress - device waits for confirmation prior starting to update
| 'installing' // progress - firmware is being installed
| 'partially-done' // progress - some old T1 firmwares can't update to the latest version. This should be handled by intermediary fw now and it shouldn't even be triggered in real world, but just to be safe let's keep it.
| 'wait-for-reboot' // progress - models TT and TR are restarting after firmware update
| 'wait-for-reboot' // progress - models TT and T2B1 are restarting after firmware update
| 'unplug' // progress - user is asked to reconnect device (T1)
| 'reconnect-in-normal' // progress - after unplugging device from previous step, user is asked to connect it again
| 'validation' // firmware validation in progress

View File

@@ -59,7 +59,7 @@ const FORMAT_MAP: { [format in FirmwareFormat]: ReturnType<typeof getDeviceModel
[FirmwareFormat.T1]: [DeviceModel.T1],
[FirmwareFormat.T1_EMBEDDED_V2]: [DeviceModel.T1],
[FirmwareFormat.T1_V2]: [DeviceModel.T1],
[FirmwareFormat.T2]: [DeviceModel.TT, DeviceModel.TR],
[FirmwareFormat.T2]: [DeviceModel.TT, DeviceModel.T2B1],
};
export const parseFirmwareFormat = (fw: ArrayBuffer): FirmwareFormat | undefined => {

View File

@@ -553,7 +553,7 @@ const getChangelogUrl = [
device: {
...SUITE_DEVICE,
features: {
model: DeviceModel.TR,
model: DeviceModel.T2B1,
},
} as TrezorDevice,
revision: 'ab12cd',
@@ -592,10 +592,10 @@ const getCheckBackupUrl = [
device: {
...SUITE_DEVICE,
features: {
model: DeviceModel.TR,
model: DeviceModel.T2B1,
},
} as TrezorDevice,
result: URLS[`HELP_CENTER_DRY_RUN_T${DeviceModel.TR}_URL`],
result: URLS[`HELP_CENTER_DRY_RUN_T${DeviceModel.T2B1}_URL`],
},
];
@@ -610,10 +610,10 @@ const getPackagingUrl = [
device: {
...SUITE_DEVICE,
features: {
model: DeviceModel.TR,
model: DeviceModel.T2B1,
},
} as TrezorDevice,
result: URLS[`HELP_CENTER_PACKAGING_T${DeviceModel.TR}_URL`],
result: URLS[`HELP_CENTER_PACKAGING_T${DeviceModel.T2B1}_URL`],
},
];
@@ -628,10 +628,10 @@ const getFirmwareDowngradeUrl = [
device: {
...SUITE_DEVICE,
features: {
model: DeviceModel.TR,
model: DeviceModel.T2B1,
},
} as TrezorDevice,
result: URLS[`HELP_CENTER_FW_DOWNGRADE_T${DeviceModel.TR}_URL`],
result: URLS[`HELP_CENTER_FW_DOWNGRADE_T${DeviceModel.T2B1}_URL`],
},
];

View File

@@ -1171,7 +1171,7 @@ export const validateDeviceCompatibility = [
description: 'validateDeviceCompatibility case 24',
deviceConditions: [
{
model: DeviceModel.TR,
model: DeviceModel.T2B1,
firmware: '2.6.0',
bootloader: '2.1.5',
firmwareRevision: '*',
@@ -1183,7 +1183,7 @@ export const validateDeviceCompatibility = [
features: {
...getDeviceFeatures({
vendor: 'trezor.io',
model: DeviceModel.TR,
model: DeviceModel.T2B1,
major_version: 2,
minor_version: 1,
patch_version: 5,
@@ -1201,7 +1201,7 @@ export const validateDeviceCompatibility = [
description: 'validateDeviceCompatibility case 25',
deviceConditions: [
{
model: DeviceModel.TR,
model: DeviceModel.T2B1,
firmware: '2',
bootloader: '*',
firmwareRevision: '123456',
@@ -1213,7 +1213,7 @@ export const validateDeviceCompatibility = [
features: {
...getDeviceFeatures({
vendor: 'trezor.io',
model: DeviceModel.TR,
model: DeviceModel.T2B1,
major_version: 2,
minor_version: 6,
patch_version: 0,

View File

@@ -119,7 +119,7 @@ describe('homescreen', () => {
describe('isValidImageSize', () => {
it('should return true for non-TT device models', () => {
const file = new File([], 'test.png', { type: 'image/png', lastModified: 0 });
expect(isValidImageSize(file, DeviceModel.TR)).toBe(true);
expect(isValidImageSize(file, DeviceModel.T2B1)).toBe(true);
expect(isValidImageSize(file, DeviceModel.T1)).toBe(true);
});

View File

@@ -5,7 +5,7 @@ import { DeviceModel, getDeviceModel } from '@trezor/device-utils';
export const deviceModelInformation = {
[DeviceModel.T1]: { width: 128, height: 64, supports: ['png', 'jpeg'] },
[DeviceModel.TT]: { width: 240, height: 240, supports: ['jpeg'] },
[DeviceModel.TR]: { width: 128, height: 64, supports: ['png', 'jpeg'] },
[DeviceModel.T2B1]: { width: 128, height: 64, supports: ['png', 'jpeg'] },
[DeviceModel.UNKNOWN]: { width: 0, height: 0, supports: [] as string[] },
};
@@ -147,7 +147,7 @@ export const isValidImageSize = (file: File, deviceModel: DeviceModel) => {
export const validateImageColors = (origImage: HTMLImageElement, deviceModel: DeviceModel) => {
const imageData = imageToImageData(origImage, deviceModel);
if ([DeviceModel.T1, DeviceModel.TR].includes(deviceModel)) {
if ([DeviceModel.T1, DeviceModel.T2B1].includes(deviceModel)) {
try {
range(imageData.height).forEach((j: number) => {
range(imageData.width).forEach(i => {

View File

@@ -61,7 +61,7 @@ const SetPinStep = () => {
const showPinMismatch =
modal.context === '@modal/context-user' && modal.payload.type === 'pin-mismatch'; // Set to true by T1 when user fails to enter same pin, not used at all with TT
// First button request that will pop out of the device is "ButtonRequest_ProtectCall" (T1) or "ButtonRequest_Other" (TT/TR), requesting us to confirm enabling PIN
// First button request that will pop out of the device is "ButtonRequest_ProtectCall" (T1) or "ButtonRequest_Other" (TT/T2B1), requesting us to confirm enabling PIN
// buttonRequests will be cleared on cancelling the confirmation prompt on the device, turning this condition to false.
const showConfirmationPrompt = device.buttonRequests.find(
b => b.code === 'ButtonRequest_Other' || b.code === 'ButtonRequest_ProtectCall',

View File

@@ -44,9 +44,9 @@ export const RecoveryStep = () => {
if (status === 'initial') {
// 1. step where users chooses number of words in case of T1
// In case of model T and model R show CTA button to start the process
// In case of TT and model T2B1 show CTA button to start the process
if (deviceModel === DeviceModel.T1) {
// Model 1
// T1
return (
<RecoveryStepBox
key={status} // to properly rerender in translation mode
@@ -63,7 +63,7 @@ export const RecoveryStep = () => {
);
}
// Model T and R
// TT and T2B1
return (
<RecoveryStepBox
key={status} // to properly rerender in translation mode
@@ -73,7 +73,7 @@ export const RecoveryStep = () => {
id={pickByDeviceModel(deviceModel, {
default: 'TR_RECOVER_SUBHEADING_TOUCH',
[DeviceModel.TT]: 'TR_RECOVER_SUBHEADING_TOUCH',
[DeviceModel.TR]: 'TR_RECOVER_SUBHEADING_BUTTONS',
[DeviceModel.T2B1]: 'TR_RECOVER_SUBHEADING_BUTTONS',
})}
/>
}
@@ -109,7 +109,7 @@ export const RecoveryStep = () => {
}
if (status === 'waiting-for-confirmation') {
// On model 1 we show confirm bubble only while we wait for confirmation that users wants to start the process
// On T1 we show confirm bubble only while we wait for confirmation that users wants to start the process
return (
<RecoveryStepBox
key={status} // to properly rerender in translation mode
@@ -117,7 +117,7 @@ export const RecoveryStep = () => {
description={pickByDeviceModel(deviceModel, {
default: undefined,
[DeviceModel.TT]: <Translation id="TR_RECOVER_SUBHEADING_TOUCH" />,
[DeviceModel.TR]: <Translation id="TR_RECOVER_SUBHEADING_BUTTONS" />,
[DeviceModel.T2B1]: <Translation id="TR_RECOVER_SUBHEADING_BUTTONS" />,
})}
deviceModel={deviceModel}
isActionAbortable={isActionAbortable}
@@ -150,7 +150,7 @@ export const RecoveryStep = () => {
default: undefined,
[DeviceModel.T1]: getModel1Description(),
[DeviceModel.TT]: <Translation id="TR_RECOVER_SUBHEADING_TOUCH" />,
[DeviceModel.TR]: <Translation id="TR_RECOVER_SUBHEADING_BUTTONS" />,
[DeviceModel.T2B1]: <Translation id="TR_RECOVER_SUBHEADING_BUTTONS" />,
})}
isActionAbortable
>

View File

@@ -169,7 +169,7 @@ export const Recovery = ({ onCancel }: ForegroundAppProps) => {
default: 'TR_SEED_WORDS_ENTER_BUTTONS',
[DeviceModel.T1]: 'TR_SEED_WORDS_ENTER_COMPUTER',
[DeviceModel.TT]: 'TR_SEED_WORDS_ENTER_TOUCHSCREEN',
[DeviceModel.TR]: 'TR_SEED_WORDS_ENTER_BUTTONS',
[DeviceModel.T2B1]: 'TR_SEED_WORDS_ENTER_BUTTONS',
})}
/>
</InstructionStep>

View File

@@ -118,7 +118,7 @@ export const Homescreen = ({ isDeviceLocked }: HomescreenProps) => {
ref={anchorRef}
shouldHighlight={shouldHighlight}
>
{[DeviceModel.T1, DeviceModel.TR].includes(deviceModel) && (
{[DeviceModel.T1, DeviceModel.T2B1].includes(deviceModel) && (
<TextColumn
title={<Translation id="TR_DEVICE_SETTINGS_HOMESCREEN_TITLE" />}
description={

View File

@@ -17,7 +17,7 @@ const Redelegate = () => {
isCurrentPoolOversaturated,
isFetchError,
} = useCardanoStaking();
const deviceModel = useDeviceModel() as DeviceModel.TT | DeviceModel.TR; // only T and R have Capability_Cardano
const deviceModel = useDeviceModel() as DeviceModel.TT | DeviceModel.T2B1; // only T and T2B1 have Capability_Cardano
useEffect(() => {
calculateFeeAndDeposit('delegate');

View File

@@ -41,7 +41,7 @@ const Rewards = (props: { account: Account }) => {
deviceAvailable,
pendingStakeTx,
} = useCardanoStaking();
const deviceModel = useDeviceModel() as DeviceModel.TT | DeviceModel.TR; // only T and R have Capability_Cardano
const deviceModel = useDeviceModel() as DeviceModel.TT | DeviceModel.T2B1; // only T and T2B1 have Capability_Cardano
const { account } = props;

View File

@@ -39,7 +39,7 @@ const Delegate = (props: { account: Account }) => {
deviceAvailable,
pendingStakeTx,
} = useCardanoStaking();
const deviceModel = useDeviceModel() as DeviceModel.TT | DeviceModel.TR; // only T and R have Capability_Cardano
const deviceModel = useDeviceModel() as DeviceModel.TT | DeviceModel.T2B1; // only T and T2B1 have Capability_Cardano
const { account } = props;

View File

@@ -11,7 +11,7 @@ const excluded = [
// 503 from CI
URLS.TREZOR_BLOG_URL,
URLS.LTC_ADDRESS_INFO_URL,
// model R urls, they don't exist yet
// T2B1 urls, they don't exist yet
URLS.HELP_CENTER_DRY_RUN_TR_URL,
URLS.HELP_CENTER_PACKAGING_TR_URL,
URLS.HELP_CENTER_FW_DOWNGRADE_TR_URL,