@@ -0,0 +1,167 @@
1+import React, { useState, useCallback } from 'react';
2+import { Just, Nothing } from 'folktale/maybe';
3+import * as need from 'lib/need';
4+import { azimuth } from 'azimuth-js';
5+import { Grid } from 'indigo-react';
7+import { P } from 'indigo-react';
8+import View from 'components/View';
9+import { ForwardButton } from 'components/Buttons';
10+import FooterButton from 'components/FooterButton';
13+ INTERSTITIAL_CHARACTER,
14+} from 'components/Blinky';
16+import { ROUTE_NAMES } from 'lib/routeNames';
17+import { eqAddr } from 'lib/wallet';
19+import useLifecycle from 'lib/useLifecycle';
20+import { useNetwork } from 'store/network';
21+import { useHistory } from 'store/history';
22+import { useWallet } from 'store/wallet';
23+import { usePointCursor } from 'store/pointCursor';
24+import { usePointCache } from 'store/pointCache';
26+//TODO consolidate with azimuth-js' getActivationBlock
27+const getRekeyDate = async (web3, contracts, point) => {
28+ const logs = await contracts.azimuth.getPastEvents('ChangedKeys', {
31+ filter: { point: [point] },
33+ if (logs.length === 0) {
36+ // last log is most recent
37+ const block = await web3.eth.getBlock(logs[logs.length - 1].blockNumber);
38+ return new Date(block.timestamp * 1000);
42+export default function Permissions() {
43+ const history = useHistory();
44+ const { web3, contracts } = useNetwork();
45+ const { wallet } = useWallet();
46+ const { pointCursor } = usePointCursor();
47+ const { pointCache } = usePointCache();
49+ const [rekeyDate, setRekeyDate] = useState(Nothing());
51+ const point = need.point(pointCursor);
52+ const pointSize = azimuth.getPointSize(point);
53+ const userAddress = need.wallet(wallet).address;
56+ getRekeyDate(need.web3(web3), need.contracts(contracts), point).then(
58+ if (res === null) setRekeyDate(Just('unknown'));
59+ else setRekeyDate(Just(res.toString()));
64+ const goSetManagement = useCallback(
65+ () => history.push(ROUTE_NAMES.SET_MANAGEMENT_PROXY),
69+ const goSetSpawn = useCallback(
70+ () => history.push(ROUTE_NAMES.SET_SPAWN_PROXY),
74+ const goSetVoting = useCallback(
75+ () => history.push(ROUTE_NAMES.SET_VOTING_PROXY),
79+ const goSetKeys = useCallback(() => history.push(ROUTE_NAMES.SET_KEYS), [
83+ const pointDetails = need.fromPointCache(pointCache, point);
85+ const isOwner = eqAddr(userAddress, pointDetails.owner);
87+ isOwner || eqAddr(userAddress, pointDetails.managementProxy);
89+ const proxyAction = (name, address, onClick) => {
90+ if (address === '0x0000000000000000000000000000000000000000')
94+ <ForwardButton disabled={!isOwner} onClick={onClick} detail={address}>
95+ {`${name} proxy address`}
103+ let spawnProxyAction = null;
104+ if (pointSize !== azimuth.PointSize.Planet) {
106+ spawnProxyAction = proxyAction(
108+ pointDetails.spawnProxy,
113+ let votingProxyAction = null;
114+ if (pointSize === azimuth.PointSize.Galaxy) {
116+ votingProxyAction = proxyAction(
118+ pointDetails.votingProxy,
124+ pointDetails.keyRevisionNumber === 0 ? (
125+ 'Not yet configured'
128+ {`Revision #${pointDetails.keyRevisionNumber}, since `}
129+ {Just.hasInstance(rekeyDate) ? (
132+ <Blinky a={LOADING_CHARACTER} b={INTERSTITIAL_CHARACTER} delayed />
139+ <Grid className={`pt${items}`}>
141+ <ForwardButton disabled="true" detail={pointDetails.owner}>
147+ pointDetails.managementProxy,
154+ disabled={!canManage}
156+ detail={netKeysText}>
162+ <FooterButton detail="Transfer this identity to a new owner" disabled>