diff --git a/package.json b/package.json index f044185c..50f76b46 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0", "@ledgerhq/hw-transport-node-hid": "^4.13.0", - "@ledgerhq/ledger-core": "2.0.0-rc.1", + "@ledgerhq/ledger-core": "2.0.0-rc.3", "@ledgerhq/live-common": "2.31.0", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/commands/installFinalFirmware.js b/src/commands/installFinalFirmware.js index ff9f677f..921665ea 100644 --- a/src/commands/installFinalFirmware.js +++ b/src/commands/installFinalFirmware.js @@ -8,20 +8,18 @@ import installFinalFirmware from 'helpers/firmware/installFinalFirmware' type Input = { devicePath: string, - firmware: Object, + targetId: string | number, + version: string, } type Result = { - targetId: number | string, - version: string, - final: boolean, - mcu: boolean, + success: boolean, } const cmd: Command = createCommand( 'installFinalFirmware', - ({ devicePath, firmware }) => - fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, firmware))), + ({ devicePath, ...rest }) => + fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, { ...rest }))), ) export default cmd diff --git a/src/commands/libcoreHardReset.js b/src/commands/libcoreHardReset.js index a195d520..e8cad9b4 100644 --- a/src/commands/libcoreHardReset.js +++ b/src/commands/libcoreHardReset.js @@ -1,20 +1,21 @@ // @flow import { createCommand } from 'helpers/ipc' -import { Observable } from 'rxjs' +import { fromPromise } from 'rxjs/observable/fromPromise' import withLibcore from 'helpers/withLibcore' +import createCustomErrorClass from 'helpers/createCustomErrorClass' + +const HardResetFail = createCustomErrorClass('HardResetFail') const cmd = createCommand('libcoreHardReset', () => - Observable.create(o => { + fromPromise( withLibcore(async core => { - try { - core.getPoolInstance().eraseDataSince(new Date(0)) - o.complete() - } catch (e) { - o.error(e) + const result = await core.getPoolInstance().eraseDataSince(new Date(0)) + if (result !== core.ERROR_CODE.FUTURE_WAS_SUCCESSFULL) { + throw new HardResetFail(`Hard reset fail with ${result} (check core.ERROR_CODE)`) } - }) - }), + }), + ), ) export default cmd diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index ee87e6a6..344f9d2b 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -53,8 +53,9 @@ type Props = { type State = { status: Status, - error: string | null, - appsList: LedgerScriptParams[] | Array<*>, + error: ?Error, + appsList: LedgerScriptParams[], + appsLoaded: boolean, app: string, mode: Mode, } @@ -64,6 +65,7 @@ class AppsList extends PureComponent { status: 'loading', error: null, appsList: [], + appsLoaded: false, app: '', mode: 'home', } @@ -84,7 +86,7 @@ class AppsList extends PureComponent { const appsList = CACHED_APPS || (await listApps.send({ targetId, version }).toPromise()) CACHED_APPS = appsList if (!this._unmounted) { - this.setState({ appsList, status: 'idle' }) + this.setState({ appsList, status: 'idle', appsLoaded: true }) } } catch (err) { this.setState({ status: 'error', error: err.message }) @@ -100,9 +102,9 @@ class AppsList extends PureComponent { } = this.props const data = { app, devicePath, targetId } await installApp.send(data).toPromise() - this.setState({ status: 'success', app: '' }) + this.setState({ status: 'success' }) } catch (err) { - this.setState({ status: 'error', error: err.message, app: '', mode: 'home' }) + this.setState({ status: 'error', error: err, mode: 'home' }) } } @@ -126,7 +128,6 @@ class AppsList extends PureComponent { renderModal = () => { const { t } = this.props const { app, status, error, mode } = this.state - return ( { } renderList() { - const { appsList, status } = this.state - return status === 'idle' ? ( + const { appsList, appsLoaded } = this.state + return appsLoaded ? ( {items => ( diff --git a/src/components/ManagerPage/FinalFirmwareUpdate.js b/src/components/ManagerPage/FirmwareFinalUpdate.js similarity index 58% rename from src/components/ManagerPage/FinalFirmwareUpdate.js rename to src/components/ManagerPage/FirmwareFinalUpdate.js index c8ea6422..7fa1b702 100644 --- a/src/components/ManagerPage/FinalFirmwareUpdate.js +++ b/src/components/ManagerPage/FirmwareFinalUpdate.js @@ -2,8 +2,12 @@ import React, { PureComponent } from 'react' import { translate } from 'react-i18next' +import logger from 'logger' + import type { Device, T } from 'types/common' +import installFinalFirmware from 'commands/installFinalFirmware' + import Box, { Card } from 'components/base/Box' // import Button from 'components/base/Button' @@ -18,15 +22,9 @@ type Props = { infos: DeviceInfos, } -type State = { - // latestFirmware: ?FirmwareInfos, -} - -class FirmwareUpdate extends PureComponent { - state = { - // latestFirmware: null, - } +type State = {} +class FirmwareFinalUpdate extends PureComponent { componentDidMount() {} componentWillUnmount() { @@ -35,6 +33,20 @@ class FirmwareUpdate extends PureComponent { _unmounting = false + installFinalFirmware = async () => { + try { + const { device, infos } = this.props + const { success } = await installFinalFirmware + .send({ devicePath: device.path, targetId: infos.targetId, version: infos.version }) + .toPromise() + if (success) { + this.setState() + } + } catch (err) { + logger.log(err) + } + } + render() { const { t, ...props } = this.props @@ -51,4 +63,4 @@ class FirmwareUpdate extends PureComponent { } } -export default translate()(FirmwareUpdate) +export default translate()(FirmwareFinalUpdate) diff --git a/src/components/ManagerPage/FirmwareUpdate.js b/src/components/ManagerPage/FirmwareUpdate.js index a9ab1e2f..b1f80c93 100644 --- a/src/components/ManagerPage/FirmwareUpdate.js +++ b/src/components/ManagerPage/FirmwareUpdate.js @@ -1,8 +1,8 @@ // @flow /* eslint-disable react/jsx-no-literals */ // FIXME -import React, { PureComponent } from 'react' -import { translate } from 'react-i18next' +import React, { PureComponent, Fragment } from 'react' +import { translate, Trans } from 'react-i18next' import isEqual from 'lodash/isEqual' import isEmpty from 'lodash/isEmpty' import invariant from 'invariant' @@ -17,19 +17,28 @@ import installOsuFirmware from 'commands/installOsuFirmware' import Box, { Card } from 'components/base/Box' import Text from 'components/base/Text' +import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal' +import Button from 'components/base/Button' +// import Progress from 'components/base/Progress' import NanoS from 'icons/device/NanoS' import CheckFull from 'icons/CheckFull' +import { PreventDeviceChangeRecheck } from '../Workflow/EnsureDevice' import UpdateFirmwareButton from './UpdateFirmwareButton' let CACHED_LATEST_FIRMWARE = null +export const getCleanVersion = (input: string): string => + input.endsWith('-osu') ? input.replace('-osu', '') : input + type DeviceInfos = { targetId: number | string, version: string, } +type ModalStatus = 'closed' | 'disclaimer' | 'installing' | 'error' | 'success' + type Props = { t: T, device: Device, @@ -38,11 +47,13 @@ type Props = { type State = { latestFirmware: ?LedgerScriptParams, + modal: ModalStatus, } class FirmwareUpdate extends PureComponent { state = { latestFirmware: null, + modal: 'closed', } componentDidMount() { @@ -86,6 +97,7 @@ class FirmwareUpdate extends PureComponent { const { device: { path: devicePath }, } = this.props + this.setState({ modal: 'installing' }) const { success } = await installOsuFirmware .send({ devicePath, firmware: latestFirmware, targetId: infos.targetId }) .toPromise() @@ -97,9 +109,49 @@ class FirmwareUpdate extends PureComponent { } } + handleCloseModal = () => this.setState({ modal: 'closed' }) + + handleInstallModal = () => this.setState({ modal: 'disclaimer' }) + + renderModal = () => { + const { t } = this.props + const { modal, latestFirmware } = this.state + return ( + ( + + + {t('app:manager.firmware.update')} + + + + You are about to install the latest + + {`firmware ${latestFirmware ? getCleanVersion(latestFirmware.name) : ''}`} + + + + + {t('app:manager.firmware.disclaimerAppDelete')} + {t('app:manager.firmware.disclaimerAppReinstall')} + + + + + + + + )} + /> + ) + } + render() { const { infos, t } = this.props - const { latestFirmware } = this.state + const { latestFirmware, modal } = this.state return ( @@ -122,8 +174,13 @@ class FirmwareUpdate extends PureComponent { })} - + + {modal !== 'closed' ? : null} + {this.renderModal()} ) } diff --git a/src/components/ManagerPage/UpdateFirmwareButton.js b/src/components/ManagerPage/UpdateFirmwareButton.js index f5b4c562..6f9cedcb 100644 --- a/src/components/ManagerPage/UpdateFirmwareButton.js +++ b/src/components/ManagerPage/UpdateFirmwareButton.js @@ -6,6 +6,7 @@ import type { T } from 'types/common' import Button from 'components/base/Button' import Text from 'components/base/Text' +import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate' type FirmwareInfos = { name: string, @@ -18,9 +19,6 @@ type Props = { installFirmware: () => void, } -const getCleanVersion = (input: string): string => - input.endsWith('-osu') ? input.replace('-osu', '') : input - const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) => firmware ? ( diff --git a/src/components/ManagerPage/index.js b/src/components/ManagerPage/index.js index 11209e93..d7399013 100644 --- a/src/components/ManagerPage/index.js +++ b/src/components/ManagerPage/index.js @@ -1,9 +1,8 @@ // @flow -/* eslint-disable react/jsx-no-literals */ // FIXME +/* eslint-disable react/jsx-no-literals */ // FIXME: remove -import React from 'react' +import React, { PureComponent } from 'react' -import type { Node } from 'react' import type { Device } from 'types/common' import Workflow from 'components/Workflow' @@ -23,36 +22,38 @@ type Error = { stack: string, } -function ManagerPage(): Node { - return ( - ( -

UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.final}

- )} - renderMcuUpdate={(device: Device, deviceInfo: DeviceInfo) => ( - - )} - renderDashboard={(device: Device, deviceInfo: DeviceInfo) => ( - - )} - renderDefault={( - device: ?Device, - deviceInfo: ?DeviceInfo, - isGenuine: ?boolean, - errors: { - dashboardError: ?Error, - genuineError: ?Error, - }, - ) => ( - - )} - /> - ) +class ManagerPage extends PureComponent<*, *> { + render() { + return ( + ( +

UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.final}

+ )} + renderMcuUpdate={(device: Device, deviceInfo: DeviceInfo) => ( + + )} + renderDashboard={(device: Device, deviceInfo: DeviceInfo) => ( + + )} + renderDefault={( + device: ?Device, + deviceInfo: ?DeviceInfo, + isGenuine: ?boolean, + errors: { + dashboardError: ?Error, + genuineError: ?Error, + }, + ) => ( + + )} + /> + ) + } } export default ManagerPage diff --git a/src/components/Workflow/EnsureDevice.js b/src/components/Workflow/EnsureDevice.js index 3327c781..bf0a5f6d 100644 --- a/src/components/Workflow/EnsureDevice.js +++ b/src/components/Workflow/EnsureDevice.js @@ -1,5 +1,7 @@ // @flow -import { PureComponent } from 'react' +/* eslint-disable react/no-multi-comp */ + +import { Component, PureComponent } from 'react' import { connect } from 'react-redux' import type { Node } from 'react' @@ -12,9 +14,24 @@ type Props = { children: (device: Device) => Node, } -type State = {} +let prevents = 0 +export class PreventDeviceChangeRecheck extends PureComponent<{}> { + componentDidMount() { + prevents++ + } + componentWillUnmount() { + prevents-- + } + render() { + return null + } +} -class EnsureDevice extends PureComponent { +class EnsureDevice extends Component { + shouldComponentUpdate(nextProps) { + if (prevents > 0) return false + return nextProps.device !== this.props.device + } render() { const { device, children } = this.props return children(device) diff --git a/src/components/modals/AddAccounts/steps/02-step-connect-device.js b/src/components/modals/AddAccounts/steps/02-step-connect-device.js index d4e210c4..5f799258 100644 --- a/src/components/modals/AddAccounts/steps/02-step-connect-device.js +++ b/src/components/modals/AddAccounts/steps/02-step-connect-device.js @@ -20,11 +20,11 @@ function StepConnectDevice({ t, currency, currentDevice, setState }: StepProps) - {`You're about to import your `} + {`Follow the steps below to add `} {`${currency.name} (${ currency.ticker })`} - {` account(s) from your Ledger device. Please follow the steps below:`} + {` account(s) from your Ledger device.`} diff --git a/src/helpers/devices/getOsuFirmware.js b/src/helpers/devices/getOsuFirmware.js new file mode 100644 index 00000000..8ee45576 --- /dev/null +++ b/src/helpers/devices/getOsuFirmware.js @@ -0,0 +1,26 @@ +// @flow +import axios from 'axios' + +import { GET_CURRENT_OSU } from 'helpers/urls' + +type Input = { + version: string, + deviceId: string | number, +} + +let error +export default async (input: Input): Promise<*> => { + try { + const provider = 1 + const { data } = await axios.post(GET_CURRENT_OSU, { + device_version: input.deviceId, + version_name: input.version, + provider, + }) + return data + } catch (err) { + error = Error(err.message) + error.stack = err.stack + throw error + } +} diff --git a/src/helpers/firmware/getFinalFirmwareById.js b/src/helpers/firmware/getFinalFirmwareById.js new file mode 100644 index 00000000..ec73461f --- /dev/null +++ b/src/helpers/firmware/getFinalFirmwareById.js @@ -0,0 +1,15 @@ +// @flow +import axios from 'axios' + +import { GET_FINAL_FIRMWARE } from 'helpers/urls' + +export default async (id: number) => { + try { + const { data } = await axios.get(`${GET_FINAL_FIRMWARE}/${id}`) + return data + } catch (err) { + const error = Error(err.message) + error.stack = err.stack + throw err + } +} diff --git a/src/helpers/firmware/installFinalFirmware.js b/src/helpers/firmware/installFinalFirmware.js index d57b0739..365a37d6 100644 --- a/src/helpers/firmware/installFinalFirmware.js +++ b/src/helpers/firmware/installFinalFirmware.js @@ -3,13 +3,31 @@ import type Transport from '@ledgerhq/hw-transport' import { WS_INSTALL } from 'helpers/urls' import { createDeviceSocket } from 'helpers/socket' +import getDeviceVersion from 'helpers/devices/getDeviceVersion' +import getOsuFirmware from 'helpers/devices/getOsuFirmware' +import getFinalFirmwareById from './getFinalFirmwareById' -type Input = Object +type Input = { + targetId: number | string, + version: string, +} type Result = * -export default async (transport: Transport<*>, firmware: Input): Result => { +export default async (transport: Transport<*>, app: Input): Result => { try { - const url = WS_INSTALL(firmware) + const { targetId, version } = app + const device = await getDeviceVersion(targetId) + const firmware = await getOsuFirmware({ deviceId: device.id, version }) + const { next_se_firmware_final_version } = firmware + const nextFirmware = await getFinalFirmwareById(next_se_firmware_final_version) + + const params = { + targetId, + ...nextFirmware, + firmwareKey: nextFirmware.firmware_key, + } + + const url = WS_INSTALL(params) await createDeviceSocket(transport, url).toPromise() return { success: true } } catch (err) { diff --git a/src/helpers/hardReset.js b/src/helpers/hardReset.js index 24477872..aacbdd87 100644 --- a/src/helpers/hardReset.js +++ b/src/helpers/hardReset.js @@ -5,9 +5,7 @@ import db from 'helpers/db' import { delay } from 'helpers/promise' export default async function hardReset() { - // TODO: wait for the libcoreHardReset to be finished - // actually, libcore doesnt goes back to js thread - await Promise.race([libcoreHardReset.send().toPromise(), delay(500)]) + await libcoreHardReset.send() disableDBMiddleware() db.resetAll() await delay(500) diff --git a/src/helpers/urls.js b/src/helpers/urls.js index a8bc82fb..4cc4b313 100644 --- a/src/helpers/urls.js +++ b/src/helpers/urls.js @@ -14,9 +14,11 @@ const wsURLBuilder = (endpoint: string) => (params?: Object) => // const wsURLBuilderProxy = (endpoint: string) => (params?: Object) => // `ws://manager.ledger.fr:3501/${endpoint}${params ? `?${qs.stringify(params)}` : ''}` +export const GET_FINAL_FIRMWARE: string = managerUrlbuilder('firmware_final_versions') export const GET_DEVICE_VERSION: string = managerUrlbuilder('get_device_version') export const APPLICATIONS_BY_DEVICE: string = managerUrlbuilder('get_apps') export const GET_CURRENT_FIRMWARE: string = managerUrlbuilder('get_firmware_version') +export const GET_CURRENT_OSU: string = managerUrlbuilder('get_osu_version') export const GET_LATEST_FIRMWARE: string = managerUrlbuilder('get_latest_firmware') export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader') diff --git a/static/i18n/en/app.yml b/static/i18n/en/app.yml index 4ef525c4..79b1bacc 100644 --- a/static/i18n/en/app.yml +++ b/static/i18n/en/app.yml @@ -12,7 +12,7 @@ common: currency: Currency selectAccount: Select an account selectAccountNoOption: 'No account matching "{{accountName}}"' - selectCurrency: Select a currency + selectCurrency: Choose a crypto asset selectCurrencyNoOption: 'No currency matching "{{currencyName}}"' selectExchange: Select an exchange selectExchangeNoOption: 'No exchange matching "{{exchangeName}}"' @@ -32,15 +32,15 @@ common: eastern: Eastern western: Western lockScreen: - title: Welcome Back - subTitle: Your application is locked - description: Please enter your password to continue - inputPlaceholder: Type your password + title: Welcome back + subTitle: Ledger Live is locked + description: Enter your password to continue + inputPlaceholder: lostPassword: I lost my password sync: - syncing: Syncing... + syncing: Synchronizing... upToDate: Up to date - error: Sync error. + error: Synchronization error refresh: Refresh ago: Synced {{time}} error: @@ -48,8 +48,12 @@ common: noResults: No results operation: type: - IN: Receive funds - OUT: Sent funds + IN: Received +# conf: Received +# unconf: Receiving... + OUT: Sent +# conf: Sent +# unconf: Sending... time: day: Day week: Week @@ -70,20 +74,20 @@ account: receive: Receive lastOperations: Last operations emptyState: - title: This is a title, use it with caution - desc: Please create a new account or recover an old account from your Ledger device. + title: No funds yet? + desc: Receive funds in this account by using your Ledger device with the [cryptocurrency] app installed. # replace [cryptocurrency] and make it bold buttons: receiveFunds: Receive Funds settings: - title: Edit Account + title: Edit account advancedLogs: Advanced logs accountName: title: Account name - desc: Lorem ipsum dolort amet - error: Name is required + desc: Describe this account. + error: An account name is required. unit: title: Unit - desc: Lorem ipsum dolort amet + desc: Choose the unit to display. endpointConfig: title: Node desc: The API node to use @@ -93,17 +97,17 @@ dashboard: accounts: title: Accounts ({{count}}) greeting: - morning: "Good Morning!" - evening: "Good Evening!" - afternoon: "Good Afternoon!" - summary: here is the summary of your account - summary_plural: 'here is the summary of your {{count}} accounts' - noAccounts: no accounts + morning: "Good morning" + evening: "Good evening" + afternoon: "Good afternoon" + summary: "Here's the summary of your account." + summary_plural: "Here's the summary of your {{count}} accounts." + noAccounts: No accounts yet recentActivity: Recent activity totalBalance: Total balance accountsOrder: - name: Alphabetic - balance: Balance + name: name + balance: balance currentAddress: title: Current address for: Address for <1><0>{{accountName}} @@ -112,16 +116,16 @@ deviceConnect: step1: choose: "We detected {{count}} devices connected, please select one:" connect: Connect and unlock your <1>Ledger device # remove key: <3>PIN code - dashboard: + dashboard: test emptyState: sidebar: - text: You don’t have any accounts at the moment. Press the + button to create an account + text: Press the + button to add an account to your portfolio. dashboard: - title: This is a title, use it with caution - desc: Please create a new account or recover an old account from your Ledger device. + title: 'Let’s set up your portfolio!' + desc: Open the Manager to install apps on your device or add accounts if your device already has apps installed. buttons: - addAccount: Add Account - installApp: Install App + addAccount: Add accounts + installApp: Open Manager exchange: title: Exchange visitWebsite: Visit website @@ -134,28 +138,28 @@ genuinecheck: addAccounts: title: Add accounts breadcrumb: - informations: Informations + informations: Choose asset connectDevice: Connect device - import: Import - finish: End - accountToImportSubtitle: Account to import - accountToImportSubtitle_plural: 'Accounts to import ({{count}})' + import: Select accounts + finish: Confirmation + accountToImportSubtitle: Select existing accounts + accountToImportSubtitle_plural: 'Select ({{count}}) existing accounts' selectAll: Select all - unselectAll: Unselect all + unselectAll: Deselect all editName: Edit name newAccount: New account legacyAccount: '{{accountName}} (legacy)' - noAccountToImport: We didnt find any {{currencyName}} account to import. - success: Great success! + noAccountToImport: No {{currencyName}} account was found. + success: Accounts have been added to your portfolio. createNewAccount: title: Create new account - noOperationOnLastAccount: You cannot create a new account because your last account has no operations - noAccountToCreate: We didnt find any {{currencyName}} account to create. - somethingWentWrong: Something went wrong during synchronization. + noOperationOnLastAccount: Receive funds on your previous account before creating a new one. + noAccountToCreate: No {{currencyName}} account was found to create. + somethingWentWrong: Something went wrong during synchronization, please try again. cta: - create: 'Create account' - import: 'Import account' - import_plural: 'Import accounts' + create: 'Add account' + import: 'Add account' # Remove + import_plural: 'Add accounts' operationDetails: title: Operation details account: Account @@ -166,12 +170,12 @@ operationDetails: fees: Fees from: From to: To - identifier: Hash - viewOperation: View operation + identifier: Transaction ID + viewOperation: View in explorer showMore: Show {{recipients}} more showLess: Show less operationList: - noMoreOperations: No more operations + noMoreOperations: That's all! manager: tabs: apps: Apps @@ -189,28 +193,32 @@ manager: installed: 'Firmware {{version}}' update: Update firmware updateTitle: Firmware update + continue: Continue update latest: 'A new firmware {{version}} is available' + disclaimerTitle: 'You are about to install the latest <1><0>firmware {{version}}' + disclaimerAppDelete: Please note that all the apps installed on your device will be deleted. + disclaimerAppReinstall: You will be able to re-install your apps after the firmware update title: Manager subtitle: Get all your apps here device: - title: Plug your device - desc: Please connect your Ledger device and follow the steps below to access the manager - cta: Plug my device + title: Connect your device + desc: Follow the steps below to connect your device + cta: Connect my device errors: - noDevice: Please make sur your device is connected (TEMPLATE NEEDED) - noDashboard: Please make sure your device is on the dashboard screen (TEMPLATED NEEDED) - noGenuine: You did not approve request on your device or your device is not genuine (TEMPLATE NEEDED) + noDevice: No device is connected (TEMPLATE NEEDED) + noDashboard: Navigate to the dashboard on your device (TEMPLATED NEEDED) + noGenuine: Allow the Manager to continue (TEMPLATE NEEDED) receive: title: Receive funds steps: chooseAccount: - title: Choose Account + title: Choose account label: Account connectDevice: - title: Connect Device + title: Connect device withoutDevice: I don't have my device confirmAddress: - title: Confirm Address + title: Confirm address action: Confirm address on device text: To receive funds, confirm the address on your device. support: Contact Support @@ -244,7 +252,7 @@ send: title: Verification warning: | You are about to validate a transaction. - Be careful, we strongly recommand you to verify that the informations on your Ledger device are correct. + Be careful, we strongly recommend you to verify that the informations on your Ledger device are correct. body: Once you have checked everything is ok, you can validate securely the transaction on your device. confirmation: title: Confirmation @@ -267,73 +275,73 @@ settings: display: Display currencies: Currencies profile: Profile - about: About + about: Help display: - desc: Lorem ipsum dolor sit amet - language: Interface language - languageDesc: Lorem ipsum dolor sit amet - counterValue: Countervalue - counterValueDesc: Lorem ipsum dolor sit amet - exchange: Exchange ({{ticker}}) - exchangeDesc: The exchange to use for countervalue conversion + desc: + language: Language + languageDesc: Choose the language to display. + counterValue: Base currency + counterValueDesc: Choose the currency to display next to your balance and operations. + exchange: Rate provider ({{ticker}}) + exchangeDesc: Choose the provider of the base currency exchange rates. region: Region - regionDesc: Lorem ipsum dolor sit amet - stock: Stock market indicators - stockDesc: Lorem ipsum dolor sit amet + regionDesc: Choose the region in which you’re located to set the application’s time zone. + stock: Regional market indicator + stockDesc: Choose Western to display an increase in market value in blue. Choose Eastern to display an increase in market value in red. currencies: - desc: Lorem ipsum dolor sit amet - exchange: Exchange ({{ticker}}) - exchangeDesc: The exchange to use for countervalue conversion - confirmationsToSpend: Confirmations to spend - confirmationsToSpendDesc: Lorem ipsum dolor sit amet + desc: Select a cryptocurrency to edit its settings + exchange: Rate provider ({{ticker}}) + exchangeDesc: Choose the provider of the base currency exchange rates. + confirmationsToSpend: Number of confirmations required to spend + confirmationsToSpendDesc: Select the number of confirmations required for your funds to be spendable. # A higher number of confirmations decreases the probability that a transaction is rejected. confirmationsNb: Number of confirmations - confirmationsNbDesc: Lorem ipsum dolor sit amet - transactionsFees: Transactions fees - transactionsFeesDesc: Lorem ipsum dolor sit amet + confirmationsNbDesc: Select the number of blocks a transaction needs to be included in to consider it as confirmed. # A higher number of confirmations increases the certainty that a transaction cannot be reversed. + transactionsFees: Default transaction fees + transactionsFeesDesc: Select your default transaction fees. The higher the fee, the quicker the transaction will be processed. explorer: Blockchain explorer - explorerDesc: Lorem ipsum dolor sit amet + explorerDesc: Which service to use to look up an operation in the blockchain. profile: - desc: Lorem ipsum dolor sit amet - password: Password - passwordDesc: Lorem ipsum dolor sit amet + desc: + password: Data encryption + passwordDesc: Enhance your privacy. Set a password to encrypt Ledger Live data stored on your computer, including account names, balances, transactions and public addresses. changePassword: Change password - sync: Sync accounts - syncDesc: Lorem ipsum dolor sit amet + sync: Synchronize accounts + syncDesc: Resynchronize your accounts with the blockchain. export: Export logs - exportDesc: Lorem ipsum dolor sit amet - softResetTitle: Clean application cache - softResetDesc: Lorem ipsum dolor sit amet - softReset: Clean cache - hardResetTitle: Reset application - hardResetDesc: Lorem ipsum dolor sit amet - hardReset: Hard reset - developerMode: Developer Mode - developerModeDesc: Enable visibility of developer apps & currencies like Bitcoin Testnet - analytics: Share analytics - analyticsDesc: Help Ledger improve its products and services by automatically sending diagnostics and usage data. - reportErrors: Sentry Logs - reportErrorsDesc: Help Ledger improve its products and services by automatically sending diagnostics and usage data. + exportDesc: Exporting Ledger Live logs may be necessary for troubleshooting purposes. + softResetTitle: Clear cache + softResetDesc: Clear the Ledger Live cache to force resynchronization with the blockchain. + softReset: Clear + hardResetTitle: Reset Ledger Live + hardResetDesc: Erase all Ledger Live data stored on your computer, including your profile, accounts, transaction history and settings. The private keys that manage your crypto assets remain secure on your Ledger device. + hardReset: Reset + developerMode: Developer mode + developerModeDesc: Show developer apps in the Manager. + analytics: Analytics + analyticsDesc: Enable analytics of anonymous data to help Ledger improve the user experience. This includes the operating system, language, firmware versions and the number of added accounts. + reportErrors: Usage and diagnostics + reportErrorsDesc: Share anonymous usage and diagnostics data to help improve Ledger products, services and security features. about: - desc: Lorem ipsum dolor sit amet - version: Version - releaseNotesBtn: Show release notes - faq: FAQ - faqDesc: Lorem ipsum dolor sit amet + desc: + version: Ledger Live version + releaseNotesBtn: Show release notes # Close button instead of continue. + faq: Ledger Support + faqDesc: A problem? Learn about Ledger Live, Ledger devices, supported crypto assets and apps. contactUs: Contact us - contactUsDesc: Lorem ipsum dolor sit amet - terms: Terms and Privacy policy - termsDesc: Lorem ipsum dolor sit amet + contactUsDesc: Need help? Request assistance from Ledger Support by email or chat. + terms: --- Terms and Privacy policy --- + termsDesc: --- Check with Legal --- hardResetModal: title: Reset Ledger Live desc: Resetting will erase all Ledger Live data stored on your computer, including your profile, accounts, transaction history and application settings. The keys to access your crypto assets in the blockchain remain secure on your Ledger device. softResetModal: - title: Clean application cache - subTitle: Are you sure houston? - desc: Lorem ipsum dolor sit amet + title: Clear cache + subTitle: Are you sure? + desc: Clearing the Ledger Live cache forces resynchronization with the blockchain. removeAccountModal: - title: Delete this account - subTitle: Are you sure houston? - desc: Lorem ipsum dolor sit amet + title: Remove account + subTitle: Are you sure? + desc: The account will no longer be included in your portfolio. Accounts can always be re-added. exportLogs: title: Export Logs desc: Export Logs @@ -349,32 +357,32 @@ password: inputFields: newPassword: label: Password - placeholder: Password + placeholder: confirmPassword: - label: Confirm Password - placeholder: Confirm Password + label: Confirm password + placeholder: currentPassword: - label: Current Password - placeholder: Current Password + label: Current password + placeholder: changePassword: - title: Edit Password + title: Data encryption subTitle: Change your password - desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam. In eget ipsum arcu donec finibus + desc: Make sure to remember your password. Losing your password requires resetting Ledger Live and re-adding accounts. setPassword: - title: Set Password - subTitle: Set a password to lock your application - desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam. In eget ipsum arcu donec finibus + title: Enable data encryption + subTitle: Set a password + desc: Make sure to remember your password. Losing your password requires resetting Ledger Live and re-adding accounts. disablePassword: - title: Disable Password - desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam. + title: Disable data encryption + desc: Ledger Live data will be stored unencrypted on your computer. This includes account names, balances, transactions and public addresses. update: newVersionReady: A new update is available. relaunch: Update now crash: - oops: Oops, something went wrong. + oops: Oops, something went wrong uselessText: You may try again by restarting Ledger Live. Please export your logs and contact Ledger Support if the problem persists. - restart: Restart app + restart: Restart reset: Hard reset - createTicket: Create issue + createTicket: Ledger Support showDetails: Show details showError: Show error diff --git a/static/i18n/en/errors.yml b/static/i18n/en/errors.yml index 108a9402..768cd711 100644 --- a/static/i18n/en/errors.yml +++ b/static/i18n/en/errors.yml @@ -20,3 +20,4 @@ DeviceSocketFail: Device socket failure DeviceSocketNoBulkStatus: Device socket failure (bulk) DeviceSocketNoHandler: Device socket failure (handler {{query}}) LatestMCUInstalledError: The latest MCU is already installed on the Device +HardResetFail: Hard reset failure diff --git a/yarn.lock b/yarn.lock index 7e315c02..6b7bad59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1502,9 +1502,9 @@ dependencies: events "^2.0.0" -"@ledgerhq/ledger-core@2.0.0-rc.1": - version "2.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.1.tgz#0b31f7d2c693b9c11d4093dbb0896f13c33bf141" +"@ledgerhq/ledger-core@2.0.0-rc.3": + version "2.0.0-rc.3" + resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.3.tgz#21b04239e9ba6b7fdcb89958eea8ad47a4a28a88" dependencies: "@ledgerhq/hw-app-btc" "^4.7.3" "@ledgerhq/hw-transport-node-hid" "^4.7.6"