on master help sign in
feat: add tank usage to useEthereumTransaction and update CreateGalaxy
b87ca5cMatt Condon (shrugs)
src/components/InlineEthereumTransaction.js+15−3
@@ -10,12 +10,14 @@ import {
10 Text,
10 Text,
11 HelpText,
11 HelpText,
12} from 'indigo-react';
12} from 'indigo-react';
13+import { fromWei } from 'web3-utils';
13
14
14import { useCheckboxInput } from 'lib/useInputs';
15import { useCheckboxInput } from 'lib/useInputs';
15−import { hexify } from 'lib/txn';
16import { useExploreTxUrl } from 'lib/explorer';
16import { useExploreTxUrl } from 'lib/explorer';
17+import { hexify } from 'lib/txn';
17
18
18import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
19import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
20+import WarningBox from './WarningBox';
19
21
20export default function InlineEthereumTransaction({
22export default function InlineEthereumTransaction({
21 // from useEthereumTransaction.bind
23 // from useEthereumTransaction.bind
@@ -34,6 +36,7 @@ export default function InlineEthereumTransaction({
34 txHash,
36 txHash,
35 nonce,
37 nonce,
36 chainId,
38 chainId,
39+ needFunds,
37 signedTransaction,
40 signedTransaction,
38
41
39 // additional from parent
42 // additional from parent
@@ -96,8 +99,8 @@ export default function InlineEthereumTransaction({
96 as={ForwardButton}
99 as={ForwardButton}
97 solid
100 solid
98 success
101 success
99− disabled={broadcasted}
102+ disabled={broadcasted || needFunds}
100− loading={broadcasted}
103+ loading={broadcasted || needFunds}
101 onClick={() => broadcast()}>
104 onClick={() => broadcast()}>
102 Send Transaction
105 Send Transaction
103 </Grid.Item>
106 </Grid.Item>
@@ -126,6 +129,15 @@ export default function InlineEthereumTransaction({
126 </Grid.Item>
129 </Grid.Item>
127 )}
130 )}
128
131
132+ {needFunds && (
133+ <Grid.Item full as={WarningBox} className="mt3">
134+ The address {needFunds.address} needs at least{' '}
135+ {fromWei(needFunds.minBalance)} ETH and currently has{' '}
136+ {fromWei(needFunds.balance)} ETH. Waiting until the account has enough
137+ funds.
138+ </Grid.Item>
139+ )}
140+
129 {showConfigureInput && (
141 {showConfigureInput && (
130 <>
142 <>
131 <Grid.Item full as={ToggleInput} {...advancedInput} />
143 <Grid.Item full as={ToggleInput} {...advancedInput} />
src/components/old/StatelessTransaction.js+1−2
@@ -15,8 +15,6 @@ import { compose } from '../../lib/lib';
15import * as tank from '../../lib/tank';
15import * as tank from '../../lib/tank';
16import {
16import {
17 sendSignedTransaction,
17 sendSignedTransaction,
18− fromWei,
19− toWei,
20 hexify,
18 hexify,
21 renderSignedTx,
19 renderSignedTx,
22 signTransaction,
20 signTransaction,
@@ -26,6 +24,7 @@ import { withNetwork } from '../../store/network';
26import { withHistory } from '../../store/history';
24import { withHistory } from '../../store/history';
27import { withWallet } from '../../store/wallet';
25import { withWallet } from '../../store/wallet';
28import { withTxnCursor } from '../../store/txnCursor';
26import { withTxnCursor } from '../../store/txnCursor';
27+import { fromWei, toWei } from 'web3-utils';
29
28
30const SUBMISSION_STATES = {
29const SUBMISSION_STATES = {
31 PROMPT: 'Send transaction',
30 PROMPT: 'Send transaction',
src/indigo-react/lib/useForm.js+3−9
@@ -1,10 +1,10 @@
1import { useCallback, useMemo } from 'react';
1import { useCallback, useMemo } from 'react';
2−import { isEqual, keyBy, get, every, some } from 'lodash';
2+import { keyBy, get, every, some } from 'lodash';
3
3
4import { compose } from 'lib/lib';
4import { compose } from 'lib/lib';
5import { kDefaultValidator } from 'lib/validators';
5import { kDefaultValidator } from 'lib/validators';
6import useSetState from 'lib/useSetState';
6import useSetState from 'lib/useSetState';
7−import usePreviousValue from 'lib/usePreviousValue';
7+import useDeepEqualReference from 'lib/useDeepEqualReference';
8
8
9// interface InputConfig {
9// interface InputConfig {
10// name: string;
10// name: string;
@@ -26,13 +26,7 @@ const defaultsFor = (configs, mapper) =>
26 * useForm manages a set of inputs for rendering them in a loop
26 * useForm manages a set of inputs for rendering them in a loop
27 */
27 */
28export default function useForm(inputConfigs = []) {
28export default function useForm(inputConfigs = []) {
29− // track the old value of the config set
30− const previousConfigs = usePreviousValue(inputConfigs);
31− // then compare equality
32− const configsAreEqual = isEqual(inputConfigs, previousConfigs);
33− // if equality changes, give `configs` a new identity
34− // eslint-disable-next-line react-hooks/exhaustive-deps
35− const configs = useMemo(() => inputConfigs, [configsAreEqual]);
29+ const configs = useDeepEqualReference(inputConfigs);
36
30
37 const byName = useMemo(() => keyBy(configs, 'name'), [configs]);
31 const byName = useMemo(() => keyBy(configs, 'name'), [configs]);
38
32
src/lib/error.js+4−2
@@ -1,3 +1,5 @@
1+import { fromWei } from 'web3-utils';
2+
1const BRIDGE_ERROR = {
3const BRIDGE_ERROR = {
2 MISSING_WEB3: 'no web3 object found',
4 MISSING_WEB3: 'no web3 object found',
3 MISSING_WALLET: 'no wallet found',
5 MISSING_WALLET: 'no wallet found',
@@ -16,13 +18,13 @@ const BRIDGE_ERROR = {
16const renderTxnError = (web3, msg) => {
18const renderTxnError = (web3, msg) => {
17 const txnCost = (web3, msg) => {
19 const txnCost = (web3, msg) => {
18 const costWei = msg.match(/upfront cost is: ([0-9]+)/);
20 const costWei = msg.match(/upfront cost is: ([0-9]+)/);
19− const costEth = web3.utils.fromWei(costWei[1], 'ether');
21+ const costEth = fromWei(costWei[1], 'ether');
20 return parseFloat(costEth).toFixed(4);
22 return parseFloat(costEth).toFixed(4);
21 };
23 };
22
24
23 const acctBalance = (web3, msg) => {
25 const acctBalance = (web3, msg) => {
24 const balWei = msg.match(/sender's account only has: ([0-9]+)/);
26 const balWei = msg.match(/sender's account only has: ([0-9]+)/);
25− const balEth = web3.utils.fromWei(balWei[1], 'ether');
27+ const balEth = fromWei(balWei[1], 'ether');
26 return parseFloat(balEth).toFixed(4);
28 return parseFloat(balEth).toFixed(4);
27 };
29 };
28
30
src/lib/tank.js+7−13
@@ -95,24 +95,18 @@ const ensureFundsFor = async (
95
95
96// returns a promise that resolves when address has at least minBalance
96// returns a promise that resolves when address has at least minBalance
97function waitForBalance(web3, address, minBalance, askForFunding, gotFunding) {
97function waitForBalance(web3, address, minBalance, askForFunding, gotFunding) {
98− let oldBalance = null;
99 return retry(async (bail, n) => {
98 return retry(async (bail, n) => {
100 const balance = await web3.eth.getBalance(address);
99 const balance = await web3.eth.getBalance(address);
101 if (balance >= minBalance) {
100 if (balance >= minBalance) {
102− // if we ever asked for funding, retract that request now
103− if (gotFunding && oldBalance !== null) {
104− gotFunding();
101+ gotFunding && gotFunding();
105− }
106 return;
102 return;
107 } else {
103 } else {
108− if (balance !== oldBalance) {
109− // TODO: minBalance is a `number` type
104+ // TODO: minBalance is a `number` type
110− // but we want to display ETH, which will never accept a number
105+ // but we want to display ETH, which will never accept a number
111− // but instead wants string or BN/BigNumber.
106+ // but instead wants string or BN/BigNumber.
112− // this will be heavily refactored to correctly do BN math, but until
107+ // this will be heavily refactored to correctly do BN math, but until
113− // then we'll manually convert this number to an integer string
108+ // then we'll manually convert this number to an integer string
114− askForFunding(address, minBalance.toFixed(), balance);
109+ askForFunding(address, minBalance.toFixed(), balance);
115− }
116 throw new Error('retrying');
110 throw new Error('retrying');
117 }
111 }
118 }, RETRY_OPTIONS);
112 }, RETRY_OPTIONS);
src/lib/txn.js−3
@@ -194,8 +194,5 @@ export {
194 getTxnInfo,
194 getTxnInfo,
195 hexify,
195 hexify,
196 renderSignedTx,
196 renderSignedTx,
197− toHex,
198− toWei,
199− fromWei,
200 canDecodePatp,
197 canDecodePatp,
201};
198};
src/lib/useDeepEqualReference.jsnew file+22
@@ -0,0 +1,22 @@
1+import { useRef } from 'react';
2+import { isEqual } from 'lodash';
3+
4+import usePreviousValue from './usePreviousValue';
5+
6+// changes the referential identity of value on deep equality change
7+export default function useDeepEqualReference(value) {
8+ const ref = useRef(value);
9+
10+ // track the old value of the config set
11+ const prevValue = usePreviousValue(value);
12+
13+ // then compare equality
14+ const areEqual = isEqual(value, prevValue);
15+
16+ // if equality changes, give value a new identity
17+ if (!areEqual) {
18+ ref.current = value;
19+ }
20+
21+ return ref.current;
22+}
src/lib/useEthereumTransaction.js+41−4
@@ -1,17 +1,21 @@
1import { useCallback, useState } from 'react';
1import { useCallback, useState } from 'react';
2+import { Just } from 'folktale/maybe';
2−import { fromWei } from 'web3-utils';
3+import { fromWei, toWei } from 'web3-utils';
3
4
4import { useNetwork } from 'store/network';
5import { useNetwork } from 'store/network';
5import { useWallet } from 'store/wallet';
6import { useWallet } from 'store/wallet';
7+import { usePointCursor } from 'store/pointCursor';
6
8
9+import { GAS_LIMITS } from './constants';
7import {
10import {
8 signTransaction,
11 signTransaction,
9 sendSignedTransaction,
12 sendSignedTransaction,
10 waitForTransactionConfirm,
13 waitForTransactionConfirm,
14+ hexify,
11} from './txn';
15} from './txn';
12import * as need from './need';
16import * as need from './need';
13−import { GAS_LIMITS } from './constants';
14import useLifecycle from './useLifecycle';
17import useLifecycle from './useLifecycle';
18+import { ensureFundsFor } from './tank';
15
19
16const STATE = {
20const STATE = {
17 NONE: 'NONE',
21 NONE: 'NONE',
@@ -30,6 +34,8 @@ export default function useEthereumTransaction(
30) {
34) {
31 const { wallet, walletType, walletHdPath } = useWallet();
35 const { wallet, walletType, walletHdPath } = useWallet();
32 const { web3, networkType } = useNetwork();
36 const { web3, networkType } = useNetwork();
37+ const { pointCursor } = usePointCursor();
38+
33 const _web3 = need.web3(web3);
39 const _web3 = need.web3(web3);
34 const _wallet = need.wallet(wallet);
40 const _wallet = need.wallet(wallet);
35
41
@@ -52,6 +58,7 @@ export default function useEthereumTransaction(
52 const [unsignedTransaction, setUnsignedTransaction] = useState();
58 const [unsignedTransaction, setUnsignedTransaction] = useState();
53 const [signedTransaction, setSignedTransaction] = useState();
59 const [signedTransaction, setSignedTransaction] = useState();
54 const [txHash, setTxHash] = useState();
60 const [txHash, setTxHash] = useState();
61+ const [needFunds, setNeedFunds] = useState();
55
62
56 const initializing = nonce === undefined || chainId === undefined;
63 const initializing = nonce === undefined || chainId === undefined;
57 const constructed = !!unsignedTransaction;
64 const constructed = !!unsignedTransaction;
@@ -111,10 +118,30 @@ export default function useEthereumTransaction(
111 const broadcast = useCallback(async () => {
118 const broadcast = useCallback(async () => {
112 try {
119 try {
113 setError(undefined);
120 setError(undefined);
121+
122+ const rawTx = hexify(signedTransaction.serialize());
123+ const cost = toWei(gasPrice.toFixed(0), 'gwei') * gasLimit;
124+
125+ let usedTank = false;
126+ // if this ethereum transaction is being executed by a specific point
127+ // see if we can use the tank
128+ if (Just.hasInstance(pointCursor)) {
129+ usedTank = await ensureFundsFor(
130+ _web3,
131+ pointCursor.value,
132+ _wallet.address,
133+ cost,
134+ [rawTx],
135+ (address, minBalance, balance) =>
136+ setNeedFunds({ address, minBalance, balance }),
137+ () => setNeedFunds(undefined)
138+ );
139+ }
140+
114 const txHash = await sendSignedTransaction(
141 const txHash = await sendSignedTransaction(
115 _web3,
142 _web3,
116 signedTransaction,
143 signedTransaction,
117− /* doubtNonceError */ false
144+ /* doubtNonceError */ usedTank
118 );
145 );
119
146
120 setState(STATE.BROADCASTED);
147 setState(STATE.BROADCASTED);
@@ -126,7 +153,15 @@ export default function useEthereumTransaction(
126 } catch (error) {
153 } catch (error) {
127 setError(error);
154 setError(error);
128 }
155 }
156+ }, [
157+ _wallet.address,
158+ _web3,
159+ gasLimit,
160+ gasPrice,
161+ pointCursor,
162+ setError,
129− }, [_web3, setError, signedTransaction]);
163+ signedTransaction,
164+ ]);
130
165
131 const reset = useCallback(() => {
166 const reset = useCallback(() => {
132 setUnsignedTransaction(undefined);
167 setUnsignedTransaction(undefined);
@@ -135,6 +170,7 @@ export default function useEthereumTransaction(
135 setGasPrice(suggestedGasPrice);
170 setGasPrice(suggestedGasPrice);
136 setState(STATE.NONE);
171 setState(STATE.NONE);
137 setError(undefined);
172 setError(undefined);
173+ setNeedFunds(undefined);
138 }, [suggestedGasPrice, setError]);
174 }, [suggestedGasPrice, setError]);
139
175
140 const resetGasPrice = useCallback(() => setGasPrice(suggestedGasPrice), [
176 const resetGasPrice = useCallback(() => setGasPrice(suggestedGasPrice), [
@@ -186,6 +222,7 @@ export default function useEthereumTransaction(
186 resetGasPrice,
222 resetGasPrice,
187 nonce,
223 nonce,
188 chainId,
224 chainId,
225+ needFunds,
189 };
226 };
190
227
191 return {
228 return {
src/lib/usePermissionsForPoint.js+5−8
@@ -5,7 +5,7 @@ import { useNetwork } from 'store/network';
5
5
6import * as need from 'lib/need';
6import * as need from 'lib/need';
7
7
8−import { eqAddr, ETH_ZERO_ADDR } from './wallet';
8+import { eqAddr, isZeroAddress } from './wallet';
9
9
10const NULL_PERMISSIONS = {
10const NULL_PERMISSIONS = {
11 isPlanet: false,
11 isPlanet: false,
@@ -55,13 +55,10 @@ export default function usePermissionsForPoint(address, point) {
55 const isVotingProxy = eqAddr(address, details.votingProxy);
55 const isVotingProxy = eqAddr(address, details.votingProxy);
56 const isTransferProxy = eqAddr(address, details.transferProxy);
56 const isTransferProxy = eqAddr(address, details.transferProxy);
57
57
58− const isManagementProxySet = !eqAddr(
58+ const isManagementProxySet = !isZeroAddress(details.managementProxy);
59− ETH_ZERO_ADDR,
60− details.managementProxy
61− );
62− const isSpawnProxySet = !eqAddr(ETH_ZERO_ADDR, details.spawnProxy);
59+ const isSpawnProxySet = !isZeroAddress(details.spawnProxy);
63− const isVotingProxySet = !eqAddr(ETH_ZERO_ADDR, details.votingProxy);
60+ const isVotingProxySet = !isZeroAddress(details.votingProxy);
64− const isTransferProxySet = !eqAddr(ETH_ZERO_ADDR, details.transferProxy);
61+ const isTransferProxySet = !isZeroAddress(details.transferProxy);
65
62
66 const canManage = isOwner || isManagementProxy;
63 const canManage = isOwner || isManagementProxy;
67 const canTransfer = isOwner || isTransferProxy;
64 const canTransfer = isOwner || isTransferProxy;
src/lib/validators.js+15−14
@@ -5,6 +5,7 @@ import { identity, includes } from 'lodash';
5import { isValidAddress, ETH_ZERO_ADDR, ETH_ZERO_ADDR_SHORT } from './wallet';
5import { isValidAddress, ETH_ZERO_ADDR, ETH_ZERO_ADDR_SHORT } from './wallet';
6import patp2dec from './patp2dec';
6import patp2dec from './patp2dec';
7import { patpStringLength } from './lib';
7import { patpStringLength } from './lib';
8+import { MIN_GALAXY, MAX_GALAXY } from './constants';
8
9
9// NOTE: do not use the /g modifier for these regexes
10// NOTE: do not use the /g modifier for these regexes
10// https://stackoverflow.com/a/21373261
11// https://stackoverflow.com/a/21373261
@@ -90,12 +91,12 @@ export const validateGalaxy = m =>
90 let point;
91 let point;
91 try {
92 try {
92 point = patp2dec(d);
93 point = patp2dec(d);
93− return point >= 0 && point < 256;
94+ return point >= MIN_GALAXY && point <= MAX_GALAXY;
94 } catch (e) {
95 } catch (e) {
95 return false;
96 return false;
96 }
97 }
97 },
98 },
98− error: 'This is not a valid galaxy',
99+ error: 'This is not a valid galaxy.',
99 });
100 });
100
101
101export const validatePoint = m =>
102export const validatePoint = m =>
@@ -108,7 +109,7 @@ export const validatePoint = m =>
108 return false;
109 return false;
109 }
110 }
110 },
111 },
111− error: 'This is not a valid point',
112+ error: 'This is not a valid point.',
112 });
113 });
113
114
114export const validateTicket = m =>
115export const validateTicket = m =>
@@ -121,7 +122,7 @@ export const validateTicket = m =>
121 return false;
122 return false;
122 }
123 }
123 },
124 },
124− error: 'This is not a valid ticket',
125+ error: 'This is not a valid ticket.',
125 });
126 });
126
127
127export const validateShard = m =>
128export const validateShard = m =>
@@ -134,7 +135,7 @@ export const validateShard = m =>
134 return false;
135 return false;
135 }
136 }
136 },
137 },
137− error: 'This is not a valid shard',
138+ error: 'This is not a valid shard.',
138 });
139 });
139
140
140export const validateOneOf = (options = []) => m =>
141export const validateOneOf = (options = []) => m =>
@@ -148,7 +149,7 @@ export const validateHexString = m =>
148 simpleValidatorWrapper({
149 simpleValidatorWrapper({
149 prevMessage: m,
150 prevMessage: m,
150 validator: d => isHexString.test(d),
151 validator: d => isHexString.test(d),
151− error: 'This is not a valid hex string',
152+ error: 'This is not a valid hex string.',
152 });
153 });
153
154
154// @deprecate
155// @deprecate
@@ -156,7 +157,7 @@ export const validateNetworkKey = m =>
156 simpleValidatorWrapper({
157 simpleValidatorWrapper({
157 prevMessage: m,
158 prevMessage: m,
158 validator: d => plain64CharHexValue.test(d),
159 validator: d => plain64CharHexValue.test(d),
159− error: 'This is not a valid network key',
160+ error: 'This is not a valid network key.',
160 });
161 });
161
162
162// @deprecate
163// @deprecate
@@ -164,7 +165,7 @@ export const validateNetworkSeed = m =>
164 simpleValidatorWrapper({
165 simpleValidatorWrapper({
165 prevMessage: m,
166 prevMessage: m,
166 validator: d => plain64CharHexValue.test(d),
167 validator: d => plain64CharHexValue.test(d),
167− error: 'This is not a valid network seed',
168+ error: 'This is not a valid network seed.',
168 });
169 });
169
170
170// Checks if a string is a valid ethereum address
171// Checks if a string is a valid ethereum address
@@ -172,14 +173,14 @@ export const validateEthereumAddress = m =>
172 simpleValidatorWrapper({
173 simpleValidatorWrapper({
173 prevMessage: m,
174 prevMessage: m,
174 validator: d => isValidAddress(d),
175 validator: d => isValidAddress(d),
175− error: 'This is not a valid Ethereum address',
176+ error: 'This is not a valid Ethereum address.',
176 });
177 });
177
178
178export const validateEmail = m =>
179export const validateEmail = m =>
179 simpleValidatorWrapper({
180 simpleValidatorWrapper({
180 prevMessage: m,
181 prevMessage: m,
181 validator: d => emailRegExp.test(d),
182 validator: d => emailRegExp.test(d),
182− error: 'This is not a valid email address',
183+ error: 'This is not a valid email address.',
183 });
184 });
184
185
185export const validateInt = m =>
186export const validateInt = m =>
@@ -194,7 +195,7 @@ export const validateInt = m =>
194 return false;
195 return false;
195 }
196 }
196 },
197 },
197− error: 'This is not a valid number',
198+ error: 'This is not a valid number.',
198 });
199 });
199
200
200export const validateExactly = (value, error) => m =>
201export const validateExactly = (value, error) => m =>
@@ -208,7 +209,7 @@ export const validateNotAny = (values = []) => m =>
208 simpleValidatorWrapper({
209 simpleValidatorWrapper({
209 prevMessage: m,
210 prevMessage: m,
210 validator: d => !values.includes(d),
211 validator: d => !values.includes(d),
211− error: `Cannot be ${m.data}`,
212+ error: `Cannot be ${m.data}.`,
212 });
213 });
213
214
214export const validateLength = l => m =>
215export const validateLength = l => m =>
@@ -221,7 +222,7 @@ export const validateLength = l => m =>
221 return false;
222 return false;
222 }
223 }
223 },
224 },
224− error: `Must be exactly ${l} characters`,
225+ error: `Must be exactly ${l} characters.`,
225 });
226 });
226
227
227export const validateMaximumLength = l => m =>
228export const validateMaximumLength = l => m =>
@@ -241,7 +242,7 @@ export const validateGreaterThan = l => m =>
241 simpleValidatorWrapper({
242 simpleValidatorWrapper({
242 prevMessage: m,
243 prevMessage: m,
243 validator: d => d > l,
244 validator: d => d > l,
244− error: `Must be at least ${l}`,
245+ error: `Must be at least ${l}.`,
245 });
246 });
246
247
247export const validatePatpByteLength = byteLength => {
248export const validatePatpByteLength = byteLength => {
src/lib/wallet.js+2−1
@@ -54,7 +54,8 @@ export const keccak256 = str =>
54
54
55export const isValidAddress = a => '0x0' === a || isAddress(a);
55export const isValidAddress = a => '0x0' === a || isAddress(a);
56
56
57−export const isZeroAddress = a => ETH_ZERO_ADDR === a;
57+export const isZeroAddress = a =>
58+ a === ETH_ZERO_ADDR || a === ETH_ZERO_ADDR_SHORT;
58
59
59export const toChecksumAddress = address => {
60export const toChecksumAddress = address => {
60 const addr = stripHexPrefix(address).toLowerCase();
61 const addr = stripHexPrefix(address).toLowerCase();
src/views/Activate/PassportTransfer.js+1−1
@@ -1,5 +1,6 @@
1import React, { useState, useCallback } from 'react';
1import React, { useState, useCallback } from 'react';
2import { Grid, Text, ErrorText } from 'indigo-react';
2import { Grid, Text, ErrorText } from 'indigo-react';
3+import { fromWei } from 'web3-utils';
3
4
4import { useNetwork } from 'store/network';
5import { useNetwork } from 'store/network';
5import { useWallet } from 'store/wallet';
6import { useWallet } from 'store/wallet';
@@ -13,7 +14,6 @@ import {
13 TRANSACTION_PROGRESS,
14 TRANSACTION_PROGRESS,
14} from 'lib/reticket';
15} from 'lib/reticket';
15import timeout from 'lib/timeout';
16import timeout from 'lib/timeout';
16−import { fromWei } from 'lib/txn';
17
17
18import WarningBox from 'components/WarningBox';
18import WarningBox from 'components/WarningBox';
19import LoadingBar from 'components/LoadingBar';
19import LoadingBar from 'components/LoadingBar';
src/views/Admin/AdminEditPermissions.js+2−2
@@ -8,7 +8,7 @@ import { usePointCursor } from 'store/pointCursor';
8import { usePointCache } from 'store/pointCache';
8import { usePointCache } from 'store/pointCache';
9
9
10import * as need from 'lib/need';
10import * as need from 'lib/need';
11−import { ETH_ZERO_ADDR } from 'lib/wallet';
11+import { isZeroAddress } from 'lib/wallet';
12import { PROXY_TYPE, proxyTypeToHuman } from 'lib/proxy';
12import { PROXY_TYPE, proxyTypeToHuman } from 'lib/proxy';
13import { useLocalRouter } from 'lib/LocalRouter';
13import { useLocalRouter } from 'lib/LocalRouter';
14import capitalize from 'lib/capitalize';
14import capitalize from 'lib/capitalize';
@@ -48,7 +48,7 @@ export default function AdminEditPermissions() {
48 ]);
48 ]);
49
49
50 const renderProxyAction = (proxyType, address) => {
50 const renderProxyAction = (proxyType, address) => {
51− if (eqAddr(address, ETH_ZERO_ADDR)) {
51+ if (isZeroAddress(address)) {
52 address = 'Not set';
52 address = 'Not set';
53 } else if (eqAddr(address, _contracts.delegatedSending.address)) {
53 } else if (eqAddr(address, _contracts.delegatedSending.address)) {
54 address = `${address} (invites contract)`;
54 address = `${address} (invites contract)`;
src/views/Admin/AdminSetProxy.js+3−2
@@ -14,7 +14,7 @@ import {
14} from 'lib/proxy';
14} from 'lib/proxy';
15import * as need from 'lib/need';
15import * as need from 'lib/need';
16import { useLocalRouter } from 'lib/LocalRouter';
16import { useLocalRouter } from 'lib/LocalRouter';
17−import { ETH_ZERO_ADDR, eqAddr } from 'lib/wallet';
17+import { ETH_ZERO_ADDR, eqAddr, isZeroAddress } from 'lib/wallet';
18import capitalize from 'lib/capitalize';
18import capitalize from 'lib/capitalize';
19import { useAddressInput, useCheckboxInput } from 'lib/useInputs';
19import { useAddressInput, useCheckboxInput } from 'lib/useInputs';
20import useEthereumTransaction from 'lib/useEthereumTransaction';
20import useEthereumTransaction from 'lib/useEthereumTransaction';
@@ -133,6 +133,7 @@ export default function AdminSetProxy() {
133 label: 'Unset',
133 label: 'Unset',
134 inverseLabel: 'Specify',
134 inverseLabel: 'Specify',
135 initialValue: false,
135 initialValue: false,
136+ disabled: inputsLocked,
136 });
137 });
137 const [
138 const [
138 addressInput,
139 addressInput,
@@ -164,7 +165,7 @@ export default function AdminSetProxy() {
164 ]);
165 ]);
165
166
166 const proxyAddress = proxyFromDetails(_details, _contracts, data.proxyType);
167 const proxyAddress = proxyFromDetails(_details, _contracts, data.proxyType);
167− const isProxySet = !eqAddr(ETH_ZERO_ADDR, proxyAddress);
168+ const isProxySet = !isZeroAddress(proxyAddress);
168
169
169 const proxyAddressLabel = `${
170 const proxyAddressLabel = `${
170 confirmed ? 'New' : 'Current'
171 confirmed ? 'New' : 'Current'
src/views/Admin/Reticket/ReticketExecute.js+1−1
@@ -1,12 +1,12 @@
1import React, { useState, useCallback } from 'react';
1import React, { useState, useCallback } from 'react';
2import { Just, Nothing } from 'folktale/maybe';
2import { Just, Nothing } from 'folktale/maybe';
3import { Grid, H4, Text, ErrorText } from 'indigo-react';
3import { Grid, H4, Text, ErrorText } from 'indigo-react';
4+import { fromWei } from 'web3-utils';
4
5
5import {
6import {
6 reticketPointBetweenWallets,
7 reticketPointBetweenWallets,
7 TRANSACTION_PROGRESS,
8 TRANSACTION_PROGRESS,
8} from 'lib/reticket';
9} from 'lib/reticket';
9−import { fromWei } from 'lib/txn';
10import * as need from 'lib/need';
10import * as need from 'lib/need';
11import useLifecycle from 'lib/useLifecycle';
11import useLifecycle from 'lib/useLifecycle';
12
12
src/views/CreateGalaxy.js+2−1
@@ -86,7 +86,7 @@ export default function CreateGalaxy() {
86 error ||
86 error ||
87 isAvailable.matchWith({
87 isAvailable.matchWith({
88 Nothing: () => 'Loading availabiliy...', // TODO: make async loading?
88 Nothing: () => 'Loading availabiliy...', // TODO: make async loading?
89− Just: p => (p.value ? undefined : 'This galaxy is already owned'),
89+ Just: p => (p.value ? undefined : 'This galaxy is already owned.'),
90 }),
90 }),
91 });
91 });
92
92
@@ -109,6 +109,7 @@ export default function CreateGalaxy() {
109 return;
109 return;
110 }
110 }
111
111
112+ setError();
112 setIsAvailable(Nothing());
113 setIsAvailable(Nothing());
113
114
114 let cancelled = false;
115 let cancelled = false;
src/views/Invite/InviteEmail.js+2−3
@@ -13,6 +13,7 @@ import {
13 useForm,
13 useForm,
14} from 'indigo-react';
14} from 'indigo-react';
15import { uniq } from 'lodash';
15import { uniq } from 'lodash';
16+import { fromWei, toWei } from 'web3-utils';
16
17
17import { usePointCursor } from 'store/pointCursor';
18import { usePointCursor } from 'store/pointCursor';
18import { useNetwork } from 'store/network';
19import { useNetwork } from 'store/network';
@@ -25,8 +26,6 @@ import {
25 sendSignedTransaction,
26 sendSignedTransaction,
26 waitForTransactionConfirm,
27 waitForTransactionConfirm,
27 hexify,
28 hexify,
28− fromWei,
29− toWei,
30} from 'lib/txn';
29} from 'lib/txn';
31import * as tank from 'lib/tank';
30import * as tank from 'lib/tank';
32import { useLocalRouter } from 'lib/LocalRouter';
31import { useLocalRouter } from 'lib/LocalRouter';
@@ -309,7 +308,7 @@ export default function InviteEmail() {
309 inputs.map(input => invites[input.name].rawTx),
308 inputs.map(input => invites[input.name].rawTx),
310 (address, minBalance, balance) =>
309 (address, minBalance, balance) =>
311 setNeedFunds({ address, minBalance, balance }),
310 setNeedFunds({ address, minBalance, balance }),
312− () => setNeedFunds(false)
311+ () => setNeedFunds(undefined)
313 );
312 );
314
313
315 setStatus(STATUS.SENDING);
314 setStatus(STATUS.SENDING);