on master help sign in
Merge pull request #360 from urbit/m/mnemonic-fixes

Mnemonic login QoL

commitd0a1881690e8601c09fe8c03e0d5d2edade8415c authorFang <git@fang.io> dateFri 20 Dec 2019, 20:53 (7 years ago) parent859a62845c8c6e
5 files changed+65−61
src/form/validators.js+4−1 src/lib/validators.js+4 src/lib/wallet.js+10−4 src/views/Login/Mnemonic.js+36−23 src/views/Senate.js+11−33
src/form/validators.js+4−1
@@ -4,6 +4,7 @@ import {
44 validateNotEmpty,
55 validatePatq,
66 validateMnemonic,
7+ validateHdPath,
78 validatePoint,
89 validateMaximumPatpByteLength,
910 validateOneOf,
@@ -60,6 +61,8 @@ export const hasErrors = iter =>
6061
6162export const buildPatqValidator = (validators = []) =>
6263 buildValidator([validateNotEmpty, validatePatq, ...validators]);
64+export const buildAnyMnemonicValidator = () =>
65+ buildValidator([validateNotEmpty]);
6366export const buildMnemonicValidator = () =>
6467 buildValidator([validateNotEmpty, validateMnemonic]);
6568export const buildCheckboxValidator = mustBe =>
@@ -68,7 +71,7 @@ export const buildCheckboxValidator = mustBe =>
6871 ]);
6972export const buildPassphraseValidator = () => buildValidator([]);
7073// TODO: validate hdpath format
71−export const buildHdPathValidator = () => buildValidator([validateNotEmpty]);
74+export const buildHdPathValidator = () => buildValidator([validateHdPath]);
7275export const buildPointValidator = (size = 4, validators = []) =>
7376 buildValidator([
7477 validateNotEmpty,
src/lib/validators.js+4
@@ -24,6 +24,10 @@ const isHexPrefixed = /^0x/;
2424export const validateMnemonic = v =>
2525 !bip39.validateMnemonic(v) && 'This is not a valid mnemonic.';
2626
27+const isHdPath = /^m(\/[0-9]+'?)*$/;
28+export const validateHdPath = v =>
29+ !isHdPath.test(v) && 'Invalid HD derivation path.';
30+
2731// Checks an empty field
2832export const validateNotEmpty = v =>
2933 (v === undefined || v.length === 0) && 'This field is required.';
src/lib/wallet.js+10−4
@@ -81,10 +81,16 @@ export const urbitWalletFromTicket = async (ticket, point, passphrase) => {
8181 });
8282};
8383
84−export const walletFromMnemonic = (mnemonic, hdpath, passphrase) => {
85− const seed = bip39.validateMnemonic(mnemonic)
86− ? Just(bip39.mnemonicToSeed(mnemonic, passphrase))
87− : Nothing();
84+export const walletFromMnemonic = (
85+ mnemonic,
86+ hdpath,
87+ passphrase,
88+ skipMnemonicCheck
89+) => {
90+ const seed =
91+ skipMnemonicCheck || bip39.validateMnemonic(mnemonic)
92+ ? Just(bip39.mnemonicToSeed(mnemonic, passphrase))
93+ : Nothing();
8894
8995 const toWallet = (sd, path) => {
9096 let wal;
src/views/Login/Mnemonic.js+36−23
@@ -1,15 +1,16 @@
1−import React, { useCallback, useMemo } from 'react';
1+import React, { useCallback, useState, useMemo } from 'react';
22import cn from 'classnames';
33import { Just, Nothing } from 'folktale/maybe';
44import { Grid, CheckboxInput } from 'indigo-react';
55
66import { useWallet } from 'store/wallet';
77
8−import { walletFromMnemonic, WALLET_TYPES } from 'lib/wallet';
8+import { walletFromMnemonic, WALLET_TYPES, DEFAULT_HD_PATH } from 'lib/wallet';
99import useLoginView from 'lib/useLoginView';
1010import { MnemonicInput, HdPathInput, PassphraseInput } from 'form/Inputs';
1111import {
1212 composeValidator,
13+ buildAnyMnemonicValidator,
1314 buildMnemonicValidator,
1415 buildCheckboxValidator,
1516 buildPassphraseValidator,
@@ -23,32 +24,36 @@ import SubmitButton from 'form/SubmitButton';
2324export default function Mnemonic({ className, goHome }) {
2425 useLoginView(WALLET_TYPES.MNEMONIC);
2526
26− const {
27− setWallet,
28− setAuthMnemonic,
29− walletHdPath,
30− setWalletHdPath,
31− } = useWallet();
27+ const { setWallet, setAuthMnemonic, setWalletHdPath } = useWallet();
3228
33− const validate = useMemo(
34− () =>
35− composeValidator({
36− useAdvanced: buildCheckboxValidator(),
37− mnemonic: buildMnemonicValidator(),
38− passphrase: buildPassphraseValidator(),
39− hdpath: buildHdPathValidator(),
40− }),
41− []
42− );
29+ const [anyMnemonic, setAnyMnemonic] = useState(false);
30+
31+ const validate = useMemo(() => {
32+ const mnemonicValidator = anyMnemonic
33+ ? buildAnyMnemonicValidator()
34+ : buildMnemonicValidator();
35+ return composeValidator({
36+ useAdvanced: buildCheckboxValidator(),
37+ mnemonic: mnemonicValidator,
38+ passphrase: buildPassphraseValidator(),
39+ hdpath: buildHdPathValidator(),
40+ });
41+ }, [anyMnemonic]);
4342
4443 // when the properties change, re-derive wallet and set global state
4544 const onValues = useCallback(
4645 ({ valid, values }) => {
46+ setAnyMnemonic(values.anyMnemonic);
4747 if (valid) {
4848 setWalletHdPath(values.hdpath);
4949 setAuthMnemonic(Just(values.mnemonic));
5050 setWallet(
51− walletFromMnemonic(values.mnemonic, values.hdpath, values.passphrase)
51+ walletFromMnemonic(
52+ values.mnemonic,
53+ values.hdpath,
54+ values.passphrase,
55+ values.anyMnemonic
56+ )
5257 );
5358 } else {
5459 setAuthMnemonic(Nothing());
@@ -58,10 +63,11 @@ export default function Mnemonic({ className, goHome }) {
5863 [setAuthMnemonic, setWallet, setWalletHdPath]
5964 );
6065
61− const initialValues = useMemo(
62− () => ({ hdpath: walletHdPath, useAdvanced: false }),
63− [walletHdPath]
64− );
66+ const initialValues = {
67+ hdpath: DEFAULT_HD_PATH,
68+ useAdvanced: false,
69+ anyMnemonic: false,
70+ };
6571
6672 return (
6773 <Grid className={cn('mt4', className)}>
@@ -79,6 +85,13 @@ export default function Mnemonic({ className, goHome }) {
7985 label="BIP39 Mnemonic"
8086 />
8187
88+ <Grid.Item
89+ full
90+ as={CheckboxInput}
91+ name="anyMnemonic"
92+ label="Skip mnemonic validation"
93+ />
94+
8295 <Condition when="useAdvanced" is={true}>
8396 <Grid.Item
8497 full
src/views/Senate.js+11−33
@@ -1,42 +1,26 @@
11import React, { useCallback, useMemo, useState } from 'react';
2−import cn from 'classnames';
3−import { Grid, Text, Input, P, LinkButton } from 'indigo-react';
2+import { Grid, Text, P, LinkButton } from 'indigo-react';
43import * as azimuth from 'azimuth-js';
5−import ob from 'urbit-ob';
64
75import { useNetwork } from 'store/network';
8−import { usePointCache } from 'store/pointCache';
96import { usePointCursor } from 'store/pointCursor';
107
118import * as need from 'lib/need';
129import useEthereumTransaction from 'lib/useEthereumTransaction';
1310import { GAS_LIMITS } from 'lib/constants';
14−import patp2dec from 'lib/patp2dec';
15−import { getSpawnCandidate } from 'lib/child';
1611import { useLocalRouter } from 'lib/LocalRouter';
17−import useConstant from 'lib/useConstant';
1812
1913import { keccak256 } from 'lib/wallet';
2014
2115import ViewHeader from 'components/ViewHeader';
2216import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
2317import View from 'components/View';
24−import { PointInput, AddressInput } from 'form/Inputs';
25−import {
26− composeValidator,
27− buildPointValidator,
28− buildAddressValidator,
29− hasErrors,
30−} from 'form/validators';
3118import BridgeForm from 'form/BridgeForm';
32−import FormError from 'form/FormError';
33−import CopiableAddress from 'components/CopiableAddress';
3419import convertToInt from 'lib/convertToInt';
3520
3621function useCastDocumentVote() {
3722 const { contracts } = useNetwork();
3823 const { pointCursor } = usePointCursor();
39− const { syncDetails } = usePointCache();
4024
4125 const _contracts = need.contracts(contracts);
4226 const _point = need.point(pointCursor);
@@ -66,15 +50,9 @@ export default function Senate() {
6650 const _contracts = need.contracts(contracts);
6751 const _point = convertToInt(need.point(pointCursor), 10);
6852
69− const {
70− construct,
71− unconstruct,
72− inputsLocked,
73− completed,
74− bind,
75− } = useCastDocumentVote();
53+ const { construct, bind } = useCastDocumentVote();
7654
77− const [documentHash, setDocumentHash] = useState('0x...');
55+ // const [documentHash, setDocumentHash] = useState('0x...');
7856 const [majorities, setMajorities] = useState([]);
7957 const [proposals, setProposals] = useState([]);
8058 const [polls, setPolls] = useState({});
@@ -103,7 +81,7 @@ export default function Senate() {
10381 setPolls(polls);
10482 setLoading(false);
10583 return;
106− }, [_contracts]);
84+ }, [_contracts, _point]);
10785
10886 const [open, closed] = useMemo(() => {
10987 let open = [];
@@ -185,15 +163,15 @@ export default function Senate() {
185163 </>
186164 );
187165 });
188− }, [open, polls, votingOn]);
166+ }, [open, polls, votingOn, doVote]);
189167
190168 const onDocumentChange = useCallback(({ valid, values }) => {
191− if (values.document) {
192− const hash = '0x' + keccak256(values.document.trim()).toString('hex');
193− setDocumentHash(hash);
194− } else {
195− setDocumentHash('0x...');
196− }
169+ // if (values.document) {
170+ // const hash = '0x' + keccak256(values.document.trim()).toString('hex');
171+ // setDocumentHash(hash);
172+ // } else {
173+ // setDocumentHash('0x...');
174+ // }
197175 }, []);
198176
199177 return (