on master help sign in
fix: clear toggled fields on hide and invalidate tx when arguments are invalid
commit7e6efa2463bff0be0525f6176b17e76ef05926e6 authorMatt Condon (shrugs) <mattgcondon@gmail.com> dateWed 17 Jul 2019, 15:55 (7 years ago) parentcf2f7f7
7 files changed+103−33
src/indigo-react/lib/useForm.js+19−7 src/lib/txn.js+1−1 src/lib/useEthereumTransaction.js+5 src/views/Admin/AdminNetworkingKeys.js+10−3 src/views/Admin/AdminSetProxy.js+43−18 src/views/Admin/AdminTransfer.js+13−2 src/views/Party/PartySetPoolSize.js+12−2
src/indigo-react/lib/useForm.js+19−7
@@ -1,4 +1,4 @@
1−import { useCallback, useMemo, useState } from 'react';
1+import { useCallback, useMemo } from 'react';
22import { isEqual, keyBy, get, every, some } from 'lodash';
33
44import { compose } from 'lib/lib';
@@ -37,7 +37,7 @@ export default function useForm(inputConfigs = []) {
3737 const byName = useMemo(() => keyBy(configs, 'name'), [configs]);
3838
3939 // track values
40− const [values, _setValues] = useState(() =>
40+ const [values, _setValues, clearValues] = useSetState(() =>
4141 defaultsFor(configs, config =>
4242 config.initialValue === undefined ? '' : config.initialValue
4343 )
@@ -50,7 +50,7 @@ export default function useForm(inputConfigs = []) {
5050 // until there's a traditional state update.
5151
5252 // track focused states
53− const [focused, setFocused] = useSetState(() =>
53+ const [focused, setFocused, clearFocused] = useSetState(() =>
5454 defaultsFor(configs, config => config.autoFocus && !config.disabled)
5555 );
5656 const focuses = useMemo(
@@ -59,10 +59,14 @@ export default function useForm(inputConfigs = []) {
5959 );
6060
6161 // track whether or not input has been focused
62− const [hasBeenFocused, setHasBeenFocused] = useSetState({});
62+ const [hasBeenFocused, setHasBeenFocused, clearHasBeenFocused] = useSetState(
63+ {}
64+ );
6365
6466 // track whether or not the input has been touched
65− const [hasBeenTouched, setHasBeenTouched] = useSetState({});
67+ const [hasBeenTouched, setHasBeenTouched, clearHasBeenTouched] = useSetState(
68+ {}
69+ );
6670
6771 // build fn that transforms a value by input name
6872 const transform = useCallback(
@@ -72,11 +76,18 @@ export default function useForm(inputConfigs = []) {
7276
7377 // set a value (and transform it)
7478 const setValue = useCallback(
75− (name, value) =>
76− _setValues(values => ({ ...values, [name]: transform(name, value) })),
79+ (name, value) => _setValues({ [name]: transform(name, value) }),
7780 [_setValues, transform]
7881 );
7982
83+ // reset the form
84+ const reset = useCallback(() => {
85+ clearFocused();
86+ clearHasBeenFocused();
87+ clearHasBeenTouched();
88+ clearValues();
89+ }, [clearFocused, clearHasBeenFocused, clearHasBeenTouched, clearValues]);
90+
8091 // build fn that validates a value by input name
8192 const validate = useCallback(
8293 (name, value) =>
@@ -246,5 +257,6 @@ export default function useForm(inputConfigs = []) {
246257 pass,
247258 error,
248259 setValue,
260+ reset,
249261 };
250262}
src/lib/txn.js+1−1
@@ -24,7 +24,7 @@ const signTransaction = async ({
2424 txn,
2525 nonce, // number
2626 chainId, // number
27− gasPrice, // string
27+ gasPrice, // string, in gwei
2828 gasLimit, // string | number
2929}) => {
3030 // TODO: require these in txn object
src/lib/useEthereumTransaction.js+5
@@ -70,6 +70,10 @@ export default function useEthereumTransaction(
7070 setUnsignedTransaction,
7171 ]);
7272
73+ const unconstruct = useCallback(() => setUnsignedTransaction(undefined), [
74+ setUnsignedTransaction,
75+ ]);
76+
7377 const generateAndSign = useCallback(async () => {
7478 try {
7579 setError(undefined);
@@ -163,6 +167,7 @@ export default function useEthereumTransaction(
163167 isDefaultState,
164168 initializing,
165169 construct,
170+ unconstruct,
166171 constructed,
167172 canSign,
168173 generateAndSign,
src/views/Admin/AdminNetworkingKeys.js+10−3
@@ -61,11 +61,13 @@ function useSetKeys() {
6161 const _point = need.point(pointCursor);
6262 const _contracts = need.contracts(contracts);
6363
64+ // NOTE: nd = 'nondeterministic' (can also be a 'manual' seed)
6465 const [ndNetworkSeed, setNdNetworkSeed] = useState();
6566
6667 const {
6768 isDefaultState,
6869 construct: _construct,
70+ unconstruct,
6971 broadcasting,
7072 confirmed,
7173 inputsLocked,
@@ -131,6 +133,7 @@ function useSetKeys() {
131133 return {
132134 isDefaultState,
133135 construct,
136+ unconstruct,
134137 broadcasting,
135138 confirmed,
136139 ndNetworkSeed,
@@ -155,6 +158,7 @@ export default function AdminNetworkingKeys() {
155158 const {
156159 isDefaultState,
157160 construct,
161+ unconstruct,
158162 broadcasting,
159163 confirmed,
160164 inputsLocked,
@@ -173,7 +177,7 @@ export default function AdminNetworkingKeys() {
173177 const [
174178 networkSeedInput,
175179 { pass: validNetworkSeed, data: networkSeed },
176− { setValue: setNetworkSeed },
180+ { reset: resetNetworkSeed },
177181 ] = useHexInput({
178182 name: 'networkseed',
179183 label: 'Network Seed (64 bytes)',
@@ -197,21 +201,24 @@ export default function AdminNetworkingKeys() {
197201 validDiscontinuity
198202 ) {
199203 construct(networkSeed, isDiscontinuity);
204+ } else {
205+ unconstruct();
200206 }
201207 }, [
202208 construct,
203209 isDiscontinuity,
204210 networkSeed,
205211 showNetworkSeed,
212+ unconstruct,
206213 validDiscontinuity,
207214 validNetworkSeed,
208215 ]);
209216
210217 useEffect(() => {
211218 if (!showNetworkSeed) {
212− setNetworkSeed('');
219+ resetNetworkSeed();
213220 }
214− }, [setNetworkSeed, showNetworkSeed]);
221+ }, [resetNetworkSeed, showNetworkSeed]);
215222
216223 const goRelocate = useCallback(() => push(names.RELOCATE), [push, names]);
217224
src/views/Admin/AdminSetProxy.js+43−18
@@ -1,6 +1,6 @@
1−import React, { useCallback, useEffect, useState } from 'react';
1+import React, { useCallback, useEffect } from 'react';
22import cn from 'classnames';
3−import { Grid, Text, Input, Flex, LinkButton } from 'indigo-react';
3+import { Grid, Text, Input, Flex, ToggleInput } from 'indigo-react';
44import * as azimuth from 'azimuth-js';
55
66import { useNetwork } from 'store/network';
@@ -16,7 +16,7 @@ import * as need from 'lib/need';
1616import { useLocalRouter } from 'lib/LocalRouter';
1717import { ETH_ZERO_ADDR, eqAddr } from 'lib/wallet';
1818import capitalize from 'lib/capitalize';
19−import { useAddressInput } from 'lib/useInputs';
19+import { useAddressInput, useCheckboxInput } from 'lib/useInputs';
2020import useEthereumTransaction from 'lib/useEthereumTransaction';
2121
2222import ViewHeader from 'components/ViewHeader';
@@ -51,8 +51,6 @@ function useSetProxy(proxyType) {
5151 const _contracts = need.contracts(contracts);
5252 const _point = need.point(pointCursor);
5353
54− const [isUnsetting, setUnsetting] = useState(false);
55−
5654 const buildUnsignedTx = useCallback(
5755 address => {
5856 const txArgs = [_contracts, _point, address];
@@ -75,6 +73,7 @@ function useSetProxy(proxyType) {
7573
7674 const {
7775 construct: _construct,
76+ unconstruct,
7877 confirmed,
7978 inputsLocked,
8079 bind,
@@ -95,16 +94,15 @@ function useSetProxy(proxyType) {
9594
9695 // force-unset
9796 const unset = useCallback(() => {
98− setUnsetting(true);
9997 _construct(buildUnsignedTx(ETH_ZERO_ADDR));
10098 }, [_construct, buildUnsignedTx]);
10199
102100 return {
103101 construct,
102+ unconstruct,
104103 confirmed,
105104 unset,
106− isUnsetting,
107− inputsLocked: inputsLocked || isUnsetting,
105+ inputsLocked: inputsLocked,
108106 bind,
109107 };
110108}
@@ -121,20 +119,49 @@ export default function AdminSetProxy() {
121119
122120 const properProxyType = capitalize(proxyTypeToHuman(data.proxyType));
123121
124− const { construct, unset, inputsLocked, confirmed, bind } = useSetProxy(
125− data.proxyType
126− );
127− const [addressInput, { pass, data: address }] = useAddressInput({
122+ const {
123+ construct,
124+ unconstruct,
125+ unset,
126+ inputsLocked,
127+ confirmed,
128+ bind,
129+ } = useSetProxy(data.proxyType);
130+
131+ const [unsetInput, { data: isUnsetting }] = useCheckboxInput({
132+ name: 'unset',
133+ label: 'Unset',
134+ inverseLabel: 'Specify',
135+ initialValue: false,
136+ });
137+ const [
138+ addressInput,
139+ { pass: validAddress, data: address },
140+ { reset: resetAddress },
141+ ] = useAddressInput({
128142 name: 'address',
129143 label: `New ${properProxyType} Address`,
130− disabled: inputsLocked,
144+ disabled: inputsLocked || isUnsetting,
131145 });
132146
133147 useEffect(() => {
134− if (pass) {
148+ if (isUnsetting) {
149+ unset();
150+ resetAddress();
151+ } else if (validAddress) {
135152 construct(address);
153+ } else {
154+ unconstruct();
136155 }
137− }, [pass, address, construct]);
156+ }, [
157+ validAddress,
158+ address,
159+ construct,
160+ isUnsetting,
161+ unset,
162+ unconstruct,
163+ resetAddress,
164+ ]);
138165
139166 const proxyAddress = proxyFromDetails(_details, _contracts, data.proxyType);
140167 const isProxySet = !eqAddr(ETH_ZERO_ADDR, proxyAddress);
@@ -176,9 +203,7 @@ export default function AdminSetProxy() {
176203 {isProxySet ? proxyAddress : 'Unset'}
177204 </Flex.Item>
178205 {!confirmed && isProxySet && (
179− <Flex.Item as={LinkButton} onClick={unset} disabled={inputsLocked}>
180− Unset
181− </Flex.Item>
206+ <Flex.Item as={ToggleInput} {...unsetInput} />
182207 )}
183208 </Grid.Item>
184209
src/views/Admin/AdminTransfer.js+13−2
@@ -28,6 +28,7 @@ function useTransfer() {
2828
2929 const {
3030 construct: _construct,
31+ unconstruct,
3132 confirmed,
3233 inputsLocked,
3334 bind,
@@ -50,6 +51,7 @@ function useTransfer() {
5051
5152 return {
5253 construct,
54+ unconstruct,
5355 confirmed,
5456 inputsLocked,
5557 bind,
@@ -60,7 +62,14 @@ export default function AdminTransfer() {
6062 const { pop } = useLocalRouter();
6163 const name = useCurrentPointName();
6264
63− const { construct, confirmed, inputsLocked, bind } = useTransfer();
65+ const {
66+ construct,
67+ unconstruct,
68+ confirmed,
69+ inputsLocked,
70+ bind,
71+ } = useTransfer();
72+
6473 const [addressInput, { pass, data: address }] = useAddressInput({
6574 name: 'address',
6675 label: `Ethereum Address`,
@@ -70,8 +79,10 @@ export default function AdminTransfer() {
7079 useEffect(() => {
7180 if (pass) {
7281 construct(address);
82+ } else {
83+ unconstruct();
7384 }
74− }, [pass, address, construct]);
85+ }, [pass, address, construct, unconstruct]);
7586
7687 return (
7788 <Grid>
src/views/Party/PartySetPoolSize.js+12−2
@@ -31,6 +31,7 @@ function useSetPoolSize() {
3131
3232 const {
3333 construct: _construct,
34+ unconstruct,
3435 confirmed,
3536 inputsLocked,
3637 bind,
@@ -59,6 +60,7 @@ function useSetPoolSize() {
5960
6061 return {
6162 construct,
63+ unconstruct,
6264 confirmed,
6365 inputsLocked,
6466 bind,
@@ -73,7 +75,13 @@ export default function PartySetPoolSize() {
7375
7476 const { spawnIsDelegatedSending } = useCurrentPermissions();
7577
76− const { construct, confirmed, inputsLocked, bind } = useSetPoolSize();
78+ const {
79+ construct,
80+ unconstruct,
81+ confirmed,
82+ inputsLocked,
83+ bind,
84+ } = useSetPoolSize();
7785
7886 const [poolOwnerInput, { pass: validPoint, data: poolOwner }] = usePointInput(
7987 {
@@ -96,8 +104,10 @@ export default function PartySetPoolSize() {
96104 useEffect(() => {
97105 if (validPoint && validPoolSize) {
98106 construct(patp2dec(poolOwner), poolSize);
107+ } else {
108+ unconstruct();
99109 }
100− }, [poolOwner, construct, validPoint, validPoolSize, poolSize]);
110+ }, [poolOwner, construct, validPoint, validPoolSize, poolSize, unconstruct]);
101111
102112 return (
103113 <View inset>