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