on fd7a195 help sign in
bridge/src/views/SetKeys.js
219 lines 5.4 kB history raw
1import React from 'react';
2import Maybe from 'folktale/maybe';
3import * as azimuth from 'azimuth-js';
4import * as ob from 'urbit-ob';
5import * as need from '../lib/need';
6import * as kg from 'urbit-key-generation/dist';
7import {
8 Row,
9 Col,
10 H1,
11 P,
12 Warning,
13 CheckboxButton,
14} from '../components/old/Base';
16import StatelessTransaction from '../components/old/StatelessTransaction';
17import { attemptNetworkSeedDerivation } from '../lib/keys';
19import { addHexPrefix } from '../lib/wallet';
20import { compose } from '../lib/lib';
22import { withNetwork } from '../store/network';
23import { withWallet } from '../store/wallet';
24import { withPointCursor } from '../store/pointCursor';
25import { withPointCache } from '../store/pointCache';
27class SetKeys extends React.Component {
28 constructor(props) {
29 super(props);
31 const point = need.pointCursor(props);
33 this.state = {
34 auth: '',
35 encr: '',
36 newNetworkSeed: '',
37 nondeterministicSeed: false,
38 point: point,
39 cryptoSuiteVersion: 1,
40 discontinuity: false,
41 isManagementSeed: false,
42 };
44 this.toggleDiscontinuity = this.toggleDiscontinuity.bind(this);
45 // Transaction
46 this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
47 }
49 toggleDiscontinuity() {
50 this.setState({ discontinuity: !this.state.discontinuity });
51 }
53 componentDidMount() {
54 const { props } = this;
56 this.deriveSeed();
58 const addr = need.address(props);
60 this.determineManagementSeed(props.contracts.value, addr);
61 }
63 async determineManagementSeed(ctrcs, addr) {
64 const managing = await azimuth.azimuth.getManagerFor(ctrcs, addr);
66 this.setState({
67 isManagementSeed: managing.length !== 0,
68 });
69 }
71 //TODO use web3.utils.randomHex when it gets fixed, see web3.js#1490
72 randomHex(len) {
73 let hex = '';
75 for (var i = 0; i < len; i++) {
76 hex =
77 hex +
78 [
79 '0',
80 '1',
81 '2',
82 '3',
83 '4',
84 '5',
85 '6',
86 '7',
87 '8',
88 '9',
89 'A',
90 'B',
91 'C',
92 'D',
93 'E',
94 'F',
95 ][Math.floor(Math.random() * 16)];
96 }
98 return hex;
99 }
101 async deriveSeed() {
102 const next = true;
103 let nondeterministicSeed = false;
105 const seed = await attemptNetworkSeedDerivation(next, this.props);
106 const newNetworkSeed = seed.matchWith({
107 Nothing: () => {
108 nondeterministicSeed = true;
109 return this.randomHex(64);
110 },
111 Just: p => p.value,
112 });
114 this.setState({
115 newNetworkSeed,
116 nondeterministicSeed,
117 });
118 }
120 createUnsignedTxn() {
121 const { state, props } = this;
123 const validContracts = need.contracts(props);
125 const validPoint = need.pointCursor(props);
127 // TODO: move this to a lib for validating things
128 const hexRegExp = /[0-9A-Fa-f]{64}/g;
130 if (hexRegExp.test(state.newNetworkSeed)) {
131 // derive network keys
132 const pair = kg.deriveNetworkKeys(state.newNetworkSeed);
134 const pencr = addHexPrefix(pair.crypt.public);
135 const pauth = addHexPrefix(pair.auth.public);
137 const txn = azimuth.ecliptic.configureKeys(
138 validContracts,
139 validPoint,
140 pencr,
141 pauth,
142 1,
143 state.discontinuity
144 );
146 return Maybe.Just(txn);
147 }
149 return Maybe.Nothing();
150 }
152 render() {
153 const { props, state } = this;
155 const canGenerate =
156 state.newNetworkSeed.length === 64 && state.newNetworkSeed.length === 64;
158 const pointDetails = need.fromPointCache(props, state.point);
160 return (
161 <Row>
162 <Col>
163 <H1>
164 {'Set Network Keys For '} <code>{`${ob.patp(state.point)}`}</code>
165 </H1>
167 <P className="mt-10">
168 {`Set new authentication and encryption keys for your Arvo ship.`}
169 </P>
171 {state.nondeterministicSeed && (
172 <Warning>
173 <h3 className={'mb-2'}>{'Warning'}</h3>
174 {`Your network seed could not be derived automatically. We've
175 generated a random one for you, so you must download your Arvo
176 keyfile during this session after setting your keys.`}
177 </Warning>
178 )}
180 {pointDetails.keyRevisionNumber === 0 ? (
181 <Warning>
182 <h3 className={'mb-2'}>{'Warning'}</h3>
183 {'Once these keys have been set, your point is considered ' +
184 "'linked'. This operation cannot be undone."}
185 </Warning>
186 ) : (
187 <div />
188 )}
190 <CheckboxButton
191 className="mt-8"
192 onToggle={this.toggleDiscontinuity}
193 state={state.discontinuity}
194 label={`I have lost important off-chain data relating to this point
195 and need to do a hard reset.
196 (For example, rebooting an Arvo ship.)`}
197 />
199 <StatelessTransaction
200 // Upper scope
201 {...props}
202 // Tx
203 canGenerate={canGenerate}
204 createUnsignedTxn={this.createUnsignedTxn}
205 newNetworkSeed={state.newNetworkSeed}
206 newRevision={parseInt(pointDetails.keyRevisionNumber) + 1}
207 />
208 </Col>
209 </Row>
210 );
211 }
214export default compose(
215 withNetwork,
216 withWallet,
217 withPointCursor,
218 withPointCache
219)(SetKeys);