on master help sign in
added change sponsor functionality
commit1352bb6037fa38176de45a1ad83ed616f4a47caf authorLiam Fitzgerald <liam@urizen.co> dateThu 13 Feb 2020, 12:17 (7 years ago) parent0b53e7d
5 files changed+210−3
src/lib/validators.js+6 src/views/Point.js+5−1 src/views/UrbitOS.js+2−1 src/views/UrbitOS/ChangeSponsor.js+190 src/views/UrbitOS/Home.js+7−1
src/lib/validators.js+6
@@ -94,6 +94,9 @@ export const validateHexLength = l => v =>
9494export const validateMaximumLength = l => v =>
9595 v.length > l && `Must be ${l} characters or fewer.`;
9696
97+export const validateMinimumLength = l => v =>
98+ v.length < l && `Must be ${l} characters or more.`;
99+
97100export const validateGreaterThan = l => v =>
98101 !(v > l) && `Must be at least ${l}.`;
99102
@@ -104,6 +107,9 @@ export const validateInSet = (set, error) => v => !set.has(v) && error;
104107export const validateMaximumPatpByteLength = byteLength =>
105108 validateMaximumLength(patpStringLength(byteLength));
106109
110+export const validateMinimumPatpByteLength = byteLength =>
111+ validateMinimumLength(patpStringLength(byteLength));
112+
107113export const validateNotNullAddress = validateNotAny([
108114 ETH_ZERO_ADDR,
109115 ETH_ZERO_ADDR_SHORT,
src/views/Point.js+5−1
@@ -222,7 +222,11 @@ export default function Point() {
222222 Sigil
223223 </Grid.Item>
224224 <Grid.Divider />
225− <Grid.Item full as={ForwardButton} onClick={goUrbitOS}>
225+ <Grid.Item
226+ full
227+ as={ForwardButton}
228+ disabled={!canManage}
229+ onClick={goUrbitOS}>
226230 Urbit OS
227231 </Grid.Item>
228232 <Grid.Item
src/views/UrbitOS.js+2−1
@@ -12,6 +12,7 @@ import Crumbs from 'components/Crumbs';
1212
1313import UrbitOSHome from './UrbitOS/Home';
1414import UrbitOSNetworkingKeys from './UrbitOS/NetworkingKeys';
15+import UrbitOSChangeSponsor from './UrbitOS/ChangeSponsor';
1516
1617const NAMES = {
1718 HOME: 'HOME',
@@ -21,7 +22,7 @@ const NAMES = {
2122
2223const VIEWS = {
2324 [NAMES.HOME]: UrbitOSHome,
24− [NAMES.CHANGE_SPONSOR]: UrbitOSHome,
25+ [NAMES.CHANGE_SPONSOR]: UrbitOSChangeSponsor,
2526 [NAMES.NETWORKING_KEYS]: UrbitOSNetworkingKeys,
2627};
2728
src/views/UrbitOS/ChangeSponsor.jsnew file+190
@@ -0,0 +1,190 @@
1+import React, { useState, useMemo, useCallback, useEffect } from 'react';
2+import { Grid } from 'indigo-react';
3+import * as ob from 'urbit-ob';
4+import { azimuth, ecliptic } from 'azimuth-js';
5+
6+import { useNetwork } from 'store/network';
7+import { usePointCache } from 'store/pointCache';
8+
9+import { PointInput } from 'form/Inputs';
10+import FormError from 'form/FormError';
11+import BridgeForm from 'form/BridgeForm';
12+
13+import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
14+import ViewHeader from 'components/ViewHeader';
15+import {
16+ composeValidator,
17+ buildPointValidator,
18+ hasErrors,
19+} from 'form/validators';
20+
21+import * as need from 'lib/need';
22+import { validateMinimumPatpByteLength } from 'lib/validators';
23+import { usePointCursor } from 'store/pointCursor';
24+import useEthereumTransaction from 'lib/useEthereumTransaction';
25+
26+function useChangeSponsor() {
27+ const { contracts } = useNetwork();
28+ const { pointCursor } = usePointCursor();
29+ const { syncOwnedPoint } = usePointCache();
30+
31+ const _contracts = need.contracts(contracts);
32+ const point = need.point(pointCursor);
33+
34+ return useEthereumTransaction(
35+ useCallback(sponsor => ecliptic.escape(_contracts, point, sponsor), [
36+ point,
37+ _contracts,
38+ ]),
39+ useCallback(() => {
40+ syncOwnedPoint(point);
41+ }, [syncOwnedPoint, point])
42+ );
43+}
44+
45+function ChangeSponsor({ onDone }) {
46+ const { contracts } = useNetwork();
47+
48+ const _contracts = need.contracts(contracts);
49+ const { construct, unconstruct, inputsLocked, bind } = useChangeSponsor();
50+
51+ const [newSponsor, setNewSponsor] = useState(false);
52+
53+ const validateFormAsync = useCallback(
54+ async values => {
55+ const sponsor = ob.patp2dec(values.sponsor);
56+ const details = await azimuth.getPoint(_contracts, sponsor);
57+ console.log(details);
58+ console.log(details.keyRevisionNumber);
59+
60+ if (details.keyRevisionNumber === 0) {
61+ return { sponsor: 'Sponsor is not online' };
62+ }
63+ },
64+ [_contracts]
65+ );
66+
67+ const validateForm = useCallback(
68+ (values, errors) => {
69+ if (hasErrors(errors)) {
70+ return errors;
71+ }
72+ return validateFormAsync(values);
73+ },
74+ [validateFormAsync]
75+ );
76+
77+ const validate = useMemo(
78+ () =>
79+ composeValidator(
80+ {
81+ sponsor: buildPointValidator(2, [validateMinimumPatpByteLength(2)]),
82+ },
83+ validateForm
84+ ),
85+ [validateForm]
86+ );
87+
88+ const onValues = useCallback(
89+ ({ valid, values }) => {
90+ if (valid) {
91+ construct(ob.patp2dec(values.sponsor));
92+ setNewSponsor(values.sponsor);
93+ } else {
94+ unconstruct();
95+ }
96+ },
97+ [construct, unconstruct]
98+ );
99+ return (
100+ <Grid>
101+ <Grid.Item full as={ViewHeader}>
102+ Change Sponsor
103+ </Grid.Item>
104+ <BridgeForm validate={validate} onValues={onValues}>
105+ {() => (
106+ <>
107+ <Grid.Item
108+ full
109+ as={PointInput}
110+ name="sponsor"
111+ disabled={inputsLocked}
112+ label="New sponsor"
113+ />
114+ <Grid.Item full as={FormError} />
115+ <Grid.Item
116+ full
117+ as={InlineEthereumTransaction}
118+ {...bind}
119+ onReturn={onDone}
120+ label="Request"
121+ />
122+ </>
123+ )}
124+ </BridgeForm>
125+ </Grid>
126+ );
127+}
128+
129+function useCancelEscape() {
130+ const { contracts } = useNetwork();
131+ const { pointCursor } = usePointCursor();
132+ const { syncOwnedPoint } = usePointCache();
133+
134+ const _contracts = need.contracts(contracts);
135+ const point = need.point(pointCursor);
136+
137+ return useEthereumTransaction(
138+ useCallback(() => ecliptic.cancelEscape(_contracts, point), [
139+ point,
140+ _contracts,
141+ ]),
142+ useCallback(() => syncOwnedPoint(point), [point, syncOwnedPoint])
143+ );
144+}
145+
146+function CurrentEscape({ onDone }) {
147+ const { construct, bind } = useCancelEscape();
148+
149+ useEffect(() => {
150+ construct();
151+ }, [construct]);
152+ return (
153+ <Grid>
154+ <Grid.Item full as={ViewHeader}>
155+ Currently requesting <span className="mono">~dopzod</span> as a new
156+ sponsor
157+ </Grid.Item>
158+ <Grid.Item
159+ full
160+ as={InlineEthereumTransaction}
161+ label="Cancel Request"
162+ {...bind}
163+ onReturn={onDone}
164+ />
165+ </Grid>
166+ );
167+}
168+
169+export default function UrbitOSChangeSponsor() {
170+ const { contracts } = useNetwork();
171+ const { pointCursor } = usePointCursor();
172+
173+ const point = need.point(pointCursor);
174+
175+ const { getDetails } = usePointCache();
176+
177+ const details = need.details(getDetails(point));
178+
179+ const [requested, setRequested] = useState(details.escapeRequested);
180+
181+ const onDone = useCallback(() => {
182+ setRequested(details.escapeRequested);
183+ }, [details, setRequested]);
184+
185+ return requested ? (
186+ <CurrentEscape onDone={onDone} />
187+ ) : (
188+ <ChangeSponsor onDone={onDone} />
189+ );
190+}
src/views/UrbitOS/Home.js+7−1
@@ -29,6 +29,11 @@ export default function UrbitOSHome() {
2929 names,
3030 push,
3131 ]);
32+
33+ const goChangeSponsor = useCallback(() => push(names.CHANGE_SPONSOR), [
34+ push,
35+ names,
36+ ]);
3237 return (
3338 <>
3439 <Hosting />
@@ -41,7 +46,8 @@ export default function UrbitOSHome() {
4146 full
4247 as={ForwardButton}
4348 detail="A sponsor finds new peers in your network"
44− accessory={<u>Change</u>}>
49+ accessory={<u>Change</u>}
50+ onClick={goChangeSponsor}>
4551 <span className="mono">{sponsor}</span>
4652 <span className="f7 bg-black white p1 ml2 r4">SPONSOR</span>
4753 </Grid.Item>