on master help sign in
Lots of fixes
368f024Will Galebach
src/components/L2/Dropdowns/AccountsDropdown.tsx+5−2
@@ -28,7 +28,7 @@ const AccountsDropdown = ({ showMigrate = false }: AccountsDropdownProps) => {
28 const walletInfo: any = useWallet();
28 const walletInfo: any = useWallet();
29 const { push, popTo, names, reset }: any = useHistory();
29 const { push, popTo, names, reset }: any = useHistory();
30 const { setPointCursor }: any = usePointCursor();
30 const { setPointCursor }: any = usePointCursor();
31− const { pointList } = useRollerStore();
31+ const { point, pointList } = useRollerStore();
32
32
33 const canBitcoin = Just.hasInstance(walletInfo.urbitWallet);
33 const canBitcoin = Just.hasInstance(walletInfo.urbitWallet);
34
34
@@ -74,11 +74,14 @@ const AccountsDropdown = ({ showMigrate = false }: AccountsDropdownProps) => {
74 return showMigrate || hasL1Points;
74 return showMigrate || hasL1Points;
75 }, [hasL1Points, showMigrate]);
75 }, [hasL1Points, showMigrate]);
76
76
77+ const displayText =
78+ point.value >= 0 ? point.patp : currentAddress.slice(0, 6);
79+
77 return (
80 return (
78 <Dropdown
81 <Dropdown
79 className="accounts-dropdown"
82 className="accounts-dropdown"
80 open={open}
83 open={open}
81− value={currentAddress.slice(0, 6)}
84+ value={displayText}
82 toggleOpen={() => setOpen(!open)}>
85 toggleOpen={() => setOpen(!open)}>
83 <CopiableAddressWrap
86 <CopiableAddressWrap
84 className="current-address"
87 className="current-address"
src/components/L2/Dropdowns/Dropdown.scss+7−1
@@ -46,8 +46,14 @@
46 background-color: white;
46 background-color: white;
47 border: 1px solid $light-gray;
47 border: 1px solid $light-gray;
48 width: 240px;
48 width: 240px;
49− max-height: 80vh;
49+ max-height: 200px;
50 overflow-y: scroll;
50 overflow-y: scroll;
51+ -ms-overflow-style: none;
52+ scrollbar-width: none;
53+
54+ &::-webkit-scrollbar {
55+ display: none;
56+ }
51 }
57 }
52 }
58 }
53}
59}
src/components/L2/Headers/L2PointHeader.tsx+2−2
@@ -60,13 +60,13 @@ const L2PointHeader = ({
60 <AccountsDropdown showMigrate={showMigrate} />
60 <AccountsDropdown showMigrate={showMigrate} />
61 </Row>
61 </Row>
62 <Row className="info">
62 <Row className="info">
63− {showInvites && point.canSpawn && (
63+ {showInvites && point.showInvites && (
64 <Row onClick={goToInvites} className="invites">
64 <Row onClick={goToInvites} className="invites">
65 <InviteIcon />
65 <InviteIcon />
66 {numInvites}
66 {numInvites}
67 </Row>
67 </Row>
68 )}
68 )}
69− {!hideTimer && point?.isL2Spawn && !pendingTransactions.length && (
69+ {!hideTimer && point.isL2Spawn && !pendingTransactions.length && (
70 <Box className="rollup-timer" onClick={goToHistory}>
70 <Box className="rollup-timer" onClick={goToHistory}>
71 {nextRoll}
71 {nextRoll}
72 </Box>
72 </Box>
src/lib/constants.ts+5
@@ -164,6 +164,9 @@ const TRANSACTION_TYPE_TITLES = {
164};
164};
165const DUMMY_L2_ADDRESS = '0x1111111111111111111111111111111111111111';
165const DUMMY_L2_ADDRESS = '0x1111111111111111111111111111111111111111';
166
166
167+const ONE_SECOND = 1000;
168+const TWO_SECONDS = 2000;
169+
167export {
170export {
168 CHECK_BLOCK_EVERY_MS,
171 CHECK_BLOCK_EVERY_MS,
169 DEFAULT_GAS_PRICE_GWEI,
172 DEFAULT_GAS_PRICE_GWEI,
@@ -203,4 +206,6 @@ export {
203 TRANSACTION_TYPE_ICONS,
206 TRANSACTION_TYPE_ICONS,
204 TRANSACTION_TYPE_TITLES,
207 TRANSACTION_TYPE_TITLES,
205 DUMMY_L2_ADDRESS,
208 DUMMY_L2_ADDRESS,
209+ ONE_SECOND,
210+ TWO_SECONDS,
206};
211};
src/lib/types/Point.ts+2−2
@@ -60,6 +60,7 @@ export default class Point {
60 canSpawn: boolean;
60 canSpawn: boolean;
61 canTransfer: boolean;
61 canTransfer: boolean;
62 canVote: boolean;
62 canVote: boolean;
63+ showInvites: boolean;
63
64
64 constructor(
65 constructor(
65 value: number,
66 value: number,
@@ -115,11 +116,10 @@ export default class Point {
115 this.networkKeysSet;
116 this.networkKeysSet;
116 this.canVote =
117 this.canVote =
117 this.isGalaxy && this.active && (this.isOwner || this.isVotingProxy);
118 this.isGalaxy && this.active && (this.isOwner || this.isVotingProxy);
118−
119 this.canMigrate =
119 this.canMigrate =
120 this.canManage &&
120 this.canManage &&
121− this.networkKeysSet &&
122 this.isL1 &&
121 this.isL1 &&
123 ((this.isGalaxy && !this.isL2Spawn) || this.isStar || this.isPlanet);
122 ((this.isGalaxy && !this.isL2Spawn) || this.isStar || this.isPlanet);
123+ this.showInvites = this.canManage || this.canSpawn;
124 }
124 }
125}
125}
src/lib/useRoller.ts+27−38
@@ -13,7 +13,11 @@ import { useNetwork } from 'store/network';
13import { usePointCursor } from 'store/pointCursor';
13import { usePointCursor } from 'store/pointCursor';
14import { EMPTY_POINT, useRollerStore } from 'store/rollerStore';
14import { EMPTY_POINT, useRollerStore } from 'store/rollerStore';
15import { useWallet } from 'store/wallet';
15import { useWallet } from 'store/wallet';
16+import {
17+ getStoredInvites,
18+ setStoredInvite,
19+ setStoredInvites,
16−import { getStoredInvites, setStoredInvites } from 'store/storage/roller';
20+} from 'store/storage/roller';
17import { usePointCache } from 'store/pointCache';
21import { usePointCache } from 'store/pointCache';
18import { getOutgoingPoints } from 'views/Points';
22import { getOutgoingPoints } from 'views/Points';
19
23
@@ -86,13 +90,14 @@ export default function useRoller() {
86 nextBatchTime,
90 nextBatchTime,
87 point,
91 point,
88 invitePoints,
92 invitePoints,
89− invites,
93+ removeInvite,
90 setNextBatchTime,
94 setNextBatchTime,
91 setPendingTransactions,
95 setPendingTransactions,
92 setInvites,
96 setInvites,
93 setInvitePoints,
97 setInvitePoints,
94 setInviteGeneratingNum,
98 setInviteGeneratingNum,
95 setPoints,
99 setPoints,
100+ updateInvite,
96 } = useRollerStore();
101 } = useRollerStore();
97 const [config, setConfig] = useState<Config | null>(null);
102 const [config, setConfig] = useState<Config | null>(null);
98
103
@@ -120,6 +125,15 @@ export default function useRoller() {
120 return new RollerRPCAPI(options);
125 return new RollerRPCAPI(options);
121 }, [options]);
126 }, [options]);
122
127
128+ const ls = useMemo(
129+ () =>
130+ new SecureLS({
131+ isCompression: false,
132+ encryptionSecret: authToken.getOrElse('default'),
133+ }),
134+ [authToken]
135+ );
136+
123 const fetchConfig = useCallback(async () => {
137 const fetchConfig = useCallback(async () => {
124 api
138 api
125 .getRollerConfig()
139 .getRollerConfig()
@@ -136,15 +150,6 @@ export default function useRoller() {
136 });
150 });
137 }, [api]); // eslint-disable-line react-hooks/exhaustive-deps
151 }, [api]); // eslint-disable-line react-hooks/exhaustive-deps
138
152
139− const ls = useMemo(
140− () =>
141− new SecureLS({
142− isCompression: false,
143− encryptionSecret: authToken.getOrElse('default'),
144− }),
145− [authToken]
146− );
147−
148 const generateInviteCodes = useCallback(
153 const generateInviteCodes = useCallback(
149 async (numInvites: number) => {
154 async (numInvites: number) => {
150 const _point = need.point(pointCursor);
155 const _point = need.point(pointCursor);
@@ -346,21 +351,20 @@ export default function useRoller() {
346 for (let i = 0; i < invitePlanets.length; i++) {
351 for (let i = 0; i < invitePlanets.length; i++) {
347 setInviteGeneratingNum(i + 1);
352 setInviteGeneratingNum(i + 1);
348 const planet = invitePlanets[i];
353 const planet = invitePlanets[i];
354+ const invite =
349− const invite = storedInvites[planet];
355+ storedInvites[planet] ||
356+ (await generateInviteInfo(planet, _authToken));
350
357
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) {
352 newInvites.push(invite);
361 newInvites.push(invite);
353− } else if (getAll) {
362+ updateInvite(invite);
354− if (isDevelopment) {
363+ setStoredInvite(ls, invite);
355− console.log('MISSING INVITE INFO', planet);
356− }
357− const newInvite = await generateInviteInfo(planet, _authToken);
358− newInvites.push(newInvite);
359 } else {
364 } else {
360− newInvites.push(inviteTemplate(planet));
365+ removeInvite(planet);
361 }
366 }
362 }
367 }
363−
364 setStoredInvites(ls, newInvites);
368 setStoredInvites(ls, newInvites);
365 setInvites(newInvites);
369 setInvites(newInvites);
366
370
@@ -379,27 +383,13 @@ export default function useRoller() {
379 pointCursor,
383 pointCursor,
380 invitePoints,
384 invitePoints,
381 ls,
385 ls,
386+ removeInvite,
382 setInvites,
387 setInvites,
383 setInviteGeneratingNum,
388 setInviteGeneratingNum,
389+ updateInvite,
384 ]
390 ]
385 );
391 );
386
392
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−
403 const getNumInvites = useCallback(
393 const getNumInvites = useCallback(
404 async (isL2: boolean) => {
394 async (isL2: boolean) => {
405 try {
395 try {
@@ -887,6 +877,5 @@ export default function useRoller() {
887 ls,
877 ls,
888 performL2Reticket,
878 performL2Reticket,
889 setProxyAddress,
879 setProxyAddress,
890− showInvite,
891 };
880 };
892}
881}
src/lib/utils/roller.ts+14−1
@@ -320,7 +320,15 @@ export const registerProxyAddress = async (
320};
320};
321
321
322const getDataAndMethod = (args: L2TransactionArgs) => {
322const 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;
324 const result: TransactionData = { data: { address }, method: () => null };
332 const result: TransactionData = { data: { address }, method: () => null };
325
333
326 switch (args.type) {
334 switch (args.type) {
@@ -353,6 +361,11 @@ const getDataAndMethod = (args: L2TransactionArgs) => {
353 };
361 };
354 result.method = api.configureKeys;
362 result.method = api.configureKeys;
355 return result;
363 return result;
364+ case 'escape':
365+ result.method = api.escape;
366+ result.data.ship = newSponsor;
367+ delete result.data.address;
368+ return result;
356 }
369 }
357};
370};
358
371
src/lib/walletgen.js+9−2
@@ -13,6 +13,9 @@ import {
13 PLANET_ENTROPY_BITS,
13 PLANET_ENTROPY_BITS,
14 ZOD,
14 ZOD,
15} from './constants';
15} from './constants';
16+import Worker from 'worker';
17+
18+const worker = new Worker();
16
19
17const SEED_LENGTH_BYTES = SEED_ENTROPY_BITS / 8;
20const SEED_LENGTH_BYTES = SEED_ENTROPY_BITS / 8;
18
21
@@ -78,9 +81,13 @@ export const generateWallet = async (point, ticket, boot) => {
78 // hangs, blocking UI updates so this cannot be done in the UI
81 // hangs, blocking UI updates so this cannot be done in the UI
79 console.log('Generating Wallet for point address: ', point);
82 console.log('Generating Wallet for point address: ', point);
80
83
84+ return new Promise(async resolve => {
85+ // Use a web worker to process the data
86+ console.log(1, config)
81− const wallet = await kg.generateWallet(config);
87+ const processed = await worker.generateWallet(JSON.stringify(config));
82
88
83− return wallet;
89+ resolve(processed);
90+ });
84};
91};
85
92
86export const generateOwnershipWallet = async (ship, ticket) => {
93export const generateOwnershipWallet = async (ship, ticket) => {
src/store/rollerStore.ts+12
@@ -18,6 +18,7 @@ export interface RollerStore {
18 invites: Invite[];
18 invites: Invite[];
19 recentlyCompleted: number;
19 recentlyCompleted: number;
20 inviteGeneratingNum: number;
20 inviteGeneratingNum: number;
21+ removeInvite: (point: number) => void;
21 setNextBatchTime: (nextBatchTime: number) => void;
22 setNextBatchTime: (nextBatchTime: number) => void;
22 setPendingTransactions: (pendingTransactions: PendingTransaction[]) => void;
23 setPendingTransactions: (pendingTransactions: PendingTransaction[]) => void;
23 setPoint: (point: number) => void;
24 setPoint: (point: number) => void;
@@ -25,6 +26,7 @@ export interface RollerStore {
25 setInvitePoints: (points: number[]) => void;
26 setInvitePoints: (points: number[]) => void;
26 setInvites: (invites: Invite[]) => void;
27 setInvites: (invites: Invite[]) => void;
27 setInviteGeneratingNum: (numGenerating: number) => void;
28 setInviteGeneratingNum: (numGenerating: number) => void;
29+ updateInvite: (invite: Invite) => void;
28}
30}
29
31
30export const useRollerStore = create<RollerStore>(set => ({
32export const useRollerStore = create<RollerStore>(set => ({
@@ -37,6 +39,10 @@ export const useRollerStore = create<RollerStore>(set => ({
37 invites: [],
39 invites: [],
38 recentlyCompleted: 0,
40 recentlyCompleted: 0,
39 inviteGeneratingNum: 0,
41 inviteGeneratingNum: 0,
42+ removeInvite: (point: number) =>
43+ set(state => ({
44+ invites: state.invites.filter(({ planet }) => point !== planet),
45+ })),
40 setNextBatchTime: (nextBatchTime: number) => set(() => ({ nextBatchTime })),
46 setNextBatchTime: (nextBatchTime: number) => set(() => ({ nextBatchTime })),
41 setPendingTransactions: (pendingTransactions: PendingTransaction[]) =>
47 setPendingTransactions: (pendingTransactions: PendingTransaction[]) =>
42 set(state => {
48 set(state => {
@@ -58,4 +64,10 @@ export const useRollerStore = create<RollerStore>(set => ({
58 setInvites: (invites: Invite[]) => set(() => ({ invites })),
64 setInvites: (invites: Invite[]) => set(() => ({ invites })),
59 setInviteGeneratingNum: (inviteGeneratingNum: number) =>
65 setInviteGeneratingNum: (inviteGeneratingNum: number) =>
60 set(() => ({ inviteGeneratingNum })),
66 set(() => ({ inviteGeneratingNum })),
67+ updateInvite: (invite: Invite) =>
68+ set(state => ({
69+ invites: state.invites.map(i =>
70+ i.planet === invite.planet ? invite : i
71+ ),
72+ })),
61}));
73}));
src/store/storage/roller.ts+10
@@ -24,6 +24,16 @@ export const setStoredInvites = (ls: SecureLS, newInvites: Invite[]) => {
24 ls.set(INVITES_KEY, invites);
24 ls.set(INVITES_KEY, invites);
25};
25};
26
26
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+
27export const clearInvitesStorage = () => localStorage.removeItem(INVITES_KEY);
37export const clearInvitesStorage = () => localStorage.removeItem(INVITES_KEY);
28
38
29export const getHideMigrationMessage = () =>
39export const getHideMigrationMessage = () =>
src/views/Invite/Cohort.tsx+16−27
@@ -5,7 +5,8 @@ import {
5 Icon,
5 Icon,
6 Row,
6 Row,
7 StatelessTextInput,
7 StatelessTextInput,
8− Button as Button2,
8+ Box,
9+ LoadingSpinner,
9} from '@tlon/indigo-react';
10} from '@tlon/indigo-react';
10
11
11import { usePointCache } from 'store/pointCache';
12import { usePointCache } from 'store/pointCache';
@@ -59,6 +60,7 @@ export default function InviteCohort() {
59 pendingTransactions,
60 pendingTransactions,
60 invites,
61 invites,
61 invitePoints,
62 invitePoints,
63+ inviteGeneratingNum,
62 setInviteGeneratingNum,
64 setInviteGeneratingNum,
63 setInvites,
65 setInvites,
64 } = useRollerStore();
66 } = useRollerStore();
@@ -70,11 +72,10 @@ export default function InviteCohort() {
70 generateInviteCodes,
72 generateInviteCodes,
71 getPendingTransactions,
73 getPendingTransactions,
72 getInvites,
74 getInvites,
73− showInvite,
74 } = useRoller();
75 } = useRoller();
75 const { contracts }: any = useNetwork();
76 const { contracts }: any = useNetwork();
76 const { syncControlledPoints }: any = usePointCache();
77 const { syncControlledPoints }: any = usePointCache();
77− const currentL2 = Boolean(point?.isL2);
78+ const currentL2 = Boolean(point?.isL2Spawn);
78
79
79 const _contracts = need.contracts(contracts);
80 const _contracts = need.contracts(contracts);
80
81
@@ -90,21 +91,9 @@ export default function InviteCohort() {
90
91
91 const { construct, unconstruct, completed, bind } = useIssueChild();
92 const { construct, unconstruct, completed, bind } = useIssueChild();
92
93
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−
105 useEffect(() => {
94 useEffect(() => {
106 if (invitePoints.length > 0) {
95 if (invitePoints.length > 0) {
107− getInvites(currentL2);
96+ getInvites(currentL2, true);
108 }
97 }
109 }, []); // eslint-disable-line react-hooks/exhaustive-deps
98 }, []); // eslint-disable-line react-hooks/exhaustive-deps
110
99
@@ -282,11 +271,12 @@ export default function InviteCohort() {
282 className="copy-invite"
271 className="copy-invite"
283 />
272 />
284 ) : (
273 ) : (
285− <Button2
286− className="secondary"
274+ <Box className="ticket-loader">
287− onClick={() => onClickShowInvite(invite.planet)}>
275+ <LoadingSpinner
288− Show Invite
276+ foreground="white"
289− </Button2>
277+ background="rgba(0,0,0,0.3)"
278+ />
279+ </Box>
290 )}
280 )}
291 </div>
281 </div>
292 ))}
282 ))}
@@ -307,7 +297,7 @@ export default function InviteCohort() {
307 <>
297 <>
308 You have no planet codes available.
298 You have no planet codes available.
309 <br />
299 <br />
310− {currentL2 && (
300+ {currentL2 && point.canSpawn && (
311 <>
301 <>
312 Generate your codes in
302 Generate your codes in
313 <br />
303 <br />
@@ -404,10 +394,9 @@ export default function InviteCohort() {
404 );
394 );
405 }
395 }
406
396
407− const showGenerateButton = !hasPending && !hasInvites;
397+ const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
398+ const showAddMoreButton = (hasInvites || hasPending) && point.canSpawn;
408− const downloadingCsvText = `Generating ${
399+ const downloadingCsvText = `Generating invite code ${inviteGeneratingNum} of ${invitePoints.length}...`;
409− invitePoints.length
410− } codes, this could take up to ${invitePoints.length * 5} seconds...`;
411
400
412 return (
401 return (
413 <View
402 <View
@@ -453,7 +442,7 @@ export default function InviteCohort() {
453 )}
442 )}
454 </BodyPane>
443 </BodyPane>
455 </Window>
444 </Window>
456− {(hasInvites || hasPending) && (
445+ {showAddMoreButton && (
457 <Button
446 <Button
458 onClick={() => setShowInviteForm(true)}
447 onClick={() => setShowInviteForm(true)}
459 className="add-more"
448 className="add-more"
src/views/UrbitID/Home.tsx+29−8
@@ -1,5 +1,5 @@
1−import React, { useCallback } from 'react';
1+import React, { useCallback, useState } from 'react';
2−import { Just } from 'folktale/maybe';
2+import { Just, Nothing } from 'folktale/maybe';
3import { Box, Button, Icon, Row } from '@tlon/indigo-react';
3import { Box, Button, Icon, Row } from '@tlon/indigo-react';
4
4
5import { useLocalRouter } from 'lib/LocalRouter';
5import { useLocalRouter } from 'lib/LocalRouter';
@@ -9,6 +9,8 @@ import useCurrentPermissions from 'lib/useCurrentPermissions';
9import { convertToInt } from 'lib/convertToInt';
9import { convertToInt } from 'lib/convertToInt';
10import { ETH_ZERO_ADDR } from 'lib/constants';
10import { ETH_ZERO_ADDR } from 'lib/constants';
11import { abbreviateAddress } from 'lib/utils/address';
11import { abbreviateAddress } from 'lib/utils/address';
12+import { downloadWallet } from 'lib/invite';
13+import useKeyfileGenerator from 'lib/useKeyfileGenerator';
12
14
13import { usePointCache } from 'store/pointCache';
15import { usePointCache } from 'store/pointCache';
14import { useWallet } from 'store/wallet';
16import { useWallet } from 'store/wallet';
@@ -18,6 +20,7 @@ import Window from 'components/L2/Window/Window';
18import HeaderPane from 'components/L2/Window/HeaderPane';
20import HeaderPane from 'components/L2/Window/HeaderPane';
19import BodyPane from 'components/L2/Window/BodyPane';
21import BodyPane from 'components/L2/Window/BodyPane';
20import CopiableWithTooltip from 'components/copiable/CopiableWithTooltip';
22import CopiableWithTooltip from 'components/copiable/CopiableWithTooltip';
23+import PaperBuilder from 'components/PaperBuilder';
21
24
22import './UrbitID.scss';
25import './UrbitID.scss';
23
26
@@ -27,10 +30,16 @@ export default function UrbitIDHome() {
27 const { urbitWallet }: any = useWallet();
30 const { urbitWallet }: any = useWallet();
28 const { point } = useRollerStore();
31 const { point } = useRollerStore();
29
32
30− const goDownloadKeys = useCallback(() => push(names.DOWNLOAD_KEYS), [
33+ const [keysDownloaded, setKeysDownloaded] = useState(false);
31− push,
34+
32− names,
35+ const _urbitWallet = need.wallet(urbitWallet);
33− ]);
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]);
34
43
35 const goSigil = useCallback(() => push(names.SIGIL_GENERATOR), [push, names]);
44 const goSigil = useCallback(() => push(names.SIGIL_GENERATOR), [push, names]);
36
45
@@ -58,8 +67,13 @@ export default function UrbitIDHome() {
58 <Row className="header-row">
67 <Row className="header-row">
59 <h5>ID</h5>
68 <h5>ID</h5>
60 {isMasterTicket && (
69 {isMasterTicket && (
61− <Button onClick={goDownloadKeys} className="header-button">
70+ <Button onClick={downloadKeys} className="header-button">
71+ {keysDownloaded
72+ ? 'Downloaded!'
73+ : paper.matchWith({
74+ Nothing: () => 'Printing and folding...',
62− Download Passport
75+ Just: (_: any) => 'Download Passport',
76+ })}
63 </Button>
77 </Button>
64 )}
78 )}
65 </Row>
79 </Row>
@@ -183,6 +197,13 @@ export default function UrbitIDHome() {
183 </Row>
197 </Row>
184 )}
198 )}
185 </BodyPane>
199 </BodyPane>
200+ <PaperBuilder
201+ point={point.value}
202+ wallets={[_urbitWallet]}
203+ callback={(paper: any) => {
204+ setPaper(Just(paper));
205+ }}
206+ />
186 </Window>
207 </Window>
187 );
208 );
188}
209}
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+}