Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lattice refactor #626

Merged
merged 35 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d42bd44
improvements to Lattice integration
mholtzman Oct 31, 2021
93c5283
temp checkin
mholtzman Nov 1, 2021
4440c44
update pairing flow
mholtzman Nov 2, 2021
d943840
UI refactor
mholtzman Nov 2, 2021
5f14835
add logging
mholtzman Nov 3, 2021
6401803
Fix device name input slide
floating Nov 3, 2021
96329f7
UX updates, finish pairing flow
mholtzman Nov 3, 2021
1045e5e
reset Lattice pair code state
mholtzman Nov 3, 2021
fa68a67
UI cleanup
mholtzman Nov 4, 2021
295aeb1
gridplus SDK version bump, types cleanup
mholtzman Nov 4, 2021
ca084a7
remove device id, update device name parsing
mholtzman Nov 4, 2021
2c65be2
remove unused code
mholtzman Nov 4, 2021
d1ec406
UI code cleanup
mholtzman Nov 4, 2021
85d1e18
typescript cleanup
mholtzman Nov 4, 2021
60f7375
finalize adapter
mholtzman Nov 5, 2021
437e9f2
adapter test
mholtzman Nov 5, 2021
590dc16
add mock store
mholtzman Nov 7, 2021
d404c19
finish adapter tests
mholtzman Nov 7, 2021
48ae0fe
start tests for signer
mholtzman Nov 8, 2021
0c4e9a5
more tests
mholtzman Nov 8, 2021
458cafa
last tests
mholtzman Nov 8, 2021
938d050
fix test timeouts
mholtzman Nov 8, 2021
7c22267
clean up block explorer URL, fix legacy tx bug
mholtzman Nov 8, 2021
e493a69
use string formatting
mholtzman Nov 9, 2021
1d29fe3
final cleanup
mholtzman Nov 9, 2021
ca8af9c
add derivation settings
mholtzman Nov 15, 2021
88545a4
remove console log
mholtzman Nov 15, 2021
4873e7b
add migrations
mholtzman Nov 16, 2021
67fb5fa
add Live derivation for Lattice
mholtzman Nov 16, 2021
2a386dc
remove 30 second timeout
mholtzman Nov 22, 2021
527235b
revert explorer change from another branch
mholtzman Nov 23, 2021
914d04c
Lattice UX (#637)
floating Nov 24, 2021
a2488e7
add NL
mholtzman Nov 24, 2021
5f8f83f
bump state version
mholtzman Nov 26, 2021
b0a3ef3
UI polish
floating Nov 29, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions @types/frame/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type Callback<T> = (err: Error | null, result?: T) => void;
59 changes: 59 additions & 0 deletions @types/gridplus-sdk/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
declare module 'gridplus-sdk' {
export class Client {
constructor(options: ClientOptions);

name: string;
baseUrl: string;
privKey: string;
fwVersion: [number, number, number] | undefined;
isPaired: boolean;

connect (deviceId: string | Callback<boolean>, cb?: Callback<boolean>);
pair (pairingSecret: string, cb: Callback<boolean>);
getAddresses (opts: DerivationOptions, cb: Callback<Array<string>>);
sign (opts: SigningOptions, cb: Callback<SignedData>)
}

type Callback<T> = (err: string | null, result: T) => void

export type Signature = {
v: Buffer,
r: string,
s: string
}

export type SignedData = {
tx?: string,
txHash?: string,
changeRecipient?: string,
sigs?: any[],
sig?: Signature
}

interface ClientOptions {
name?: string,
baseUrl: string,
privKey?: string,
crypto: any,
timeout?: number,
retryCount?: number
}

interface DerivationOptions {
startPath: number[],
n: number,
skipCache?: boolean
}

interface SigningOptions {
currency: string,
data: ({
protocol: string,
payload: string
} | {
chainId?: string
}) & {
signerPath: number[]
}
}
}
51 changes: 21 additions & 30 deletions app/App/Panel/Local/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ class Settings extends React.Component {
const secondaryCustom = context.store('main.networks', this.networkType, this.network, 'connection.secondary.custom') || this.customMessage
const latticeEndpoint = context.store('main.latticeSettings.endpointCustom')
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 }
this.state = { localShake: {}, primaryCustom, secondaryCustom, latticeEndpoint, latticeEndpointMode, resetConfirm: false, expandNetwork: false }
context.store.observer(() => {
const { type, id } = context.store('main.currentNetwork')
if (this.network !== id || this.networkType !== type) {
Expand Down Expand Up @@ -119,19 +118,6 @@ class Settings extends React.Component {
this.inputLatticeTimeout = setTimeout(() => link.send('tray:action', 'setLatticeEndpointCustom', this.state.latticeEndpoint), 1000)
}

inputLatticeSuffix (e) {
e.preventDefault()
clearTimeout(this.inputLatticeSuffixTimeout)

// Lattice only supports a suffix of up to 24 characters, and we append "Frame-"
// to the front so limit it to 18 characters
const value = e.target.value.replace(/\s+/g, '').substring(0, 18)

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

localShake (key) {
const localShake = Object.assign({}, this.state.localShake)
localShake[key] = true
Expand Down Expand Up @@ -283,7 +269,7 @@ class Settings extends React.Component {
Run Frame when your computer starts
</div>
</div>
<div className='signerPermission localSetting' style={{ zIndex: 210 }}>
<div className='signerPermission localSetting' style={{ zIndex: 211 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Glide</div>
<div className={this.store('main.reveal') ? 'signerPermissionToggle signerPermissionToggleOn' : 'signerPermissionToggle'} onMouseDown={_ => link.send('tray:action', 'toggleReveal')}>
Expand All @@ -294,7 +280,7 @@ class Settings extends React.Component {
{'Mouse to display\'s right edge to summon Frame'}
</div>
</div>
<div className='signerPermission localSetting' style={{ zIndex: 209 }}>
<div className='signerPermission localSetting' style={{ zIndex: 210 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Adjustable Nonce</div>
<div
Expand Down Expand Up @@ -322,7 +308,7 @@ class Settings extends React.Component {
</div>
</div> */}
{this.store('platform') === 'darwin' ? (
<div className='signerPermission localSetting' style={{ zIndex: 208 }}>
<div className='signerPermission localSetting' style={{ zIndex: 209 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Display Gas in Menubar</div>
<div className={this.store('main.menubarGasPrice') ? 'signerPermissionToggle signerPermissionToggleOn' : 'signerPermissionToggle'} onMouseDown={_ => link.send('tray:action', 'setMenubarGasPrice', !this.store('main.menubarGasPrice'))}>
Expand All @@ -334,7 +320,7 @@ class Settings extends React.Component {
</div>
</div>
) : null}
<div className='signerPermission localSetting' style={{ zIndex: 207 }}>
<div className='signerPermission localSetting' style={{ zIndex: 208 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Colorway</div>
<Dropdown
Expand All @@ -349,7 +335,7 @@ class Settings extends React.Component {
</span>
</div>
</div>
<div className='signerPermission localSetting' style={{ zIndex: 206 }}>
<div className='signerPermission localSetting' style={{ zIndex: 207 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Trezor Derivation</div>
<Dropdown
Expand All @@ -362,7 +348,7 @@ class Settings extends React.Component {
{'Derivation path for connected Trezor devices'}
</div>
</div>
<div className='signerPermission localSetting' style={{ zIndex: 205 }}>
<div className='signerPermission localSetting' style={{ zIndex: 206 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Ledger Derivation</div>
<Dropdown
Expand All @@ -376,7 +362,7 @@ class Settings extends React.Component {
</div>
</div>
{this.store('main.ledger.derivation') === 'live' ? (
<div className='signerPermission localSetting' style={{ zIndex: 204 }}>
<div className='signerPermission localSetting' style={{ zIndex: 205 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Ledger Live Accounts</div>
<Dropdown
Expand All @@ -395,6 +381,19 @@ class Settings extends React.Component {
</div>
</div>
) : null}
<div className='signerPermission localSetting' style={{ zIndex: 204 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Lattice Derivation</div>
<Dropdown
syncValue={this.store('main.latticeSettings.derivation')}
onChange={(value) => link.send('tray:action', 'setLatticeDerivation', value)}
options={[{ text: 'Standard', value: 'standard' }, { text: 'Legacy', value: 'legacy' }, { text: 'Live', value: 'live' }]}
/>
</div>
<div className='signerPermissionDetails'>
{'Derivation path for connected Lattice devices'}
</div>
</div>
<div className='signerPermission localSetting' style={{ zIndex: 203 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Lattice Accounts</div>
Expand Down Expand Up @@ -429,14 +428,6 @@ class Settings extends React.Component {
<input tabIndex='-1' placeholder={'Custom Relay'} value={this.state.latticeEndpoint} onChange={e => this.inputLatticeEndpoint(e)} />
</div>
</div>
<div className='signerPermission localSetting' style={{ zIndex: 201 }}>
<div className='signerPermissionControls'>
<div className='signerPermissionSetting'>Lattice Frame Suffix</div>
</div>
<div className='connectionCustomInput connectionCustomInputOn'>
<input placeholder={'Lattice Suffix'} tabIndex='-2' value={this.state.latticeSuffix} onChange={e => this.inputLatticeSuffix(e)} />
</div>
</div>

<div className='signerPermission localSetting' style={{ zIndex: 200 }}>
<div className='signerPermissionControls'>
Expand Down
4 changes: 2 additions & 2 deletions app/App/Panel/Main/style/index.styl
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,12 @@
display flex
justify-content center
align-items center
font-size 10px
font-size 11px
font-weight 300
overflow hidden
background-position 0 100%
text-transform uppercase
letter-spacing 2px
letter-spacing 1px
font-weight 600
cursor pointer

Expand Down
5 changes: 4 additions & 1 deletion app/App/Panel/Networks/style/index.styl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
background var(--ghostA)
border-radius 12px
margin 0px 0px 16px 0px
border-bottom 2px solid var(--ghostZ)
box-shadow 0px 6px 8px 0px var(--ghostY)
// box-shadow 0px 18px 70px -32px var(--ghostY)

.networkActive
Expand All @@ -22,8 +24,9 @@
input
font-size 20px
text-align left
font-weight 300
font-weight 500
padding-left 16px
font-family 'Exo2', sans-serif

.signerPermissionToggle
position absolute
Expand Down
57 changes: 42 additions & 15 deletions dash/App/Add/AddHardwareLattice/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import Restore from 'react-restore'
import link from '../../../../resources/link'
import svg from '../../../../resources/svg' // TODO: get gridplus svg

import Signer from '../../Signer'
function parseDeviceName (name) {
// Lattice supports a device name of up to 24 characters and we append
// a dash and a 6 character device code to the end, so limit this to 17 characters
return name.replace(/\s+/g, '-').substring(0, 17)
}

class AddHardwareLattice extends React.Component {
constructor (...args) {
Expand All @@ -15,16 +19,20 @@ class AddHardwareLattice extends React.Component {
status: '',
error: false,
deviceId: '',
deviceName: 'GridPlus',
pairCode: ''
}
this.forms = [React.createRef(), React.createRef(), React.createRef()]
this.forms = [React.createRef(), React.createRef()]
}

onChange (key, e) {
e.preventDefault()
const update = {}
update[key] = (e.target.value || '') // .replace(/\W/g, '')
this.setState(update)

const value = (key === 'deviceName')
? parseDeviceName(e.target.value)
: e.target.value

this.setState({ [key]: value || '' })
}

onBlur (key, e) {
Expand Down Expand Up @@ -66,11 +74,14 @@ class AddHardwareLattice extends React.Component {
}

createLattice () {
link.rpc('createLattice', this.state.deviceId, (err, signer) => {
link.rpc('createLattice', this.state.deviceId, this.state.deviceName, (err, signer) => {
if (err) {
this.setState({ status: err, error: true })
} else {
this.setState({ status: 'Successful', error: false, createdSignerId: signer.id })
this.setState({ status: 'Successful', error: false })

// TODO: signal some sort of success and close this more gracefully
this.props.close()
}
})
}
Expand All @@ -90,10 +101,6 @@ class AddHardwareLattice extends React.Component {

render () {
let itemClass = 'addAccountItem addAccountItemSmart addAccountItemAdding'
let signer
if (this.state.createdSignerId) {
signer = this.store('main.signers', this.state.createdSignerId)
}

return (
<div className={itemClass} style={{ transitionDelay: (0.64 * this.props.index / 4) + 's' }}>
Expand All @@ -115,11 +122,34 @@ class AddHardwareLattice extends React.Component {
style={{ transform: `translateX(-${100 * this.state.index}%)` }}
>
<div className='addAccountItemOptionSetupFrames'>
<div className='addAccountItemOptionSetupFrame'>
<div className='addAccountItemOptionTitle'>Device Name</div>
<div className='addAccountItemOptionInputPhrase'>
<input
tabIndex='-1' ref={this.forms[0]} value={this.state.deviceName}
onChange={e => this.onChange('deviceName', e)}
onFocus={e => this.onFocus('deviceName', e)}
onBlur={e => this.onBlur('deviceName', e)}
onKeyPress={e => {
if (e.key === 'Enter') {
this.next()
}
}}
/>
</div>
<div
className='addAccountItemOptionSubmit'
onMouseDown={() => {
this.next()
}}
>Next
</div>
</div>
<div className='addAccountItemOptionSetupFrame'>
<div className='addAccountItemOptionTitle'>Enter device id</div>
<div className='addAccountItemOptionInputPhrase'>
<input
tabIndex='-1' ref={this.forms[0]} value={this.state.deviceId}
tabIndex='-1' ref={this.forms[1]} value={this.state.deviceId}
onChange={e => this.onChange('deviceId', e)}
onFocus={e => this.onFocus('deviceId', e)}
onBlur={e => this.onBlur('deviceId', e)}
Expand All @@ -141,13 +171,10 @@ class AddHardwareLattice extends React.Component {
</div>
</div>
<div className='addAccountItemOptionSetupFrame'>
{signer ? <Signer key={signer.id} {...signer} />
: (
<>
<div className='phaseItemOptionTitle'>{this.state.status}</div>
{this.state.error ? <div className='phaseItemOptionSubmit' onMouseDown={() => this.restart()}>try again</div> : null}
</>
)}
</div>
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions dash/App/Add/style/index.styl
Original file line number Diff line number Diff line change
Expand Up @@ -619,27 +619,27 @@
input
width 100%
height 100%
padding 10px 20px
padding 10px 20px 13px 21px
background transparent
border none
outline none
color var(--outerspace)
text-align center
font-size 20px
font-size 22px
// letter-spacing 3px
line-height 20px
font-weight 400
// font-family FiraCode, monospace
display flex
justify-content center
align-items center
// overflow hidden
letter-spacing 1px
resize none
transform translate3d(0, 0, 0)
letter-spacing 3px
font-family 'Exo2', sans-serif

input::selection
background var(--ghostA)
background var(--ghostY)

textarea
width 100%
Expand Down
Loading