on master help sign in
visual qa && lint fixes
commit7701299f4db1c2e73eaeb18c30ec55ad4b3d3c7b authorLiam Fitzgerald <liam@urizen.co> dateWed 4 Mar 2020, 16:01 (7 years ago) parent8d566ea
24 files changed+229−310
src/Bridge.js+1−1 src/components/Buttons.js−6 src/components/Greeting.js−6 src/components/InlineEthereumTransaction.js+1−2 src/lib/hosting.js+2 src/lib/routeNames.js−1 src/lib/router.js−4 src/lib/useEthereumTransaction.js+2−2 src/lib/useHostedShip.js−166 src/store/lib/useHostingStore.js+5−9 src/store/lib/useResidentsStore.js+2−3 src/style/hosted-ship.scss−14 src/views/Admin/AdminNetworkingKeys.js−2 src/views/Point.js+15−10 src/views/Residents.js+14−10 src/views/UrbitID.js+5 src/views/UrbitID/Home.js+18−8 src/views/UrbitID/ResetKeys.js−2 src/views/UrbitID/SetProxy.js+1−7 src/views/UrbitID/SigilGenerator.js−3 src/views/UrbitID/Transfer.js+113 src/views/UrbitOS.js+7−2 src/views/UrbitOS/Home.js+23−38 src/views/UrbitOS/NetworkingKeys.js+20−14
src/Bridge.js+1−1
@@ -20,7 +20,7 @@ import WithErrorBoundary from 'components/WithErrorBoundary';
2020import GlobalErrorBoundary from 'components/GlobalErrorBoundary';
2121
2222const INITIAL_NETWORK_TYPE = isDevelopment
23− ? NETWORK_TYPES.LOCAL
23+ ? NETWORK_TYPES.ROPSTEN
2424 : NETWORK_TYPES.MAINNET;
2525
2626// NB(shrugs): modify these variables to change the default local state.
src/components/Buttons.js−6
@@ -23,9 +23,3 @@ export const OfflineButton = props => (
2323 Offline
2424 </OutButton>
2525);
26−
27−export const HostingButton = props => (
28− <ForwardButton detail="Boot your Urbit OS" {...props}>
29− Boot your Urbit OS
30− </ForwardButton>
31−);
src/components/Greeting.js−6
@@ -3,18 +3,12 @@ import cn from 'classnames';
33import ob from 'urbit-ob';
44import { Grid, Text, LinkButton } from 'indigo-react';
55
6−import { useLocalRouter } from 'lib/LocalRouter';
7−
86import useWasGreeted from 'lib/useWasGreeted';
9−import useCurrentPermissions from 'lib/useCurrentPermissions';
107
118const TEXT_STYLE = 'f5';
129
1310export default function ActivateDisclaimer({ point }) {
14− const { push, names } = useLocalRouter();
15−
1611 const [wasGreeted, setWasGreeted] = useWasGreeted();
17− const { isActiveOwner } = useCurrentPermissions();
1812
1913 const pointName = ob.patp(point);
2014
src/components/InlineEthereumTransaction.js+1−2
@@ -8,7 +8,6 @@ import {
88 LinkButton,
99 H5,
1010 Text,
11− IconButton,
1211} from 'indigo-react';
1312import { toBN } from 'web3-utils';
1413
@@ -16,7 +15,6 @@ import { ReactComponent as InfoIcon } from 'assets/info.svg';
1615
1716import { useExploreTxUrls } from 'lib/explorer';
1817import { hexify } from 'lib/txn';
19−import pluralize from 'lib/pluralize';
2018import { safeFromWei, safeToWei } from 'lib/lib';
2119
2220import { composeValidator, buildCheckboxValidator } from 'form/validators';
@@ -275,6 +273,7 @@ export default function InlineEthereumTransaction({
275273
276274 {completed && (
277275 <>
276+ <Grid.Divider />
278277 <Grid.Item full as={RestartButton} onClick={onReturn}>
279278 Return
280279 </Grid.Item>
src/lib/hosting.js+2
@@ -18,6 +18,8 @@ export const getVaneName = code => {
1818 return 'Iris';
1919 case 'j':
2020 return 'Jael';
21+ default:
22+ return '';
2123 }
2224};
2325
src/lib/routeNames.js−1
@@ -23,7 +23,6 @@ export const ROUTE_NAMES = {
2323 INVITE_COHORT: Symbol('INVITE_COHORT'),
2424 STAR_RELEASE: Symbol('STAR_RELEASE'),
2525 URBIT_OS: Symbol('URBIT_OS'),
26− HOSTING: Symbol('HOSTING'),
2726 URBIT_ID: Symbol('URBIT_ID'),
2827 RESIDENTS: Symbol('RESIDENTS'),
2928 ADOPT: Symbol('ADOPT'),
src/lib/router.js−4
@@ -18,8 +18,6 @@ import UrbitOS from 'views/UrbitOS';
1818import UrbitID from 'views/UrbitID';
1919import Residents from 'views/Residents';
2020import Adopt from 'views/Adopt';
21−import Boot from 'views/Boot';
22−import Hosting from 'views/Hosting';
2321
2422import { ROUTE_NAMES } from './routeNames';
2523
@@ -41,8 +39,6 @@ export const ROUTES = {
4139 [ROUTE_NAMES.INVITE_COHORT]: InviteCohort,
4240 [ROUTE_NAMES.STAR_RELEASE]: StarRelease,
4341 [ROUTE_NAMES.URBIT_OS]: UrbitOS,
44− [ROUTE_NAMES.BOOT]: Boot,
45− [ROUTE_NAMES.HOSTING]: Hosting,
4642 [ROUTE_NAMES.URBIT_ID]: UrbitID,
4743 [ROUTE_NAMES.RESIDENTS]: Residents,
4844 [ROUTE_NAMES.ADOPT]: Adopt,
src/lib/useEthereumTransaction.js+2−2
@@ -1,4 +1,4 @@
1−import { useCallback, useEffect, useState, useMemo } from 'react';
1+import { useCallback, useEffect, useState } from 'react';
22import { Just } from 'folktale/maybe';
33import { toBN } from 'web3-utils';
44
@@ -22,7 +22,7 @@ import { ensureFundsFor } from 'lib/tank';
2222import useDeepEqualReference from 'lib/useDeepEqualReference';
2323import useGasPrice from 'lib/useGasPrice';
2424import timeout from 'lib/timeout';
25−import { safeToWei, safeFromWei } from 'lib/lib';
25+import { safeToWei } from 'lib/lib';
2626
2727const STATE = {
2828 NONE: 'NONE',
src/lib/useHostedShip.jsdeleted−166
@@ -1,166 +0,0 @@
1−import { useCallback, useState } from 'react';
2−
3−const STATE = {
4− // container states
5− UNKNOWN: 'UNKNOWN',
6− MISSING: 'MISSING',
7− RUNNING: 'RUNNING',
8− PENDING: 'PENDING',
9− // api states
10− QUERYING: 'QUERYING',
11− BOOTING: 'BOOTING',
12− CONNECTING: 'CONNECTING',
13− // connection states
14− CONNECTED: 'CONNECTED',
15−};
16−
17−export function useHostedShip(client, patp) {
18− const [state, _setState] = useState(STATE.UNKNOWN);
19− const setState = useCallback(
20− s => {
21− console.log(s);
22− _setState(s);
23− },
24− [_setState]
25− );
26−
27− const [sysEvents, setSysEvents] = useState([]);
28− const [newEvents, setNewEvents] = useState([]);
29− const [runEvents, setRunEvents] = useState([]);
30−
31− const [error, _setError] = useState();
32− const setError = useCallback(
33− error => {
34− _setError(error);
35− if (error) {
36− setState(STATE.UNKNOWN);
37− console.error(error);
38− }
39− },
40− [_setError, setState]
41− );
42−
43− const unknown = state === STATE.UNKNOWN;
44− const missing = state === STATE.MISSING;
45− const running = state === STATE.RUNNING;
46− const pending = state === STATE.PENDING;
47− const querying = state === STATE.QUERYING;
48− const booting = state === STATE.BOOTING;
49− const connecting = state === STATE.CONNECTING;
50− const connected = state === STATE.CONNECTED;
51−
52− const resetEvents = useCallback(() => {
53− setSysEvents([]);
54− setNewEvents([]);
55− setRunEvents([]);
56− }, []);
57−
58− const getStatus = useCallback(async () => {
59− try {
60− setError(undefined);
61−
62− resetEvents();
63−
64− setState(STATE.QUERYING);
65−
66− const response = await client.getShipsByPatp(patp);
67−
68− if (response.status === 404) {
69− setState(STATE.MISSING);
70− } else if (!response.ok) {
71− setError(response.statusText);
72− } else {
73− const ship = await response.json();
74−
75− if (ship.status === 'Pending') {
76− setState(STATE.PENDING);
77− } else if (ship.status === 'Running') {
78− setState(STATE.RUNNING);
79− } else {
80− setError(ship);
81− }
82− }
83− } catch (error) {
84− setError(error);
85− }
86− }, [client, patp, resetEvents, setError, setState]);
87−
88− const getEvents = useCallback(() => {
89− try {
90− setError(undefined);
91−
92− resetEvents();
93−
94− setState(STATE.CONNECTING);
95−
96− const url = client.getShipsByPatpUrl(patp) + '/events';
97− const source = new EventSource(url);
98−
99− source.onopen = () => setState(STATE.CONNECTED);
100− // source.onerror = () => setState(STATE.UNKNOWN);
101− // source.onmessage = console.log;
102−
103− source.addEventListener('sys', event => {
104− setSysEvents(previous => [...previous, JSON.parse(event.data)]);
105− });
106−
107− source.addEventListener('new', event => {
108− if (event.data !== '') {
109− setNewEvents(previous => [...previous, event.data]);
110− }
111− });
112−
113− source.addEventListener('run', event => {
114− if (event.data !== '') {
115− setRunEvents(previous => [...previous, event.data]);
116− }
117− });
118− } catch (error) {
119− setError(error);
120− }
121− }, [setError, resetEvents, client, patp, setState]);
122−
123− const create = useCallback(async () => {
124− try {
125− setError(undefined);
126−
127− setState(STATE.BOOTING);
128−
129− const response = await client.postShips({
130− patp,
131− key: '123',
132− });
133−
134− if (!response.ok) {
135− setError(response.statusText);
136− } else {
137− getEvents();
138− }
139− } catch (error) {
140− setError(error);
141− }
142− }, [setError, setState, client, patp, getEvents]);
143−
144− return {
145− error,
146− unknown,
147− missing,
148− running,
149− pending,
150− querying,
151− booting,
152− connecting,
153− connected,
154−
155− sysEvents,
156− newEvents,
157− runEvents,
158−
159− getStatus,
160− getEvents,
161− create,
162−
163− // debugging
164− state,
165− };
166−}
src/store/lib/useHostingStore.js+5−9
@@ -1,13 +1,13 @@
11import { useState, useCallback, useMemo } from 'react';
2−import { Just, Nothing } from 'folktale/maybe';
2+import { Nothing } from 'folktale/maybe';
33import * as ob from 'urbit-ob';
44
55import { getVaneName, getVaneNumber } from 'lib/hosting';
66import SolarisClient from 'lib/SolarisClient';
7−// import { usePointCursor } from 'store/pointCursor';
8−import useKeyfileGenerator from 'lib/useKeyfileGenerator';
7+
8+import { usePointCursor } from 'store/pointCursor';
9+
910const STATE = {
10− // container states
1111 UNKNOWN: 'UNKNOWN',
1212 MISSING: 'MISSING',
1313 RUNNING: 'RUNNING',
@@ -17,9 +17,7 @@ const STATE = {
1717function useHostingStore(url) {
1818 const client = new SolarisClient(url);
1919
20− // const { pointCursor } = usePointCursor();
21− //
22− const pointCursor = Just(ob.patp2dec('~wicdev-wisryt'));
20+ const { pointCursor } = usePointCursor();
2321
2422 const [bootProgress, setBootProgress] = useState(0);
2523 const [bootMessage, setBootMessage] = useState('Assembling Urbit');
@@ -182,8 +180,6 @@ function useHostingStore(url) {
182180 if (Nothing.hasInstance(pointCursor)) {
183181 return;
184182 }
185− keyfile =
186− '0wnE.Z56pm.i2HLZ.6Pf1R.tAVZH.65R~C.Zgy6y.caI5Z.bZ2vV.09M5A.QP5-p.29UfR.35h2U.2k8-D.QP~~p.6bL62.~x3Em.t9h0x.0y01N.w80c1';
187183 const patp = ob.patp(pointCursor.value).slice(1);
188184 setError(undefined);
189185
src/store/lib/useResidentsStore.js+2−3
@@ -1,11 +1,10 @@
1−import { useState, useCallback, useEffect } from 'react';
1+import { useState, useCallback } from 'react';
22import { Just, Nothing } from 'folktale/maybe';
33
44import { azimuth } from 'azimuth-js';
55
66import { useNetwork } from 'store/network';
77
8−import useCurrentPermissions from 'lib/useCurrentPermissions';
98import * as need from 'lib/need';
109
1110const emptyCacheEntry = {
@@ -29,7 +28,7 @@ export default function useResidents() {
2928 [residentCache]
3029 );
3130
32− const { contracts, web3 } = useNetwork();
31+ const { contracts } = useNetwork();
3332 const _contracts = need.contracts(contracts);
3433
3534 const syncResidentCount = useCallback(
src/style/hosted-ship.scssdeleted−14
@@ -1,14 +0,0 @@
1−.hosting-events {
2− margin: 0;
3− padding: 2px;
4− background: #000;
5− list-style: none;
6− font-family: monospace;
7−
8− li {
9− margin: 1px;
10− padding: 2px;
11− background: #111;
12− color: #26ca41;
13− }
14−}
src/views/Admin/AdminNetworkingKeys.js−2
@@ -26,7 +26,6 @@ import { addHexPrefix } from 'lib/wallet';
2626import useKeyfileGenerator from 'lib/useKeyfileGenerator';
2727
2828import ViewHeader from 'components/ViewHeader';
29−import { HostingButton } from 'components/Buttons';
3029import FooterButton from 'components/FooterButton';
3130import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
3231import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
@@ -417,7 +416,6 @@ export default function AdminNetworkingKeys() {
417416
418417 {completed && (
419418 <>
420− <Grid.Item full as={HostingButton} onReturn={() => pop()} />
421419 <Grid.Divider />
422420 </>
423421 )}
src/views/Point.js+15−10
@@ -1,4 +1,4 @@
1−import React, { useCallback, useState, useEffect } from 'react';
1+import React, { useCallback, useState } from 'react';
22import cn from 'classnames';
33import { Just } from 'folktale/maybe';
44import { Grid, Flex, Button } from 'indigo-react';
@@ -14,9 +14,7 @@ import Blinky, { matchBlinky } from 'components/Blinky';
1414import BarGraph from 'components/BarGraph';
1515import Chip from 'components/Chip';
1616import InviteSigilList from 'components/InviteSigilList';
17−import { ForwardButton, HostingButton } from 'components/Buttons';
18−import CopyButton from 'components/CopyButton';
19−import DownloadSigilButton from 'components/DownloadSigilButton';
17+import { ForwardButton } from 'components/Buttons';
2018
2119import * as need from 'lib/need';
2220import useInvites from 'lib/useInvites';
@@ -72,8 +70,6 @@ export default function Point() {
7270
7371 const goSenate = useCallback(() => push(names.SENATE), [push, names]);
7472
75− const goSigil = useCallback(() => push(names.SIGIL_GENERATOR), [push, names]);
76−
7773 const goCohort = useCallback(() => push(names.INVITE_COHORT), [push, names]);
7874
7975 const goUrbitOS = useCallback(() => push(names.URBIT_OS), [push, names]);
@@ -96,9 +92,6 @@ export default function Point() {
9692
9793 const [showInviteForm, setShowInviteForm] = useState(false);
9894
99− const goBoot = useCallback(() => push(names.BOOT), [push, names]);
100− const goHosting = useCallback(() => push(names.HOSTING), [push, names]);
101−
10295 const inviteButton = (() => {
10396 if (azimuth.getPointSize(point) === azimuth.PointSize.Star) {
10497 return (
@@ -210,7 +203,19 @@ export default function Point() {
210203 <Grid.Item full className="mb2" />
211204 </>
212205 );
213− });
206+ }, [
207+ showInviteForm,
208+ setShowInviteForm,
209+ _pendingInvites,
210+ _totalInvites,
211+ acceptedInvites,
212+ acceptedPoints,
213+ availableInvites,
214+ goCohort,
215+ pendingPoints,
216+ sentInvites,
217+ showInvites,
218+ ]);
214219
215220 const _requestCount = requestCount.getOrElse(0);
216221
src/views/Residents.js+14−10
@@ -125,19 +125,23 @@ export default function Residents() {
125125
126126 const isRequests = useMemo(() => currentTab === NAMES.REQUESTS, [currentTab]);
127127
128− const _onAccept = useCallback(adoptee =>
129− push(names.ADOPT, {
130− adoptee,
131− denied: false,
132− })
128+ const _onAccept = useCallback(
129+ adoptee =>
130+ push(names.ADOPT, {
131+ adoptee,
132+ denied: false,
133+ }),
134+ [push, names]
133135 );
134136 const onAccept = isRequests && _onAccept;
135137
136− const _onDecline = useCallback(adoptee =>
137− push(names.ADOPT, {
138− adoptee,
139− denied: true,
140− })
138+ const _onDecline = useCallback(
139+ adoptee =>
140+ push(names.ADOPT, {
141+ adoptee,
142+ denied: true,
143+ }),
144+ [push, names]
141145 );
142146 const onDecline = isRequests && _onDecline;
143147
src/views/UrbitID.js+5
@@ -16,6 +16,7 @@ import SigilGenerator from './UrbitID/SigilGenerator';
1616import DownloadKeys from './UrbitID/DownloadKeys';
1717import SetProxy from './UrbitID/SetProxy';
1818import ResetKeys from './UrbitID/ResetKeys';
19+import Transfer from './UrbitID/Transfer';
1920
2021const NAMES = {
2122 HOME: 'HOME',
@@ -23,6 +24,7 @@ const NAMES = {
2324 DOWNLOAD_KEYS: 'DOWNLOAD_KEYS',
2425 SET_PROXY: 'SET_PROXY',
2526 RESET_KEYS: 'RESET_KEYS',
27+ TRANSFER: 'TRANSFER',
2628};
2729
2830const VIEWS = {
@@ -31,6 +33,7 @@ const VIEWS = {
3133 [NAMES.DOWNLOAD_KEYS]: DownloadKeys,
3234 [NAMES.RESET_KEYS]: ResetKeys,
3335 [NAMES.SET_PROXY]: SetProxy,
36+ [NAMES.TRANSFER]: Transfer,
3437};
3538
3639const humanizeName = name => {
@@ -43,6 +46,8 @@ const humanizeName = name => {
4346 return 'Set Key';
4447 case NAMES.RESET_KEYS:
4548 return 'Reset Keys';
49+ case NAMES.TRANSFER:
50+ return 'Transfer';
4651 default:
4752 return undefined;
4853 }
src/views/UrbitID/Home.js+18−8
@@ -7,17 +7,14 @@ import { ForwardButton } from 'components/Buttons';
77import CopyButton from 'components/CopyButton';
88
99import { useLocalRouter } from 'lib/LocalRouter';
10−import { isZeroAddress } from 'lib/wallet';
1110import { PROXY_TYPE, proxyTypeToHuman } from 'lib/proxy';
1211import * as need from 'lib/need';
1312import capitalize from 'lib/capitalize';
14−import { eqAddr } from 'lib/wallet';
1513import useCurrentPermissions from 'lib/useCurrentPermissions';
1614import convertToInt from 'lib/convertToInt';
1715
1816import { usePointCursor } from 'store/pointCursor';
1917import { usePointCache } from 'store/pointCache';
20−import { useNetwork } from 'store/network';
2118import { useWallet } from 'store/wallet';
2219
2320export default function UrbitIDHome() {
@@ -26,8 +23,6 @@ export default function UrbitIDHome() {
2623 const { getDetails } = usePointCache();
2724 const { urbitWallet } = useWallet();
2825
29− const { contracts } = useNetwork();
30−
3126 const goSigil = useCallback(() => push(names.SIGIL_GENERATOR), [push, names]);
3227
3328 const goDownloadKeys = useCallback(() => push(names.DOWNLOAD_KEYS), [
@@ -38,10 +33,9 @@ export default function UrbitIDHome() {
3833 const goResetKeys = useCallback(() => push(names.RESET_KEYS), [push, names]);
3934
4035 const isMasterTicket = Just.hasInstance(urbitWallet);
41− const _contracts = need.contracts(contracts);
4236 const point = need.point(pointCursor);
4337 const details = need.details(getDetails(point));
44− const { canManage, isOwner } = useCurrentPermissions();
38+ const { isOwner } = useCurrentPermissions();
4539 const networkRevision = convertToInt(details.keyRevisionNumber, 10);
4640
4741 const pointSize = azimuth.getPointSize(point);
@@ -53,6 +47,8 @@ export default function UrbitIDHome() {
5347 [push, names]
5448 );
5549
50+ const goTransfer = useCallback(() => push(names.TRANSFER), [names, push]);
51+
5652 const renderProxyAction = useCallback(
5753 (proxyType, address) => {
5854 const disabled =
@@ -74,7 +70,7 @@ export default function UrbitIDHome() {
7470 );
7571 return (
7672 <Grid>
77− <Grid.Item full className="mv7 f5">
73+ <Grid.Item full className="mb7 f5">
7874 Urbit ID
7975 </Grid.Item>
8076 <Grid.Divider />
@@ -99,6 +95,10 @@ export default function UrbitIDHome() {
9995 full
10096 as={ForwardButton}
10197 onClick={goResetKeys}
98+ disabled={!isOwner}
99+ disabledDetail={
100+ <B className="wrap ws-normal"> · Ownership key required</B>
101+ }
102102 detail="Reset Master Key and all other keys">
103103 Reset Keys
104104 </Grid.Item>
@@ -145,6 +145,16 @@ export default function UrbitIDHome() {
145145 <Grid.Divider />
146146 </>
147147 )}
148+ <Grid.Item
149+ full
150+ as={ForwardButton}
151+ onClick={goTransfer}
152+ disabled={!isOwner}
153+ disabledDetail={
154+ <B className="wrap ws-normal"> · Ownership key required</B>
155+ }>
156+ Transfer this point
157+ </Grid.Item>
148158 </Grid>
149159 );
150160}
src/views/UrbitID/ResetKeys.js−2
@@ -7,8 +7,6 @@ import useRouter from 'lib/useRouter';
77
88import Steps from 'components/Steps';
99
10−import { usePointCursor } from 'store/pointCursor';
11−
1210import ResetConfirm from './ResetKeys/ResetConfirm';
1311import ResetDownload from './ResetKeys/ResetDownload';
1412import ResetVerify from './ResetKeys/ResetVerify';
src/views/UrbitID/SetProxy.js+1−7
@@ -1,6 +1,6 @@
11import React, { useCallback, useMemo } from 'react';
22import cn from 'classnames';
3−import { Grid, Text, Flex, ToggleInput } from 'indigo-react';
3+import { Grid, Text, Flex } from 'indigo-react';
44import * as azimuth from 'azimuth-js';
55
66import { useNetwork } from 'store/network';
@@ -18,7 +18,6 @@ import { ETH_ZERO_ADDR, eqAddr, isZeroAddress } from 'lib/wallet';
1818import capitalize from 'lib/capitalize';
1919import useEthereumTransaction from 'lib/useEthereumTransaction';
2020
21−import ViewHeader from 'components/ViewHeader';
2221import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
2322import { GAS_LIMITS } from 'lib/constants';
2423import { AddressInput } from 'form/Inputs';
@@ -29,7 +28,6 @@ import {
2928} from 'form/validators';
3029import BridgeForm from 'form/BridgeForm';
3130import FormError from 'form/FormError';
32−import CopiableAddress from 'components/CopiableAddress';
3331
3432const proxyFromDetails = (details, contracts, proxyType) => {
3533 switch (proxyType) {
@@ -154,10 +152,6 @@ export default function SetProxy() {
154152 const proxyAddress = proxyFromDetails(_details, _contracts, data.proxyType);
155153 const isProxySet = !isZeroAddress(proxyAddress);
156154
157− const proxyAddressLabel = useMemo(() => `Current ${properProxyType} Key`, [
158− properProxyType,
159− ]);
160−
161155 const header = useMemo(() => {
162156 const pfix = completed ? 'New' : 'Edit';
163157 return `${pfix} ${properProxyType} Key`;
src/views/UrbitID/SigilGenerator.js−3
@@ -6,11 +6,9 @@ import { colors } from 'indigo-tokens';
66
77import { usePointCursor } from 'store/pointCursor';
88
9−import View from 'components/View';
109import Sigil from 'components/Sigil';
1110
1211import * as need from 'lib/need';
13−import { useLocalRouter } from 'lib/LocalRouter';
1412import useSigilDownloader from 'lib/useSigilDownloader';
1513
1614import { composeValidator, buildNumberValidator } from 'form/validators';
@@ -40,7 +38,6 @@ const BG_COLORS = [
4038const FG_COLORS = [colors.black, colors.white];
4139
4240export default function SigilGenerator() {
43− const { pop } = useLocalRouter();
4441 const { pointCursor } = usePointCursor();
4542
4643 const validate = composeValidator({ size: buildNumberValidator(16) });
src/views/UrbitID/Transfer.jsnew file+113
@@ -0,0 +1,113 @@
1+import React, { useCallback, useMemo } from 'react';
2+import cn from 'classnames';
3+import { Grid, Text } from 'indigo-react';
4+import * as azimuth from 'azimuth-js';
5+
6+import { useNetwork } from 'store/network';
7+import { usePointCursor } from 'store/pointCursor';
8+import { usePointCache } from 'store/pointCache';
9+
10+import * as need from 'lib/need';
11+import { useLocalRouter } from 'lib/LocalRouter';
12+import useCurrentPointName from 'lib/useCurrentPointName';
13+import useEthereumTransaction from 'lib/useEthereumTransaction';
14+import { GAS_LIMITS } from 'lib/constants';
15+
16+import ViewHeader from 'components/ViewHeader';
17+import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
18+import { AddressInput } from 'form/Inputs';
19+import { composeValidator, buildAddressValidator } from 'form/validators';
20+import BridgeForm from 'form/BridgeForm';
21+import FormError from 'form/FormError';
22+
23+function useTransfer() {
24+ const { contracts } = useNetwork();
25+ const { pointCursor } = usePointCursor();
26+ const { syncDetails } = usePointCache();
27+
28+ const _contracts = need.contracts(contracts);
29+ const _point = need.point(pointCursor);
30+
31+ return useEthereumTransaction(
32+ useCallback(
33+ address => azimuth.ecliptic.setTransferProxy(_contracts, _point, address),
34+ [_contracts, _point]
35+ ),
36+ useCallback(() => syncDetails(_point), [_point, syncDetails]),
37+ GAS_LIMITS.SET_PROXY
38+ );
39+}
40+
41+export default function AdminTransfer() {
42+ const { pop } = useLocalRouter();
43+ const name = useCurrentPointName();
44+
45+ const {
46+ construct,
47+ unconstruct,
48+ completed,
49+ inputsLocked,
50+ bind,
51+ } = useTransfer();
52+
53+ const validate = useMemo(
54+ () => composeValidator({ address: buildAddressValidator() }),
55+ []
56+ );
57+
58+ const onValues = useCallback(
59+ ({ valid, values }) => {
60+ if (valid) {
61+ construct(values.address);
62+ } else {
63+ unconstruct();
64+ }
65+ },
66+ [construct, unconstruct]
67+ );
68+
69+ return (
70+ <Grid>
71+ <Grid.Item full as={ViewHeader}>
72+ Transfer Point
73+ </Grid.Item>
74+
75+ <BridgeForm validate={validate} onValues={onValues}>
76+ {({ handleSubmit, values }) => (
77+ <>
78+ <Grid.Item
79+ full
80+ as={Text}
81+ className={cn('f5 wrap', {
82+ green3: completed,
83+ })}>
84+ {completed
85+ ? `${values.address} is now the Transfer Proxy for ${name} and can accept the transfer by logging into Bridge themselves. Until they accept your transfer, you will still have ownership over ${name}.`
86+ : `Transfer ${name} to a new owner.`}
87+ </Grid.Item>
88+
89+ {!completed && (
90+ <Grid.Item
91+ full
92+ as={AddressInput}
93+ className="mv4"
94+ name="address"
95+ label="Ethereum Address"
96+ disabled={inputsLocked}
97+ />
98+ )}
99+
100+ <Grid.Item full as={FormError} />
101+
102+ <Grid.Item
103+ full
104+ as={InlineEthereumTransaction}
105+ {...bind}
106+ onReturn={() => pop()}
107+ />
108+ </>
109+ )}
110+ </BridgeForm>
111+ </Grid>
112+ );
113+}
src/views/UrbitOS.js+7−2
@@ -1,4 +1,4 @@
1−import React from 'react';
1+import React, { useState } from 'react';
22import { Grid } from 'indigo-react';
33
44import { useHistory } from 'store/history';
@@ -37,6 +37,8 @@ export default function UrbitOS() {
3737 initialRoutes: [{ key: NAMES.HOME }],
3838 });
3939
40+ const [manualNetworkSeed, setManualNetworkSeed] = useState();
41+
4042 return (
4143 <View pop={router.pop} inset>
4244 <NavHeader>
@@ -49,7 +51,10 @@ export default function UrbitOS() {
4951 </NavHeader>
5052 <LocalRouterProvider value={router}>
5153 <Grid className="mb4"></Grid>
52− <Route />
54+ <Route
55+ manualNetworkSeed={manualNetworkSeed}
56+ setManualNetworkSeed={setManualNetworkSeed}
57+ />
5358 </LocalRouterProvider>
5459 </View>
5560 );
src/views/UrbitOS/Home.js+23−38
@@ -21,7 +21,7 @@ import { useLocalRouter } from 'lib/LocalRouter';
2121import { useHosting } from 'store/hosting';
2222import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
2323
24−export default function UrbitOSHome() {
24+export default function UrbitOSHome({ manualNetworkSeed }) {
2525 const { pointCursor } = usePointCursor();
2626 const { getDetails } = usePointCache();
2727
@@ -51,7 +51,7 @@ export default function UrbitOSHome() {
5151 ]);
5252 return (
5353 <>
54− <Hosting />
54+ <Hosting manualNetworkSeed={manualNetworkSeed} />
5555
5656 <Grid>
5757 <Grid.Item full className="mv7 f5">
@@ -91,22 +91,12 @@ export default function UrbitOSHome() {
9191}
9292
9393// eslint-disable-next-line
94−function Hosting() {
95− const bind = useKeyfileGenerator();
96− const { keyfile, code, notice } = bind;
94+function Hosting({ manualNetworkSeed }) {
95+ const bind = useKeyfileGenerator(manualNetworkSeed);
96+ const { keyfile, code } = bind;
9797 const ship = useHosting();
9898
99− const {
100− syncStatus,
101− url,
102− unknown,
103− running,
104− sysEvents,
105− runEvents,
106− newEvents,
107− bootProgress,
108− bootMessage,
109− } = ship;
99+ const { syncStatus, url, unknown, bootProgress, bootMessage } = ship;
110100
111101 const [synced, setSynced] = useState(false);
112102 useEffect(() => {
@@ -121,8 +111,6 @@ function Hosting() {
121111 const name = useCurrentPointName();
122112 const options = [{ text: 'Tlon', value: 'tlon' }];
123113
124− const props = { name, options, ship };
125−
126114 const renderMain = useCallback(() => {
127115 if (ship.running) {
128116 return (
@@ -181,18 +169,14 @@ function Hosting() {
181169 </>
182170 );
183171 }
184− if (ship.missing) {
172+ if (!keyfile && ship.missing) {
185173 return (
186− <>
187− <Grid.Item full className="gray4">
188− <span className="gray3">Status:</span> Disconnected
189− <br />
190− <span className="f6">Last connected: 4m ago</span>
191− </Grid.Item>
192− </>
174+ <Grid.Item full className="gray4">
175+ Please reset your networking keys in order to use hosting
176+ </Grid.Item>
193177 );
194178 }
195− }, [name, ship]);
179+ }, [name, ship, keyfile]);
196180
197181 return (
198182 <>
@@ -201,7 +185,7 @@ function Hosting() {
201185 <Flex.Item>Urbit OS </Flex.Item>
202186 <Flex.Item
203187 className={cn(
204− { green3: ship.running, grey4: !ship.running },
188+ { green3: ship.running, gray4: !ship.running },
205189 'ml3'
206190 )}>
207191 {ship.running ? 'Connected' : 'Disconnected'}
@@ -233,16 +217,17 @@ function Hosting() {
233217 detail="A keyfile authenticates your Urbit ID to Urbit OS"
234218 />
235219 <Grid.Divider />
236− <Grid.Item
237− full
238− className="mt2"
239− as={ForwardButton}
240− accessory={code && <CopyButton text={code} />}
241− detail={code || notice}
242− disabled={!code}
243− detailClassName="mono">
244− Login Code
245− </Grid.Item>
220+ {code && (
221+ <Grid.Item
222+ full
223+ className="mt2"
224+ as={ForwardButton}
225+ accessory={<CopyButton text={code} />}
226+ detail={code}
227+ detailClassName="mono">
228+ Login Code
229+ </Grid.Item>
230+ )}
246231 </Grid>
247232 </>
248233 );
src/views/UrbitOS/NetworkingKeys.js+20−14
@@ -1,4 +1,4 @@
1−import React, { useCallback, useMemo, useRef, useState } from 'react';
1+import React, { useCallback, useMemo, useRef } from 'react';
22import { Just } from 'folktale/maybe';
33import { Grid, ToggleInput, CheckboxInput } from 'indigo-react';
44import * as azimuth from 'azimuth-js';
@@ -37,7 +37,7 @@ import Condition from 'form/Condition';
3737import FormError from 'form/FormError';
3838import convertToInt from 'lib/convertToInt';
3939
40−function useSetKeys() {
40+function useSetKeys(manualNetworkSeed, setManualNetworkSeed) {
4141 const { urbitWallet, wallet, authMnemonic } = useWallet();
4242 const { pointCursor } = usePointCursor();
4343 const { syncDetails, syncRekeyDate, getDetails } = usePointCache();
@@ -50,19 +50,16 @@ function useSetKeys() {
5050 const networkRevision = convertToInt(_details.keyRevisionNumber, 10);
5151 const randomSeed = useRef();
5252
53− // NOTE: nd = 'nondeterministic' (can also be a 'manual' seed)
54− const [ndNetworkSeed, setNdNetworkSeed] = useState();
55−
5653 const {
5754 available: keyfileAvailable,
5855 filename,
5956 bind: keyfileBind,
60− } = useKeyfileGenerator(ndNetworkSeed);
57+ } = useKeyfileGenerator(manualNetworkSeed);
6158
6259 const buildNetworkSeed = useCallback(
6360 async manualSeed => {
6461 if (manualSeed !== undefined) {
65− setNdNetworkSeed(manualSeed);
62+ setManualNetworkSeed(manualSeed);
6663 return manualSeed;
6764 } else {
6865 const newNetworkRevision = networkRevision + 1;
@@ -81,12 +78,19 @@ function useSetKeys() {
8178 }
8279
8380 randomSeed.current = randomSeed.current || randomHex(32); // 32 bytes
84− setNdNetworkSeed(randomSeed.current);
81+ setManualNetworkSeed(randomSeed.current);
8582
8683 return randomSeed.current;
8784 }
8885 },
89− [_details, authMnemonic, networkRevision, urbitWallet, wallet]
86+ [
87+ _details,
88+ authMnemonic,
89+ networkRevision,
90+ setManualNetworkSeed,
91+ urbitWallet,
92+ wallet,
93+ ]
9094 );
9195
9296 const { completed: _completed, ...rest } = useEthereumTransaction(
@@ -118,14 +122,16 @@ function useSetKeys() {
118122
119123 return {
120124 completed,
121− ndNetworkSeed,
122125 filename,
123126 keyfileBind,
124127 ...rest,
125128 };
126129}
127130
128−export default function UrbitOSNetworkingKeys() {
131+export default function UrbitOSNetworkingKeys({
132+ manualNetworkSeed,
133+ setManualNetworkSeed,
134+}) {
129135 const { pop } = useLocalRouter();
130136 const { pointCursor } = usePointCursor();
131137 const { getDetails } = usePointCache();
@@ -143,12 +149,11 @@ export default function UrbitOSNetworkingKeys() {
143149 const {
144150 construct,
145151 unconstruct,
146− broadcasting,
147152 completed,
148153 inputsLocked,
149154 bind,
150155 keyfileBind,
151− } = useSetKeys();
156+ } = useSetKeys(manualNetworkSeed, setManualNetworkSeed);
152157
153158 const validateForm = useCallback((values, errors) => {
154159 if (values.useNetworkSeed && errors.networkSeed) {
@@ -195,7 +200,8 @@ export default function UrbitOSNetworkingKeys() {
195200 []
196201 );
197202
198− const usageMessage = 'You need this to authenticate with arvo';
203+ const usageMessage =
204+ 'You need this to authenticate with Arvo. Please download';
199205
200206 return (
201207 <>