on master help sign in
feat: implement local ignore list
commit766cfe4fe5558c58375b31f0f94bd865f640d607 authorMatt Condon (shrugs) <mattgcondon@gmail.com> dateTue 23 Jul 2019, 12:14 (7 years ago) parent33c8b8d
8 files changed+76−104
src/components/InlineEthereumTransaction.js+1−1 src/lib/routeNames.js−1 src/lib/router.js−2 src/lib/useEthereumTransaction.js+7−4 src/lib/useLocalStorageState.js+38 src/lib/useRejectedIncomingPointTransfers.js+19 src/views/Points.js+11−3 src/views/RejectTransfer.js−93
src/components/InlineEthereumTransaction.js+1−1
@@ -51,7 +51,7 @@ export default function InlineEthereumTransaction({
5151 const showConfigureInput = !(signed || broadcasted || confirmed || completed);
5252 // show the send/loading button while signed, broadcasting, or confirme
5353 const showBroadcastButton = signed || broadcasted || confirmed;
54− const canBroadcast = signed;
54+ const canBroadcast = signed && !needFunds;
5555 const isLoading = broadcasted || confirmed;
5656 // show signed tx only when signing (for offline usage)
5757 const showSignedTx = signed;
src/lib/routeNames.js−1
@@ -14,7 +14,6 @@ export const ROUTE_NAMES = {
1414 PERMISSIONS: Symbol('PERMISSIONS'),
1515 //
1616 ACCEPT_TRANSFER: Symbol('ACCEPT_TRANSFER'),
17− REJECT_TRANSFER: Symbol('REJECT_TRANSFER'),
1817 CANCEL_TRANSFER: Symbol('CANCEL_TRANSFER'),
1918 LANDING: Symbol('LANDING'),
2019 VIEW_POINT: Symbol('VIEW_POINT'),
src/lib/router.js−2
@@ -14,7 +14,6 @@ import Activate from 'views/Activate';
1414import PartySetPoolSize from 'views/Party/PartySetPoolSize';
1515import AcceptTransfer from 'views/AcceptTransfer';
1616import CancelTransfer from 'views/CancelTransfer';
17−import RejectTransfer from 'views/RejectTransfer';
1817
1918import { ROUTE_NAMES } from './routeNames';
2019
@@ -33,7 +32,6 @@ export const ROUTES = {
3332 // TODO: nest this route under the Party.js router
3433 [ROUTE_NAMES.PARTY_SET_POOL_SIZE]: PartySetPoolSize,
3534 [ROUTE_NAMES.ACCEPT_TRANSFER]: AcceptTransfer,
36− [ROUTE_NAMES.REJECT_TRANSFER]: RejectTransfer,
3735 // TODO: replace this with deep link to AdminCancelTransfer
3836 [ROUTE_NAMES.CANCEL_TRANSFER]: CancelTransfer,
3937};
src/lib/useEthereumTransaction.js+7−4
@@ -14,7 +14,6 @@ import {
1414 hexify,
1515} from './txn';
1616import * as need from './need';
17−import useLifecycle from './useLifecycle';
1817import { ensureFundsFor } from './tank';
1918import useDeepEqualReference from './useDeepEqualReference';
2019
@@ -174,7 +173,6 @@ export default function useEthereumTransaction(
174173 ]);
175174
176175 const reset = useCallback(() => {
177− setUnsignedTransaction(undefined);
178176 setTxHash(undefined);
179177 setSignedTransaction(undefined);
180178 setGasPrice(suggestedGasPrice);
@@ -188,7 +186,12 @@ export default function useEthereumTransaction(
188186 suggestedGasPrice,
189187 ]);
190188
191− useLifecycle(() => {
189+ useEffect(() => {
190+ // if nonce or chainId is undefined, re-fetch on-chain info
191+ if (!(nonce === undefined || chainId === undefined)) {
192+ return;
193+ }
194+
192195 (async () => {
193196 try {
194197 setError(undefined);
@@ -207,7 +210,7 @@ export default function useEthereumTransaction(
207210 setError(error);
208211 }
209212 })();
210− });
213+ }, [_wallet, _web3, setError, nonce, chainId]);
211214
212215 useEffect(() => {
213216 let cancelled = false;
src/lib/useLocalStorageState.jsnew file+38
@@ -0,0 +1,38 @@
1+import { useState, useEffect } from 'react';
2+
3+/**
4+ * useLocalStorageState is useState but it persists to localStorage
5+ *
6+ * inspired by:
7+ * https://github.com/streamich/react-use/blob/master/src/useLocalStorage.ts
8+ * https://usehooks.com/useLocalStorage/
9+ */
10+export default function useLocalStorageState(key, initialValue) {
11+ const [state, setState] = useState(() => {
12+ try {
13+ const value = localStorage.getItem(key);
14+ if (value === null) {
15+ localStorage.setItem(key, JSON.stringify(initialValue));
16+ return initialValue;
17+ } else {
18+ return JSON.parse(value);
19+ }
20+ } catch {
21+ // if user is in private mode or has storage restriction
22+ // localStorage can throw. JSON.parse and JSON.stringify
23+ // can throw, too.
24+ return initialValue;
25+ }
26+ });
27+
28+ useEffect(() => {
29+ try {
30+ localStorage.setItem(key, JSON.stringify(state));
31+ } catch {
32+ // if user is in private mode or has storage restriction
33+ // localStorage can throw. Also JSON.stringify can throw.
34+ }
35+ }, [key, state]);
36+
37+ return [state, setState];
38+}
src/lib/useRejectedIncomingPointTransfers.jsnew file+19
@@ -0,0 +1,19 @@
1+import { useCallback } from 'react';
2+
3+import useLocalStorageState from './useLocalStorageState';
4+
5+const REJECTED_POINTS_KEY = 'bridge:rejected-points';
6+
7+export default function useRejectedIncomingPointTransfers() {
8+ const [rejectedPoints, setRejectedPoints] = useLocalStorageState(
9+ REJECTED_POINTS_KEY,
10+ []
11+ );
12+
13+ const addRejectedPoint = useCallback(
14+ point => setRejectedPoints([...rejectedPoints, point]),
15+ [rejectedPoints, setRejectedPoints]
16+ );
17+
18+ return [rejectedPoints, addRejectedPoint];
19+}
src/views/Points.js+11−3
@@ -17,6 +17,7 @@ import View from 'components/View';
1717import FooterButton from 'components/FooterButton';
1818import Blinky from 'components/Blinky';
1919import Passport from 'components/Passport';
20+import useRejectedIncomingPointTransfers from 'lib/useRejectedIncomingPointTransfers';
2021
2122const getFromMaybe = (obj, key, defaultValue) =>
2223 obj.matchWith({
@@ -81,13 +82,21 @@ export default function Points() {
8182 const { setPointCursor } = usePointCursor();
8283 const { controlledPoints, getDetails } = usePointCache();
8384 const isEclipticOwner = useIsEclipticOwner();
85+ const [
86+ rejectedPoints,
87+ addRejectedPoint,
88+ ] = useRejectedIncomingPointTransfers();
8489
8590 const address = need.addressFromWallet(wallet);
8691
8792 const loading = Nothing.hasInstance(controlledPoints);
8893
8994 const ownedPoints = getFromMaybe(controlledPoints, 'ownedPoints', []);
90− const incomingPoints = getFromMaybe(controlledPoints, 'incomingPoints', []);
95+ const incomingPoints = getFromMaybe(
96+ controlledPoints,
97+ 'incomingPoints',
98+ []
99+ ).filter(point => !rejectedPoints.includes(point));
91100 const managingPoints = getFromMaybe(controlledPoints, 'managingPoints', []);
92101 const votingPoints = getFromMaybe(controlledPoints, 'votingPoints', []);
93102 const spawningPoints = getFromMaybe(controlledPoints, 'spawningPoints', []);
@@ -149,8 +158,7 @@ export default function Points() {
149158 {
150159 text: 'Reject',
151160 onClick: () => {
152− setPointCursor(Just(point));
153− history.push(history.names.REJECT_TRANSFER);
161+ addRejectedPoint(point);
154162 },
155163 },
156164 ]}
src/views/RejectTransfer.jsdeleted−93
@@ -1,93 +0,0 @@
1−import React, { useCallback } from 'react';
2−import cn from 'classnames';
3−import { Grid, Text } from 'indigo-react';
4−import * as azimuth from 'azimuth-js';
5−
6−import { useNetwork } from 'store/network';
7−import { usePointCursor } from 'store/pointCursor';
8−import { usePointCache } from 'store/pointCache';
9−import { useHistory } from 'store/history';
10−
11−import * as need from 'lib/need';
12−import useCurrentPointName from 'lib/useCurrentPointName';
13−import useEthereumTransaction from 'lib/useEthereumTransaction';
14−import { GAS_LIMITS } from 'lib/constants';
15−import { ETH_ZERO_ADDR } from 'lib/wallet';
16−import useLifecycle from 'lib/useLifecycle';
17−
18−import ViewHeader from 'components/ViewHeader';
19−import MiniBackButton from 'components/MiniBackButton';
20−import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
21−import View from 'components/View';
22−
23−function useRejectTransfer() {
24− const { contracts } = useNetwork();
25− const { pointCursor } = usePointCursor();
26− const { syncDetails, syncControlledPoints } = usePointCache();
27−
28− const _contracts = need.contracts(contracts);
29− const _point = need.point(pointCursor);
30−
31− const { construct, ...rest } = useEthereumTransaction(
32− useCallback(
33− () =>
34− azimuth.ecliptic.setTransferProxy(_contracts, _point, ETH_ZERO_ADDR),
35− [_contracts, _point]
36− ),
37− useCallback(
38− () => Promise.all([syncDetails(_point), syncControlledPoints()]),
39− [_point, syncControlledPoints, syncDetails]
40− ),
41− GAS_LIMITS.SET_PROXY
42− );
43−
44− useLifecycle(() => {
45− construct();
46− });
47−
48− return {
49− ...rest,
50− };
51−}
52−
53−export default function RejectTransfer() {
54− const { pop } = useHistory();
55− const { getDetails } = usePointCache();
56− const { pointCursor } = usePointCursor();
57− const _point = need.point(pointCursor);
58−
59− const name = useCurrentPointName();
60− const _details = need.details(getDetails(_point));
61−
62− const { completed, bind } = useRejectTransfer();
63−
64− return (
65− <View inset>
66− <Grid>
67− <Grid.Item full as={MiniBackButton} onClick={() => pop()} />
68−
69− <Grid.Item full as={ViewHeader}>
70− Reject Incoming Transfer
71− </Grid.Item>
72−
73− <Grid.Item
74− full
75− as={Text}
76− className={cn('f5', {
77− green3: completed,
78− })}>
79− {completed
80− ? `The incoming transfer of ${name} has been rejected.`
81− : `Reject the incoming transfer of ${name} from ${_details.owner}.`}
82− </Grid.Item>
83−
84− <Grid.Item
85− full
86− as={InlineEthereumTransaction}
87− {...bind}
88− onReturn={() => pop()}
89− />
90− </Grid>
91− </View>
92− );
93−}