Browse Source

Merge branch 'develop' of github.com:ledgerhq/ledger-live-desktop into fix/circular-ref-error

master
Gaëtan Renaudeau 7 years ago
parent
commit
0be6c0c209
  1. 2
      package.json
  2. 12
      src/commands/installFinalFirmware.js
  3. 17
      src/commands/libcoreHardReset.js
  4. 17
      src/components/ManagerPage/AppsList.js
  5. 30
      src/components/ManagerPage/FirmwareFinalUpdate.js
  6. 65
      src/components/ManagerPage/FirmwareUpdate.js
  7. 4
      src/components/ManagerPage/UpdateFirmwareButton.js
  8. 9
      src/components/ManagerPage/index.js
  9. 23
      src/components/Workflow/EnsureDevice.js
  10. 4
      src/components/modals/AddAccounts/steps/02-step-connect-device.js
  11. 26
      src/helpers/devices/getOsuFirmware.js
  12. 15
      src/helpers/firmware/getFinalFirmwareById.js
  13. 24
      src/helpers/firmware/installFinalFirmware.js
  14. 4
      src/helpers/hardReset.js
  15. 2
      src/helpers/urls.js
  16. 254
      static/i18n/en/app.yml
  17. 1
      static/i18n/en/errors.yml
  18. 6
      yarn.lock

2
package.json

@ -41,7 +41,7 @@
"@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-app-xrp": "^4.13.0",
"@ledgerhq/hw-transport": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0",
"@ledgerhq/hw-transport-node-hid": "^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", "@ledgerhq/live-common": "2.31.0",
"async": "^2.6.1", "async": "^2.6.1",
"axios": "^0.18.0", "axios": "^0.18.0",

12
src/commands/installFinalFirmware.js

@ -8,20 +8,18 @@ import installFinalFirmware from 'helpers/firmware/installFinalFirmware'
type Input = { type Input = {
devicePath: string, devicePath: string,
firmware: Object, targetId: string | number,
version: string,
} }
type Result = { type Result = {
targetId: number | string, success: boolean,
version: string,
final: boolean,
mcu: boolean,
} }
const cmd: Command<Input, Result> = createCommand( const cmd: Command<Input, Result> = createCommand(
'installFinalFirmware', 'installFinalFirmware',
({ devicePath, firmware }) => ({ devicePath, ...rest }) =>
fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, firmware))), fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, { ...rest }))),
) )
export default cmd export default cmd

17
src/commands/libcoreHardReset.js

@ -1,20 +1,21 @@
// @flow // @flow
import { createCommand } from 'helpers/ipc' import { createCommand } from 'helpers/ipc'
import { Observable } from 'rxjs' import { fromPromise } from 'rxjs/observable/fromPromise'
import withLibcore from 'helpers/withLibcore' import withLibcore from 'helpers/withLibcore'
import createCustomErrorClass from 'helpers/createCustomErrorClass'
const HardResetFail = createCustomErrorClass('HardResetFail')
const cmd = createCommand('libcoreHardReset', () => const cmd = createCommand('libcoreHardReset', () =>
Observable.create(o => { fromPromise(
withLibcore(async core => { withLibcore(async core => {
try { const result = await core.getPoolInstance().eraseDataSince(new Date(0))
core.getPoolInstance().eraseDataSince(new Date(0)) if (result !== core.ERROR_CODE.FUTURE_WAS_SUCCESSFULL) {
o.complete() throw new HardResetFail(`Hard reset fail with ${result} (check core.ERROR_CODE)`)
} catch (e) {
o.error(e)
} }
})
}), }),
),
) )
export default cmd export default cmd

17
src/components/ManagerPage/AppsList.js

