on master help sign in
feat: add disabledDetails to admin buttons
commite7ae14d179f505bf2731ce6329285f10a8df9007 authorMatt Condon (shrugs) <mattgcondon@gmail.com> dateTue 16 Jul 2019, 20:57 (7 years ago) parent1a6981c
7 files changed+134−48
src/components/DownloadKeyfileButton.js+22−2 src/indigo-react/components/Button.js+12−9 src/lib/constants.js+1 src/lib/useKeyfileGenerator.js+1−3 src/views/Admin/AdminHome.js+7−2 src/views/Admin/AdminTransfer.js+60−13 src/views/Login.js+31−19
src/components/DownloadKeyfileButton.js+22−2
@@ -1,12 +1,13 @@
11import React from 'react';
2−
3−import { DownloadButton } from 'components/Buttons';
2+import { Flex, B } from 'indigo-react';
43
54import { usePointCursor } from 'store/pointCursor';
65
76import useKeyfileGenerator from 'lib/useKeyfileGenerator';
87import * as need from 'lib/need';
98
9+import { DownloadButton } from 'components/Buttons';
10+
1011export default function DownloadKeyfileButton({
1112 networkSeed,
1213 className,
@@ -22,8 +23,27 @@ export default function DownloadKeyfileButton({
2223
2324 return (
2425 <DownloadButton
26+ as="span"
2527 className={className}
2628 disabled={downloaded || !available}
29+ disabledDetail={
30+ !generating &&
31+ !available && (
32+ // TODO: make this a toggle-able 'help' or something
33+ <Flex col>
34+ <Flex.Item as={B} className="wrap ws-normal">
35+ · You are using nondeterministic networking keys. To download your
36+ Arvo keyfile, either:
37+ </Flex.Item>
38+ <Flex.Item as={B} className="wrap ws-normal">
39+ a) Reset your networking keys, or
40+ </Flex.Item>
41+ <Flex.Item as={B} className="wrap ws-normal">
42+ b) Reticket to get deterministic networking keys.
43+ </Flex.Item>
44+ </Flex>
45+ )
46+ }
2747 loading={generating}
2848 onClick={download}
2949 {...rest}>
src/indigo-react/components/Button.js+12−9
@@ -10,6 +10,7 @@ export default function Button({
1010 solid = false,
1111 success = false,
1212 disabled = false,
13+ disabledDetail,
1314 detail,
1415 className,
1516 accessory = '→',
@@ -33,6 +34,11 @@ export default function Button({
3334 'bg-gray3': !success && solid && disabled,
3435 'bg-transparent': !success && !solid,
3536 },
37+ {
38+ white: solid,
39+ black: !solid && !disabled,
40+ gray4: !solid && disabled,
41+ },
3642 className
3743 )}
3844 style={{
@@ -43,15 +49,7 @@ export default function Button({
4349 }}
4450 onClick={!disabled && onClick ? onClick : undefined}
4551 {...rest}>
46− <Grid.Item
47− full
48− as={Flex}
49− justify="between"
50− className={cn({
51− white: solid,
52− black: !solid && !disabled,
53− gray4: !solid && disabled,
54− })}>
52+ <Grid.Item full as={Flex} justify="between">
5553 <span>{children}</span>
5654 <div className={cn('pl4')}>{accessory}</div>
5755 </Grid.Item>
@@ -60,6 +58,11 @@ export default function Button({
6058 {detail}
6159 </Grid.Item>
6260 )}
61+ {disabled && disabledDetail && (
62+ <Grid.Item full className="f6 black mt1">
63+ {disabledDetail}
64+ </Grid.Item>
65+ )}
6366 </Grid>
6467 );
6568}
src/lib/constants.js+1
@@ -17,6 +17,7 @@ const GALAXY_ENTROPY_BITS = 384;
1717
1818const SEED_ENTROPY_BITS = 128;
1919
20+// the null result if a key is unset within azimuth
2021const ZERO_KEY =
2122 '0x0000000000000000000000000000000000000000000000000000000000000000';
2223
src/lib/useKeyfileGenerator.js+1−3
@@ -21,7 +21,7 @@ export default function useKeyfileGenerator(point, manualNetworkSeed) {
2121 const { urbitWallet, wallet, authMnemonic } = useWallet();
2222
2323 const [downloaded, setDownloaded] = useState(false);
24− const [generating, setGenerating] = useState(false);
24+ const [generating, setGenerating] = useState(true);
2525 const [keyfile, setKeyfile] = useState(false);
2626
2727 const _address = need.wallet(wallet).address;
@@ -38,8 +38,6 @@ export default function useKeyfileGenerator(point, manualNetworkSeed) {
3838 (isOwner || isManagementProxy) && hasNetworkingKeys && keyfile;
3939
4040 const generate = useCallback(async () => {
41− setGenerating(true);
42−
4341 console.log('generating for network revision', networkRevision);
4442
4543 const networkSeed = manualNetworkSeed
src/views/Admin/AdminHome.js+7−2
@@ -1,6 +1,6 @@
11import React, { useCallback } from 'react';
22import { Just } from 'folktale/maybe';
3−import { Grid } from 'indigo-react';
3+import { Grid, B } from 'indigo-react';
44import * as need from 'lib/need';
55
66import { ForwardButton } from 'components/Buttons';
@@ -47,7 +47,12 @@ export default function AdminHome() {
4747 as={ForwardButton}
4848 disabled={!canDownloadPassport}
4949 onClick={goRedownload}
50− detail="Re-download your paper wallet">
50+ detail="Re-download your paper wallet"
51+ disabledDetail={
52+ <B className="wrap ws-normal">
53+ · Master Ticket Authentication required.
54+ </B>
55+ }>
5156 Download Passport
5257 </Grid.Item>
5358 <Grid.Divider />
src/views/Admin/AdminTransfer.js+60−13
@@ -1,18 +1,49 @@
1−import React, { useCallback } from 'react';
1+import React, { useCallback, useEffect } from 'react';
2+import cn from 'classnames';
23import { Grid, Text, Input } from 'indigo-react';
4+import * as azimuth from 'azimuth-js';
5+
6+import { useNetwork } from 'store/network';
7+import { usePointCursor } from 'store/pointCursor';
8+
9+import * as need from 'lib/need';
310import { useLocalRouter } from 'lib/LocalRouter';
11+import { useAddressInput } from 'lib/useInputs';
12+import useCurrentPointName from 'lib/useCurrentPointName';
13+import useEthereumTransaction from 'lib/useEthereumTransaction';
14+import { GAS_LIMITS } from 'lib/constants';
415
516import ViewHeader from 'components/ViewHeader';
617import MiniBackButton from 'components/MiniBackButton';
7−import { GenerateButton } from 'components/Buttons';
8−import { useAddressInput } from 'lib/useInputs';
9−import useCurrentPointName from 'lib/useCurrentPointName';
18+import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
1019
1120function useTransfer() {
12− const transfer = useCallback(async () => {}, []);
21+ const { contracts } = useNetwork();
22+ const { pointCursor } = usePointCursor();
23+
24+ const _contracts = need.contracts(contracts);
25+ const _point = need.point(pointCursor);
26+
27+ const {
28+ construct: _construct,
29+ confirmed,
30+ inputsLocked,
31+ bind,
32+ } = useEthereumTransaction(GAS_LIMITS.TRANSFER);
33+
34+ const construct = useCallback(
35+ address =>
36+ _construct(
37+ azimuth.ecliptic.setTransferProxy(_contracts, _point, address)
38+ ),
39+ [_construct, _contracts, _point]
40+ );
1341
1442 return {
15− transfer,
43+ construct,
44+ confirmed,
45+ inputsLocked,
46+ bind,
1647 };
1748}
1849
@@ -20,12 +51,18 @@ export default function AdminTransfer() {
2051 const { pop } = useLocalRouter();
2152 const name = useCurrentPointName();
2253
23− const [addressInput, { pass }] = useAddressInput({
54+ const { construct, confirmed, inputsLocked, bind } = useTransfer();
55+ const [addressInput, { pass, data: address }] = useAddressInput({
2456 name: 'address',
2557 label: `Ethereum Address`,
58+ disabled: inputsLocked,
2659 });
2760
28− const { transfer } = useTransfer();
61+ useEffect(() => {
62+ if (pass) {
63+ construct(address);
64+ }
65+ }, [pass, address, construct]);
2966
3067 return (
3168 <Grid>
@@ -33,15 +70,25 @@ export default function AdminTransfer() {
3370 <Grid.Item full as={ViewHeader}>
3471 Transfer Point
3572 </Grid.Item>
36− <Grid.Item full as={Text}>
37− Transfer {name} to a new owner.
73+ <Grid.Item
74+ full
75+ as={Text}
76+ className={cn('f5', {
77+ green3: confirmed,
78+ })}>
79+ {confirmed
80+ ? `${address} is now the Transfer Proxy for ${name} and can accept the transfer by logging into Multipass themselves. Until they accept your transfer, you will still have ownership over ${name}.`
81+ : `Transfer ${name} to a new owner.`}
3882 </Grid.Item>
3983
4084 <Grid.Item full as={Input} {...addressInput} className="mv4" />
4185
42− <Grid.Item full as={GenerateButton} onClick={transfer} disabled={!pass}>
43− Generate & Sign Transaction
44− </Grid.Item>
86+ <Grid.Item
87+ full
88+ as={InlineEthereumTransaction}
89+ {...bind}
90+ onReturn={() => pop()}
91+ />
4592 </Grid>
4693 );
4794}
src/views/Login.js+31−19
@@ -1,27 +1,27 @@
11import React, { useCallback, useState } from 'react';
22import { Just, Nothing } from 'folktale/maybe';
33import * as azimuth from 'azimuth-js';
4−
54import { H4, Grid } from 'indigo-react';
65
7−import Ticket from './Login/Ticket';
8−import Mnemonic from './Login/Mnemonic';
9−import Advanced from './Login/Advanced';
10−import Hardware from './Login/Hardware';
11−
12−import * as need from 'lib/need';
13−
146import { useHistory } from 'store/history';
157import { useNetwork } from 'store/network';
168import { useWallet } from 'store/wallet';
179import { usePointCursor } from 'store/pointCursor';
1810
11+import * as need from 'lib/need';
12+import { WALLET_TYPES } from 'lib/wallet';
13+
1914import View from 'components/View';
2015import Tabs from 'components/Tabs';
2116import Crumbs from 'components/Crumbs';
2217import Footer from 'components/Footer';
2318import { ForwardButton, OfflineButton } from 'components/Buttons';
2419
20+import Ticket from './Login/Ticket';
21+import Mnemonic from './Login/Mnemonic';
22+import Advanced from './Login/Advanced';
23+import Hardware from './Login/Hardware';
24+
2525const NAMES = {
2626 TICKET: 'TICKET',
2727 MNEMONIC: 'MNEMONIC',
@@ -43,17 +43,37 @@ const OPTIONS = [
4343 { text: 'Advanced', value: NAMES.ADVANCED },
4444];
4545
46+const walletTypeToViewName = walletType => {
47+ switch (walletType) {
48+ case WALLET_TYPES.MNEMONIC:
49+ return NAMES.MNEMONIC;
50+ case WALLET_TYPES.LEDGER:
51+ case WALLET_TYPES.TREZOR:
52+ return NAMES.HARDWARE;
53+ case WALLET_TYPES.KEYSTORE:
54+ case WALLET_TYPES.PRIVATE_KEY:
55+ return NAMES.ADVANCED;
56+ case WALLET_TYPES.TICKET:
57+ case WALLET_TYPES.SHARDS:
58+ return NAMES.TICKET;
59+ default:
60+ return NAMES.TICKET;
61+ }
62+};
63+
4664export default function Login() {
4765 // globals
4866 const { push, replaceWith, names } = useHistory();
4967 const { contracts } = useNetwork();
50− const { wallet } = useWallet();
68+ const { wallet, walletType } = useWallet();
5169 const { pointCursor, setPointCursor } = usePointCursor();
5270
5371 const [deducing, setDeducing] = useState(false);
5472
5573 // inputs
56− const [currentTab, setCurrentTab] = useState(NAMES.TICKET);
74+ const [currentTab, setCurrentTab] = useState(
75+ walletTypeToViewName(walletType)
76+ );
5777
5878 const goToActivate = useCallback(
5979 () => replaceWith([{ key: names.LANDING }, { key: names.ACTIVATE }]),
@@ -75,8 +95,8 @@ export default function Login() {
7595
7696 setDeducing(true);
7797
78− // if no point cursor set by login logic, try to deduce it
7998 let deduced = pointCursor;
99+ // if no point cursor set by login logic, try to deduce it
80100 if (Nothing.hasInstance(deduced)) {
81101 const owned = await azimuth.azimuth.getOwnedPoints(
82102 _contracts,
@@ -84,14 +104,6 @@ export default function Login() {
84104 );
85105 if (owned.length === 1) {
86106 deduced = Just(owned[0]);
87− } else if (owned.length === 0) {
88− const canOwn = await azimuth.azimuth.getTransferringFor(
89− _contracts,
90− _wallet.address
91− );
92− if (canOwn.length === 1) {
93− deduced = Just(canOwn[0]);
94− }
95107 }
96108 }
97109