diff --git a/app/App/Panel/Local/index.js b/app/App/Panel/Local/index.js index 49287f018..c6b0b8f75 100644 --- a/app/App/Panel/Local/index.js +++ b/app/App/Panel/Local/index.js @@ -14,9 +14,9 @@ class Settings extends React.Component { this.networkType = context.store('main.currentNetwork.type') const primaryCustom = context.store('main.networks', this.networkType, this.network, 'connection.primary.custom') || this.customMessage const secondaryCustom = context.store('main.networks', this.networkType, this.network, 'connection.secondary.custom') || this.customMessage - const latticeEndpoint = context.store('main.lattice.endpoint') - const latticeEndpointMode = context.store('main.lattice.endpointMode') - const latticeSuffix = context.store('main.lattice.suffix') + const latticeEndpoint = context.store('main.latticeSettings.endpoint') + const latticeEndpointMode = context.store('main.latticeSettings.endpointMode') + const latticeSuffix = context.store('main.latticeSettings.suffix') this.state = { localShake: {}, primaryCustom, secondaryCustom, latticeEndpoint, latticeSuffix, latticeEndpointMode, resetConfirm: false, expandNetwork: false } context.store.observer(() => { const { type, id } = context.store('main.currentNetwork') @@ -102,6 +102,7 @@ class Settings extends React.Component { clearTimeout(this.inputLatticeTimeout) const value = e.target.value.replace(/\s+/g, '') this.setState({ latticeEndpoint: value }) + // TODO: Update to target specific Lattice device rather than global this.inputLatticeTimeout = setTimeout(() => link.send('tray:action', 'setLatticeEndpoint', this.state.latticeEndpoint), 1000) } @@ -110,6 +111,7 @@ class Settings extends React.Component { clearTimeout(this.inputLatticeSuffixTimeout) const value = e.target.value.replace(/\s+/g, '') this.setState({ latticeSuffix: value }) + // TODO: Update to target specific Lattice device rather than global this.inputLatticeSuffixTimeout = setTimeout(() => link.send('tray:action', 'setLatticeSuffix', this.state.latticeSuffix), 1000) } @@ -358,7 +360,7 @@ class Settings extends React.Component {
Lattice Accounts
link.send('tray:action', 'setLatticeAccountLimit', value)} options={[ { text: '1', value: 1 }, @@ -382,7 +384,7 @@ class Settings extends React.Component {
Lattice Relay
{ let newState = { diff --git a/app/App/Panel/Main/Account/index.js b/app/App/Panel/Main/Account/index.js index b0a77aaf0..0c9898ff4 100644 --- a/app/App/Panel/Main/Account/index.js +++ b/app/App/Panel/Main/Account/index.js @@ -610,6 +610,7 @@ class Account extends React.Component { if (type === 'trezor') return
{svg.trezor(20)}
if (type === 'seed' || type === 'ring') return
{svg.flame(24)}
if (type === 'aragon') return
{svg.aragon(28)}
+ if (type === 'lattice') return
{svg.lattice(22)}
return
{svg.logo(20)}
})()}
diff --git a/app/App/Panel/Main/Add/AddGnosisSafe/index.js b/app/App/Panel/Main/Add/AddGnosisSafe/index.js deleted file mode 100644 index 4210b3c74..000000000 --- a/app/App/Panel/Main/Add/AddGnosisSafe/index.js +++ /dev/null @@ -1,220 +0,0 @@ -import React from 'react' -import Restore from 'react-restore' - -import link from '../../../../../link' -import svg from '../../../../../svg' - -class AddAragon extends React.Component { - constructor (...args) { - super(...args) - this.state = { - adding: false, - agent: '0x0000000000000000000000000000000000000000', - index: 0, - status: '', - error: false, - name: '' - } - this.forms = [React.createRef()] - } - - onChange (key, e) { - e.preventDefault() - const update = {} - update[key] = (e.target.value || '') // .replace(/\W/g, '') - this.setState(update) - } - - onBlur (key, e) { - e.preventDefault() - const update = {} - update[key] = this.state[key] || '' - this.setState(update) - } - - onFocus (key, e) { - e.preventDefault() - if (this.state[key] === '') { - const update = {} - update[key] = '' - this.setState(update) - } - } - - currentForm () { - return this.forms[this.state.index] - } - - blurActive () { - const formInput = this.currentForm() - if (formInput) formInput.current.blur() - } - - focusActive () { - setTimeout(() => { - const formInput = this.currentForm() - if (formInput) formInput.current.focus() - }, 500) - } - - next () { - this.blurActive() - this.setState({ index: ++this.state.index }) - this.focusActive() - } - - actorAccount (actorId) { - this.setState({ actorId }) - this.next() - } - - capitalize (s) { - if (typeof s !== 'string') return '' - return s.charAt(0).toUpperCase() + s.slice(1) - } - - actorAddress (actorAddress, actorIndex) { - link.rpc('resolveAragonName', this.state.name, (err, dao) => { - this.next() - if (err) return this.setState({ status: err, error: true }) - const aragonAccount = { - id: dao.apps.kernel.proxyAddress, - index: 0, - addresses: [dao.apps.agent.proxyAddress], // Agent Address - type: 'aragon', - name: this.capitalize(dao.name) + ' DAO', - ens: dao.ens, - network: dao.network, - smart: { - type: 'aragon', - actor: { // Reference to Frame account that will act on behalf of the agent - id: this.state.actorId, - index: actorIndex, - address: actorAddress // External Signer - }, - dao: dao.apps.kernel.proxyAddress, // DAO Address - agent: dao.apps.agent.proxyAddress // Agent Address - } - } - link.rpc('addAragon', aragonAccount, (err) => { - if (err) { - this.setState({ status: err, error: true }) - } else { - this.setState({ status: 'Successful', error: false }) - setTimeout(() => { - this.store.toggleAddAccount() - }, 2000) - } - }) - }) - } - - accountSort (a, b) { - const accounts = this.store('main.accounts') - a = accounts[a].created - b = accounts[b].created - if (a === -1 && b !== -1) return -1 - if (a !== -1 && b === -1) return 1 - if (a > b) return -1 - if (a < b) return 1 - return 0 - } - - accountFilter (id) { - // Need to migrate accounts to use network type - const network = this.store('main.currentNetwork.id') - const account = this.store('main.accounts', id) - if (account.type === 'aragon') return false - return account.network === network - } - - restart () { - this.setState({ adding: false, agent: '0x0000000000000000000000000000000000000000', index: 0, name: '' }) - setTimeout(() => { - this.setState({ status: '', error: false }) - }, 500) - this.focusActive() - } - - adding () { - this.setState({ adding: true }) - this.focusActive() - } - - render () { - let itemClass = 'addAccountItem addAccountItemSmart' - if (this.state.adding) itemClass += ' addAccountItemAdding' - return ( -
-
-
-
-
-
{svg.aragon(30)}
-
-
-
Aragon
-
-
-
An Aragon smart account allows you to use your Aragon DAO with any dapp
-
-
this.adding()}> -
Add Aragon Account
-
-
-
-
-
enter dao name
-
- this.onChange('name', e)} onFocus={e => this.onFocus('name', e)} onBlur={e => this.onBlur('name', e)} onKeyPress={e => { if (e.key === 'Enter') this.next() }} /> -
-
this.next()}>Next
-
-
-
Choose acting account
-
- {Object.keys(this.store('main.accounts')) - .filter(id => this.accountFilter(id)) - .sort((a, b) => this.accountSort(a, b)) - .map(id => { - const account = this.store('main.accounts', id) - return
this.actorAccount(id)}>{account.name}
- })} -
-
-
-
Choose acting address
-
- {(this.store('main.accounts', this.state.actorId, 'addresses') || []).map((a, i) => { - return ( -
this.actorAddress(a, i)}> - {a ? a.substring(0, 10) : ''}{svg.octicon('kebab-horizontal', { height: 16 })}{a ? a.substr(a.length - 10) : ''} -
- ) - })} -
-
-
-
{this.state.status}
- {this.state.error ?
this.restart()}>try again
: null} -
-
-
-
-
{ - const net = this.store('main.currentNetwork.id') - const open = url => this.store.notify('openExternal', { url }) - if (net === '1') return open('https://mainnet.aragon.org') - if (net === '4') return open('https://rinkeby.aragon.org') - return open('https://aragon.org') - }} - >{'Don\'t have a dao? Create one'} -
-
-
- ) - } -} - -export default Restore.connect(AddAragon) diff --git a/app/App/Panel/Main/Add/AddHardwareLattice/index.js b/app/App/Panel/Main/Add/AddHardwareLattice/index.js deleted file mode 100644 index e68b201fa..000000000 --- a/app/App/Panel/Main/Add/AddHardwareLattice/index.js +++ /dev/null @@ -1,188 +0,0 @@ -import React from 'react' -import Restore from 'react-restore' - -import link from '../../../../../link' -import svg from '../../../../../svg' //TODO: get gridplus svg - -class AddHardwareLattice extends React.Component { - constructor(...args) { - super(...args) - this.state = { - adding: false, - index: 0, - status: '', - error: false, - deviceID: '', - pairCode: '', - } - this.forms = [React.createRef(), React.createRef(), React.createRef()] - } - - onChange(key, e) { - e.preventDefault() - const update = {} - update[key] = (e.target.value || '') // .replace(/\W/g, '') - this.setState(update) - } - - onBlur(key, e) { - e.preventDefault() - const update = {} - update[key] = this.state[key] || '' - this.setState(update) - } - - onFocus(key, e) { - e.preventDefault() - if (this.state[key] === '') { - const update = {} - update[key] = '' - this.setState(update) - } - } - - currentForm() { - return this.forms[this.state.index] - } - - blurActive() { - const formInput = this.currentForm() - if (formInput && formInput.current) formInput.current.blur() - } - - focusActive() { - setTimeout(() => { - const formInput = this.currentForm() - if (formInput && formInput.current) formInput.current.focus() - }, 500) - } - - next() { - this.blurActive() - this.setState({index: ++this.state.index}) - this.focusActive() - } - - connectToLattice() { - link.rpc('latticeConnect', { - deviceID: this.state.deviceID, - }, (err, response = []) => { - if (err || !response || response && response.length === 0) { - return this.setState({status: err, index: 2, error: true}) - } - const [accounts, isPaired] = response; - if (!isPaired) { - this.next(); - this.setState({status: 'Pairing Device', error: false}) - } else if (accounts && accounts.length > 0) { - this.setState({status: 'Adding Accounts', index: 2, error: false}) - setTimeout(() => { - this.store.toggleAddAccount() - }, 1000) - } else if (!err && isPaired === typeof 'undefined') { - this.setState({status: 'ok', index: 2, error: true}) - } - }); - } - - - pairToLattice() { - this.next(); - link.rpc('latticePair', this.state.deviceID, this.state.pairCode, (err, accounts) => { - if (err) { - this.setState({status: err, error: true}) - } else if(accounts.length > 0) { - this.setState({status: 'Adding Accounts', index:2, error: false}) - setTimeout(() => { - this.store.toggleAddAccount() - }, 2000) - } - }) - } - - capitalize(s) { - if (typeof s !== 'string') return '' - return s.charAt(0).toUpperCase() + s.slice(1) - } - - - restart() { - this.setState({adding: false, index: 0, pairCode: ''}) - setTimeout(() => { - this.setState({status: '', error: false}) - }, 500) - this.focusActive() - } - - adding() { - this.setState({adding: true}) - this.focusActive() - } - - render() { - let itemClass = 'addAccountItem addAccountItemSmart' - if (this.state.adding) itemClass += ' addAccountItemAdding' - return ( -
-
-
-
-
-
{svg.lattice(32)}
-
-
-
Lattice
-
-
-
Unlock your Lattice to get started
-
-
this.adding()}> -
Add Lattice
-
-
-
-
-
enter device id
-
- this.onChange('deviceID', e)} - onFocus={e => this.onFocus('deviceID', e)} - onBlur={e => this.onBlur('deviceID', e)} onKeyPress={e => { - if (e.key === 'Enter') this.connectToLattice() - }}/> -
-
this.connectToLattice()}>Next -
-
-
-
enter generated passcode
-
- this.onChange('pairCode', e)} - onFocus={e => this.onFocus('pairCode', e)} - onBlur={e => this.onBlur('pairCode', e)} onKeyPress={e => { - if (e.key === 'Enter') this.pairToLattice() - }}/> -
-
this.pairToLattice()}>Pair -
-
-
-
{this.state.status}
- {this.state.error ?
this.restart()}>try again
: null} -
-
-
-
-
-
- ) - } -} - -export default Restore.connect(AddHardwareLattice) diff --git a/dash/App/Add/AddAddress/index.js b/dash/App/Add/AddAddress/index.js index f744a78eb..907039357 100644 --- a/dash/App/Add/AddAddress/index.js +++ b/dash/App/Add/AddAddress/index.js @@ -110,6 +110,7 @@ class AddPhrase extends React.Component {
Address
+
this.props.close()}>{svg.close(24)}
An address account represents an address but cannot sign for it
diff --git a/dash/App/Add/AddAragon/index.js b/dash/App/Add/AddAragon/index.js index c175e2804..70dabec18 100644 --- a/dash/App/Add/AddAragon/index.js +++ b/dash/App/Add/AddAragon/index.js @@ -151,10 +151,10 @@ class AddAragon extends React.Component {
{svg.aragon(30)}
-
Aragon
+
this.props.close()}>{svg.close(24)}
An Aragon smart account allows you to use your Aragon DAO with any dapp
diff --git a/dash/App/Add/AddHardware/index.js b/dash/App/Add/AddHardware/index.js index d02cd707c..35b8fe071 100644 --- a/dash/App/Add/AddHardware/index.js +++ b/dash/App/Add/AddHardware/index.js @@ -37,6 +37,7 @@ class AddHardware extends React.Component {
{this.deviceName}
+
this.props.close()}>{svg.close(24)}
{`Unlock your ${this.deviceName} to get started`}
diff --git a/dash/App/Add/AddHardwareLattice/index.js b/dash/App/Add/AddHardwareLattice/index.js index 33d08553f..74dccd089 100644 --- a/dash/App/Add/AddHardwareLattice/index.js +++ b/dash/App/Add/AddHardwareLattice/index.js @@ -4,6 +4,8 @@ import Restore from 'react-restore' import link from '../../../../resources/link' import svg from '../../../../resources/svg' // TODO: get gridplus svg +import Signer from '../../Signer' + class AddHardwareLattice extends React.Component { constructor (...args) { super(...args) @@ -12,7 +14,7 @@ class AddHardwareLattice extends React.Component { index: 0, status: '', error: false, - deviceID: '', + deviceId: '', pairCode: '' } this.forms = [React.createRef(), React.createRef(), React.createRef()] @@ -63,38 +65,12 @@ class AddHardwareLattice extends React.Component { this.focusActive() } - connectToLattice () { - link.rpc('latticeConnect', { - deviceID: this.state.deviceID - }, (err, response = []) => { - if (err || !response || response.length === 0) { - return this.setState({ status: err, index: 2, error: true }) - } - const [accounts, isPaired] = response - if (!isPaired) { - this.next() - this.setState({ status: 'Pairing Device', error: false }) - } else if (accounts && accounts.length > 0) { - this.setState({ status: 'Adding Accounts', index: 2, error: false }) - setTimeout(() => { - this.store.toggleAddAccount() - }, 1000) - } else if (!err && isPaired === typeof 'undefined') { - this.setState({ status: 'ok', index: 2, error: true }) - } - }) - } - - pairToLattice () { - this.next() - link.rpc('latticePair', this.state.deviceID, this.state.pairCode, (err, accounts) => { + createLattice () { + link.rpc('createLattice', this.state.deviceId, (err, signer) => { if (err) { this.setState({ status: err, error: true }) - } else if (accounts.length > 0) { - this.setState({ status: 'Adding Accounts', index: 2, error: false }) - setTimeout(() => { - this.store.toggleAddAccount() - }, 2000) + } else { + this.setState({ status: 'Successful', error: false, createdSignerId: signer.id }) } }) } @@ -112,90 +88,67 @@ class AddHardwareLattice extends React.Component { this.focusActive() } - adding () { - this.setState({ adding: true }) - this.focusActive() - } - render () { - let itemClass = 'addAccountItem addAccountItemSmart' - if (this.state.adding) itemClass += ' addAccountItemAdding' + let itemClass = 'addAccountItem addAccountItemSmart addAccountItemAdding' + let signer + if (this.state.createdSignerId) { + signer = this.store('main.signers', this.state.createdSignerId) + } + return (
-
-
{svg.lattice(32)} +
+
+
{svg.lattice(24)}
-
+
Lattice
-
Lattice
-
+
this.props.close()}>{svg.close(24)}
+
Grid+ Lattice1
-
Unlock your Lattice to get started
-
this.adding()}> -
Add Lattice
-
-
enter device id
-
- this.onChange('deviceID', e)} - onFocus={e => this.onFocus('deviceID', e)} - onBlur={e => this.onBlur('deviceID', e)} onKeyPress={e => { - if (e.key === 'Enter') this.connectToLattice() - }} - /> -
-
this.connectToLattice()} - >Next -
-
-
-
enter generated passcode
+
Enter device id
this.onChange('pairCode', e)} - onFocus={e => this.onFocus('pairCode', e)} - onBlur={e => this.onBlur('pairCode', e)} onKeyPress={e => { - if (e.key === 'Enter') this.pairToLattice() + tabIndex='-1' ref={this.forms[0]} value={this.state.deviceId} + onChange={e => this.onChange('deviceId', e)} + onFocus={e => this.onFocus('deviceId', e)} + onBlur={e => this.onBlur('deviceId', e)} onKeyPress={e => { + if (e.key === 'Enter') this.createLattice() }} />
this.pairToLattice()} - >Pair + onMouseDown={() => { + this.createLattice() + this.next() + }} + >Create
-
{this.state.status}
- {this.state.error ? ( -
this.restart()} - > - try again -
- ) : null} + {signer ? + : ( + <> +
{this.state.status}
+ {this.state.error ?
this.restart()}>try again
: null} + + )}
+
) diff --git a/dash/App/Add/AddPhrase/index.js b/dash/App/Add/AddPhrase/index.js index 2bf452202..87478090f 100644 --- a/dash/App/Add/AddPhrase/index.js +++ b/dash/App/Add/AddPhrase/index.js @@ -119,6 +119,7 @@ class AddPhrase extends React.Component {
Phrase
+
this.props.close()}>{svg.close(24)}
A phrase account uses a list of words to backup and restore your account
diff --git a/dash/App/Add/AddRing/index.js b/dash/App/Add/AddRing/index.js index c14579bc4..6a4f4a368 100644 --- a/dash/App/Add/AddRing/index.js +++ b/dash/App/Add/AddRing/index.js @@ -166,6 +166,7 @@ class AddRing extends React.Component {
Keyring
+
this.props.close()}>{svg.close(24)}
A keyring account lets you to add individual private keys to an account
diff --git a/dash/App/Add/style/index.styl b/dash/App/Add/style/index.styl index 052cd616b..e55ca316e 100644 --- a/dash/App/Add/style/index.styl +++ b/dash/App/Add/style/index.styl @@ -231,6 +231,20 @@ flex-direction column position relative + .addAccountItemClose + position absolute + top 15px + right 14px + padding 10px + border-radius 8px + cursor pointer + + * + pointer-events none + + .addAccountItemClose:hover + background var(--ghostC) + .addAccountItemTopType position absolute top 0 @@ -466,7 +480,6 @@ display flex width 1000% height 100% - // background var(--ghostA) .addAccountItemOptionSetupFrame display flex @@ -476,7 +489,11 @@ transition var(--standardSlow) width 10% overflow-y scroll - // background red + background var(--ghost) + height 100% + display flex + justify-content center + align-items center // .addressList // .signerAddress diff --git a/dash/App/Signer/index.js b/dash/App/Signer/index.js index f8e1dde39..96fd4cba8 100644 --- a/dash/App/Signer/index.js +++ b/dash/App/Signer/index.js @@ -9,7 +9,8 @@ class Signer extends React.Component { super(...args) this.state = { page: 0, - addressLimit: 4 + addressLimit: 4, + latticePairCode: '' } } status () { @@ -46,6 +47,16 @@ class Signer extends React.Component { this.setState({ page }) } + pairToLattice () { + link.rpc('latticePair', this.props.id, this.state.latticePairCode, (err, accounts) => { + if (err) { + this.setState({ status: err, error: true }) + } else { + this.setState({ status: 'Adding Accounts', index: 2, error: false }) + } + }) + } + render () { const signer = this.store('main.signers', this.props.id) const { page, addressLimit } = this.state @@ -54,45 +65,94 @@ class Signer extends React.Component { const activeAccounts = signer.addresses.filter(a => this.store('main.accounts', a.toLowerCase())) return ( -
+
{this.props.type + ' Signer'}
-
{'Signer Name'}
+
+ {'Signer Name'} +
+ {svg.save(14)} +
+
{this.status()}
-
- {'Add & Remove Accounts'} - 0 ? 'signerAccountsTitleActive signerAccountsTitleActiveOn' : 'signerAccountsTitleActive'}> - {activeAccounts.length} - {'active'} - -
-
{signer.addresses.slice(startIndex, startIndex + addressLimit).map((address, index) => { - const added = this.store('main.accounts', address.toLowerCase()) - return ( -
{ - if (this.store('main.accounts', address.toLowerCase())) { - link.rpc('removeAccount', address, {}, () => { - // console.log('Removed account ', address) - }) - } else { - link.rpc('createAccount', address, { type: signer.type }, () => { - // console.log('Added account ', address) - }) - } - }}> -
{index + 1 + startIndex}
-
{address.substr(0, 11)} {svg.octicon('kebab-horizontal', { height: 20 })} {address.substr(address.length - 10)}
-
{svg.check(22)}
+ {this.props.status === 'loading' ? ( +
+
+
+ ) : this.props.type === 'lattice' && this.props.status === 'pairing' ? ( +
+
Please input your Lattice's pairing code
+
+
+ this.setState({ latticePairCode: e.target.value })} + // onFocus={e => this.onFocus('pairCode', e)} + // onBlur={e => this.onBlur('pairCode', e)} + onKeyPress={e => { + if (e.key === 'Enter') this.pairToLattice() + }} + /> +
+
+
- ) - })}
-
-
this.nextPage(true)}>{svg.triangleLeft(20)}
-
{(page + 1) + ' / ' + Math.ceil(signer.addresses.length / addressLimit)}
-
this.nextPage()}>{svg.triangleLeft(20)}
+
this.pairToLattice()} + className='signerLatticePairSubmit' + >Pair
+
+ ) : ( + <> +
+ {'Add & Remove Accounts'} + 0 ? 'signerAccountsTitleActive signerAccountsTitleActiveOn' : 'signerAccountsTitleActive'}> + {'active'} + {activeAccounts.length} + +
+
{signer.addresses.slice(startIndex, startIndex + addressLimit).map((address, index) => { + const added = this.store('main.accounts', address.toLowerCase()) + return ( +
{ + if (this.store('main.accounts', address.toLowerCase())) { + link.rpc('removeAccount', address, {}, () => { + // console.log('Removed account ', address) + }) + } else { + link.rpc('createAccount', address, { type: signer.type }, () => { + // console.log('Added account ', address) + }) + } + }}> +
{index + 1 + startIndex}
+
{address.substr(0, 11)} {svg.octicon('kebab-horizontal', { height: 20 })} {address.substr(address.length - 10)}
+
{svg.check(22)}
+
+ ) + })}
+
+
this.nextPage(true)}>{svg.triangleLeft(20)}
+
{(page + 1) + ' / ' + Math.ceil(signer.addresses.length / addressLimit)}
+
this.nextPage()}>{svg.triangleLeft(20)}
+
+ + )} +
this.setState({ showControls: !this.state.showControls })}> +
+ {this.state.showControls ? 'hide' : 'settings'} +
+
- + {this.state.showControls ? ( +
+
Deactivte Accounts
+
{ + link.send('dash:removeSigner', this.props.id) + }}>Remove Signer
+
+ ) : null}
) } diff --git a/dash/App/Signer/style/index.styl b/dash/App/Signer/style/index.styl index c5746a75e..bf46e06fb 100644 --- a/dash/App/Signer/style/index.styl +++ b/dash/App/Signer/style/index.styl @@ -1,11 +1,11 @@ .signer position relative - width 348px + width 100% // height 300px overflow hidden - background var(--ghostB) + background var(--ghostA) box-sizing border-box - margin 4px + margin 0px 10px 40px 10px border-radius 8px .signerTop @@ -14,18 +14,40 @@ .signerName position absolute - top 30px + top 9px left 4px - right 4px - height 36px - border-radius 18px + height 28px + padding 0px 9px + border-radius 8px // text-align center // border-top 1px solid var(--ghostZ) // border-bottom 1px solid var(--ghostZ) - background var(--ghostA) display flex - justify-content center + // justify-content center align-items center + box-sizing border-box + + .signerNameUpdate + position absolute + width 28px + height 28px + // background red + right -34px + color var(--good) + display flex + align-items center + cursor pointer + pointer-events none + opacity 0 + * + pointer-events none + + .signerNameFocused + background var(--ghostZ) + .signerNameUpdate + opacity 1 + + .signerType // position absolute @@ -35,9 +57,9 @@ // text-transform uppercase // font-weight 400 position absolute - top 6px - left 10px - font-size 12px + top 38px + left 14px + font-size 10px text-transform uppercase font-weight 400 letter-spacing 1px @@ -52,8 +74,8 @@ .signerStatusIndicator position absolute - top 10px - right 10px + top 18px + right 18px font-size 12px text-transform uppercase font-weight 400 @@ -71,8 +93,8 @@ .signerStatusText position absolute - top 6px - right 30px + top 15px + right 45px font-size 12px text-transform uppercase font-weight 400 @@ -108,7 +130,7 @@ text-align center .signerBottomPageBack - background var(--ghostD) + background var(--ghostC) padding 2px 1px 2px 2px height 24px width 24px @@ -119,7 +141,7 @@ pointer-events none .signerBottomPageNext - background var(--ghostD) + background var(--ghostC) transform rotate(180deg) padding 2px 2px 2px 1px height 24px @@ -130,11 +152,101 @@ * pointer-events none + .signerDrawer + position relative + height 40px + + .showControls + position absolute + height 20px + border-radius 10px + border 1px solid var(--ghostZ) + background var(--ghostA) + z-index 2 + top 9px + left 50% + width 100px + margin-left -50px + font-size 10px + display flex + justify-content center + align-items center + text-transform uppercase + cursor pointer + color var(--outerspace02) + transition var(--standardFast) + + .showControls:hover + background var(--ghostB) + color var(--outerspace) + + .showControlsLine + height 1px + position absolute + top 50% + left 0 + right 0 + background var(--ghostZ) + z-index 1 + margin-top -1px + + .signerControls + padding-top 10px + + .signerControlOption + height 40px + background var(--ghostB) + margin 0px 10px 10px 10px + border-radius 8px + display flex + justify-content center + align-items center + font-size 14px + cursor pointer + + * + pointer-events none + + .signerControlOptionImportant + color var(--bad) + + .signerLatticePair + height 200px + + .signerLatticePairTitle + height 40px + display flex + justify-content center + align-items center + font-size 17px + font-weight 200 + text-transform none + + .signerLatticePairInput + background var(--ghostC) + height 60px + border-radius 8px + margin 10px 0px 20px 0px + + .signerLatticePairSubmit + width 100px + height 30px + display flex + justify-content center + align-items center + background var(--ghostC) + border-radius 15px + position relative + left 50% + margin-left -50px + cursor pointer + * + pointer-events none .signerAccountsTitle // background pink - font-size 13px - font-weight 400 + font-size 12px + font-weight 300 display flex justify-content space-between align-items center @@ -142,19 +254,33 @@ padding 0px 12px 4px 12px .signerAccountsTitleActive - font-weight 600 text-transform uppercase font-size 10px + font-weight 600 + letter-spacing 1px display flex justify-content space-between align-items center + color var(--outerspace) .signerAccountsTitleActiveCount - font-size 14px - padding-right 4px + font-size 13px + margin-left 5px + font-weight 400 + margin-top -1px + height 24px + width 24px + border-radius 12px + box-sizing border-box + display flex + justify-content center + align-items center + padding-left 1px + background var(--ghostZ) .signerAccountsTitleActiveOn - color var(--good) + .signerAccountsTitleActiveCount + color var(--good) .signerAccounts //position absolute @@ -178,8 +304,8 @@ margin 4px 6px width calc(100% - 12px) position relative - border-bottom 1px solid var(--ghostC) - background var(--ghostD) + border-bottom 1px solid var(--ghostB) + background var(--ghostC) border-radius 12px box-shadow 0px 2px 3px var(--ghostZ) cursor pointer @@ -226,12 +352,45 @@ display flex justify-content center align-items center - color var(--ghostA) + color var(--ghostZ) .signerAccountAdded color var(--good) .signerAccountCheck color var(--good) - .signerAccount:last-child - border-bottom none \ No newline at end of file + .signerAccountlast-child + border-bottom none + +.signerLoading + height 60px + display flex + justify-content center + align-items center + padding-bottom 20px + +.signerLoadingLoader, .signerLoadingLoaderafter + border-radius 50% + width 50px + height 50px + +.signerLoadingLoader + margin 60px auto + font-size 10px + position relative + text-indent -9999em + border-top 3px solid var(--ghostZ) + border-right 3px solid var(--ghostZ) + border-bottom 3px solid var(--ghostZ) + border-left 3px solid var(--good) + transform translateZ(0) + animation load8 0.5s infinite linear + +@keyframes load8 + 0% + -webkit-transform rotate(0deg) + transform rotate(0deg) + + 100% + -webkit-transform rotate(360deg) + transform rotate(360deg) diff --git a/dash/App/index.js b/dash/App/index.js index 75d270ab5..8cf3c2f35 100644 --- a/dash/App/index.js +++ b/dash/App/index.js @@ -22,42 +22,42 @@ class AddAccounts extends React.Component { renderAddNonsigning () { return (
- +
) } renderAddKeystore () { return (
- +
) } renderAddSeed () { return (
- +
) } renderAddTrezor () { return (
- +
) } renderAddLedger () { return (
- +
) } renderAddLattice () { return (
- +
) } @@ -71,13 +71,17 @@ class AddAccounts extends React.Component { renderAddAragon () { return (
- +
) } renderDefault () { return (
+
+
What type of account would you like to add?
+
this.props.close()}>x
+
this.setState({ view: 'aragon' })}>Aragon DAO
{/*
this.setState({ view: 'gnosis' })}>Gnosis Safe
*/}
this.setState({ view: 'ledger' })}>Ledger Wallet
@@ -85,7 +89,7 @@ class AddAccounts extends React.Component {
this.setState({ view: 'lattice' })}>Grid+ Lattice1
this.setState({ view: 'seed' })}>Seed Phrase
this.setState({ view: 'keystore' })}>Keystore.json
-
this.setState({ view: 'nonsigning' })}>Non-signing Account
+
this.setState({ view: 'nonsigning' })}>A Non-signing Account
) } @@ -149,7 +153,7 @@ class Dash extends React.Component { }).filter(s => s) return (
- {this.state.showAddAccounts ? : null} + {this.state.showAddAccounts ? this.setState({ showAddAccounts: false })} /> : null}
this.setState({ showAddAccounts: !this.state.showAddAccounts })}> Add New Accounts
@@ -160,7 +164,7 @@ class Dash extends React.Component {
{hardwareSigners.length ? ( - hardwareSigners.map(signer => ) + hardwareSigners.map((signer, index) => ) ) : (
{'No hardware signers detected'} @@ -172,7 +176,7 @@ class Dash extends React.Component {
{hotSigners.length ? ( - hotSigners.map(signer => ) + hotSigners.map((signer, index) => ) ) : (
{'No hot signers detected'} diff --git a/dash/index.js b/dash/index.js index e841688ee..2c4798505 100644 --- a/dash/index.js +++ b/dash/index.js @@ -12,7 +12,6 @@ document.addEventListener('drop', e => e.preventDefault()) window.eval = global.eval = () => { throw new Error(`This app does not support window.eval()`) } // eslint-disable-line link.rpc('getState', (err, state) => { if (err) return console.error('Could not get initial state from main') - console.log('initial state', state) const store = _store(state) window.store = store store.observer(() => { diff --git a/dash/index.styl b/dash/index.styl index 19331a0ca..9fe5bd033 100644 --- a/dash/index.styl +++ b/dash/index.styl @@ -26,7 +26,7 @@ div .addAccounts position absolute - top 100px + top 0px left 0 right 0 bottom 0 @@ -35,6 +35,23 @@ div overflow-y scroll overflow-x hidden + .addAccountsHeader + height 100px + + .addAccountsHeaderClose + position absolute + top 15px + right 14px + padding 10px + border-radius 8px + cursor pointer + + * + pointer-events none + + .addAccountsHeaderClose:hover + background var(--ghostC) + .accountTypeSelect height 60px width 320px @@ -47,18 +64,26 @@ div cursor pointer .newAccount - height 64px - width 310px + height 40px + // width 310px background var(--ghostB) // var(--ghostE) 0%, var(--ghostG) 70%) - border-radius 12px + border-radius 24px display flex justify-content center align-items center - margin 20px + margin 40px box-shadow 0px 9px 3px outerspace cursor pointer - font-size 20px - font-weight 100 + font-size 15px + font-weight 500 + background var(--good) + color var(--goodDark) + text-transform uppercase + border-bottom 3px solid var(--goodShade) + box-shadow 0px 0px 12px var(--good02), 0px 24px 12px -14px var(--ghostY) + padding-top 1px + box-sizing border-box + .signers width 100% @@ -84,23 +109,26 @@ div // padding 4px .signersHeader - height 40px - width 100% + width calc(100% - 24px) display flex align-items center - padding-left 8px - padding-top 16px - font-size 19px + padding 12px 4px 11px 4px + font-size 18px font-weight 100 + border-bottom 1px solid var(--ghostY) + border-top 1px solid var(--ghostY) + // background var(--ghostY) + margin 0px 12px 10px 12px + box-sizing border-box .noSigners position relative - width 348px - height 30px + width 100% + height 48px overflow hidden - background var(--ghostC) + background var(--ghostA) box-sizing border-box - margin 4px + margin 0px 10px 40px 10px border-radius 8px display flex justify-content center diff --git a/main/accounts/Account/index.js b/main/accounts/Account/index.js index b2fabc298..ae74a0cd7 100644 --- a/main/accounts/Account/index.js +++ b/main/accounts/Account/index.js @@ -88,6 +88,7 @@ class Account { const availiableSigners = [] const signers = store('main.signers') Object.keys(signers).forEach(id => { + if (!signers[id] || !id) return if (signers[id].addresses.map(a => a.toLowerCase()).indexOf(address) > -1) { availiableSigners.push(signers[id]) } diff --git a/main/index.js b/main/index.js index 4f817e2be..7a04fa431 100644 --- a/main/index.js +++ b/main/index.js @@ -100,7 +100,6 @@ ipcMain.on('tray:installAvailableUpdate', (e, install, dontRemind) => { }) ipcMain.on('tray:removeAccount', (e, id) => { - signers.remove(id) accounts.remove(id) }) @@ -108,7 +107,7 @@ ipcMain.on('tray:renameAccount', (e, id, name) => { accounts.rename(id, name) }) -ipcMain.on('tray:removeSigner', (e, id) => { +ipcMain.on('dash:removeSigner', (e, id) => { signers.remove(id) }) diff --git a/main/rpc/index.js b/main/rpc/index.js index a0ec51932..212c15509 100644 --- a/main/rpc/index.js +++ b/main/rpc/index.js @@ -1,6 +1,6 @@ const { ipcMain, dialog } = require('electron') const fs = require('fs') -// const log = require('electron-log') +const log = require('electron-log') const utils = require('web3-utils') const accounts = require('../accounts') @@ -48,11 +48,21 @@ const rpc = { // unsetSigner: signers.unsetSigner, trezorPin: (id, pin, cb) => signers.trezorPin(id, pin, cb), trezorPhrase: (id, phrase, cb) => signers.trezorPhrase(id, phrase, cb), - latticePair (id, pin, cb) { - signers.latticePair(id, pin).then(result => cb(null, result)).catch(err => cb(err)) + createLattice: async (id, cb) => { + try { + cb(null, await signers.createLattice(id)) + } catch (e) { + log.error('latticeContactError', e) + cb(e) + } }, - latticeConnect (connectOpts, cb) { - signers.latticeConnect(connectOpts).then((result) => cb(null, result)).catch(err => cb(err)) + latticePair (id, pin, cb) { + signers.latticePair(id, pin).then(result => { + cb(null, result) + }).catch(err => { + log.error('latticePairError', err) + cb(err) + }) }, launchStatus: launch.status, providerSend: (payload, cb) => provider.send(payload, cb), diff --git a/main/signers/index.js b/main/signers/index.js index 29b5bfa8e..163914391 100644 --- a/main/signers/index.js +++ b/main/signers/index.js @@ -6,12 +6,14 @@ const ledger = require('./ledger') const trezorConnect = require('./trezor-connect') const lattice = require('./lattice') +const store = require('../store') + class Signers extends EventEmitter { constructor () { super() this.signers = [] - this.lattice = lattice(this) - this.lattice.scan() + // this.lattice = lattice(this) + lattice.scan(this) hot.scan(this) ledger.scan(this) trezorConnect.scan(this) @@ -39,13 +41,13 @@ class Signers extends EventEmitter { async latticePair (id, pin) { try { - const signer = this.get(`Lattice-${id}`) - if (signer && signer.setPin) { + const signer = this.get(id) + if (signer && signer.setPair) { try { - const result = await signer.setPin(pin) - + const result = await signer.setPair(pin) return result } catch (err) { + log.error('latticePair Error', err) return new Error(err) } } else { @@ -56,6 +58,21 @@ class Signers extends EventEmitter { } } + async createLattice (deviceId) { + if (deviceId) { + store.updateLattice(deviceId, { + deviceId, + baseUrl: 'https://signing.gridpl.us', + endpointMode: 'default', + suffix: '' + }) + return { id: 'lattice-' + deviceId} + } else { + throw new Error('No Device ID') + } + } + + async latticeConnect (connectOpts) { const signer = lattice(this) if (signer && signer.open) { @@ -64,10 +81,10 @@ class Signers extends EventEmitter { return response } catch (err) { - throw new Error('could not connect to lattice') + throw new Error('Could not connect to lattice', err) } } else { - return new Error('signer library issue') + return new Error('Lattice, no signer or signer not open') } } diff --git a/main/signers/lattice/Lattice/index.js b/main/signers/lattice/Lattice/index.js index c50b27577..abf64465e 100644 --- a/main/signers/lattice/Lattice/index.js +++ b/main/signers/lattice/Lattice/index.js @@ -1,19 +1,15 @@ -const windows = require('../../../windows') +const crypto = require('crypto') const log = require('electron-log') const utils = require('web3-utils') -const Client = require('gridplus-sdk').Client const EthereumTx = require('ethereumjs-tx') +const { Client } = require('gridplus-sdk') +const { promisify } = require('util') + const store = require('../../../store') const Signer = require('../../Signer') -const crypto = require('crypto') -const promisify = require('util').promisify + const HARDENED_OFFSET = 0x80000000 -const clientConfig = { - name: 'Frame', - crypto: crypto, - privKey: null, - timeout: 30000 -} + function humanReadable (str) { for (let i = 0; i < str.length; i++) { if (str.charCodeAt(i) < 0x0020 || str.charCodeAt(i) > 0x007f) { return false } @@ -22,83 +18,92 @@ function humanReadable (str) { } class Lattice extends Signer { - constructor (device, signers) { + constructor (deviceId, signers) { super() this.signers = signers - log.info('Setting up Lattice device') - this.device = device - this.id = this.getId() - this.accountLimit = store('main.lattice.accountLimit') - clientConfig.baseUrl = store('main.lattice.endpoint') - const frameSuffix = store('main.lattice.suffix') - if (frameSuffix) clientConfig.name = `Frame-${frameSuffix}` - - let password = store('main.lattice.password') - if (!password) { - password = crypto.randomBytes(32).toString('hex') - store.setLatticePassword(password) - } - clientConfig.privKey = password - this.client = new Client(clientConfig) + this.id = 'lattice-' + deviceId + this.deviceId = deviceId this.type = 'lattice' - this.network = store('main.currentNetwork.id') this.status = 'loading' - this.index = 0 - this.varObserver = store.observer(() => { - if ( - this.network !== store('main.currentNetwork.id') - ) { - this.reset() + this.suffix = '' + this.baseUrl = '' + this.privKey = '' + + this.latticeObs = store.observer(() => { + this.config = store('main.lattice', deviceId) || {} + if (!this.config.privKey) { + store.updateLattice(deviceId, { privKey: crypto.randomBytes(32).toString('hex') }) + } else { + if ( + this.suffix !== this.config.suffix || + this.baseUrl !== this.config.baseUrl || + this.privKey !== this.config.privKey + ) { + this.client = this.createClient() + } } }) + this.client = this.createClient() + + this.update() this.deviceStatus() } - getId () { - return this.fingerprint() || 'Lattice-' + this.device.deviceID + createClient () { + const { suffix, baseUrl, privKey } = this.config + const clientConfig = { + name: suffix ? `Frame-${suffix}` : 'Frame', + crypto: crypto, + privKey: null, + timeout: 30000, + baseUrl, + privKey + } + return new Client(clientConfig) } - async setPin (pin) { + async setPair (pin) { try { const clientPair = promisify(this.client.pair).bind(this.client) - const hasActiveWallet = await clientPair(pin) - - if (hasActiveWallet) { - await this.deriveAddresses() - store.setLatticeDeviceID(this.device.deviceID) - } + if (hasActiveWallet) await this.deriveAddresses() return this.addresses } catch (err) { + log.error('Lattice setPair Error', err) return new Error(err) } } async open () { try { - if (this.device.deviceID) { + if (this.config.deviceId) { const clientConnect = promisify(this.client.connect).bind(this.client) - - const isPaired = await clientConnect(this.device.deviceID) - - if (isPaired) { + this.paired = await clientConnect(this.config.deviceId) + if (this.paired) { + this.status = 'addresses' await this.deriveAddresses() + } else { + this.status = 'pairing' + this.update() } - return [this.addresses, isPaired] + } else { + return new Error('No deviceId') } } catch (err) { + log.error('Lattice Open Error', err) return new Error(err) } } close () { if (this._pollStatus) clearTimeout(this._pollStatus) - this.varObserver.remove() + this.latticeObs.remove() this.closed = true store.removeSigner(this.id) + store.removeLattice(this.deviceId) super.close() } @@ -107,22 +112,24 @@ class Lattice extends Signer { } async deriveAddresses () { + // TODO: Move these settings to be device spectifc + const accountLimit = store('main.latticeSettings.accountLimit') try { const req = { currency: 'ETH', startPath: [HARDENED_OFFSET + 44, HARDENED_OFFSET + 60, HARDENED_OFFSET, 0, 0], - n: this.accountLimit, + n: accountLimit, skipCache: true } const getAddresses = promisify(this.client.getAddresses).bind(this.client) - const result = await getAddresses(req) this.status = 'ok' this.addresses = result this.update() return result } catch (err) { - // no active wallet return nothing + this.status = 'locked' + this.update() return [] } } @@ -138,7 +145,7 @@ class Lattice extends Signer { this.deviceStatusActive = true try { // If signer has no addresses, try deriving them - await this.deriveAddresses() + await this.open() this.deviceStatusActive = false } catch (err) { this.deviceStatusActive = false @@ -183,20 +190,7 @@ class Lattice extends Signer { } } - setIndex (i, cb) { - this.index = i - this.requests = {} // TODO Decline these requests before clobbering them - windows.broadcast('main:action', 'updateSigner', this.summary()) - cb(null, this.summary()) - this.deriveAddresses() - } - update () { - const id = this.getId() - if (this.id !== id) { // Singer address representation changed - store.removeSigner(this.id) - this.id = id - } store.updateSigner(this.summary()) } @@ -204,7 +198,6 @@ class Lattice extends Signer { this.network = store('main.currentNetwork.id') this.status = 'loading' this.addresses = [] - windows.broadcast('main:action', 'updateSigner', this.summary()) await this.deriveAddresses() } @@ -264,10 +257,7 @@ class Lattice extends Signer { signerPath: [HARDENED_OFFSET + 44, HARDENED_OFFSET + 60, HARDENED_OFFSET, 0, index] } - const signOpts = { - currency: 'ETH', - data: unsignedTxn - } + const signOpts = { currency: 'ETH', data: unsignedTxn } const clientSign = promisify(this.client.sign).bind(this.client) const result = await clientSign(signOpts) diff --git a/main/signers/lattice/index.js b/main/signers/lattice/index.js index a5d23dc5d..a82b6cdf7 100644 --- a/main/signers/lattice/index.js +++ b/main/signers/lattice/index.js @@ -1,28 +1,18 @@ -const windows = require('../../windows') - +const log = require('electron-log') const store = require('../../store') const LatticeDevice = require('./Lattice') -const openConnect = async (device, signers) => { - const signer = new LatticeDevice(device, signers) - // signers.signers[`Lattice-${device.deviceID}`] = signer; - windows.broadcast('main:action', 'addSigner', signer.summary()) - const response = await signer.open() - signers.add(signer) - return response -} - -module.exports = (signers) => ({ - scan: () => { - const deviceID = store('main.lattice.deviceID') - if (deviceID) { - openConnect({ deviceID }, signers) - } - }, - pair: async () => { - - }, - open: async (device) => { - return await openConnect(device, signers) +module.exports = { + scan: (signers) => { + store.observer(() => { + const lattice = store('main.lattice') || {} + Object.keys(lattice).forEach(async deviceId => { + if (!deviceId) return + log.info('Found a Lattice that isn\'t a signer, deviceId ', deviceId) + if (store('main.signers', deviceId)) return console.log('signer already exists', store('main.signers', deviceId)) + const signer = new LatticeDevice(deviceId, signers) + signers.add(signer) + }) + }) } -}) +} \ No newline at end of file diff --git a/main/store/actions/index.js b/main/store/actions/index.js index 0994a99ec..45ca90475 100644 --- a/main/store/actions/index.js +++ b/main/store/actions/index.js @@ -115,23 +115,22 @@ module.exports = { const data = { on: false, state: 'off', latest: false, installed: false, version: null } u(`main.clients.${client}`, () => data) }, - setLatticeSuffix: (u, value) => { - u('main.lattice.suffix', () => value) + setLatticeConfig: (u, id, key, value) => { + u('main.lattice', id, key, () => value) }, - setLatticePassword: (u, value) => { - u('main.lattice.password', () => value) + updateLattice: (u, deviceId, update) => { + if (deviceId && update) u('main.lattice', deviceId, (current = {}) => Object.assign(current, update)) }, - setLatticeEndpoint: (u, value) => { - u('main.lattice.endpoint', () => value) - }, - setLatticeEndpointMode: (u, value) => { - u('main.lattice.endpointMode', () => value) - }, - setLatticeAccountLimit: (u, value) => { - u('main.lattice.accountLimit', () => value) + removeLattice: (u, deviceId) => { + if (deviceId) { + u('main.lattice', (lattice = {}) => { + delete lattice[deviceId] + return lattice + }) + } }, - setLatticeDeviceID: (u, value) => { - u('main.lattice.deviceID', () => value) + setLatticeAccountLimit: (u, limit) => { + u('main.latticeSettings.accountLimit', () => limit) }, setLedgerDerivation: (u, value) => { u('main.ledger.derivation', () => value) diff --git a/main/store/state/index.js b/main/store/state/index.js index 653f58532..af68f3cff 100644 --- a/main/store/state/index.js +++ b/main/store/state/index.js @@ -145,13 +145,9 @@ const initial = { accountCloseLock: main('accountCloseLock', false), hardwareDerivation: main('hardwareDerivation', 'mainnet'), menubarGasPrice: main('menubarGasPrice', false), - lattice: { - deviceID: main('lattice.deviceID', ''), - password: main('lattice.password', ''), - endpoint: main('lattice.endpoint', 'https://signing.gridpl.us'), - accountLimit: main('lattice.accountLimit', 4), - endpointMode: main('lattice.endpointMode', 'default'), - suffix: main('lattice.suffix', '') + lattice: main('lattice', {}), + latticeSettings: { + accountLimit: main('latticeSettings.accountLimit', 4) }, ledger: { derivation: main('ledger.derivation', 'legacy'), diff --git a/package-lock.json b/package-lock.json index 93ab86c7f..f61fd50dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -184,11 +184,11 @@ } }, "@babel/generator": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.0.tgz", - "integrity": "sha512-C6u00HbmsrNPug6A+CiNl8rEys7TsdcXwg12BHi2ca5rUfAs3+UwZsuDQSXnc+wCElCXMB8gMaJ3YXDdh8fAlg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz", + "integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==", "requires": { - "@babel/types": "^7.14.0", + "@babel/types": "^7.14.1", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -241,9 +241,9 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.0.tgz", - "integrity": "sha512-6pXDPguA5zC40Y8oI5mqr+jEUpjMJonKvknvA+vD8CYDz5uuXEwWBK8sRAsE/t3gfb1k15AQb9RhwpscC4nUJQ==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.1.tgz", + "integrity": "sha512-r8rsUahG4ywm0QpGcCrLaUSOuNAISR3IZCg4Fx05Ozq31aCUrQsTLH6KPxy0N5ULoQ4Sn9qjNdGNtbPWAC6hYg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.12.13", @@ -463,9 +463,9 @@ } }, "@babel/parser": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.0.tgz", - "integrity": "sha512-AHbfoxesfBALg33idaTBVUkLnfXtsgvJREf93p4p0Lwsz4ppfE7g1tpEXVm4vrxUcH4DVhAa9Z1m1zqf9WUC7Q==" + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", + "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==" }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.13.12", @@ -962,9 +962,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.13.16.tgz", - "integrity": "sha512-ad3PHUxGnfWF4Efd3qFuznEtZKoBp0spS+DgqzVzRPV7urEBvPLue3y2j80w4Jf2YLzZHj8TOv/Lmvdmh3b2xg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.1.tgz", + "integrity": "sha512-2mQXd0zBrwfp0O1moWIhPpEeTKDvxyHcnma3JATVP1l+CctWBuot6OJG8LQ4DnBj4ZZPSmlb/fm4mu47EOAnVA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0" @@ -1465,9 +1465,9 @@ } }, "@babel/types": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.0.tgz", - "integrity": "sha512-O2LVLdcnWplaGxiPBz12d0HcdN8QdxdsWYhz5LSeuukV/5mn2xUUc3gBeU4QBYPJ18g/UToe8F532XJ608prmg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", + "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", "requires": { "@babel/helper-validator-identifier": "^7.14.0", "to-fast-properties": "^2.0.0" @@ -4000,9 +4000,9 @@ } }, "acorn": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.2.tgz", - "integrity": "sha512-VrMS8kxT0e7J1EX0p6rI/E0FbfOVcvBpbIqHThFv+f8YrZIlMfVotYcXKVPmTvPW8sW5miJzfUFrrvthUZg8VQ==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", + "integrity": "sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==", "dev": true }, "acorn-globals": { @@ -4073,9 +4073,9 @@ } }, "ajv-formats": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.0.2.tgz", - "integrity": "sha512-Brah4Uo5/U8v76c6euTwtjVFFaVishwnJrQBYpev1JRh4vjA1F4HY3UzQez41YUCszUCXKagG8v6eVRBHV1gkw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", "requires": { "ajv": "^8.0.0" }, @@ -5984,9 +5984,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001220", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001220.tgz", - "integrity": "sha512-pjC2T4DIDyGAKTL4dMvGUQaMUHRmhvPpAgNNTa14jaBWHu+bLQgvpFqElxh9L4829Fdx0PlKiMp3wnYldRtECA==" + "version": "1.0.30001221", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001221.tgz", + "integrity": "sha512-b9TOZfND3uGSLjMOrLh8XxSQ41x8mX+9MLJYDM4AAHLfaZHttrLNPrScWjVnBITRZbY5sPpCt7X85n7VSLZ+/g==" }, "capture-exit": { "version": "2.0.0", @@ -6805,11 +6805,11 @@ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-compat": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.11.1.tgz", - "integrity": "sha512-aZ0e4tmlG/aOBHj92/TuOuZwp6jFvn1WNabU5VOVixzhu5t5Ao+JZkQOPlgNXu6ynwLrwJxklT4Gw1G1VGEh+g==", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.11.2.tgz", + "integrity": "sha512-gYhNwu7AJjecNtRrIfyoBabQ3ZG+llfPmg9BifIX8yxIpDyfNLRM73zIjINSm6z3dMdI1nwNC9C7uiy4pIC6cw==", "requires": { - "browserslist": "^4.16.5", + "browserslist": "^4.16.6", "semver": "7.0.0" }, "dependencies": { @@ -8436,9 +8436,9 @@ } }, "electron-to-chromium": { - "version": "1.3.725", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.725.tgz", - "integrity": "sha512-2BbeAESz7kc6KBzs7WVrMc1BY5waUphk4D4DX5dSQXJhsc3tP5ZFaiyuL0AB7vUKzDYpIeYwTYlEfxyjsGUrhw==" + "version": "1.3.726", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.726.tgz", + "integrity": "sha512-dw7WmrSu/JwtACiBzth8cuKf62NKL1xVJuNvyOg0jvruN/n4NLtGYoTzciQquCPNaS2eR+BT5GrxHbslfc/w1w==" }, "electron-updater": { "version": "4.3.8", @@ -8880,9 +8880,9 @@ "dev": true }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, "glob-parent": { @@ -11823,9 +11823,9 @@ }, "dependencies": { "core-js": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.1.tgz", - "integrity": "sha512-k93Isqg7e4txZWMGNYwevZL9MiogLk8pd1PtwrmFmi8IBq4GXqUaVW/a33Llt6amSI36uSjd0GWwc9pTT9ALlQ==", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.2.tgz", + "integrity": "sha512-3tfrrO1JpJSYGKnd9LKTBPqgUES/UYiCzMKeqwR1+jF16q4kD1BY2NvqkfuzXwQ6+CIWm55V9cjD7PQd+hijdw==", "dev": true, "optional": true } @@ -14117,9 +14117,9 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" }, "is-binary-path": { "version": "1.0.1", @@ -18453,15 +18453,15 @@ } }, "libp2p-websockets": { - "version": "0.15.6", - "resolved": "https://registry.npmjs.org/libp2p-websockets/-/libp2p-websockets-0.15.6.tgz", - "integrity": "sha512-epnRSZ+XeKUGpziNIniyEzjtf0K2TgtqPIABAynTFmav7FPch0jJ0ONQxD6hq46xgPvm3NEdVyk4Z2qdKeEzWg==", + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/libp2p-websockets/-/libp2p-websockets-0.15.7.tgz", + "integrity": "sha512-wtbRYrWmobb3qEwHEDRZBoqWY9lqq3luCWAMAMdgrS9OLQn9E2h18De8GZlT9X3CidPixxRb5mOALIhOqSjcsA==", "requires": { "abortable-iterator": "^3.0.0", "class-is": "^1.1.0", "debug": "^4.3.1", "err-code": "^3.0.1", - "ipfs-utils": "^6.0.6", + "ipfs-utils": "^7.0.0", "it-ws": "^4.0.0", "libp2p-utils": "^0.3.0", "mafmt": "^9.0.0", @@ -18471,6 +18471,15 @@ "p-timeout": "^4.1.0" }, "dependencies": { + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "cids": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.6.tgz", @@ -18487,6 +18496,33 @@ "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" }, + "ipfs-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-7.0.0.tgz", + "integrity": "sha512-25Nj95cPcLVYROCk3vtfqQ30HBzsmgLjy6YlHkYbub4uO1JBKzP2gJMBFLfRPOfLGzT+0rYOCpWjnbYqDDxqIA==", + "requires": { + "abort-controller": "^3.0.0", + "any-signal": "^2.1.0", + "buffer": "^6.0.1", + "electron-fetch": "^1.7.2", + "err-code": "^3.0.1", + "is-electron": "^2.2.0", + "iso-url": "^1.0.0", + "it-glob": "~0.0.11", + "it-to-stream": "^1.0.0", + "merge-options": "^3.0.4", + "nanoid": "^3.1.20", + "native-abort-controller": "^1.0.3", + "native-fetch": "^3.0.0", + "node-fetch": "^2.6.1", + "stream-to-it": "^0.2.2" + } + }, + "iso-url": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-1.1.5.tgz", + "integrity": "sha512-+3JqoKdBTGmyv9vOkS6b9iHhvK34UajfTibrH/1HOK8TI7K2VsM0qOCd+aJdWKtSOA8g3PqZfcwDmnR0p3klqQ==" + }, "mafmt": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/mafmt/-/mafmt-9.0.0.tgz", @@ -20130,9 +20166,9 @@ }, "dependencies": { "p-cancelable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", - "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" } } }, @@ -20272,9 +20308,9 @@ }, "dependencies": { "p-cancelable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", - "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" } } }, @@ -26228,9 +26264,9 @@ "dev": true }, "utf-8-validate": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz", - "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz", + "integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==", "requires": { "node-gyp-build": "^4.2.0" } diff --git a/resources/base.styl b/resources/base.styl index dfdd12d1a..f7be7f3fb 100644 --- a/resources/base.styl +++ b/resources/base.styl @@ -93,6 +93,8 @@ body --good04 rgba(0, 210, 180, 0.4) --good06 rgba(0, 210, 180, 0.6) + --goodDark rgba(0, 70, 50, 1) + --bad rgb(250, 100, 155) // --bad01 rgba(250, 100, 155, 0.1) --bad04 rgba(250, 100, 155, 0.4) diff --git a/resources/svg/index.js b/resources/svg/index.js index 3e74c07da..12faebd02 100644 --- a/resources/svg/index.js +++ b/resources/svg/index.js @@ -404,7 +404,18 @@ module.exports = { lattice: size => { return (
- + + + +
+ ) + }, + close: size => { + return ( +
+ + +
) },