Browse Source

Merge pull request #23 from loeck/master

Add simple call for get bitcoinAddress on Account page
master
Meriadec Pillet 7 years ago
committed by GitHub
parent
commit
9e085b436a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      README.md
  2. 2
      package.json
  3. 26
      src/actions/devices.js
  4. 9
      src/actions/wallets.js
  5. 66
      src/components/AccountPage.js
  6. 12
      src/components/AppRegionDrag.js
  7. 15
      src/components/SideBar/index.js
  8. 12
      src/components/TopBar.js
  9. 26
      src/components/Wrapper.js
  10. 6
      src/internals/usb/index.js
  11. 8
      src/internals/usb/wallet.js
  12. 8
      src/reducers/devices.js
  13. 6
      src/reducers/index.js
  14. 20
      src/reducers/wallets.js
  15. 31
      src/renderer/events.js
  16. 4
      src/renderer/index.js
  17. 1
      src/styles/global.js

26
README.md

@ -1,32 +1,38 @@
### requirements
# Ledger Wallet Desktop
#### Linux
## Requirements
```
libicns
graphicsmagick
```
* nodejs v8.x (https://nodejs.org/en/)
* yarn latest (https://yarnpkg.com/fr/docs/install)
install dependencies
## Installation
```
yarn
```
launch development version
## Development
```
yarn start
```
build, but not package for distribution
## Build
> Not package for distribution
```
yarn dist:dir
```
build and package everything
> Package everything
```
yarn dist
```
## Release
```
yarn release
```

2
package.json

@ -1,7 +1,7 @@
{
"name": "ledger-wallet-desktop",
"description": "Ledger Wallet Desktop",
"repository": "https://github.com/meriadec/ledger-wallet-desktop-releases-DEV",
"repository": "https://github.com/LedgerHQ/ledger-wallet-desktop",
"version": "0.1.0",
"author": "Ledger",
"license": "BSD-2-Clause",

26
src/actions/devices.js

@ -1,29 +1,29 @@
// @flow
// eslint-disable import/prefer-default-export
/* eslint-disable import/prefer-default-export */
import type { Device, Devices } from 'types/common'
export type deviceChooseType = (Device | null) => { type: string, payload: Device | null }
export const deviceChoose: deviceChooseType = payload => ({
type: 'DEVICE_CHOOSE',
export type SetCurrentDevice = (Device | null) => { type: string, payload: Device | null }
export const setCurrentDevice: SetCurrentDevice = payload => ({
type: 'SET_CURRENT_DEVICE',
payload,
})
type devicesAddType = Device => { type: string, payload: Device }
export const deviceAdd: devicesAddType = payload => ({
type: 'DEVICE_ADD',
type AddDevice = Device => { type: string, payload: Device }
export const addDevice: AddDevice = payload => ({
type: 'ADD_DEVICE',
payload,
})
type devicesRemoveType = Device => { type: string, payload: Device }
export const deviceRemove: devicesRemoveType = payload => ({
type: 'DEVICE_REMOVE',
type RemoveDevice = Device => { type: string, payload: Device }
export const removeDevice: RemoveDevice = payload => ({
type: 'REMOVE_DEVICE',
payload,
})
type devicesUpdateType = Devices => { type: string, payload: Devices }
export const devicesUpdate: devicesUpdateType = payload => ({
type: 'DEVICES_UPDATE',
type UpdateDevices = Devices => { type: string, payload: Devices }
export const updateDevices: UpdateDevices = payload => ({
type: 'UPDATE_DEVICES',
payload,
})

9
src/actions/wallets.js

@ -0,0 +1,9 @@
// @flow
/* eslint-disable import/prefer-default-export */
export type SetCurrentWalletType = (Object | null) => { type: string, payload: Object | null }
export const setCurrentWallet: SetCurrentWalletType = payload => ({
type: 'SET_CURRENT_WALLET',
payload,
})

66
src/components/AccountPage.js

@ -1,15 +1,73 @@
// @flow
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import type { MapStateToProps } from 'react-redux'
import type { Device } from 'types/common'
import { getCurrentDevice } from 'reducers/devices'
import { sendEvent } from 'renderer/events'
import Box from 'components/base/Box'
type Props = {}
const mapStateToProps: MapStateToProps<*, *, *> = state => ({
currentDevice: getCurrentDevice(state),
currentWallet: state.wallets.currentWallet,
})
type Props = {
currentDevice: Device | null,
currentWallet: Object | null,
}
type State = {
address: Object | null,
}
class AccountPage extends PureComponent<Props, State> {
state = {
address: null,
}
componentDidMount() {
this.getWalletInfos()
}
componentWillReceiveProps(nextProps) {
const { currentWallet } = nextProps
if (currentWallet !== null && !currentWallet.err) {
this.setState({
address: currentWallet.data.bitcoinAddress,
})
} else {
this._timeout = setTimeout(() => this.getWalletInfos(), 2e3)
}
}
componentWillUnmount() {
clearTimeout(this._timeout)
}
getWalletInfos() {
const { currentDevice } = this.props
if (currentDevice !== null) {
sendEvent('usb', 'wallet.infos.request', {
path: currentDevice.path,
wallet: 'btc',
})
}
}
_timeout = undefined
class AccountPage extends PureComponent<Props> {
render() {
return <Box>{'account'}</Box>
const { address } = this.state
return <Box>{address === null ? 'Select Bitcoin App on your Ledger' : address}</Box>
}
}
export default AccountPage
export default connect(mapStateToProps)(AccountPage)

12
src/components/AppRegionDrag.js

@ -0,0 +1,12 @@
// @flow
import styled from 'styled-components'
export default styled.div`
-webkit-app-region: drag;
height: 40px;
left: 0;
position: absolute;
right: 0;
top: 0;
`

15
src/components/SideBar/index.js

@ -17,18 +17,19 @@ const CapsSubtitle = styled(Box).attrs({
font-weight: bold;
`
const Container = styled(GrowScroll).attrs({
flow: 4,
py: 4,
const Container = styled(Box).attrs({
noShrink: true,
})`
background-color: ${p => rgba(p.theme.colors[p.bg], 0.4)};
padding-top: 40px;
width: 250px;
`
class SideBar extends PureComponent<{}> {
render() {
return (
<Box noShrink style={{ width: 250 }}>
<Container bg="night">
<Container>
<GrowScroll flow={4} py={4}>
<Box flow={2}>
<CapsSubtitle>{'Menu'}</CapsSubtitle>
<div>
@ -55,8 +56,8 @@ class SideBar extends PureComponent<{}> {
</Item>
</div>
</Box>
</Container>
</Box>
</GrowScroll>
</Container>
)
}
}

12
src/components/TopBar.js

@ -5,11 +5,11 @@ import { connect } from 'react-redux'
import type { MapStateToProps, MapDispatchToProps } from 'react-redux'
import type { Device, Devices } from 'types/common'
import type { deviceChooseType } from 'actions/devices'
import type { SetCurrentDevice } from 'actions/devices'
import { getDevices, getCurrentDevice } from 'reducers/devices'
import { deviceChoose } from 'actions/devices'
import { setCurrentDevice } from 'actions/devices'
import Box from 'components/base/Box'
import Overlay from 'components/base/Overlay'
@ -20,13 +20,13 @@ const mapStateToProps: MapStateToProps<*, *, *> = state => ({
})
const mapDispatchToProps: MapDispatchToProps<*, *, *> = {
deviceChoose,
setCurrentDevice,
}
type Props = {
devices: Devices,
currentDevice: Device,
deviceChoose: deviceChooseType,
setCurrentDevice: SetCurrentDevice,
}
type State = {
@ -59,9 +59,9 @@ class TopBar extends PureComponent<Props, State> {
}
handleSelectDevice = device => () => {
const { deviceChoose } = this.props
const { setCurrentDevice } = this.props
deviceChoose(device)
setCurrentDevice(device)
this.setState({
changeDevice: false,

26
src/components/Wrapper.js

@ -1,6 +1,6 @@
// @flow
import React, { PureComponent } from 'react'
import React, { Fragment, PureComponent } from 'react'
import { ipcRenderer } from 'electron'
import { Route } from 'react-router'
import { translate } from 'react-i18next'
@ -14,6 +14,7 @@ import SendModal from 'components/SendModal'
import ReceiveModal from 'components/ReceiveModal'
import UpdateNotifier from 'components/UpdateNotifier'
import AppRegionDrag from 'components/AppRegionDrag'
import SideBar from 'components/SideBar'
import TopBar from 'components/TopBar'
@ -24,20 +25,25 @@ class Wrapper extends PureComponent<{}> {
render() {
return (
<Box grow horizontal>
<SideBar />
<Box shrink grow bg="cream">
<TopBar />
<Route path="/" component={DashboardPage} />
<Route path="/settings" component={SettingsPage} />
<Route path="/account/:account" component={AccountPage} />
</Box>
<Fragment>
<AppRegionDrag />
<SendModal />
<ReceiveModal />
<UpdateNotifier />
</Box>
<Box grow horizontal>
<SideBar />
<Box shrink grow bg="cream">
<TopBar />
<Route path="/" exact component={DashboardPage} />
<Route path="/settings" component={SettingsPage} />
<Route path="/account/:account" component={AccountPage} />
</Box>
</Box>
</Fragment>
)
}
}

6
src/internals/usb/index.js

@ -7,13 +7,13 @@ import wallet from './wallet'
process.title = 'ledger-wallet-desktop-usb'
function send(type: string, data: any, options: Object = { kill: true }) {
function sendEvent(type: string, data: any, options: Object = { kill: true }) {
process.send({ type, data, options })
}
const handlers = {
devices: devices(send),
wallet: wallet(send),
devices: devices(sendEvent),
wallet: wallet(sendEvent),
}
process.on('message', payload => {

8
src/internals/usb/wallet.js

@ -13,14 +13,14 @@ async function getWalletInfos(path, wallet) {
throw new Error('invalid wallet')
}
export default (send: Function) => ({
export default (sendEvent: Function) => ({
infos: {
request: async ({ path, wallet }: { path: string, wallet: string }) => {
try {
const publicKey = await getWalletInfos(path, wallet)
send('wallet.infos.success', { path, publicKey })
const data = await getWalletInfos(path, wallet)
sendEvent('wallet.infos.success', { path, wallet, data })
} catch (err) {
send('wallet.infos.fail', { path, err: err.stack || err })
sendEvent('wallet.infos.fail', { path, wallet, err: err.stack || err })
}
},
},

8
src/reducers/devices.js

@ -22,19 +22,19 @@ function setCurrentDevice(state) {
}
const handlers: Object = {
DEVICES_UPDATE: (state: DevicesState, { payload: devices }: { payload: Devices }) =>
UPDATE_DEVICES: (state: DevicesState, { payload: devices }: { payload: Devices }) =>
setCurrentDevice({
...state,
devices,
}),
DEVICE_ADD: (state: DevicesState, { payload: device }: { payload: Device }) =>
ADD_DEVICE: (state: DevicesState, { payload: device }: { payload: Device }) =>
setCurrentDevice({
...state,
devices: [...state.devices, device].filter(
(v, i, s) => s.findIndex(t => t.path === v.path) === i,
),
}),
DEVICE_REMOVE: (state: DevicesState, { payload: device }: { payload: Device }) => ({
REMOVE_DEVICE: (state: DevicesState, { payload: device }: { payload: Device }) => ({
...state,
currentDevice:
state.currentDevice !== null && state.currentDevice.path === device.path
@ -42,7 +42,7 @@ const handlers: Object = {
: state.currentDevice,
devices: state.devices.filter(d => d.path !== device.path),
}),
DEVICE_CHOOSE: (state: DevicesState, { payload: currentDevice }: { payload: Device }) => ({
SET_CURRENT_DEVICE: (state: DevicesState, { payload: currentDevice }: { payload: Device }) => ({
...state,
currentDevice,
}),

6
src/reducers/index.js

@ -8,21 +8,25 @@ import type { LocationShape } from 'react-router'
import devices from './devices'
import modals from './modals'
import update from './update'
import wallets from './wallets'
import type { DevicesState } from './devices'
import type { ModalsState } from './modals'
import type { UpdateState } from './update'
import type { WalletsState } from './wallets'
export type State = {
router: LocationShape,
devices: DevicesState,
modals: ModalsState,
update: UpdateState,
wallets: WalletsState,
}
export default combineReducers({
router,
devices,
modals,
router,
update,
wallets,
})

20
src/reducers/wallets.js

@ -0,0 +1,20 @@
// @flow
import { handleActions } from 'redux-actions'
export type WalletsState = {
currentWallet: Object | null,
}
const state: WalletsState = {
currentWallet: null,
}
const handlers: Object = {
SET_CURRENT_WALLET: (state: Object, { payload: currentWallet }: { payload: WalletsState }) => ({
...state,
currentWallet,
}),
}
export default handleActions(handlers, state)

31
src/renderer/initEvents.js → src/renderer/events.js

@ -3,7 +3,8 @@
import { ipcRenderer } from 'electron'
import objectPath from 'object-path'
import { devicesUpdate, deviceAdd, deviceRemove } from 'actions/devices'
import { updateDevices, addDevice, removeDevice } from 'actions/devices'
import { setCurrentWallet } from 'actions/wallets'
import { setUpdateStatus } from 'reducers/update'
type MsgPayload = {
@ -14,7 +15,7 @@ type MsgPayload = {
// wait a bit before launching update check
const CHECK_UPDATE_TIMEOUT = 3e3
function send(channel: string, msgType: string, data: *) {
export function sendEvent(channel: string, msgType: string, data: any) {
ipcRenderer.send(channel, {
type: msgType,
data,
@ -25,27 +26,17 @@ export default (store: Object) => {
const handlers = {
devices: {
update: devices => {
store.dispatch(devicesUpdate(devices))
if (devices.length) {
send('usb', 'wallet.infos.request', {
path: devices[0].path,
wallet: 'btc',
})
}
store.dispatch(updateDevices(devices))
},
},
device: {
add: device => store.dispatch(deviceAdd(device)),
remove: device => store.dispatch(deviceRemove(device)),
add: device => store.dispatch(addDevice(device)),
remove: device => store.dispatch(removeDevice(device)),
},
wallet: {
infos: {
success: ({ path, publicKey }) => {
console.log({ path, publicKey })
},
fail: ({ path, err }) => {
console.log({ path, err })
},
success: ({ wallet, data }) => store.dispatch(setCurrentWallet({ wallet, data })),
fail: ({ wallet, err }) => store.dispatch(setCurrentWallet({ wallet, err })),
},
},
updater: {
@ -70,13 +61,13 @@ export default (store: Object) => {
})
// First time, we get all devices
send('usb', 'devices.all')
sendEvent('usb', 'devices.all')
// Start detection when we plug/unplug devices
send('usb', 'devices.listen')
sendEvent('usb', 'devices.listen')
if (__PROD__) {
// Start check of eventual updates
setTimeout(() => send('msg', 'updater.init'), CHECK_UPDATE_TIMEOUT)
setTimeout(() => sendEvent('msg', 'updater.init'), CHECK_UPDATE_TIMEOUT)
}
}

4
src/renderer/index.js

@ -6,7 +6,7 @@ import { AppContainer } from 'react-hot-loader'
import createHistory from 'history/createHashHistory'
import createStore from 'renderer/createStore'
import initEvents from 'renderer/initEvents'
import events from 'renderer/events'
import App from 'components/App'
@ -16,7 +16,7 @@ const history = createHistory()
const store = createStore(history)
const rootNode = document.getElementById('app')
initEvents(store)
events(store)
function r(Comp) {
if (rootNode) {

1
src/styles/global.js

@ -22,7 +22,6 @@ injectGlobal`
line-height: 1.5;
font-size: 16px;
font-family: "Open Sans", Arial, Helvetica, sans-serif;
-webkit-app-region: drag;
}
#app {

Loading…
Cancel
Save