Browse Source

Add new RequestAmount component in ReceiveModal

master
Loëck Vézien 7 years ago
parent
commit
850ca38a03
No known key found for this signature in database GPG Key ID: CBCDCE384E853AC4
  1. 2
      .storybook/config.js
  2. 5
      src/components/AccountPage/index.js
  3. 266
      src/components/RequestAmount/index.js
  4. 7
      src/components/RequestAmount/stories.js
  5. 2
      src/components/SelectAccount/stories.js
  6. 10
      src/components/base/Button/index.js
  7. 98
      src/components/base/Input/index.js
  8. 132
      src/components/base/InputCurrency/index.js
  9. 15
      src/components/base/InputCurrency/stories.js
  10. 27
      src/components/modals/Receive/index.js
  11. 14
      src/reducers/counterValues.js
  12. 1
      static/i18n/en/common.yml
  13. 55
      yarn.lock

2
.storybook/config.js

@ -3,7 +3,7 @@ import { configure, addDecorator } from '@storybook/react'
import { withKnobs } from '@storybook/addon-knobs'
import { setOptions } from '@storybook/addon-options'
import { ThemeProvider } from 'styled-components'
import { I18nextProvider } from 'react-i18next'
import { I18nextProvider, translate } from 'react-i18next'
import 'globals'

5
src/components/AccountPage/index.js

