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

remove networkSeed input from setKeys / genKeyfile flows #85

Merged
merged 13 commits into from
Apr 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 21 additions & 4 deletions src/Bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Bridge extends React.Component {
this.state = {
// routes
routeCrumbs: Stack([ ROUTE_NAMES.LANDING ]),
routeData: {},
// network
networkType: networkType,
web3: Maybe.Nothing(),
Expand All @@ -51,6 +52,7 @@ class Bridge extends React.Component {
// urbit wallet-related
urbitWallet: Maybe.Nothing(),
authMnemonic: Maybe.Nothing(),
networkSeedCache: null,
// point
pointCursor: Maybe.Nothing(),
pointCache: {},
Expand All @@ -70,6 +72,7 @@ class Bridge extends React.Component {
this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
this.setPointCursor = this.setPointCursor.bind(this)
this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this)
this.addToPointCache = this.addToPointCache.bind(this)
}

Expand All @@ -88,7 +91,7 @@ class Bridge extends React.Component {

// if (process.env.NODE_ENV === 'development') {
//
// const socket = 'wss://localhost:8545'
// const socket = 'ws://localhost:8545'
// const provider = new Web3.providers.WebsocketProvider(socket)
// const web3 = new Web3(provider)
// const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV)
Expand All @@ -98,28 +101,31 @@ class Bridge extends React.Component {
//
// this.setState({
// routeCrumbs: Stack([
// ROUTE_NAMES.CREATE_GALAXY,
// // ROUTE_NAMES.CREATE_GALAXY,
// // ROUTE_NAMES.SHIP,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see anything about this in your commit messages, but I think these (and the couple lines below) are just dev setup tweaks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep; hopefully that's okay. There were a couple issues with the flow so I just updated it.

// ROUTE_NAMES.SHIPS,
// // ROUTE_NAMES.MNEMONIC,
// ROUTE_NAMES.WALLET,
// ROUTE_NAMES.NETWORK,
// ROUTE_NAMES.LANDING
// ]),
// networkType: NETWORK_NAMES.LOCAL,
// pointCursor: Maybe.Just(0),
// web3: Maybe.Just(web3),
// contracts: Maybe.Just(contracts),
// walletType: WALLET_NAMES.MNEMONIC,
// wallet: walletFromMnemonic(mnemonic, hdpath),
// urbitWallet: Maybe.Nothing(),
// authMnemonic: Maybe.Nothing()
// authMnemonic: Maybe.Just('benefit crew supreme gesture quantum web media hazard theory mercy wing kitten')
// })
// }
}

pushRoute(symbol) {
pushRoute(symbol, routeData) {
if (lodash.includes(ROUTE_NAMES, symbol)) {
this.setState((state, _) => ({
routeCrumbs: state.routeCrumbs.push(symbol),
routeData: routeData
}));

// Scroll to top of page with each route transition.
Expand Down Expand Up @@ -152,6 +158,12 @@ class Bridge extends React.Component {
}
}

setNetworkSeedCache(networkSeed) {
this.setState({
networkSeedCache: networkSeed
})
}

setNetwork(web3, contracts) {
this.setState({
web3: web3,
Expand Down Expand Up @@ -202,12 +214,14 @@ class Bridge extends React.Component {
render() {
const {
routeCrumbs,
routeData,
networkType,
walletType,
walletHdPath,
wallet,
urbitWallet,
authMnemonic,
networkSeedCache,
pointCursor,
pointCache,
txnHashCursor,
Expand Down Expand Up @@ -235,6 +249,7 @@ class Bridge extends React.Component {
// router
pushRoute={ this.pushRoute }
popRoute={ this.popRoute }
routeData={ routeData }
// network
setNetworkType={ this.setNetworkType }
setNetwork={ this.setNetwork }
Expand All @@ -258,6 +273,8 @@ class Bridge extends React.Component {
addToPointCache={ this.addToPointCache }
pointCursor={ pointCursor }
pointCache={ pointCache }
networkSeedCache= { networkSeedCache }
setNetworkSeedCache= { this.setNetworkSeedCache }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Q, to confirm my understanding: putting these as properties into the View is what makes these accessible by other components?

Copy link
Contributor

@jtobin jtobin Mar 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. If you have some component Foo, then <Foo foo=1 bar=2 /> is that component with the foo and bar properties set to 1 and 2 respectively. In src/Bridge.js, View is actually just whatever component is currently being pointed at by the router, so it gets passed all the properties you see listed there.

// txn
setTxnHashCursor={ this.setTxnHashCursor }
txnHashCursor={ txnHashCursor } />
Expand Down
7 changes: 7 additions & 0 deletions src/style/extend.css
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,10 @@ code {
.clickable {
cursor: pointer;
}

.keyfile {
white-space: pre-wrap;
word-break: break-word;
padding: 1rem 2rem;
margin-bottom: 4rem;
}
167 changes: 75 additions & 92 deletions src/views/GenKeyfile.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'
import Maybe from 'folktale/maybe'

import { Button } from '../components/Base'
import { RequiredInput, InnerLabel } from '../components/Base'
Expand All @@ -21,39 +22,14 @@ class GenKeyfile extends React.Component {

this.state = {
keyfile: '',
networkSeed: ''
loaded: false
}

this.handleNetworkSeedInput = this.handleNetworkSeedInput.bind(this)
this.handleKeyfileChange = this.handleKeyfileChange.bind(this)
}

componentDidMount() {
this.deriveSeed()
}

async deriveSeed() {
const next = false
const seed = await attemptSeedDerivation(next, this.props)
this.setState({
networkSeed: seed.getOrElse('')
})
}

handleNetworkSeedInput = (networkSeed) => {
this.setState({ networkSeed })
}

handleKeyfileChange = (keyfile) => {
this.setState({ keyfile })
}

render() {
getPointDetails() {
const { pointCache } = this.props
const { pointCursor } = this.props

const { keyfile, networkSeed } = this.state

const point = pointCursor.matchWith({
Just: (pt) => pt.value,
Nothing: () => {
Expand All @@ -68,6 +44,34 @@ class GenKeyfile extends React.Component {

const revision = parseInt(pointDetails.keyRevisionNumber)

return {
point,
pointDetails,
revision
}
}

async componentDidMount() {
const { point, pointDetails, revision } = this.getPointDetails();
let keyfile = ''

const hexRegExp = /[0-9A-Fa-f]{64}/g
const networkSeed = await this.deriveSeed()

const keysmatch = this.checkKeysMatch(networkSeed, pointDetails)
const seedValid = hexRegExp.test(networkSeed)

if (keysmatch && seedValid) {
keyfile = genKey(networkSeed, point, revision)
}

this.setState({
keyfile: keyfile,
loaded: true
});
}

checkKeysMatch(networkSeed, pointDetails) {
const crypub = pointDetails.encryptionKey
const sgnpub = pointDetails.authenticationKey

Expand All @@ -77,85 +81,64 @@ class GenKeyfile extends React.Component {
crypub === addHexPrefix(crypt.public)
&& sgnpub === addHexPrefix(auth.public)

const warning =
keyfile !== '' && keysmatch === false
? <Row>
<Col>
<b>{ 'WARNING' }</b>{ ": derived key doesn't match Azimuth keys!" }
</Col>
</Row>
: <div />
return keysmatch;
}

const hexRegExp = /[0-9A-Fa-f]{64}/g
async deriveSeed() {
const next = false
let seed = await attemptSeedDerivation(next, this.props)

const download =
keyfile !== ''
? <Button
onClick={
() => {
let blob = new Blob([keyfile], {type:"text/plain;charset=utf-8"});
saveAs(blob, `${ob.patp(point).slice(1)}-${revision}.key`)
}
}>
Download →
</Button>
: ''
if (seed.getOrElse('') === '' && this.props.networkSeedCache) {
seed = Maybe.Just(this.props.networkSeedCache)
}

return seed.getOrElse('')
}

render() {
const { point, pointDetails, revision } = this.getPointDetails();
const { keyfile, loaded } = this.state

return (
<Row>
<Col className={'col-md-8'}>
<H1>{ 'Generate keyfile' }</H1>

<P>
{ "Generate a private key file for booting this point in Arvo." }
{ "Download a private key file for booting this point in Arvo." }
</P>

<P>
{
`Enter a network seed below for generating your key file. Your
network seed must be a string of 64 characters (containing 0-9, A-Z, a-z)`
{ keyfile === '' && !loaded &&
<P>
{ "Generating keyfile..." }
</P>
}
</P>
<P>
{
`If you've authenticated with either a master ticket or a
management proxy mnemonic, a seed will be generated for you
automatically.`

{ keyfile === '' && loaded &&
<P>
<b>Warning: </b>
{ `No valid network seed detected. To generate a keyfile, you
must reset your networking keys, or try logging in with your
master ticket or management mnemonic` }
</P>
}
</P>

<RequiredInput
className='mono'
prop-size='lg'
prop-format='innerLabel'
autoFocus
value={ networkSeed }
onChange={ this.handleNetworkSeedInput }>
<InnerLabel>{ 'Network seed' }</InnerLabel>
</RequiredInput>

<Button
className={'mt-8'}
color={'blue'}
onClick={
() => {
if (hexRegExp.test(networkSeed)) {
const keyfile = genKey(networkSeed, point, revision)
this.setState({ keyfile })
}
}
}
>
{ 'Generate →' }
</Button>

<Code>
{ keyfile }
</Code>

{ warning }

{ download }
{ keyfile !== '' &&
<React.Fragment>
<div className="pb-5 text-code keyfile">
{ keyfile }
</div>
<Button
onClick={
() => {
let blob = new Blob([keyfile], {type:"text/plain;charset=utf-8"});
saveAs(blob, `${ob.patp(point).slice(1)}-${revision}.key`)
}
}>
Download →
</Button>
</React.Fragment>
}

</Col>
</Row>
Expand Down
27 changes: 26 additions & 1 deletion src/views/SentTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { Row, Col, H1, H3, P, Warning, Anchor } from '../components/Base'
import { Button } from '../components/Base'

import { ROUTE_NAMES } from '../lib/router'
import { BRIDGE_ERROR, renderTxnError } from '../lib/error'
import { NETWORK_NAMES } from '../lib/network'

Expand Down Expand Up @@ -75,9 +76,11 @@ const Failure = (props) =>
</Row>

const SentTransaction = (props) => {
const { web3, txnHashCursor, networkType, popRoute } = props
const { web3, txnHashCursor, networkType, popRoute, pushRoute } = props
const { setPointCursor, pointCursor } = props

const promptKeyfile = props.routeData && props.routeData.promptKeyfile

const w3 = web3.matchWith({
Nothing: _ => { throw BRIDGE_ERROR.MISSING_WEB3 },
Just: res => res.value
Expand Down Expand Up @@ -113,10 +116,32 @@ const SentTransaction = (props) => {
</Col>
</Row>

let keyfile;

if (promptKeyfile) {
keyfile = (
<Row>
<Col>
<Button
prop-type={'link'}
onClick={
() => {
popRoute()
pushRoute(ROUTE_NAMES.GEN_KEYFILE)
}
}>
{ 'Download Keyfile →' }
</Button>
</Col>
</Row>
)
}

return (
<div>
{ body }
{ ok }
{ keyfile }
</div>
)
}
Expand Down
Loading