|
|
@ -7,17 +7,19 @@ const ConnectScreen = require('./connect-screen') |
|
|
|
const AccountList = require('./account-list') |
|
|
|
const AccountList = require('./account-list') |
|
|
|
const { DEFAULT_ROUTE } = require('../../../../routes') |
|
|
|
const { DEFAULT_ROUTE } = require('../../../../routes') |
|
|
|
const { formatBalance } = require('../../../../util') |
|
|
|
const { formatBalance } = require('../../../../util') |
|
|
|
|
|
|
|
const { getPlatform } = require('../../../../../../app/scripts/lib/util') |
|
|
|
|
|
|
|
const { PLATFORM_FIREFOX } = require('../../../../../../app/scripts/lib/enums') |
|
|
|
|
|
|
|
|
|
|
|
class ConnectHardwareForm extends Component { |
|
|
|
class ConnectHardwareForm extends Component { |
|
|
|
constructor (props, context) { |
|
|
|
constructor (props, context) { |
|
|
|
super(props) |
|
|
|
super(props) |
|
|
|
this.state = { |
|
|
|
this.state = { |
|
|
|
error: null, |
|
|
|
error: null, |
|
|
|
btnText: context.t('connectToTrezor'), |
|
|
|
|
|
|
|
selectedAccount: null, |
|
|
|
selectedAccount: null, |
|
|
|
accounts: [], |
|
|
|
accounts: [], |
|
|
|
browserSupported: true, |
|
|
|
browserSupported: true, |
|
|
|
unlocked: false, |
|
|
|
unlocked: false, |
|
|
|
|
|
|
|
device: null, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -38,25 +40,44 @@ class ConnectHardwareForm extends Component { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async checkIfUnlocked () { |
|
|
|
async checkIfUnlocked () { |
|
|
|
const unlocked = await this.props.checkHardwareStatus('trezor') |
|
|
|
['trezor', 'ledger'].forEach(async device => { |
|
|
|
if (unlocked) { |
|
|
|
const unlocked = await this.props.checkHardwareStatus(device, this.props.defaultHdPaths[device]) |
|
|
|
this.setState({unlocked: true}) |
|
|
|
if (unlocked) { |
|
|
|
this.getPage(0) |
|
|
|
this.setState({unlocked: true}) |
|
|
|
} |
|
|
|
this.getPage(device, 0, this.props.defaultHdPaths[device]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
connectToTrezor = () => { |
|
|
|
connectToHardwareWallet = (device) => { |
|
|
|
|
|
|
|
// None of the hardware wallets are supported
|
|
|
|
|
|
|
|
// At least for now
|
|
|
|
|
|
|
|
if (getPlatform() === PLATFORM_FIREFOX) { |
|
|
|
|
|
|
|
this.setState({ browserSupported: false, error: null}) |
|
|
|
|
|
|
|
return null |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (this.state.accounts.length) { |
|
|
|
if (this.state.accounts.length) { |
|
|
|
return null |
|
|
|
return null |
|
|
|
} |
|
|
|
} |
|
|
|
this.setState({ btnText: this.context.t('connecting')}) |
|
|
|
|
|
|
|
this.getPage(0) |
|
|
|
// Default values
|
|
|
|
|
|
|
|
this.getPage(device, 0, this.props.defaultHdPaths[device]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onPathChange = (path) => { |
|
|
|
|
|
|
|
this.props.setHardwareWalletDefaultHdPath({device: this.state.device, path}) |
|
|
|
|
|
|
|
this.getPage(this.state.device, 0, path) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onAccountChange = (account) => { |
|
|
|
onAccountChange = (account) => { |
|
|
|
this.setState({selectedAccount: account.toString(), error: null}) |
|
|
|
this.setState({selectedAccount: account.toString(), error: null}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onAccountRestriction = () => { |
|
|
|
|
|
|
|
this.setState({error: this.context.t('ledgerAccountRestriction') }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
showTemporaryAlert () { |
|
|
|
showTemporaryAlert () { |
|
|
|
this.props.showAlert(this.context.t('hardwareWalletConnected')) |
|
|
|
this.props.showAlert(this.context.t('hardwareWalletConnected')) |
|
|
|
// Autohide the alert after 5 seconds
|
|
|
|
// Autohide the alert after 5 seconds
|
|
|
@ -65,9 +86,9 @@ class ConnectHardwareForm extends Component { |
|
|
|
}, 5000) |
|
|
|
}, 5000) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
getPage = (page) => { |
|
|
|
getPage = (device, page, hdPath) => { |
|
|
|
this.props |
|
|
|
this.props |
|
|
|
.connectHardware('trezor', page) |
|
|
|
.connectHardware(device, page, hdPath) |
|
|
|
.then(accounts => { |
|
|
|
.then(accounts => { |
|
|
|
if (accounts.length) { |
|
|
|
if (accounts.length) { |
|
|
|
|
|
|
|
|
|
|
@ -77,7 +98,7 @@ class ConnectHardwareForm extends Component { |
|
|
|
this.showTemporaryAlert() |
|
|
|
this.showTemporaryAlert() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const newState = { unlocked: true } |
|
|
|
const newState = { unlocked: true, device, error: null } |
|
|
|
// Default to the first account
|
|
|
|
// Default to the first account
|
|
|
|
if (this.state.selectedAccount === null) { |
|
|
|
if (this.state.selectedAccount === null) { |
|
|
|
accounts.forEach((a, i) => { |
|
|
|
accounts.forEach((a, i) => { |
|
|
@ -104,18 +125,18 @@ class ConnectHardwareForm extends Component { |
|
|
|
}) |
|
|
|
}) |
|
|
|
.catch(e => { |
|
|
|
.catch(e => { |
|
|
|
if (e === 'Window blocked') { |
|
|
|
if (e === 'Window blocked') { |
|
|
|
this.setState({ browserSupported: false }) |
|
|
|
this.setState({ browserSupported: false, error: null}) |
|
|
|
|
|
|
|
} else if (e !== 'Window closed') { |
|
|
|
|
|
|
|
this.setState({ error: e.toString() }) |
|
|
|
} |
|
|
|
} |
|
|
|
this.setState({ btnText: this.context.t('connectToTrezor') }) |
|
|
|
|
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onForgetDevice = () => { |
|
|
|
onForgetDevice = (device) => { |
|
|
|
this.props.forgetDevice('trezor') |
|
|
|
this.props.forgetDevice(device) |
|
|
|
.then(_ => { |
|
|
|
.then(_ => { |
|
|
|
this.setState({ |
|
|
|
this.setState({ |
|
|
|
error: null, |
|
|
|
error: null, |
|
|
|
btnText: this.context.t('connectToTrezor'), |
|
|
|
|
|
|
|
selectedAccount: null, |
|
|
|
selectedAccount: null, |
|
|
|
accounts: [], |
|
|
|
accounts: [], |
|
|
|
unlocked: false, |
|
|
|
unlocked: false, |
|
|
@ -125,13 +146,13 @@ class ConnectHardwareForm extends Component { |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onUnlockAccount = () => { |
|
|
|
onUnlockAccount = (device) => { |
|
|
|
|
|
|
|
|
|
|
|
if (this.state.selectedAccount === null) { |
|
|
|
if (this.state.selectedAccount === null) { |
|
|
|
this.setState({ error: this.context.t('accountSelectionRequired') }) |
|
|
|
this.setState({ error: this.context.t('accountSelectionRequired') }) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.props.unlockTrezorAccount(this.state.selectedAccount) |
|
|
|
this.props.unlockHardwareWalletAccount(this.state.selectedAccount, device) |
|
|
|
.then(_ => { |
|
|
|
.then(_ => { |
|
|
|
this.props.history.push(DEFAULT_ROUTE) |
|
|
|
this.props.history.push(DEFAULT_ROUTE) |
|
|
|
}).catch(e => { |
|
|
|
}).catch(e => { |
|
|
@ -145,20 +166,22 @@ class ConnectHardwareForm extends Component { |
|
|
|
|
|
|
|
|
|
|
|
renderError () { |
|
|
|
renderError () { |
|
|
|
return this.state.error |
|
|
|
return this.state.error |
|
|
|
? h('span.error', { style: { marginBottom: 40 } }, this.state.error) |
|
|
|
? h('span.error', { style: { margin: '20px 20px 10px', display: 'block', textAlign: 'center' } }, this.state.error) |
|
|
|
: null |
|
|
|
: null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
renderContent () { |
|
|
|
renderContent () { |
|
|
|
if (!this.state.accounts.length) { |
|
|
|
if (!this.state.accounts.length) { |
|
|
|
return h(ConnectScreen, { |
|
|
|
return h(ConnectScreen, { |
|
|
|
connectToTrezor: this.connectToTrezor, |
|
|
|
connectToHardwareWallet: this.connectToHardwareWallet, |
|
|
|
btnText: this.state.btnText, |
|
|
|
|
|
|
|
browserSupported: this.state.browserSupported, |
|
|
|
browserSupported: this.state.browserSupported, |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return h(AccountList, { |
|
|
|
return h(AccountList, { |
|
|
|
|
|
|
|
onPathChange: this.onPathChange, |
|
|
|
|
|
|
|
selectedPath: this.props.defaultHdPaths[this.state.device], |
|
|
|
|
|
|
|
device: this.state.device, |
|
|
|
accounts: this.state.accounts, |
|
|
|
accounts: this.state.accounts, |
|
|
|
selectedAccount: this.state.selectedAccount, |
|
|
|
selectedAccount: this.state.selectedAccount, |
|
|
|
onAccountChange: this.onAccountChange, |
|
|
|
onAccountChange: this.onAccountChange, |
|
|
@ -168,6 +191,7 @@ class ConnectHardwareForm extends Component { |
|
|
|
onUnlockAccount: this.onUnlockAccount, |
|
|
|
onUnlockAccount: this.onUnlockAccount, |
|
|
|
onForgetDevice: this.onForgetDevice, |
|
|
|
onForgetDevice: this.onForgetDevice, |
|
|
|
onCancel: this.onCancel, |
|
|
|
onCancel: this.onCancel, |
|
|
|
|
|
|
|
onAccountRestriction: this.onAccountRestriction, |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -188,13 +212,15 @@ ConnectHardwareForm.propTypes = { |
|
|
|
forgetDevice: PropTypes.func, |
|
|
|
forgetDevice: PropTypes.func, |
|
|
|
showAlert: PropTypes.func, |
|
|
|
showAlert: PropTypes.func, |
|
|
|
hideAlert: PropTypes.func, |
|
|
|
hideAlert: PropTypes.func, |
|
|
|
unlockTrezorAccount: PropTypes.func, |
|
|
|
unlockHardwareWalletAccount: PropTypes.func, |
|
|
|
|
|
|
|
setHardwareWalletDefaultHdPath: PropTypes.func, |
|
|
|
numberOfExistingAccounts: PropTypes.number, |
|
|
|
numberOfExistingAccounts: PropTypes.number, |
|
|
|
history: PropTypes.object, |
|
|
|
history: PropTypes.object, |
|
|
|
t: PropTypes.func, |
|
|
|
t: PropTypes.func, |
|
|
|
network: PropTypes.string, |
|
|
|
network: PropTypes.string, |
|
|
|
accounts: PropTypes.object, |
|
|
|
accounts: PropTypes.object, |
|
|
|
address: PropTypes.string, |
|
|
|
address: PropTypes.string, |
|
|
|
|
|
|
|
defaultHdPaths: PropTypes.object, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const mapStateToProps = state => { |
|
|
|
const mapStateToProps = state => { |
|
|
@ -202,28 +228,35 @@ const mapStateToProps = state => { |
|
|
|
metamask: { network, selectedAddress, identities = {}, accounts = [] }, |
|
|
|
metamask: { network, selectedAddress, identities = {}, accounts = [] }, |
|
|
|
} = state |
|
|
|
} = state |
|
|
|
const numberOfExistingAccounts = Object.keys(identities).length |
|
|
|
const numberOfExistingAccounts = Object.keys(identities).length |
|
|
|
|
|
|
|
const { |
|
|
|
|
|
|
|
appState: { defaultHdPaths }, |
|
|
|
|
|
|
|
} = state |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
return { |
|
|
|
network, |
|
|
|
network, |
|
|
|
accounts, |
|
|
|
accounts, |
|
|
|
address: selectedAddress, |
|
|
|
address: selectedAddress, |
|
|
|
numberOfExistingAccounts, |
|
|
|
numberOfExistingAccounts, |
|
|
|
|
|
|
|
defaultHdPaths, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const mapDispatchToProps = dispatch => { |
|
|
|
const mapDispatchToProps = dispatch => { |
|
|
|
return { |
|
|
|
return { |
|
|
|
connectHardware: (deviceName, page) => { |
|
|
|
setHardwareWalletDefaultHdPath: ({device, path}) => { |
|
|
|
return dispatch(actions.connectHardware(deviceName, page)) |
|
|
|
return dispatch(actions.setHardwareWalletDefaultHdPath({device, path})) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
connectHardware: (deviceName, page, hdPath) => { |
|
|
|
|
|
|
|
return dispatch(actions.connectHardware(deviceName, page, hdPath)) |
|
|
|
}, |
|
|
|
}, |
|
|
|
checkHardwareStatus: (deviceName) => { |
|
|
|
checkHardwareStatus: (deviceName, hdPath) => { |
|
|
|
return dispatch(actions.checkHardwareStatus(deviceName)) |
|
|
|
return dispatch(actions.checkHardwareStatus(deviceName, hdPath)) |
|
|
|
}, |
|
|
|
}, |
|
|
|
forgetDevice: (deviceName) => { |
|
|
|
forgetDevice: (deviceName) => { |
|
|
|
return dispatch(actions.forgetDevice(deviceName)) |
|
|
|
return dispatch(actions.forgetDevice(deviceName)) |
|
|
|
}, |
|
|
|
}, |
|
|
|
unlockTrezorAccount: index => { |
|
|
|
unlockHardwareWalletAccount: (index, deviceName, hdPath) => { |
|
|
|
return dispatch(actions.unlockTrezorAccount(index)) |
|
|
|
return dispatch(actions.unlockHardwareWalletAccount(index, deviceName, hdPath)) |
|
|
|
}, |
|
|
|
}, |
|
|
|
showImportPage: () => dispatch(actions.showImportPage()), |
|
|
|
showImportPage: () => dispatch(actions.showImportPage()), |
|
|
|
showConnectPage: () => dispatch(actions.showConnectPage()), |
|
|
|
showConnectPage: () => dispatch(actions.showConnectPage()), |
|
|
|