@ -79,19 +79,20 @@ class AccountPage extends PureComponent<Props, State> {
<Box horizontal mb={5}>
<AccountHeader account={account} />
<Box horizontal alignItems="center" justifyContent="flex-end" grow flow={2}>
<Button primary onClick={() => openModal(MODAL_SEND, { account })}>
<Button small primary onClick={() => openModal(MODAL_SEND, { account })}>
<Box horizontal flow={1} alignItems="center">
<IconArrowUp width={12} />
<Box>{t('send:title')}</Box>
</Box>
</Button>
<Button primary onClick={() => openModal(MODAL_RECEIVE, { account })}>
<Button small primary onClick={() => openModal(MODAL_RECEIVE, { account })}>
<Box horizontal flow={1} alignItems="center">
<IconArrowDown width={12} />
<Box>{t('receive:title')}</Box>
</Box>
</Button>
<Button
small
style={{ width: 30, padding: 0 }}
onClick={() => openModal(MODAL_SETTINGS_ACCOUNT, { account })}
>

266
src/components/RequestAmount/index.js

@ -1,65 +1,70 @@
// @flow
import React, { PureComponent } from 'react'
import { compose } from 'redux'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { getDefaultUnitByCoinType, getFiatUnit } from '@ledgerhq/currencies'
import isNaN from 'lodash/isNaN'
import noop from 'lodash/noop'
import type { Account } from 'types/common'
import type { T, Account } from 'types/common'
import { getCounterValue } from 'reducers/settings'
import { getLastCounterValueBySymbol } from 'reducers/counterValues'
import Input from 'components/base/Input'
import InputCurrency from 'components/base/InputCurrency'
import Button from 'components/base/Button'
import Box from 'components/base/Box'
const mapStateToProps = state => ({
counterValue: getCounterValue(state),
counterValues: state.counterValues,
})
function calculateMax(props) {
const { account, counterValue, lastCounterValue } = props
const unit = {
currency: getDefaultUnitByCoinType(account.coinType),
fiat: getFiatUnit(counterValue),
}
const leftMax = account.balance / 10 ** unit.currency.magnitude
const InputRight = styled(Box).attrs({
ff: 'Rubik',
color: 'graphite',
fontSize: 4,
justifyContent: 'center',
pr: 3,
})``
const InputCenter = styled(Box).attrs({
ff: 'Rubik',
color: 'graphite',
fontSize: 4,
justifyContent: 'center',
})``
const mapStateToProps = (state, { account }) => {
const counterValue = getCounterValue(state)
const unit = getDefaultUnitByCoinType(account.coinType)
const symbol = `${unit.code}-${counterValue}`
return {
left: account.balance / 10 ** unit.currency.magnitude,
right: leftMax * lastCounterValue,
counterValue,
lastCounterValue: getLastCounterValueBySymbol(symbol, state),
}
}
function formatCur(unit, val) {
if (val === '') {
return ''
}
if (val === '0' || val <= 0) {
return 0
}
const factor = 10 ** unit.magnitude
return (Math.round(val * factor) / factor).toFixed(unit.magnitude)
function maxUnitDigits(unit, value) {
const [leftDigits, rightDigits] = value.toString().split('.')
return Number(`${leftDigits}${rightDigits ? `.${rightDigits.slice(0, unit.magnitude)}` : ''}`)
}
function cleanValue(value) {
function calculateMax(props) {
const { account, counterValue, lastCounterValue } = props
const unit = getUnit({ account, counterValue })
const leftMax = account.balance / 10 ** unit.left.magnitude
return {
left: value.left || 0,
right: value.right || 0,
left: account.balance / 10 ** unit.left.magnitude,
right: maxUnitDigits(unit.right, leftMax * lastCounterValue),
}
}
function parseValue(value) {
return value.toString().replace(/,/, '.')
}
function getUnit({ account, counterValue }) {
return {
currency: getDefaultUnitByCoinType(account.coinType),
fiat: getFiatUnit(counterValue),
left: getDefaultUnitByCoinType(account.coinType),
right: getFiatUnit(counterValue),
}
}
@ -67,32 +72,30 @@ function calculateValues({
dir,
value,
max,
unit,
lastCounterValue,
}: {
dir: string,
value: string | number,
value: Object,
max: Object,
unit: Object,
lastCounterValue: number,
}) {
value = parseValue(value)
const v = value[dir]
const getMax = (d, v) => {
const result = v > max[d] ? max[d] : v
return isNaN(result) ? 0 : result
return isNaN(result) ? '0' : result.toString()
}
const newValue = {}
if (dir === 'left') {
newValue.left = value === '' ? value : getMax('left', value)
newValue.right = formatCur(unit.fiat, getMax('right', Number(value) * lastCounterValue))
newValue.left = v === '' ? v : getMax('left', v)
newValue.right = getMax('right', Number(v) * lastCounterValue)
}
if (dir === 'right') {
newValue.left = formatCur(unit.currency, getMax('left', Number(value) / lastCounterValue))
newValue.right = value === '' ? value : getMax('right', value)
newValue.left = getMax('left', Number(v) / lastCounterValue)
newValue.right = v === '' ? v : getMax('right', v)
}
return newValue
@ -102,9 +105,10 @@ type Direction = 'left' | 'right'
type Props = {
account: Account,
lastCounterValue: number,
counterValue: string,
lastCounterValue: number, // eslint-disable-line react/no-unused-prop-types
onChange: Function,
t: T,
value: Object,
}
@ -121,6 +125,7 @@ type State = {
export class RequestAmount extends PureComponent<Props, State> {
static defaultProps = {
onChange: noop,
value: {},
}
@ -131,125 +136,113 @@ export class RequestAmount extends PureComponent<Props, State> {
const max = calculateMax(props)
let value = {}
let v = {
left: 0,
right: 0,
}
if (props.value.left) {
value = {
...calculateValues({
v = calculateValues({
...props,
dir: 'left',
value: props.value.left,
max,
lastCounterValue: props.lastCounterValue,
unit: getUnit({
account: props.account,
counterValue: props.counterValue,
}),
}),
}
})
}
if (props.value.right) {
value = {
...calculateValues({
v = calculateValues({
...props,
dir: 'right',
value: props.value.right,
max,
lastCounterValue: props.lastCounterValue,
unit: getUnit({
account: props.account,
counterValue: props.counterValue,
}),
}),
}
})
}
value = cleanValue(value)
this.state = {
max,
value,
value: v,
}
}
componentWillReceiveProps(nextProps: Props) {
if (this.props.account !== nextProps.account) {
const max = calculateMax(nextProps)
this.setState({
max: calculateMax(nextProps),
})
}
if (this.props.value.left !== nextProps.value.left) {
this.setState({
value: cleanValue({
...calculateValues({
max,
value: calculateValues({
...nextProps,
dir: 'left',
value: nextProps.value.left,
max: this.state.max,
lastCounterValue: nextProps.lastCounterValue,
unit: getUnit({
account: nextProps.account,
counterValue: nextProps.counterValue,
}),
}),
max,
}),
})
}
if (this.props.value.right !== nextProps.value.right) {
this.setState({
value: cleanValue({
...calculateValues({
dir: 'right',
value: nextProps.value.right,
max: this.state.max,
lastCounterValue: nextProps.lastCounterValue,
unit: getUnit({
account: nextProps.account,
counterValue: nextProps.counterValue,
}),
}),
}),
})
}
componentDidUpdate(prevProps: Props) {
this.updateValueWithProps(prevProps, this.props)
}
handleChangeAmount = (dir: Direction) => (v: string) => {
const { onChange, lastCounterValue, account, counterValue } = this.props
handleChangeAmount = (dir: Direction) => (v: number | string) => {
const { onChange, value, account, counterValue, ...otherProps } = this.props
const { max } = this.state
v = parseValue(v)
// Check if value is valid Number
if (isNaN(Number(v))) {
return
}
const otherDir = dir === 'left' ? 'right' : 'left'
const unit = getUnit({
account,
counterValue,
})
const newValue = calculateValues({
...otherProps,
dir,
value: v,
value: {
[dir]: v.toString(),
},
max,
lastCounterValue,
unit: getUnit({
account,
counterValue,
}),
})
newValue[otherDir] = maxUnitDigits(unit[otherDir], newValue[otherDir]).toString()
this.setState({
value: newValue,
})
onChange(newValue)
}
onChange(cleanValue(newValue))
handleClickMax = () => {
const { account } = this.props
this.handleChangeAmount('left')(account.balance)
}
updateValueWithProps = (props: Props, nextProps: Props) => {
if (
props.value.left !== nextProps.value.left &&
nextProps.value.left !== this.state.value.left
) {
this.setState({
value: calculateValues({
...nextProps,
dir: 'left',
max: this.state.max,
}),
})
}
handleBlur = () =>
this.setState(prev => ({
value: cleanValue(prev.value),
}))
if (
props.value.right !== nextProps.value.right &&
nextProps.value.right !== this.state.value.right
) {
this.setState({
value: calculateValues({
...nextProps,
dir: 'right',
max: this.state.max,
}),
})
}
}
render() {
const { account, counterValue, t } = this.props
const { value } = this.state
const { account, counterValue } = this.props
const unit = getUnit({
account,
@ -258,30 +251,25 @@ export class RequestAmount extends PureComponent<Props, State> {
return (
<Box horizontal flow={2}>
<Box grow horizontal flow={2}>
<Box justifyContent="center">{unit.currency.code}</Box>
<Box grow>
<Input
<InputCurrency
unit={unit.left}
value={value.left}
onBlur={this.handleBlur}
onChange={this.handleChangeAmount('left')}
renderRight={<InputRight>{unit.left.code}</InputRight>}
/>
</Box>
</Box>
<Box justifyContent="center">=</Box>
<Box grow horizontal flow={2}>
<Box justifyContent="center">{unit.fiat.code}</Box>
<Box grow>
<Input
<InputCenter>=</InputCenter>
<InputCurrency
unit={unit.right}
value={value.right}
onBlur={this.handleBlur}
onChange={this.handleChangeAmount('right')}
renderRight={<InputRight>{unit.right.code}</InputRight>}
/>
</Box>
</Box>
<Button ml={5} primary onClick={this.handleClickMax}>
{t('common:max')}
</Button>
</Box>
)
}
}
export default connect(mapStateToProps)(RequestAmount)
export default compose(connect(mapStateToProps), translate())(RequestAmount)

7
src/components/RequestAmount/stories.js

@ -3,7 +3,7 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'
import { text } from '@storybook/addon-knobs'
import { number } from '@storybook/addon-knobs'
import { accounts } from 'components/SelectAccount/stories'
@ -20,10 +20,11 @@ const props = {
stories.add('basic', () => (
<RequestAmount
{...props}
t={k => k}
onChange={action('onChange')}
value={{
left: text('left value', 0),
right: text('right value', 0),
left: number('left value', 0),
right: number('right value', 0),
}}
/>
))

2
src/components/SelectAccount/stories.js

@ -14,7 +14,7 @@ export const accounts = [...Array(20)].map(() => ({
id: chance.string(),
address: chance.string(),
addresses: [],
balance: chance.integer({ min: 10000000, max: 2000000000 }),
balance: chance.integer({ min: 10000000000, max: 2000000000000 }),
balanceByDay: {},
coinType: 1,
currency: getCurrencyByCoinType(1),

10
src/components/base/Button/index.js

@ -12,7 +12,7 @@ import fontFamily from 'styles/styled/fontFamily'
const Base = styled.button.attrs({
ff: 'Museo Sans|Regular',
fontSize: 3,
px: 2,
px: p => (p.small ? 2 : 4),
})`
${space};
${color};
@ -23,7 +23,7 @@ const Base = styled.button.attrs({
border: ${p =>
p.primary ? 'none' : `2px solid ${p.disabled ? 'transparent' : p.theme.colors.grey}`};
cursor: ${p => (p.disabled ? 'default' : 'pointer')};
height: 30px;
height: ${p => (p.small ? 30 : 40)}px;
outline: none;
&:hover {
@ -46,6 +46,7 @@ type Props = {
primary?: boolean,
disabled?: boolean,
onClick?: Function,
small?: boolean,
}
function getProps({ disabled, icon, primary }: Object) {
@ -98,10 +99,11 @@ const Button = (props: Props) => {
Button.defaultProps = {
children: undefined,
icon: undefined,
disabled: undefined,
primary: false,
icon: undefined,
onClick: noop,
primary: false,
small: false,
}
export default Button

98
src/components/base/Input/index.js

@ -2,42 +2,67 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { space, fontSize } from 'styled-system'
import { fontSize } from 'styled-system'
import noop from 'lodash/noop'
import fontFamily from 'styles/styled/fontFamily'
import Box from 'components/base/Box'
const Container = styled(Box).attrs({
horizontal: true,
})`
background: ${p => p.theme.colors.white};
border-radius: 3px;
border: 1px solid ${p => p.theme.colors.fog};
box-shadow: ${p => (p.isFocus ? `rgba(0, 0, 0, 0.05) 0 2px 2px` : 'none')};
height: 40px;
`
const Base = styled.input.attrs({
px: 3,
ff: 'Open Sans|SemiBold',
ff: p => p.ff || 'Open Sans|SemiBold',
fontSize: 4,
})`
${space};
${fontFamily};
${fontSize};
height: 40px;
border: 1px solid ${p => p.theme.colors.fog};
border-radius: 3px;
display: flex;
border: 0;
color: ${p => p.theme.colors.dark};
height: 100%;
outline: none;
padding: 0;
width: 100%;
color: ${p => p.theme.colors.graphite};
background: ${p => p.theme.colors.white};
&::placeholder {
color: ${p => p.theme.colors.fog};
}
&:focus {
outline: none;
box-shadow: rgba(0, 0, 0, 0.05) 0 2px 2px;
}
`
type Props = {
onChange?: Function,
keepEvent?: boolean,
onBlur: Function,
onChange?: Function,
onFocus: Function,
renderLeft?: any,
renderRight?: any,
}
type State = {
isFocus: boolean,
}
class Input extends PureComponent<Props> {
class Input extends PureComponent<Props, State> {
static defaultProps = {
onBlur: noop,
onFocus: noop,
renderLeft: null,
renderRight: null,
}
state = {
isFocus: false,
}
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
const { onChange, keepEvent } = this.props
@ -46,8 +71,45 @@ class Input extends PureComponent<Props> {
}
}
handleClick = () => this._input && this._input.focus()
handleFocus = () => {
const { onFocus } = this.props
this.setState({
isFocus: true,
})
onFocus()
}
handleBlur = () => {
const { onBlur } = this.props
this.setState({
isFocus: false,
})
onBlur()
}
_input = null
render() {
return <Base {...this.props} onChange={this.handleChange} />
const { isFocus } = this.state
const { renderLeft, renderRight } = this.props
return (
<Container onClick={this.handleClick} isFocus={isFocus} shrink>
{renderLeft}
<Box px={3} grow shrink>
<Base
{...this.props}
innerRef={n => (this._input = n)}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onChange={this.handleChange}
/>
</Box>
{renderRight}
</Container>
)
}
}

132
src/components/base/InputCurrency/index.js

@ -0,0 +1,132 @@
// @flow
import React, { PureComponent } from 'react'
import { parseCurrencyUnit, formatCurrencyUnit } from '@ledgerhq/currencies'
import noop from 'lodash/noop'
import isNaN from 'lodash/isNaN'
import Input from 'components/base/Input'
import type { Unit } from '@ledgerhq/currencies'
function parseValue(value) {
return value.toString().replace(/,/, '.')
}
function format(unit: Unit, value: Value) {
let v = value === '' ? 0 : Number(value)
v *= 10 ** unit.magnitude
return formatCurrencyUnit(unit, v, {
disableRounding: true,
showAllDigits: false,
})
}
function unformat(unit, value) {
if (value === 0 || value === '') {
return 0
}
let v = parseCurrencyUnit(unit, value.toString())
v /= 10 ** unit.magnitude
return v
}
type Value = string | number
type Props = {
onChange: Function,
value: Value,
unit: Unit,
}
type State = {
isFocus: boolean,
value: Value,
}
class InputCurrency extends PureComponent<Props, State> {
static defaultProps = {
onChange: noop,
value: 0,
}
state = {
isFocus: false,
value: this.props.value,
}
componentWillReceiveProps(nextProps: Props) {
if (this.props.value !== nextProps.value) {
const { isFocus } = this.state
const value = isFocus ? nextProps.value : format(nextProps.unit, nextProps.value)
this.setState({
value,
})
}
}
handleChange = (v: Value) => {
v = parseValue(v)
// Check if value is valid Number
if (isNaN(Number(v))) {
return
}
this.emitOnChange(v)
this.setState({
value: v,
})
}
handleBlur = () => {
const { unit } = this.props
const { value } = this.state
const v = format(unit, value)
this.setState({
isFocus: false,
value: v,
})
}
handleFocus = () => {
const { unit } = this.props
this.setState(prev => ({
isFocus: true,
value: unformat(unit, prev.value),
}))
}
emitOnChange = (v: Value) => {
const { onChange } = this.props
const { value } = this.state
if (value.toString() !== v.toString()) {
onChange(v.toString())
}
}
render() {
const { value } = this.state
return (
<Input
{...this.props}
ff="Rubik"
value={value}
onChange={this.handleChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
)
}
}
export default InputCurrency

15
src/components/base/InputCurrency/stories.js

@ -0,0 +1,15 @@
// @flow
import React from 'react'
import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import InputCurrency from 'components/base/InputCurrency'
const stories = storiesOf('Components/InputCurrency', module)
const unit = getDefaultUnitByCoinType(1)
stories.add('basic', () => <InputCurrency unit={unit} onChange={action('onChange')} />)

27
src/components/modals/Receive/index.js

@ -7,14 +7,12 @@ import get from 'lodash/get'
import { MODAL_RECEIVE } from 'constants'
// import { getCounterValue } from 'reducers/settings'
import Box from 'components/base/Box'
// import Button from 'components/base/Button'
// import Input from 'components/base/Input'
import Label from 'components/base/Label'
import Button from 'components/base/Button'
import Modal, { ModalBody, ModalTitle, ModalFooter, ModalContent } from 'components/base/Modal'
import ReceiveBox from 'components/ReceiveBox'
import RequestAmount from 'components/RequestAmount'
import SelectAccount from 'components/SelectAccount'
import type { Account as AccountType, T } from 'types/common'
@ -25,12 +23,15 @@ type Props = {
type State = {
account: AccountType | null,
amount: string,
amount: Object,
}
const defaultState = {
account: null,
amount: '',
amount: {
left: 0,
right: 0,
},
}
class ReceiveModal extends PureComponent<Props, State> {
@ -62,13 +63,14 @@ class ReceiveModal extends PureComponent<Props, State> {
].map(v => ({ label: this.props.t(v) }))
render() {
// const { amount } = this.state
const { t } = this.props
const { amount } = this.state
return (
<Modal
name={MODAL_RECEIVE}
onHide={this.handleHide}
render={({ data }) => {
render={({ data, onClose }) => {
const account = this.getAccount(data)
return (
@ -83,14 +85,13 @@ class ReceiveModal extends PureComponent<Props, State> {
<Fragment>
<Box flow={1}>
<Label>Request amount</Label>
<Input
type="number"
min={0}
max={account.balance / 1e8}
<RequestAmount
account={account}
value={amount}
onChange={this.handleChangeInput('amount')}
/>
</Box>
<ReceiveBox account={account} amount={amount} />
<ReceiveBox account={account} amount={amount.left} />
</Fragment>
)}
</ModalContent>

14
src/reducers/counterValues.js

@ -2,7 +2,12 @@
import { handleActions } from 'redux-actions'
export type CounterValuesState = {}
export type CounterValuesState = {
[string]: {
byDate: Object,
list: Array<[string, number]>,
},
}
const state: CounterValuesState = {}
@ -16,6 +21,13 @@ const handlers = {
}),
}
export function getLastCounterValueBySymbol(
symbol: string,
state: { counterValues: CounterValuesState },
): number {
return state.counterValues[symbol].list[0][1]
}
export function serializeCounterValues(counterValues: Object) {
return Object.keys(counterValues).reduce((result, key) => {
const counterValue = counterValues[key].sort(([dateA], [dateB]) => (dateA < dateB ? 1 : -1))

1
static/i18n/en/common.yml

@ -9,3 +9,4 @@ save: Save
password: Password
editProfile: Edit profile
lockApplication: Lock application
max: Max

55
yarn.lock

@ -3658,35 +3658,6 @@ ejs@^2.5.7:
version "2.5.7"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
electron-builder-lib@20.4.0:
version "20.4.0"
resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.4.0.tgz#e9a6d34b4bc6ed848a39a9ee894a3da015474c2a"
dependencies:
"7zip-bin" "~3.1.0"
app-builder-bin "1.7.2"
async-exit-hook "^2.0.1"
bluebird-lst "^1.0.5"
builder-util "5.6.4"
builder-util-runtime "4.0.5"
chromium-pickle-js "^0.2.0"
debug "^3.1.0"
ejs "^2.5.7"
electron-osx-sign "0.4.8"
electron-publish "20.2.0"
fs-extra-p "^4.5.2"
hosted-git-info "^2.5.0"
is-ci "^1.1.0"
isbinaryfile "^3.0.2"
js-yaml "^3.11.0"
lazy-val "^1.0.3"
minimatch "^3.0.4"
normalize-package-data "^2.4.0"
plist "^2.1.0"
read-config-file "3.0.0"
sanitize-filename "^1.6.1"
semver "^5.5.0"
temp-file "^3.1.1"
electron-builder-lib@20.4.1:
version "20.4.1"
resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.4.1.tgz#8560563e21ca0596046eac398cad204154665a5e"
@ -3745,29 +3716,6 @@ electron-builder-lib@~20.2.0:
semver "^5.5.0"
temp-file "^3.1.1"
<<<<<<< HEAD
electron-builder@^20.4.0:
=======
electron-builder@^20.0.4:
>>>>>>> Clean RequestAmount
version "20.4.0"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.4.0.tgz#d1393719339c17dd7c2dd16d58b4e138ca6646ce"
dependencies:
bluebird-lst "^1.0.5"
builder-util "5.6.4"
builder-util-runtime "4.0.5"
chalk "^2.3.2"
dmg-builder "4.1.1"
electron-builder-lib "20.4.0"
electron-download-tf "4.3.4"
fs-extra-p "^4.5.2"
is-ci "^1.1.0"
lazy-val "^1.0.3"
read-config-file "3.0.0"
sanitize-filename "^1.6.1"
update-notifier "^2.3.0"
yargs "^11.0.0"
electron-builder@^20.4.1:
version "20.4.1"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.4.1.tgz#ec8b5ada929df8d7a4ab4b1685568be4e12bf8f3"
@ -6537,6 +6485,9 @@ ledger-test-library@KhalilBellakrid/ledger-test-library-nodejs#7d37482:
dependencies:
axios "^0.17.1"
bindings "^1.3.0"
electron "^1.8.2"
electron-builder "^20.0.4"
electron-rebuild "^1.7.3"
nan "^2.6.2"
prebuild-install "^2.2.2"

Loading…
Cancel
Save