on master help sign in
Lots of fixes
commit368f0246e5b7e6d87b2a670b6db4a06e15a854d6 authorWill Galebach <willbach@gmail.com> dateTue 16 Nov 2021, 16:38 (5 years ago) parent65d744f
15 files changed+165−83
src/components/L2/Dropdowns/AccountsDropdown.tsx+5−2 src/components/L2/Dropdowns/Dropdown.scss+7−1 src/components/L2/Headers/L2PointHeader.tsx+2−2 src/lib/constants.ts+5 src/lib/types/Point.ts+2−2 src/lib/useRoller.ts+27−38 src/lib/utils/roller.ts+14−1 src/lib/walletgen.js+9−2 src/store/rollerStore.ts+12 src/store/storage/roller.ts+10 src/views/Invite/Cohort.tsx+16−27 src/views/UrbitID/Home.tsx+29−8 src/worker/custom.d.ts+11 src/worker/index.ts+4 src/worker/worker.ts+12
src/components/L2/Dropdowns/AccountsDropdown.tsx+5−2
@@ -28,7 +28,7 @@ const AccountsDropdown = ({ showMigrate = false }: AccountsDropdownProps) => {
2828 const walletInfo: any = useWallet();
2929 const { push, popTo, names, reset }: any = useHistory();
3030 const { setPointCursor }: any = usePointCursor();
31− const { pointList } = useRollerStore();
31+ const { point, pointList } = useRollerStore();
3232
3333 const canBitcoin = Just.hasInstance(walletInfo.urbitWallet);
3434
@@ -74,11 +74,14 @@ const AccountsDropdown = ({ showMigrate = false }: AccountsDropdownProps) => {
7474 return showMigrate || hasL1Points;
7575 }, [hasL1Points, showMigrate]);
7676
77+ const displayText =
78+ point.value >= 0 ? point.patp : currentAddress.slice(0, 6);
79+
7780 return (
7881 <Dropdown
7982 className="accounts-dropdown"
8083 open={open}
81− value={currentAddress.slice(0, 6)}
84+ value={displayText}
8285 toggleOpen={() => setOpen(!open)}>
8386 <CopiableAddressWrap
8487 className="current-address"
src/components/L2/Dropdowns/Dropdown.scss+7−1
@@ -46,8 +46,14 @@
4646 background-color: white;
4747 border: 1px solid $light-gray;
4848 width: 240px;
49− max-height: 80vh;
49+ max-height: 200px;
5050 overflow-y: scroll;
51+ -ms-overflow-style: none;
52+ scrollbar-width: none;
53+
54+ &::-webkit-scrollbar {
55+ display: none;
56+ }
5157 }
5258 }
5359}
src/components/L2/Headers/L2PointHeader.tsx+2−2
@@ -60,13 +60,13 @@ const L2PointHeader = ({
6060 <AccountsDropdown showMigrate={showMigrate} />
6161 </Row>
6262 <Row className="info">
63− {showInvites && point.canSpawn && (
63+ {showInvites && point.showInvites && (
6464 <Row onClick={goToInvites} className="invites">
6565 <InviteIcon />
6666 {numInvites}
6767 </Row>
6868 )}
69− {!hideTimer && point?.isL2Spawn && !pendingTransactions.length && (
69+ {!hideTimer && point.isL2Spawn && !pendingTransactions.length && (
7070 <Box className="rollup-timer" onClick={goToHistory}>
7171 {nextRoll}
7272 </Box>
src/lib/constants.ts+5
@@ -164,6 +164,9 @@ const TRANSACTION_TYPE_TITLES = {
164164};
165165const DUMMY_L2_ADDRESS = '0x1111111111111111111111111111111111111111';
166166
167+const ONE_SECOND = 1000;
168+const TWO_SECONDS = 2000;
169+
167170export {
168171 CHECK_BLOCK_EVERY_MS,
169172 DEFAULT_GAS_PRICE_GWEI,
@@ -203,4 +206,6 @@ export {
203206 TRANSACTION_TYPE_ICONS,
204207 TRANSACTION_TYPE_TITLES,
205208 DUMMY_L2_ADDRESS,
209+ ONE_SECOND,
210+ TWO_SECONDS,
206211};
src/lib/types/Point.ts+2−2
@@ -60,6 +60,7 @@ export default class Point {
6060 canSpawn: boolean;
6161 canTransfer: boolean;
6262 canVote: boolean;
63+ showInvites: boolean;
6364
6465 constructor(
6566 value: number,
@@ -115,11 +116,10 @@ export default class Point {
115116 this.networkKeysSet;
116117 this.canVote =
117118 this.isGalaxy && this.active && (this.isOwner || this.isVotingProxy);
118−
119119 this.canMigrate =
120120 this.canManage &&
121− this.networkKeysSet &&
122121 this.isL1 &&
123122 ((this.isGalaxy && !this.isL2Spawn) || this.isStar || this.isPlanet);
123+ this.showInvites = this.canManage || this.canSpawn;
124124 }
125125}
src/lib/useRoller.ts+27−38
@@ -13,7 +13,11 @@ import { useNetwork } from 'store/network';
1313import { usePointCursor } from 'store/pointCursor';
1414import { EMPTY_POINT, useRollerStore } from 'store/rollerStore';
1515import { useWallet } from 'store/wallet';
16−import { getStoredInvites, setStoredInvites } from 'store/storage/roller';
16+import {
17+ getStoredInvites,
18+ setStoredInvite,
19+ setStoredInvites,
20+} from 'store/storage/roller';
1721import { usePointCache } from 'store/pointCache';
1822import { getOutgoingPoints } from 'views/Points';
1923
@@ -86,13 +90,14 @@ export default function useRoller() {
8690 nextBatchTime,
8791 point,
8892 invitePoints,
89− invites,
93+ removeInvite,
9094 setNextBatchTime,
9195 setPendingTransactions,
9296 setInvites,
9397 setInvitePoints,
9498 setInviteGeneratingNum,
9599 setPoints,
100+ updateInvite,
96101 } = useRollerStore();
97102 const [config, setConfig] = useState<Config | null>(null);
98103
@@ -120,6 +125,15 @@ export default function useRoller() {
120125 return new RollerRPCAPI(options);
121126 }, [options]);
122127
128+ const ls = useMemo(
129+ () =>
130+ new SecureLS({
131+ isCompression: false,
132+ encryptionSecret: authToken.getOrElse('default'),
133+ }),
134+ [authToken]
135+ );
136+
123137 const fetchConfig = useCallback(async () => {
124138 api
125139 .getRollerConfig()
@@ -136,15 +150,6 @@ export default function useRoller() {
136150 });
137151 }, [api]); // eslint-disable-line react-hooks/exhaustive-deps
138152
139− const ls = useMemo(
140− () =>
141− new SecureLS({
142− isCompression: false,
143− encryptionSecret: authToken.getOrElse('default'),
144− }),
145− [authToken]
146− );
147−
148153 const generateInviteCodes = useCallback(
149154 async (numInvites: number) => {
150155 const _point = need.point(pointCursor);
@@ -346,21 +351,20 @@ export default function useRoller() {
346351 for (let i = 0; i < invitePlanets.length; i++) {
347352 setInviteGeneratingNum(i + 1);
348353 const planet = invitePlanets[i];
349− const invite = storedInvites[planet];
354+ const invite =
355+ storedInvites[planet] ||
356+ (await generateInviteInfo(planet, _authToken));
350357
351− if (invite?.ticket) {
358+ // TODO: check if the invite point's owner still matches the deterministic wallet address
359+ const planetInfo = await api.getPoint(planet);
360+ if (invite.owner === planetInfo.ownership?.transferProxy?.address) {
352361 newInvites.push(invite);
353− } else if (getAll) {
354− if (isDevelopment) {
355− console.log('MISSING INVITE INFO', planet);
356− }
357− const newInvite = await generateInviteInfo(planet, _authToken);
358− newInvites.push(newInvite);
362+ updateInvite(invite);
363+ setStoredInvite(ls, invite);
359364 } else {
360− newInvites.push(inviteTemplate(planet));
365+ removeInvite(planet);
361366 }
362367 }
363−
364368 setStoredInvites(ls, newInvites);
365369 setInvites(newInvites);
366370
@@ -379,27 +383,13 @@ export default function useRoller() {
379383 pointCursor,
380384 invitePoints,
381385 ls,
386+ removeInvite,
382387 setInvites,
383388 setInviteGeneratingNum,
389+ updateInvite,
384390 ]
385391 );
386392
387− const showInvite = useCallback(
388− async (planet: number) => {
389− const _authToken = authToken.getOrElse(null);
390−
391− if (_authToken) {
392− const newInvite = await generateInviteInfo(planet, _authToken);
393− const newInvites = invites.map(invite =>
394− invite.planet === planet ? newInvite : invite
395− );
396− setInvites(newInvites);
397− setStoredInvites(ls, newInvites);
398− }
399− },
400− [authToken, invites, ls, setInvites]
401− );
402−
403393 const getNumInvites = useCallback(
404394 async (isL2: boolean) => {
405395 try {
@@ -887,6 +877,5 @@ export default function useRoller() {
887877 ls,
888878 performL2Reticket,
889879 setProxyAddress,
890− showInvite,
891880 };
892881}
src/lib/utils/roller.ts+14−1
@@ -320,7 +320,15 @@ export const registerProxyAddress = async (
320320};
321321
322322const getDataAndMethod = (args: L2TransactionArgs) => {
323− const { address, api, breach, networkSeed, reset, pointToSpawn } = args;
323+ const {
324+ address,
325+ api,
326+ breach,
327+ networkSeed,
328+ reset,
329+ pointToSpawn,
330+ newSponsor,
331+ } = args;
324332 const result: TransactionData = { data: { address }, method: () => null };
325333
326334 switch (args.type) {
@@ -353,6 +361,11 @@ const getDataAndMethod = (args: L2TransactionArgs) => {
353361 };
354362 result.method = api.configureKeys;
355363 return result;
364+ case 'escape':
365+ result.method = api.escape;
366+ result.data.ship = newSponsor;
367+ delete result.data.address;
368+ return result;
356369 }
357370};
358371
src/lib/walletgen.js+9−2
@@ -13,6 +13,9 @@ import {
1313 PLANET_ENTROPY_BITS,
1414 ZOD,
1515} from './constants';
16+import Worker from 'worker';
17+
18+const worker = new Worker();
1619
1720const SEED_LENGTH_BYTES = SEED_ENTROPY_BITS / 8;
1821
@@ -78,9 +81,13 @@ export const generateWallet = async (point, ticket, boot) => {
7881 // hangs, blocking UI updates so this cannot be done in the UI
7982 console.log('Generating Wallet for point address: ', point);
8083
81− const wallet = await kg.generateWallet(config);
84+ return new Promise(async resolve => {
85+ // Use a web worker to process the data
86+ console.log(1, config)
87+ const processed = await worker.generateWallet(JSON.stringify(config));
8288
83− return wallet;
89+ resolve(processed);
90+ });
8491};
8592
8693export const generateOwnershipWallet = async (ship, ticket) => {
src/store/rollerStore.ts+12
@@ -18,6 +18,7 @@ export interface RollerStore {
1818 invites: Invite[];
1919 recentlyCompleted: number;
2020 inviteGeneratingNum: number;
21+ removeInvite: (point: number) => void;
2122 setNextBatchTime: (nextBatchTime: number) => void;
2223 setPendingTransactions: (pendingTransactions: PendingTransaction[]) => void;
2324 setPoint: (point: number) => void;
@@ -25,6 +26,7 @@ export interface RollerStore {
2526 setInvitePoints: (points: number[]) => void;
2627 setInvites: (invites: Invite[]) => void;
2728 setInviteGeneratingNum: (numGenerating: number) => void;
29+ updateInvite: (invite: Invite) => void;
2830}
2931
3032export const useRollerStore = create<RollerStore>(set => ({
@@ -37,6 +39,10 @@ export const useRollerStore = create<RollerStore>(set => ({
3739 invites: [],
3840 recentlyCompleted: 0,
3941 inviteGeneratingNum: 0,
42+ removeInvite: (point: number) =>
43+ set(state => ({
44+ invites: state.invites.filter(({ planet }) => point !== planet),
45+ })),
4046 setNextBatchTime: (nextBatchTime: number) => set(() => ({ nextBatchTime })),
4147 setPendingTransactions: (pendingTransactions: PendingTransaction[]) =>
4248 set(state => {
@@ -58,4 +64,10 @@ export const useRollerStore = create<RollerStore>(set => ({
5864 setInvites: (invites: Invite[]) => set(() => ({ invites })),
5965 setInviteGeneratingNum: (inviteGeneratingNum: number) =>
6066 set(() => ({ inviteGeneratingNum })),
67+ updateInvite: (invite: Invite) =>
68+ set(state => ({
69+ invites: state.invites.map(i =>
70+ i.planet === invite.planet ? invite : i
71+ ),
72+ })),
6173}));
src/store/storage/roller.ts+10
@@ -24,6 +24,16 @@ export const setStoredInvites = (ls: SecureLS, newInvites: Invite[]) => {
2424 ls.set(INVITES_KEY, invites);
2525};
2626
27+export const setStoredInvite = (ls: SecureLS, newInvite: Invite) => {
28+ let invites: Invites = {};
29+ try {
30+ invites = ls.get(INVITES_KEY) || {};
31+ } catch (e) {}
32+
33+ invites[Number(newInvite.planet)] = newInvite;
34+ ls.set(INVITES_KEY, invites);
35+};
36+
2737export const clearInvitesStorage = () => localStorage.removeItem(INVITES_KEY);
2838
2939export const getHideMigrationMessage = () =>
src/views/Invite/Cohort.tsx+16−27
@@ -5,7 +5,8 @@ import {
55 Icon,
66 Row,
77 StatelessTextInput,
8− Button as Button2,
8+ Box,
9+ LoadingSpinner,
910} from '@tlon/indigo-react';
1011
1112import { usePointCache } from 'store/pointCache';
@@ -59,6 +60,7 @@ export default function InviteCohort() {
5960 pendingTransactions,
6061 invites,
6162 invitePoints,
63+ inviteGeneratingNum,
6264 setInviteGeneratingNum,
6365 setInvites,
6466 } = useRollerStore();
@@ -70,11 +72,10 @@ export default function InviteCohort() {
7072 generateInviteCodes,
7173 getPendingTransactions,
7274 getInvites,
73− showInvite,
7475 } = useRoller();
7576 const { contracts }: any = useNetwork();
7677 const { syncControlledPoints }: any = usePointCache();
77− const currentL2 = Boolean(point?.isL2);
78+ const currentL2 = Boolean(point?.isL2Spawn);
7879
7980 const _contracts = need.contracts(contracts);
8081
@@ -90,21 +91,9 @@ export default function InviteCohort() {
9091
9192 const { construct, unconstruct, completed, bind } = useIssueChild();
9293
93− const onClickShowInvite = useCallback(
94− (planet: number) => {
95− setLoading(true);
96− // Put this in a timeout to let the UI update
97− setTimeout(async () => {
98− await showInvite(planet);
99− setLoading(false);
100− }, 50);
101− },
102− [setLoading, showInvite]
103− );
104−
10594 useEffect(() => {
10695 if (invitePoints.length > 0) {
107− getInvites(currentL2);
96+ getInvites(currentL2, true);
10897 }
10998 }, []); // eslint-disable-line react-hooks/exhaustive-deps
11099
@@ -282,11 +271,12 @@ export default function InviteCohort() {
282271 className="copy-invite"
283272 />
284273 ) : (
285− <Button2
286− className="secondary"
287− onClick={() => onClickShowInvite(invite.planet)}>
288− Show Invite
289− </Button2>
274+ <Box className="ticket-loader">
275+ <LoadingSpinner
276+ foreground="white"
277+ background="rgba(0,0,0,0.3)"
278+ />
279+ </Box>
290280 )}
291281 </div>
292282 ))}
@@ -307,7 +297,7 @@ export default function InviteCohort() {
307297 <>
308298 You have no planet codes available.
309299 <br />
310− {currentL2 && (
300+ {currentL2 && point.canSpawn && (
311301 <>
312302 Generate your codes in
313303 <br />
@@ -404,10 +394,9 @@ export default function InviteCohort() {
404394 );
405395 }
406396
407− const showGenerateButton = !hasPending && !hasInvites;
408− const downloadingCsvText = `Generating ${
409− invitePoints.length
410− } codes, this could take up to ${invitePoints.length * 5} seconds...`;
397+ const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
398+ const showAddMoreButton = (hasInvites || hasPending) && point.canSpawn;
399+ const downloadingCsvText = `Generating invite code ${inviteGeneratingNum} of ${invitePoints.length}...`;
411400
412401 return (
413402 <View
@@ -453,7 +442,7 @@ export default function InviteCohort() {
453442 )}
454443 </BodyPane>
455444 </Window>
456− {(hasInvites || hasPending) && (
445+ {showAddMoreButton && (
457446 <Button
458447 onClick={() => setShowInviteForm(true)}
459448 className="add-more"
src/views/UrbitID/Home.tsx+29−8
@@ -1,5 +1,5 @@
1−import React, { useCallback } from 'react';
2−import { Just } from 'folktale/maybe';
1+import React, { useCallback, useState } from 'react';
2+import { Just, Nothing } from 'folktale/maybe';
33import { Box, Button, Icon, Row } from '@tlon/indigo-react';
44
55import { useLocalRouter } from 'lib/LocalRouter';
@@ -9,6 +9,8 @@ import useCurrentPermissions from 'lib/useCurrentPermissions';
99import { convertToInt } from 'lib/convertToInt';
1010import { ETH_ZERO_ADDR } from 'lib/constants';
1111import { abbreviateAddress } from 'lib/utils/address';
12+import { downloadWallet } from 'lib/invite';
13+import useKeyfileGenerator from 'lib/useKeyfileGenerator';
1214
1315import { usePointCache } from 'store/pointCache';
1416import { useWallet } from 'store/wallet';
@@ -18,6 +20,7 @@ import Window from 'components/L2/Window/Window';
1820import HeaderPane from 'components/L2/Window/HeaderPane';
1921import BodyPane from 'components/L2/Window/BodyPane';
2022import CopiableWithTooltip from 'components/copiable/CopiableWithTooltip';
23+import PaperBuilder from 'components/PaperBuilder';
2124
2225import './UrbitID.scss';
2326
@@ -27,10 +30,16 @@ export default function UrbitIDHome() {
2730 const { urbitWallet }: any = useWallet();
2831 const { point } = useRollerStore();
2932
30− const goDownloadKeys = useCallback(() => push(names.DOWNLOAD_KEYS), [
31− push,
32− names,
33− ]);
33+ const [keysDownloaded, setKeysDownloaded] = useState(false);
34+
35+ const _urbitWallet = need.wallet(urbitWallet);
36+ const { keyfile, filename } = useKeyfileGenerator();
37+ const [paper, setPaper] = useState(Nothing());
38+
39+ const downloadKeys = useCallback(() => {
40+ downloadWallet(paper.value, keyfile, filename);
41+ setKeysDownloaded(true);
42+ }, [paper, keyfile, filename, setKeysDownloaded]);
3443
3544 const goSigil = useCallback(() => push(names.SIGIL_GENERATOR), [push, names]);
3645
@@ -58,8 +67,13 @@ export default function UrbitIDHome() {
5867 <Row className="header-row">
5968 <h5>ID</h5>
6069 {isMasterTicket && (
61− <Button onClick={goDownloadKeys} className="header-button">
62− Download Passport
70+ <Button onClick={downloadKeys} className="header-button">
71+ {keysDownloaded
72+ ? 'Downloaded!'
73+ : paper.matchWith({
74+ Nothing: () => 'Printing and folding...',
75+ Just: (_: any) => 'Download Passport',
76+ })}
6377 </Button>
6478 )}
6579 </Row>
@@ -183,6 +197,13 @@ export default function UrbitIDHome() {
183197 </Row>
184198 )}
185199 </BodyPane>
200+ <PaperBuilder
201+ point={point.value}
202+ wallets={[_urbitWallet]}
203+ callback={(paper: any) => {
204+ setPaper(Just(paper));
205+ }}
206+ />
186207 </Window>
187208 );
188209}
src/worker/custom.d.tsnew file+11
@@ -0,0 +1,11 @@
1+declare module 'comlink-loader!*' {
2+ class WebpackWorker extends Worker {
3+ constructor();
4+
5+ // Add any custom functions to this class.
6+ // Make note that the return type needs to be wrapped in a promise.
7+ processData(data: string): Promise<string>;
8+ }
9+
10+ export = WebpackWorker;
11+}
src/worker/index.tsnew file+4
@@ -0,0 +1,4 @@
1+// eslint-disable-next-line
2+import Worker from 'comlink-loader!./worker'; // inline loader
3+
4+export default Worker;
src/worker/worker.tsnew file+12
@@ -0,0 +1,12 @@
1+import kg from 'urbit-key-generation';
2+
3+export async function generateWallet(data: string): Promise<string> {
4+ console.log(2, data)
5+ // Process the data without stalling the UI
6+ const config = JSON.parse(data);
7+ console.log(3)
8+ const wallet = await kg.generateWallet(config);
9+ console.log(4)
10+
11+ return wallet;
12+}