@ -53,8 +53,9 @@ type Props = {
type State = { type State = {
status: Status, status: Status,
error: string | null, error: ?Error,
appsList: LedgerScriptParams[] | Array<*>, appsList: LedgerScriptParams[],
appsLoaded: boolean,
app: string, app: string,
mode: Mode, mode: Mode,
} }
@ -64,6 +65,7 @@ class AppsList extends PureComponent<Props, State> {
status: 'loading', status: 'loading',
error: null, error: null,
appsList: [], appsList: [],
appsLoaded: false,
app: '', app: '',
mode: 'home', mode: 'home',
} }
@ -84,7 +86,7 @@ class AppsList extends PureComponent<Props, State> {
const appsList = CACHED_APPS || (await listApps.send({ targetId, version }).toPromise()) const appsList = CACHED_APPS || (await listApps.send({ targetId, version }).toPromise())
CACHED_APPS = appsList CACHED_APPS = appsList
if (!this._unmounted) { if (!this._unmounted) {
this.setState({ appsList, status: 'idle' }) this.setState({ appsList, status: 'idle', appsLoaded: true })
} }
} catch (err) { } catch (err) {
this.setState({ status: 'error', error: err.message }) this.setState({ status: 'error', error: err.message })
@ -100,9 +102,9 @@ class AppsList extends PureComponent<Props, State> {
} = this.props } = this.props
const data = { app, devicePath, targetId } const data = { app, devicePath, targetId }
await installApp.send(data).toPromise() await installApp.send(data).toPromise()
this.setState({ status: 'success', app: '' }) this.setState({ status: 'success' })
} catch (err) { } 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<Props, State> {
renderModal = () => { renderModal = () => {
const { t } = this.props const { t } = this.props
const { app, status, error, mode } = this.state const { app, status, error, mode } = this.state
return ( return (
<Modal <Modal
isOpened={status !== 'idle' && status !== 'loading'} isOpened={status !== 'idle' && status !== 'loading'}
@ -175,8 +176,8 @@ class AppsList extends PureComponent<Props, State> {
} }
renderList() { renderList() {
const { appsList, status } = this.state const { appsList, appsLoaded } = this.state
return status === 'idle' ? ( return appsLoaded ? (
<Box> <Box>
<AppSearchBar list={appsList}> <AppSearchBar list={appsList}>
{items => ( {items => (

30
src/components/ManagerPage/FinalFirmwareUpdate.js → src/components/ManagerPage/FirmwareFinalUpdate.js

@ -2,8 +2,12 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
import logger from 'logger'
import type { Device, T } from 'types/common' import type { Device, T } from 'types/common'
import installFinalFirmware from 'commands/installFinalFirmware'
import Box, { Card } from 'components/base/Box' import Box, { Card } from 'components/base/Box'
// import Button from 'components/base/Button' // import Button from 'components/base/Button'
@ -18,15 +22,9 @@ type Props = {
infos: DeviceInfos, infos: DeviceInfos,
} }
type State = { type State = {}
// latestFirmware: ?FirmwareInfos,
}
class FirmwareUpdate extends PureComponent<Props, State> {
state = {
// latestFirmware: null,
}
class FirmwareFinalUpdate extends PureComponent<Props, State> {
componentDidMount() {} componentDidMount() {}
componentWillUnmount() { componentWillUnmount() {
@ -35,6 +33,20 @@ class FirmwareUpdate extends PureComponent<Props, State> {
_unmounting = false _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() { render() {
const { t, ...props } = this.props const { t, ...props } = this.props
@ -51,4 +63,4 @@ class FirmwareUpdate extends PureComponent<Props, State> {
} }
} }
export default translate()(FirmwareUpdate) export default translate()(FirmwareFinalUpdate)

65
src/components/ManagerPage/FirmwareUpdate.js

@ -1,8 +1,8 @@
// @flow // @flow
/* eslint-disable react/jsx-no-literals */ // FIXME /* eslint-disable react/jsx-no-literals */ // FIXME
import React, { PureComponent } from 'react' import React, { PureComponent, Fragment } from 'react'
import { translate } from 'react-i18next' import { translate, Trans } from 'react-i18next'
import isEqual from 'lodash/isEqual' import isEqual from 'lodash/isEqual'
import isEmpty from 'lodash/isEmpty' import isEmpty from 'lodash/isEmpty'
import invariant from 'invariant' import invariant from 'invariant'
@ -17,19 +17,28 @@ import installOsuFirmware from 'commands/installOsuFirmware'
import Box, { Card } from 'components/base/Box' import Box, { Card } from 'components/base/Box'
import Text from 'components/base/Text' 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 NanoS from 'icons/device/NanoS'
import CheckFull from 'icons/CheckFull' import CheckFull from 'icons/CheckFull'
import { PreventDeviceChangeRecheck } from '../Workflow/EnsureDevice'
import UpdateFirmwareButton from './UpdateFirmwareButton' import UpdateFirmwareButton from './UpdateFirmwareButton'
let CACHED_LATEST_FIRMWARE = null let CACHED_LATEST_FIRMWARE = null
export const getCleanVersion = (input: string): string =>
input.endsWith('-osu') ? input.replace('-osu', '') : input
type DeviceInfos = { type DeviceInfos = {
targetId: number | string, targetId: number | string,
version: string, version: string,
} }
type ModalStatus = 'closed' | 'disclaimer' | 'installing' | 'error' | 'success'
type Props = { type Props = {
t: T, t: T,
device: Device, device: Device,
@ -38,11 +47,13 @@ type Props = {
type State = { type State = {
latestFirmware: ?LedgerScriptParams, latestFirmware: ?LedgerScriptParams,
modal: ModalStatus,
} }
class FirmwareUpdate extends PureComponent<Props, State> { class FirmwareUpdate extends PureComponent<Props, State> {
state = { state = {
latestFirmware: null, latestFirmware: null,
modal: 'closed',
} }
componentDidMount() { componentDidMount() {
@ -86,6 +97,7 @@ class FirmwareUpdate extends PureComponent<Props, State> {
const { const {
device: { path: devicePath }, device: { path: devicePath },
} = this.props } = this.props
this.setState({ modal: 'installing' })
const { success } = await installOsuFirmware const { success } = await installOsuFirmware
.send({ devicePath, firmware: latestFirmware, targetId: infos.targetId }) .send({ devicePath, firmware: latestFirmware, targetId: infos.targetId })
.toPromise() .toPromise()
@ -97,9 +109,49 @@ class FirmwareUpdate extends PureComponent<Props, State> {
} }
} }
handleCloseModal = () => this.setState({ modal: 'closed' })
handleInstallModal = () => this.setState({ modal: 'disclaimer' })
renderModal = () => {
const { t } = this.props
const { modal, latestFirmware } = this.state
return (
<Modal
isOpened={modal !== 'closed'}
render={() => (
<ModalBody grow align="center" justify="center" mt={3}>
<Fragment>
<ModalTitle>{t('app:manager.firmware.update')}</ModalTitle>
<ModalContent>
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center">
<Trans i18nKey="app:manager.firmware.disclaimerTitle">
You are about to install the latest
<Text ff="Open Sans|SemiBold" color="dark">
{`firmware ${latestFirmware ? getCleanVersion(latestFirmware.name) : ''}`}
</Text>
</Trans>
</Text>
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center">
{t('app:manager.firmware.disclaimerAppDelete')}
{t('app:manager.firmware.disclaimerAppReinstall')}
</Text>
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end" style={{ width: '100%' }}>
<Button primary padded onClick={this.installFirmware}>
{t('app:manager.firmware.continue')}
</Button>
</ModalFooter>
</Fragment>
</ModalBody>
)}
/>
)
}
render() { render() {
const { infos, t } = this.props const { infos, t } = this.props
const { latestFirmware } = this.state const { latestFirmware, modal } = this.state
return ( return (
<Card p={4}> <Card p={4}>
@ -122,8 +174,13 @@ class FirmwareUpdate extends PureComponent<Props, State> {
})} })}
</Text> </Text>
</Box> </Box>
<UpdateFirmwareButton firmware={latestFirmware} installFirmware={this.installFirmware} /> <UpdateFirmwareButton
firmware={latestFirmware}
installFirmware={this.handleInstallModal}
/>
</Box> </Box>
{modal !== 'closed' ? <PreventDeviceChangeRecheck /> : null}
{this.renderModal()}
</Card> </Card>
) )
} }

4
src/components/ManagerPage/UpdateFirmwareButton.js

@ -6,6 +6,7 @@ import type { T } from 'types/common'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import Text from 'components/base/Text' import Text from 'components/base/Text'
import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate'
type FirmwareInfos = { type FirmwareInfos = {
name: string, name: string,
@ -18,9 +19,6 @@ type Props = {
installFirmware: () => void, installFirmware: () => void,
} }
const getCleanVersion = (input: string): string =>
input.endsWith('-osu') ? input.replace('-osu', '') : input
const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) => const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) =>
firmware ? ( firmware ? (
<Fragment> <Fragment>

9
src/components/ManagerPage/index.js

@ -1,9 +1,8 @@
// @flow // @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 type { Device } from 'types/common'
import Workflow from 'components/Workflow' import Workflow from 'components/Workflow'
@ -23,7 +22,8 @@ type Error = {
stack: string, stack: string,
} }
function ManagerPage(): Node { class ManagerPage extends PureComponent<*, *> {
render() {
return ( return (
<Workflow <Workflow
renderFinalUpdate={(device: Device, deviceInfo: DeviceInfo) => ( renderFinalUpdate={(device: Device, deviceInfo: DeviceInfo) => (
@ -54,5 +54,6 @@ function ManagerPage(): Node {
/> />
) )
} }
}
export default ManagerPage export default ManagerPage

23
src/components/Workflow/EnsureDevice.js

@ -1,5 +1,7 @@
// @flow // @flow
import { PureComponent } from 'react' /* eslint-disable react/no-multi-comp */
import { Component, PureComponent } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import type { Node } from 'react' import type { Node } from 'react'
@ -12,9 +14,24 @@ type Props = {
children: (device: Device) => Node, 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<Props, State> { class EnsureDevice extends Component<Props> {
shouldComponentUpdate(nextProps) {
if (prevents > 0) return false
return nextProps.device !== this.props.device
}
render() { render() {
const { device, children } = this.props const { device, children } = this.props
return children(device) return children(device)

4
src/components/modals/AddAccounts/steps/02-step-connect-device.js

@ -20,11 +20,11 @@ function StepConnectDevice({ t, currency, currentDevice, setState }: StepProps)
<CurrencyCircleIcon mb={3} size={40} currency={currency} /> <CurrencyCircleIcon mb={3} size={40} currency={currency} />
<Box ff="Open Sans" fontSize={4} color="dark" textAlign="center" style={{ width: 370 }}> <Box ff="Open Sans" fontSize={4} color="dark" textAlign="center" style={{ width: 370 }}>
<Trans i18nKey="app:addAccounts.connectDevice.desc" parent="div"> <Trans i18nKey="app:addAccounts.connectDevice.desc" parent="div">
{`You're about to import your `} {`Follow the steps below to add `}
<strong style={{ fontWeight: 'bold' }}>{`${currency.name} (${ <strong style={{ fontWeight: 'bold' }}>{`${currency.name} (${
currency.ticker currency.ticker
})`}</strong> })`}</strong>
{` account(s) from your Ledger device. Please follow the steps below:`} {` account(s) from your Ledger device.`}
</Trans> </Trans>
</Box> </Box>
</Box> </Box>

26
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
}
}

15
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
}
}

24
src/helpers/firmware/installFinalFirmware.js

@ -3,13 +3,31 @@ import type Transport from '@ledgerhq/hw-transport'
import { WS_INSTALL } from 'helpers/urls' import { WS_INSTALL } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket' 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 = * type Result = *
export default async (transport: Transport<*>, firmware: Input): Result => { export default async (transport: Transport<*>, app: Input): Result => {
try { 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() await createDeviceSocket(transport, url).toPromise()
return { success: true } return { success: true }
} catch (err) { } catch (err) {

4
src/helpers/hardReset.js

@ -5,9 +5,7 @@ import db from 'helpers/db'
import { delay } from 'helpers/promise' import { delay } from 'helpers/promise'
export default async function hardReset() { export default async function hardReset() {
// TODO: wait for the libcoreHardReset to be finished await libcoreHardReset.send()
// actually, libcore doesnt goes back to js thread
await Promise.race([libcoreHardReset.send().toPromise(), delay(500)])
disableDBMiddleware() disableDBMiddleware()
db.resetAll() db.resetAll()
await delay(500) await delay(500)

2
src/helpers/urls.js

@ -14,9 +14,11 @@ const wsURLBuilder = (endpoint: string) => (params?: Object) =>
// const wsURLBuilderProxy = (endpoint: string) => (params?: Object) => // const wsURLBuilderProxy = (endpoint: string) => (params?: Object) =>
// `ws://manager.ledger.fr:3501/${endpoint}${params ? `?${qs.stringify(params)}` : ''}` // `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 GET_DEVICE_VERSION: string = managerUrlbuilder('get_device_version')
export const APPLICATIONS_BY_DEVICE: string = managerUrlbuilder('get_apps') export const APPLICATIONS_BY_DEVICE: string = managerUrlbuilder('get_apps')
export const GET_CURRENT_FIRMWARE: string = managerUrlbuilder('get_firmware_version') 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_LATEST_FIRMWARE: string = managerUrlbuilder('get_latest_firmware')
export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader') export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader')

254
static/i18n/en/app.yml

@ -12,7 +12,7 @@ common:
currency: Currency currency: Currency
selectAccount: Select an account selectAccount: Select an account
selectAccountNoOption: 'No account matching "{{accountName}}"' selectAccountNoOption: 'No account matching "{{accountName}}"'
selectCurrency: Select a currency selectCurrency: Choose a crypto asset
selectCurrencyNoOption: 'No currency matching "{{currencyName}}"' selectCurrencyNoOption: 'No currency matching "{{currencyName}}"'
selectExchange: Select an exchange selectExchange: Select an exchange
selectExchangeNoOption: 'No exchange matching "{{exchangeName}}"' selectExchangeNoOption: 'No exchange matching "{{exchangeName}}"'
@ -32,15 +32,15 @@ common:
eastern: Eastern eastern: Eastern
western: Western western: Western
lockScreen: lockScreen:
title: Welcome Back title: Welcome back
subTitle: Your application is locked subTitle: Ledger Live is locked
description: Please enter your password to continue description: Enter your password to continue
inputPlaceholder: Type your password inputPlaceholder:
lostPassword: I lost my password lostPassword: I lost my password
sync: sync:
syncing: Syncing... syncing: Synchronizing...
upToDate: Up to date upToDate: Up to date
error: Sync error. error: Synchronization error
refresh: Refresh refresh: Refresh
ago: Synced {{time}} ago: Synced {{time}}
error: error:
@ -48,8 +48,12 @@ common:
noResults: No results noResults: No results
operation: operation:
type: type:
IN: Receive funds IN: Received
OUT: Sent funds # conf: Received
# unconf: Receiving...
OUT: Sent
# conf: Sent
# unconf: Sending...
time: time:
day: Day day: Day
week: Week week: Week
@ -70,20 +74,20 @@ account:
receive: Receive receive: Receive
lastOperations: Last operations lastOperations: Last operations
emptyState: emptyState:
title: This is a title, use it with caution title: No funds yet?
desc: Please create a new account or recover an old account from your Ledger device. desc: Receive funds in this account by using your Ledger device with the [cryptocurrency] app installed. # replace [cryptocurrency] and make it bold
buttons: buttons:
receiveFunds: Receive Funds receiveFunds: Receive Funds
settings: settings:
title: Edit Account title: Edit account
advancedLogs: Advanced logs advancedLogs: Advanced logs
accountName: accountName:
title: Account name title: Account name
desc: Lorem ipsum dolort amet desc: Describe this account.
error: Name is required error: An account name is required.
unit: unit:
title: Unit title: Unit
desc: Lorem ipsum dolort amet desc: Choose the unit to display.
endpointConfig: endpointConfig:
title: Node title: Node
desc: The API node to use desc: The API node to use
@ -93,17 +97,17 @@ dashboard:
accounts: accounts:
title: Accounts ({{count}}) title: Accounts ({{count}})
greeting: greeting:
morning: "Good Morning!" morning: "Good morning"
evening: "Good Evening!" evening: "Good evening"
afternoon: "Good Afternoon!" afternoon: "Good afternoon"
summary: here is the summary of your account summary: "Here's the summary of your account."
summary_plural: 'here is the summary of your {{count}} accounts' summary_plural: "Here's the summary of your {{count}} accounts."
noAccounts: no accounts noAccounts: No accounts yet
recentActivity: Recent activity recentActivity: Recent activity
totalBalance: Total balance totalBalance: Total balance
accountsOrder: accountsOrder:
name: Alphabetic name: name
balance: Balance balance: balance
currentAddress: currentAddress:
title: Current address title: Current address
for: Address for <1><0>{{accountName}}</0></1> for: Address for <1><0>{{accountName}}</0></1>
@ -112,16 +116,16 @@ deviceConnect:
step1: step1:
choose: "We detected {{count}} devices connected, please select one:" choose: "We detected {{count}} devices connected, please select one:"
connect: Connect and unlock your <1>Ledger device</1> # remove key: <3>PIN code</3> connect: Connect and unlock your <1>Ledger device</1> # remove key: <3>PIN code</3>
dashboard: dashboard: test
emptyState: emptyState:
sidebar: 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: dashboard:
title: This is a title, use it with caution title: 'Let’s set up your portfolio!'
desc: Please create a new account or recover an old account from your Ledger device. desc: Open the Manager to install apps on your device or add accounts if your device already has apps installed.
buttons: buttons:
addAccount: Add Account addAccount: Add accounts
installApp: Install App installApp: Open Manager
exchange: exchange:
title: Exchange title: Exchange
visitWebsite: Visit website visitWebsite: Visit website
@ -134,28 +138,28 @@ genuinecheck:
addAccounts: addAccounts:
title: Add accounts title: Add accounts
breadcrumb: breadcrumb:
informations: Informations informations: Choose asset
connectDevice: Connect device connectDevice: Connect device
import: Import import: Select accounts
finish: End finish: Confirmation
accountToImportSubtitle: Account to import accountToImportSubtitle: Select existing accounts
accountToImportSubtitle_plural: 'Accounts to import ({{count}})' accountToImportSubtitle_plural: 'Select ({{count}}) existing accounts'
selectAll: Select all selectAll: Select all
unselectAll: Unselect all unselectAll: Deselect all
editName: Edit name editName: Edit name
newAccount: New account newAccount: New account
legacyAccount: '{{accountName}} (legacy)' legacyAccount: '{{accountName}} (legacy)'
noAccountToImport: We didnt find any {{currencyName}} account to import. noAccountToImport: No {{currencyName}} account was found.
success: Great success! success: Accounts have been added to your portfolio.
createNewAccount: createNewAccount:
title: Create new account title: Create new account
noOperationOnLastAccount: You cannot create a new account because your last account has no operations noOperationOnLastAccount: Receive funds on your previous account before creating a new one.
noAccountToCreate: We didnt find any {{currencyName}} account to create. noAccountToCreate: No {{currencyName}} account was found to create.
somethingWentWrong: Something went wrong during synchronization. somethingWentWrong: Something went wrong during synchronization, please try again.
cta: cta:
create: 'Create account' create: 'Add account'
import: 'Import account' import: 'Add account' # Remove
import_plural: 'Import accounts' import_plural: 'Add accounts'
operationDetails: operationDetails:
title: Operation details title: Operation details
account: Account account: Account
@ -166,12 +170,12 @@ operationDetails:
fees: Fees fees: Fees
from: From from: From
to: To to: To
identifier: Hash identifier: Transaction ID
viewOperation: View operation viewOperation: View in explorer
showMore: Show {{recipients}} more showMore: Show {{recipients}} more
showLess: Show less showLess: Show less
operationList: operationList:
noMoreOperations: No more operations noMoreOperations: That's all!
manager: manager:
tabs: tabs:
apps: Apps apps: Apps
@ -189,28 +193,32 @@ manager:
installed: 'Firmware {{version}}' installed: 'Firmware {{version}}'
update: Update firmware update: Update firmware
updateTitle: Firmware update updateTitle: Firmware update
continue: Continue update
latest: 'A new firmware {{version}} is available' latest: 'A new firmware {{version}} is available'
disclaimerTitle: 'You are about to install the latest <1><0>firmware {{version}}</0></1>'
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 title: Manager
subtitle: Get all your apps here subtitle: Get all your apps here
device: device:
title: Plug your device title: Connect your device
desc: Please connect your Ledger device and follow the steps below to access the manager desc: Follow the steps below to connect your device
cta: Plug my device cta: Connect my device
errors: errors:
noDevice: Please make sur your device is connected (TEMPLATE NEEDED) noDevice: No device is connected (TEMPLATE NEEDED)
noDashboard: Please make sure your device is on the dashboard screen (TEMPLATED NEEDED) noDashboard: Navigate to the dashboard on your device (TEMPLATED NEEDED)
noGenuine: You did not approve request on your device or your device is not genuine (TEMPLATE NEEDED) noGenuine: Allow the Manager to continue (TEMPLATE NEEDED)
receive: receive:
title: Receive funds title: Receive funds
steps: steps:
chooseAccount: chooseAccount:
title: Choose Account title: Choose account
label: Account label: Account
connectDevice: connectDevice:
title: Connect Device title: Connect device
withoutDevice: I don't have my device withoutDevice: I don't have my device
confirmAddress: confirmAddress:
title: Confirm Address title: Confirm address
action: Confirm address on device action: Confirm address on device
text: To receive funds, confirm the address on your device. text: To receive funds, confirm the address on your device.
support: Contact Support support: Contact Support
@ -244,7 +252,7 @@ send:
title: Verification title: Verification
warning: | warning: |
You are about to validate a transaction. 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. body: Once you have checked everything is ok, you can validate securely the transaction on your device.
confirmation: confirmation:
title: Confirmation title: Confirmation
@ -267,73 +275,73 @@ settings:
display: Display display: Display
currencies: Currencies currencies: Currencies
profile: Profile profile: Profile
about: About about: Help
display: display:
desc: Lorem ipsum dolor sit amet desc:
language: Interface language language: Language
languageDesc: Lorem ipsum dolor sit amet languageDesc: Choose the language to display.
counterValue: Countervalue counterValue: Base currency
counterValueDesc: Lorem ipsum dolor sit amet counterValueDesc: Choose the currency to display next to your balance and operations.
exchange: Exchange ({{ticker}}) exchange: Rate provider ({{ticker}})
exchangeDesc: The exchange to use for countervalue conversion exchangeDesc: Choose the provider of the base currency exchange rates.
region: Region region: Region
regionDesc: Lorem ipsum dolor sit amet regionDesc: Choose the region in which you’re located to set the application’s time zone.
stock: Stock market indicators stock: Regional market indicator
stockDesc: Lorem ipsum dolor sit amet stockDesc: Choose Western to display an increase in market value in blue. Choose Eastern to display an increase in market value in red.
currencies: currencies:
desc: Lorem ipsum dolor sit amet desc: Select a cryptocurrency to edit its settings
exchange: Exchange ({{ticker}}) exchange: Rate provider ({{ticker}})
exchangeDesc: The exchange to use for countervalue conversion exchangeDesc: Choose the provider of the base currency exchange rates.
confirmationsToSpend: Confirmations to spend confirmationsToSpend: Number of confirmations required to spend
confirmationsToSpendDesc: Lorem ipsum dolor sit amet 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 confirmationsNb: Number of confirmations
confirmationsNbDesc: 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: Transactions fees transactionsFees: Default transaction fees
transactionsFeesDesc: Lorem ipsum dolor sit amet transactionsFeesDesc: Select your default transaction fees. The higher the fee, the quicker the transaction will be processed.
explorer: Blockchain explorer explorer: Blockchain explorer
explorerDesc: Lorem ipsum dolor sit amet explorerDesc: Which service to use to look up an operation in the blockchain.
profile: profile:
desc: Lorem ipsum dolor sit amet desc:
password: Password password: Data encryption
passwordDesc: Lorem ipsum dolor sit amet 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 changePassword: Change password
sync: Sync accounts sync: Synchronize accounts
syncDesc: Lorem ipsum dolor sit amet syncDesc: Resynchronize your accounts with the blockchain.
export: Export logs export: Export logs
exportDesc: Lorem ipsum dolor sit amet exportDesc: Exporting Ledger Live logs may be necessary for troubleshooting purposes.
softResetTitle: Clean application cache softResetTitle: Clear cache
softResetDesc: Lorem ipsum dolor sit amet softResetDesc: Clear the Ledger Live cache to force resynchronization with the blockchain.
softReset: Clean cache softReset: Clear
hardResetTitle: Reset application hardResetTitle: Reset Ledger Live
hardResetDesc: Lorem ipsum dolor sit amet 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: Hard reset hardReset: Reset
developerMode: Developer Mode developerMode: Developer mode
developerModeDesc: Enable visibility of developer apps & currencies like Bitcoin Testnet developerModeDesc: Show developer apps in the Manager.
analytics: Share analytics analytics: Analytics
analyticsDesc: Help Ledger improve its products and services by automatically sending diagnostics and usage data. 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: Sentry Logs reportErrors: Usage and diagnostics
reportErrorsDesc: Help Ledger improve its products and services by automatically sending diagnostics and usage data. reportErrorsDesc: Share anonymous usage and diagnostics data to help improve Ledger products, services and security features.
about: about:
desc: Lorem ipsum dolor sit amet desc:
version: Version version: Ledger Live version
releaseNotesBtn: Show release notes releaseNotesBtn: Show release notes # Close button instead of continue.
faq: FAQ faq: Ledger Support
faqDesc: Lorem ipsum dolor sit amet faqDesc: A problem? Learn about Ledger Live, Ledger devices, supported crypto assets and apps.
contactUs: Contact us contactUs: Contact us
contactUsDesc: Lorem ipsum dolor sit amet contactUsDesc: Need help? Request assistance from Ledger Support by email or chat.
terms: Terms and Privacy policy terms: --- Terms and Privacy policy ---
termsDesc: Lorem ipsum dolor sit amet termsDesc: --- Check with Legal ---
hardResetModal: hardResetModal:
title: Reset Ledger Live 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. 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: softResetModal:
title: Clean application cache title: Clear cache
subTitle: Are you sure houston? subTitle: Are you sure?
desc: Lorem ipsum dolor sit amet desc: Clearing the Ledger Live cache forces resynchronization with the blockchain.
removeAccountModal: removeAccountModal:
title: Delete this account title: Remove account
subTitle: Are you sure houston? subTitle: Are you sure?
desc: Lorem ipsum dolor sit amet desc: The account will no longer be included in your portfolio. Accounts can always be re-added.
exportLogs: exportLogs:
title: Export Logs title: Export Logs
desc: Export Logs desc: Export Logs
@ -349,32 +357,32 @@ password:
inputFields: inputFields:
newPassword: newPassword:
label: Password label: Password
placeholder: Password placeholder:
confirmPassword: confirmPassword:
label: Confirm Password label: Confirm password
placeholder: Confirm Password placeholder:
currentPassword: currentPassword:
label: Current Password label: Current password
placeholder: Current Password placeholder:
changePassword: changePassword:
title: Edit Password title: Data encryption
subTitle: Change your password 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: setPassword:
title: Set Password title: Enable data encryption
subTitle: Set a password to lock your application subTitle: Set a 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.
disablePassword: disablePassword:
title: Disable Password title: Disable data encryption
desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam. desc: Ledger Live data will be stored unencrypted on your computer. This includes account names, balances, transactions and public addresses.
update: update:
newVersionReady: A new update is available. newVersionReady: A new update is available.
relaunch: Update now relaunch: Update now
crash: 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. 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 reset: Hard reset
createTicket: Create issue createTicket: Ledger Support
showDetails: Show details showDetails: Show details
showError: Show error showError: Show error

1
static/i18n/en/errors.yml

@ -20,3 +20,4 @@ DeviceSocketFail: Device socket failure
DeviceSocketNoBulkStatus: Device socket failure (bulk) DeviceSocketNoBulkStatus: Device socket failure (bulk)
DeviceSocketNoHandler: Device socket failure (handler {{query}}) DeviceSocketNoHandler: Device socket failure (handler {{query}})
LatestMCUInstalledError: The latest MCU is already installed on the Device LatestMCUInstalledError: The latest MCU is already installed on the Device
HardResetFail: Hard reset failure

6
yarn.lock

@ -1502,9 +1502,9 @@
dependencies: dependencies:
events "^2.0.0" events "^2.0.0"
"@ledgerhq/ledger-core@2.0.0-rc.1": "@ledgerhq/ledger-core@2.0.0-rc.3":
version "2.0.0-rc.1" version "2.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.1.tgz#0b31f7d2c693b9c11d4093dbb0896f13c33bf141" resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.3.tgz#21b04239e9ba6b7fdcb89958eea8ad47a4a28a88"
dependencies: dependencies:
"@ledgerhq/hw-app-btc" "^4.7.3" "@ledgerhq/hw-app-btc" "^4.7.3"
"@ledgerhq/hw-transport-node-hid" "^4.7.6" "@ledgerhq/hw-transport-node-hid" "^4.7.6"

Loading…
Cancel
Save