on ef914ee help sign in
bridge/src/views/Admin/AdminSetProxy.js
225 lines 6.0 kB history raw
1import React, { useCallback, useEffect } from 'react';
2import cn from 'classnames';
3import { Grid, Text, Input, Flex, ToggleInput } from 'indigo-react';
4import * as azimuth from 'azimuth-js';
6import { useNetwork } from 'store/network';
7import { usePointCache } from 'store/pointCache';
8import { usePointCursor } from 'store/pointCursor';
10import {
11 PROXY_TYPE,
12 proxyTypeToHuman,
13 proxyTypeToHumanDescription,
14} from 'lib/proxy';
15import * as need from 'lib/need';
16import { useLocalRouter } from 'lib/LocalRouter';
17import { ETH_ZERO_ADDR, eqAddr, isZeroAddress } from 'lib/wallet';
18import capitalize from 'lib/capitalize';
19import { useAddressInput, useCheckboxInput } from 'lib/useInputs';
20import useEthereumTransaction from 'lib/useEthereumTransaction';
22import ViewHeader from 'components/ViewHeader';
23import MiniBackButton from 'components/MiniBackButton';
24import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
25import { GAS_LIMITS } from 'lib/constants';
27const proxyFromDetails = (details, contracts, proxyType) => {
28 switch (proxyType) {
29 case PROXY_TYPE.MANAGEMENT:
30 return details.managementProxy;
31 case PROXY_TYPE.SPAWN:
32 return details.spawnProxy;
33 case PROXY_TYPE.TRANSFER:
34 return details.transferProxy;
35 case PROXY_TYPE.VOTING:
36 if (eqAddr(details.votingProxy, contracts.delegatedSending.address)) {
37 return `${details.votingProxy} (invites contract)`;
38 } else {
39 return details.votingProxy;
40 }
41 default:
42 throw new Error(`Unknown proxyType: ${proxyType}`);
43 }
44};
46function useSetProxy(proxyType) {
47 const { contracts } = useNetwork();
48 const { pointCursor } = usePointCursor();
49 const { syncOwnedPoint } = usePointCache();
51 const _contracts = need.contracts(contracts);
52 const _point = need.point(pointCursor);
54 const buildUnsignedTx = useCallback(
55 address => {
56 const txArgs = [_contracts, _point, address];
58 switch (proxyType) {
59 case PROXY_TYPE.MANAGEMENT:
60 return azimuth.ecliptic.setManagementProxy(...txArgs);
61 case PROXY_TYPE.SPAWN:
62 return azimuth.ecliptic.setSpawnProxy(...txArgs);
63 case PROXY_TYPE.TRANSFER:
64 return azimuth.ecliptic.setTransferProxy(...txArgs);
65 case PROXY_TYPE.VOTING:
66 return azimuth.ecliptic.setVotingProxy(...txArgs);
67 default:
68 throw new Error(`Unknown proxyType ${proxyType}`);
69 }
70 },
71 [_contracts, _point, proxyType]
72 );
74 const {
75 construct: _construct,
76 unconstruct,
77 confirmed,
78 inputsLocked,
79 bind,
80 } = useEthereumTransaction(GAS_LIMITS.SET_PROXY);
82 // sync point details after success
83 useEffect(() => {
84 if (confirmed) {
85 syncOwnedPoint(_point);
86 }
87 }, [_point, confirmed, syncOwnedPoint]);
89 // construct the unsigned transaction when we have a valid address
90 const construct = useCallback(
91 address => _construct(buildUnsignedTx(address)),
92 [_construct, buildUnsignedTx]
93 );
95 // force-unset
96 const unset = useCallback(() => {
97 _construct(buildUnsignedTx(ETH_ZERO_ADDR));
98 }, [_construct, buildUnsignedTx]);
100 return {
101 construct,
102 unconstruct,
103 confirmed,
104 unset,
105 inputsLocked: inputsLocked,
106 bind,
107 };
110export default function AdminSetProxy() {
111 const { data, pop } = useLocalRouter();
112 const { getDetails } = usePointCache();
113 const { pointCursor } = usePointCursor();
114 const { contracts } = useNetwork();
116 const _point = need.point(pointCursor);
117 const _details = need.details(getDetails(_point));
118 const _contracts = need.contracts(contracts);
120 const properProxyType = capitalize(proxyTypeToHuman(data.proxyType));
122 const {
123 construct,
124 unconstruct,
125 unset,
126 inputsLocked,
127 confirmed,
128 bind,
129 } = useSetProxy(data.proxyType);
131 const [unsetInput, { data: isUnsetting }] = useCheckboxInput({
132 name: 'unset',
133 label: 'Unset',
134 inverseLabel: 'Specify',
135 initialValue: false,
136 disabled: inputsLocked,
137 });
138 const [
139 addressInput,
140 { pass: validAddress, data: address },
141 { reset: resetAddress },
142 ] = useAddressInput({
143 name: 'address',
144 label: `New ${properProxyType} Address`,
145 disabled: inputsLocked || isUnsetting,
146 });
148 useEffect(() => {
149 if (isUnsetting) {
150 unset();
151 resetAddress();
152 } else if (validAddress) {
153 construct(address);
154 } else {
155 unconstruct();
156 }
157 }, [
158 validAddress,
159 address,
160 construct,
161 isUnsetting,
162 unset,
163 unconstruct,
164 resetAddress,
165 ]);
167 const proxyAddress = proxyFromDetails(_details, _contracts, data.proxyType);
168 const isProxySet = !isZeroAddress(proxyAddress);
170 const proxyAddressLabel = `${
171 confirmed ? 'New' : 'Current'
172 } ${properProxyType} Address`;
174 return (
175 <Grid>
176 <Grid.Item full as={MiniBackButton} onClick={() => pop()} />
178 <Grid.Item full as={ViewHeader}>
179 {properProxyType} Address
180 </Grid.Item>
182 <Grid.Item full as={Text} className="mb4 f5">
183 {proxyTypeToHumanDescription(data.proxyType)}
184 </Grid.Item>
186 <Grid.Item
187 full
188 as={Text}
189 className={cn('f6 mb1', {
190 green3: confirmed,
191 })}>
192 {proxyAddressLabel}
193 </Grid.Item>
195 <Grid.Item full as={Flex} row justify="between" align="center">
196 <Flex.Item
197 flex
198 as={Text}
199 className={cn('mono', {
200 black: !confirmed && isProxySet,
201 gray4: !confirmed && !isProxySet,
202 green3: confirmed,
203 })}>
204 {isProxySet ? proxyAddress : 'Unset'}
205 </Flex.Item>
206 {!confirmed && isProxySet && (
207 <Flex.Item as={ToggleInput} {...unsetInput} />
208 )}
209 </Grid.Item>
211 {confirmed ? (
212 <Grid.Item full className="mb4" />
213 ) : (
214 <Grid.Item full as={Input} {...addressInput} className="mv4" />
215 )}
217 <Grid.Item
218 full
219 as={InlineEthereumTransaction}
220 {...bind}
221 onReturn={() => pop()}
222 />
223 </Grid>
224 );