on master help sign in
WIP: api hanging
commit70004bbb9bf9e845c1eb2ec00017263a13569d7f authorWill Galebach <willbach@gmail.com> dateWed 8 Sep 2021, 21:42 (5 years ago) parentd8aa1ca
34 files changed+579−60
src/assets/star.svg+3 src/assets/wallet.svg+3 src/components/L2/Dropdowns/AccountsDropdown.tsx+10−7 src/components/L2/Dropdowns/Dropdown.scss+2−2 src/components/L2/Headers/L2BackHeader.scss+8−3 src/components/L2/Headers/L2BackHeader.tsx+5−1 src/components/L2/Headers/L2PointHeader.scss+61−2 src/components/L2/Headers/L2PointHeader.tsx+43−2 src/components/L2/Modal.scss+14 src/components/L2/Modal.tsx+26 src/components/L2/Points/IncomingPoint.scss+1−1 src/components/MiniBackButton.scss+1−1 src/components/Passport.js+1 src/indigo-react/components/Grid.d.ts+7 src/lib/routeNames.js+1 src/lib/router.js+9−6 src/lib/useRoller.ts+5 src/lib/utils/roller.ts+2 src/store/lib/useControlledPointsStore.js+29−11 src/store/roller.ts+1−3 src/store/storage/roller.ts+7 src/style/shared/variables.scss+4−1 src/views/Invite/Cohort.js+1−1 src/views/Invite/Cohort.scss+3−3 src/views/IssueChild.js → src/views/Point/IssueChild.js src/views/Point/MigrateL2.scss+114 src/views/Point/MigrateL2.tsx+198 src/views/Point.js → src/views/Point/Point.js+2−1 src/views/Point.scss → src/views/Point/Point.scss src/views/Residents.js → src/views/Point/Residents.js src/views/Senate.js → src/views/Point/Senate.js src/views/UrbitID.js → src/views/Point/UrbitID.js+6−6 src/views/UrbitOS.js → src/views/Point/UrbitOS.js+3−3 src/views/Points.js+9−6
src/assets/star.svgnew file+3
@@ -0,0 +1,3 @@
1+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
2+<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 0.5V4.73077H6.5V0.5H7.5ZM4.80029 5.5074L2.03106 2.73817L2.73817 2.03106L5.5074 4.80029L4.80029 5.5074ZM8.4926 4.80029L11.2618 2.03106L11.9689 2.73817L9.19971 5.5074L8.4926 4.80029ZM9.26988 6.49519L13.5006 6.50065L13.4994 7.50064L9.26859 7.49519L9.26988 6.49519ZM0.5 6.49583H4.73077V7.49583H0.5V6.49583ZM5.5074 9.19971L2.73817 11.9689L2.03106 11.2618L4.80029 8.4926L5.5074 9.19971ZM11.2618 11.9689L8.4926 9.19971L9.19971 8.4926L11.9689 11.2618L11.2618 11.9689ZM7.5 9.26923V13.5H6.5V9.26923H7.5Z" fill="white"/>
3+</svg>
src/assets/wallet.svgnew file+3
@@ -0,0 +1,3 @@
1+<svg width="13" height="12" viewBox="0 0 13 12" fill="none" xmlns="http://www.w3.org/2000/svg">
2+<path d="M0.5 2V10C0.5 10.2652 0.605357 10.5196 0.792893 10.7071C0.98043 10.8946 1.23478 11 1.5 11H11.5C11.6326 11 11.7598 10.9473 11.8536 10.8536C11.9473 10.7598 12 10.6326 12 10.5V3.5C12 3.36739 11.9473 3.24021 11.8536 3.14645C11.7598 3.05268 11.6326 3 11.5 3H10M0.5 2C0.5 2.26522 0.605357 2.51957 0.792893 2.70711C0.98043 2.89464 1.23478 3 1.5 3H10M0.5 2C0.5 1.73478 0.605357 1.48043 0.792893 1.29289C0.98043 1.10536 1.23478 1 1.5 1H10V3" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
3+</svg>
src/components/L2/Dropdowns/AccountsDropdown.tsx+10−7
@@ -16,6 +16,11 @@ import Dropdown from './Dropdown';
1616import './AccountsDropdown.scss';
1717import { abbreviateAddress } from 'lib/utils/address';
1818
19+interface PointLayer {
20+ point: number;
21+ layer: 1 | 2;
22+}
23+
1924const AccountsDropdown = () => {
2025 const [open, setOpen] = useState<boolean>(false);
2126 const walletInfo: any = useWallet();
@@ -25,10 +30,8 @@ const AccountsDropdown = () => {
2530
2631 const canBitcoin = Just.hasInstance(walletInfo.urbitWallet);
2732
28− const points =
29− controlledPoints?.value?.value?.ownedPoints?.map((point: string) =>
30− Number(point)
31− ) || [];
33+ console.log('WHAT', controlledPoints)
34+ const points = controlledPoints?.value?.value?.pointsWithLayers || [];
3235
3336 const currentAddress = walletInfo?.wallet?.value?.address || '';
3437 const displayAddress = abbreviateAddress(currentAddress);
@@ -49,14 +52,14 @@ const AccountsDropdown = () => {
4952 <Dropdown
5053 className="accounts-dropdown"
5154 open={open}
52− value={displayAddress}
55+ value={currentAddress.slice(0, 6)}
5356 toggleOpen={() => setOpen(!open)}>
5457 <CopiableAddressWrap className="current-address">
5558 {displayAddress}
5659 </CopiableAddressWrap>
5760 <Box className="divider" />
5861 <Box className="points">
59− {points.map((point: number) => {
62+ {points.map(({ point, layer }: PointLayer) => {
6063 const patp = ob.patp(point);
6164
6265 return (
@@ -66,7 +69,7 @@ const AccountsDropdown = () => {
6669 key={`point-${point}`}>
6770 <Box>{patp}</Box>
6871 <Row>
69− <LayerIndicator layer={1} size="md" />
72+ <LayerIndicator layer={layer} size="md" />
7073 <Box className="sigil">
7174 <Sigil patp={patp} size={1} colors={['#000000', '#FFFFFF']} />
7275 </Box>
src/components/L2/Dropdowns/Dropdown.scss+2−2
@@ -5,7 +5,7 @@
55 position: relative;
66
77 .selector {
8− background-color: $washedGray;
8+ background-color: $washed-gray;
99 padding: 8px;
1010 min-width: 84px;
1111 border-radius: $medium-border-radius;
@@ -26,7 +26,7 @@
2626 }
2727
2828 .content-border {
29− border: 3px solid $washedGray;
29+ border: 3px solid $washed-gray;
3030 position: absolute;
3131 top: 36px;
3232 left: -3px;
src/components/L2/Headers/L2BackHeader.scss+8−3
@@ -6,13 +6,13 @@
66 justify-content: space-between;
77 align-items: center;
88 font-size: 14px;
9− margin: 48px 0px 16px;
9+ margin: 48px 0px 8px;
1010
1111 svg.back-button {
1212 padding: 6px 9px;
1313 width: 14px;
1414 height: 20px;
15− background-color: $washedGray;
15+ background-color: $washed-gray;
1616 border-radius: $medium-border-radius;
1717 cursor: pointer;
1818 }
@@ -31,6 +31,11 @@
3131 }
3232
3333 .eth-balance {
34− font-weight: 600;
34+ .wallet-icon {
35+ height: 12px;
36+ width: 14px;
37+ margin-right: 4px;
38+ margin-top: 2px;
39+ }
3540 }
3641}
src/components/L2/Headers/L2BackHeader.tsx+5−1
@@ -11,6 +11,7 @@ import { useWallet } from 'store/wallet';
1111import { toBN } from 'web3-utils';
1212import BN from 'bn.js';
1313import { isDevelopment } from 'lib/flags';
14+import { ReactComponent as Wallet } from 'assets/wallet.svg';
1415
1516export interface L2BackHeaderProps {
1617 back?: () => void;
@@ -66,7 +67,10 @@ const L2BackHeader = ({ back, hideBalance = false }: L2BackHeaderProps) => {
6667 </Row>
6768 ) : (
6869 !hideBalance && (
69− <Box className="eth-balance">Balance: {Number(ethBalance)} ETH</Box>
70+ <Row className="eth-balance">
71+ <Wallet className="wallet-icon" />
72+ <Box>{ethBalance.toString()} ETH</Box>
73+ </Row>
7074 )
7175 )}
7276 </Row>
src/components/L2/Headers/L2PointHeader.scss+61−2
@@ -10,7 +10,7 @@
1010
1111 .dropdown {
1212 border-radius: $medium-border-radius;
13− background-color: $washedGray;
13+ background-color: $washed-gray;
1414 }
1515
1616 .info {
@@ -28,7 +28,7 @@
2828 }
2929
3030 .invites, .history {
31− background-color: $washedGray;
31+ background-color: $washed-gray;
3232 padding: 8px;
3333 }
3434
@@ -47,4 +47,63 @@
4747 width: 90px;
4848 }
4949 }
50+
51+ .migrate-modal {
52+ padding: 16px;
53+ background-color: white;
54+ border-radius: $medium-border-radius;
55+ line-height: 24px;
56+ position: relative;
57+ width: 368px;
58+
59+ .close {
60+ position: absolute;
61+ top: 3px;
62+ right: 8px;
63+ font-size: 18px;
64+ font-weight: 200;
65+ cursor: pointer;
66+ }
67+
68+ .title {
69+ font-weight: 700;
70+ }
71+
72+ .message {
73+ width: 340px;
74+ }
75+
76+ .warning {
77+ font-weight: 600;
78+ color: $warning-red;
79+ }
80+
81+ .buttons {
82+ display: flex;
83+ flex-direction: row;
84+ justify-content: flex-end;
85+ margin-top: 24px;
86+
87+ .cancel, .migrate {
88+ border-radius: $medium-border-radius;
89+ border: none;
90+ height: 32px;
91+ font-family: $default-font;
92+
93+ &:hover {
94+ opacity: 0.8;
95+ }
96+ }
97+
98+ .cancel {
99+ margin-right: 8px;
100+ background-color: $washed-gray;
101+ }
102+
103+ .migrate {
104+ background-color: black;
105+ color: white;
106+ }
107+ }
108+ }
50109}
src/components/L2/Headers/L2PointHeader.tsx+43−2
@@ -1,15 +1,18 @@
1−import React, { useEffect, useCallback } from 'react';
2−import { Box, Row } from '@tlon/indigo-react';
1+import React, { useEffect, useCallback, useState } from 'react';
2+import { azimuth } from 'azimuth-js';
3+import { Box, Button, Icon, Row } from '@tlon/indigo-react';
34
45import useRoller from 'lib/useRoller';
56import { useHistory } from 'store/history';
67import { ReactComponent as InviteIcon } from 'assets/invite.svg';
78import { ReactComponent as HistoryIcon } from 'assets/history.svg';
89import AccountsDropdown from '../Dropdowns/AccountsDropdown';
10+import Modal from '../Modal';
911import { useRollerStore } from 'store/roller';
1012
1113import './L2PointHeader.scss';
1214import { isDevelopment } from 'lib/flags';
15+import { usePointCursor } from 'store/pointCursor';
1316
1417export interface L2PointHeaderProps {
1518 numInvites: number;
@@ -24,6 +27,8 @@ const L2PointHeader = ({
2427}: L2PointHeaderProps) => {
2528 const { config } = useRoller();
2629 const { nextRoll, currentL2, pendingTransactions } = useRollerStore();
30+ const { pointCursor }: any = usePointCursor();
31+ const [showModal, setShowModal] = useState(false);
2732
2833 useEffect(() => {
2934 if (isDevelopment) {
@@ -41,6 +46,14 @@ const L2PointHeader = ({
4146 names.TRANSACTION_HISTORY,
4247 push,
4348 ]);
49+ const goMigrate = useCallback(() => push(names.MIGRATE_L2), [
50+ names.MIGRATE_L2,
51+ push,
52+ ]);
53+
54+ const isStar =
55+ pointCursor?.value &&
56+ azimuth.getPointSize(pointCursor?.value) === azimuth.PointSize.Star;
4457
4558 return (
4659 <Row className="l2-point-header">
@@ -58,7 +71,35 @@ const L2PointHeader = ({
5871 </Box>
5972 )}
6073 {currentL2 && <HistoryIcon className="history" onClick={goToHistory} />}
74+ {!currentL2 && isStar && (
75+ <Icon
76+ icon="Swap"
77+ className="history"
78+ onClick={() => setShowModal(true)}
79+ />
80+ )}
6181 </Row>
82+ <Modal show={showModal} hide={() => setShowModal(false)}>
83+ <Box className="migrate-modal">
84+ <Box className="close" onClick={() => setShowModal(false)}>
85+ &#215;
86+ </Box>
87+ <Box className="title">Migrating to Layer 2</Box>
88+ <Box className="message">
89+ We've upgraded Bridge to support Layer 2 transactions. If you don't
90+ migrate now, you can always do it later.
91+ </Box>
92+ <Box className="warning">Migrating to Layer 2 is irreversible.</Box>
93+ <Row className="buttons">
94+ <Button className="cancel" onClick={() => setShowModal(false)}>
95+ Cancel
96+ </Button>
97+ <Button className="migrate" onClick={goMigrate}>
98+ Migrate
99+ </Button>
100+ </Row>
101+ </Box>
102+ </Modal>
62103 </Row>
63104 );
64105};
src/components/L2/Modal.scssnew file+14
@@ -0,0 +1,14 @@
1+@import 'style/shared/variables.scss';
2+
3+.modal {
4+ background-color: rgba(0,0,0,0.2);
5+ position: fixed;
6+ top: 0;
7+ bottom: 0;
8+ left: 0;
9+ right: 0;
10+ display: flex;
11+ flex-direction: column;
12+ justify-content: center;
13+ align-items: center;
14+}
src/components/L2/Modal.tsxnew file+26
@@ -0,0 +1,26 @@
1+import React, { MouseEvent } from 'react';
2+import { Box } from '@tlon/indigo-react';
3+
4+import './Modal.scss';
5+
6+export interface ModalProps {
7+ show: boolean;
8+ hide: () => void;
9+ children: React.ReactNode;
10+}
11+
12+export default function Modal({ show, hide, children }: ModalProps) {
13+ const dontHide = (e: MouseEvent) => {
14+ e.stopPropagation();
15+ };
16+
17+ if (!show) {
18+ return null;
19+ }
20+
21+ return (
22+ <Box className="modal" onClick={hide}>
23+ <Box onClick={dontHide}>{children}</Box>
24+ </Box>
25+ );
26+}
src/components/L2/Points/IncomingPoint.scss+1−1
@@ -42,6 +42,6 @@
4242 }
4343
4444 .reject {
45− background-color: $washedGray;
45+ background-color: $washed-gray;
4646 }
4747}
src/components/MiniBackButton.scss+1−1
@@ -4,7 +4,7 @@ svg.back-button {
44 padding: 6px 9px;
55 width: 14px;
66 height: 20px;
7− background-color: $washedGray;
7+ background-color: $washed-gray;
88 border-radius: $medium-border-radius;
99 cursor: pointer;
1010}
src/components/Passport.js+1
@@ -170,6 +170,7 @@ function Passport({
170170 inverted={inverted}
171171 loading={loading}
172172 animationMode={animationMode}
173+ key={`cell-${_col}`}
173174 />
174175 );
175176 })}
src/indigo-react/components/Grid.d.tsnew file+7
@@ -0,0 +1,7 @@
1+import React from 'react';
2+
3+const Grid = {
4+ Item: React.ReactNode,
5+}
6+
7+export default Grid;
src/lib/routeNames.js+1
@@ -34,4 +34,5 @@ export const ROUTE_NAMES = {
3434 BITCOIN_XPUB: Symbol('BITCOIN_XPUB'),
3535 BITCOIN_SIGN_TRANSACTION: Symbol('BITCOIN_SIGN_TRANSACTION'),
3636 TRANSACTION_HISTORY: Symbol('TRANSACTION_HISTORY'),
37+ MIGRATE_L2: Symbol('MIGRATE_L2'),
3738};
src/lib/router.js+9−6
@@ -1,25 +1,27 @@
11import Disclaimer from 'views/Disclaimer';
22import Login from 'views/Login';
33import Other from 'views/Login/Other.js';
4−import Senate from 'views/Senate';
4+import Senate from 'views/Point/Senate';
55import Documents from 'views/Senate/Documents';
66import Upgrades from 'views/Senate/Upgrades';
77import CreateGalaxy from 'views/CreateGalaxy';
8−import IssueChild from 'views/IssueChild';
98import StarRelease from 'views/Release';
109import AcceptLockup from 'views/AcceptLockup';
1110
12−import Point from 'views/Point';
1311import Points from 'views/Points';
1412import Activate from 'views/Activate';
1513
14+import Point from 'views/Point/Point';
15+import UrbitOS from 'views/Point/UrbitOS';
16+import UrbitID from 'views/Point/UrbitID';
17+import Residents from 'views/Point/Residents';
18+import MigrateL2 from 'views/Point/MigrateL2.tsx';
19+import IssueChild from 'views/Point/IssueChild';
20+
1621import PartySetPoolSize from 'views/Party/PartySetPoolSize';
1722import InviteCohort from 'views/Invite/Cohort';
1823import AcceptTransfer from 'views/AcceptTransfer';
1924import CancelTransfer from 'views/CancelTransfer';
20−import UrbitOS from 'views/UrbitOS';
21−import UrbitID from 'views/UrbitID';
22−import Residents from 'views/Residents';
2325import Adopt from 'views/Adopt';
2426import Bitcoin from 'views/Bitcoin/Bitcoin';
2527import Xpub from 'views/Bitcoin/Xpub';
@@ -56,4 +58,5 @@ export const ROUTES = {
5658 [ROUTE_NAMES.BITCOIN_XPUB]: Xpub,
5759 [ROUTE_NAMES.BITCOIN_SIGN_TRANSACTION]: SignTransaction,
5860 [ROUTE_NAMES.TRANSACTION_HISTORY]: TransactionHistory,
61+ [ROUTE_NAMES.MIGRATE_L2]: MigrateL2,
5962};
src/lib/useRoller.ts+5
@@ -344,6 +344,10 @@ export default function useRoller() {
344344 ]
345345 );
346346
347+ const migratePoint = useCallback(async () => {
348+ console.log('MIGRATING')
349+ }, []);
350+
347351 // On load, get initial config
348352 useEffect(() => {
349353 if (config) {
@@ -377,5 +381,6 @@ export default function useRoller() {
377381 getInvites,
378382 getPendingTransactions,
379383 generateInviteCodes,
384+ migratePoint,
380385 };
381386}
src/lib/utils/roller.ts+2
@@ -14,3 +14,5 @@ export const getTimeToNextBatch = (nextBatch: number, now: number) => {
1414
1515 return `${hours}h ${padZero(minutes)}m ${padZero(seconds)}s`;
1616};
17+
18+export const isL2 = (dom?: string) => dom === 'l2' || dom === 'spawn';
src/store/lib/useControlledPointsStore.js+29−11
@@ -6,13 +6,14 @@ import * as azimuth from 'azimuth-js';
66import { useNetwork } from '../network';
77import { useWallet } from 'store/wallet';
88import useRoller from 'lib/useRoller';
9+import { isL2 } from 'lib/utils/roller';
910
1011const onlyUnique = (value, index, self) => self.indexOf(value) === index;
1112
1213export default function useControlledPointsStore() {
1314 const { contracts } = useNetwork();
1415 const { wallet } = useWallet();
15− const { getPoints } = useRoller();
16+ const { api, getPoints } = useRoller();
1617
1718 const [controlledPoints, _setControlledPoints] = useState(Nothing());
1819
@@ -34,21 +35,17 @@ export default function useControlledPointsStore() {
3435 managingPoints,
3536 votingPoints,
3637 spawningPoints,
37− ] = await Promise.all([
38− getPoints('own', address),
39− getPoints('transfer', address),
40− getPoints('manage', address),
41− getPoints('vote', address),
42− getPoints('spawn', address),
43− ]);
44−
45− const [
4638 ownedPointsL1,
4739 incomingPointsL1,
4840 managingPointsL1,
4941 votingPointsL1,
5042 spawningPointsL1,
5143 ] = await Promise.all([
44+ getPoints('own', address),
45+ getPoints('transfer', address),
46+ getPoints('manage', address),
47+ getPoints('vote', address),
48+ getPoints('spawn', address),
5249 azimuth.azimuth.getOwnedPoints(_contracts, address),
5350 azimuth.azimuth.getTransferringFor(_contracts, address),
5451 azimuth.azimuth.getManagerFor(_contracts, address),
@@ -56,6 +53,26 @@ export default function useControlledPointsStore() {
5653 azimuth.azimuth.getSpawningFor(_contracts, address),
5754 ]);
5855
56+ console.log(1)
57+ const pointsWithLayers = await Promise.all(
58+ ownedPoints.map(async ship => {
59+ console.log(2)
60+ try {
61+ const pointInfo = await api.getPoint(Number(ship));
62+ console.log(3, pointInfo)
63+ return {
64+ point: Number(ship),
65+ layer: isL2(pointInfo?.dominion) ? 1 : 2,
66+ };
67+ } catch (error) {
68+ console.warn(error)
69+ return { point: ship, layer: 1 };
70+ }
71+ })
72+ );
73+
74+ console.log(4, pointsWithLayers)
75+
5976 if (
6077 ownedPoints === null &&
6178 incomingPoints === null &&
@@ -90,6 +107,7 @@ export default function useControlledPointsStore() {
90107 .concat(spawningPointsL1)
91108 .map(Number)
92109 .filter(onlyUnique),
110+ pointsWithLayers,
93111 })
94112 )
95113 );
@@ -98,7 +116,7 @@ export default function useControlledPointsStore() {
98116 console.error('failed to fetch controlled points', error);
99117 _setControlledPoints(Just(Result.Error(error)));
100118 }
101− }, [contracts, wallet, getPoints]);
119+ }, [contracts, wallet, getPoints, api]);
102120
103121 // sync controlled points whenever wallet or contracts changes
104122 useEffect(() => {
src/store/roller.ts+1−3
@@ -1,11 +1,9 @@
11import create from 'zustand';
22import { L2Point, PendingTransaction } from '@urbit/roller-api/build';
33
4−import { HOUR } from 'lib/utils/roller';
4+import { HOUR, isL2 } from 'lib/utils/roller';
55import { Invite } from 'types/Invite';
66
7−export const isL2 = (dom?: string) => dom === 'l2' || dom === 'spawn';
8−
97export interface RollerStore {
108 nextBatchTime: number;
119 nextRoll: string;
src/store/storage/roller.ts+7
@@ -1,6 +1,7 @@
11import { Invite } from 'types/Invite';
22
33const INVITES_KEY = 'invites';
4+const HIDE_MIGRATION_MESSAGE_KEY = 'hide_migration_message';
45
56export interface StoredInvites {
67 available: Invite[];
@@ -32,3 +33,9 @@ export const setPendingInvites = (point: number, pendingInvites: Invite[]) => {
3233};
3334
3435export const clearInvitesStorage = () => localStorage.removeItem(INVITES_KEY);
36+
37+export const getHideMigrationMessage = () =>
38+ Boolean(localStorage.getItem(HIDE_MIGRATION_MESSAGE_KEY));
39+
40+export const storeHideMigrationMessage = () =>
41+ localStorage.setItem(HIDE_MIGRATION_MESSAGE_KEY, 'true');
src/style/shared/variables.scss+4−1
@@ -1,4 +1,6 @@
1−$washedGray: rgba(0, 0, 0, 0.04);
1+$default-font: "Inter", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji";
2+
3+$washed-gray: rgba(0, 0, 0, 0.04);
24$small-border-radius: 2px;
35$medium-border-radius: 4px;
46$large-border-radius: 8px;
@@ -8,3 +10,4 @@ $mid-gray: rgba(0, 0, 0, 0.6);
810$dark-gray: rgba(102, 102, 102, 1);
911$rollup-yellow: rgba(255, 199, 0, 1);
1012$accept-green: rgba(0, 159, 101, 1);
13+$warning-red: rgb(242, 33, 33);
src/views/Invite/Cohort.js+1−1
@@ -17,7 +17,7 @@ import useRoller from 'lib/useRoller';
1717import { convertToInt } from 'lib/convertToInt';
1818import { generateUrl } from 'lib/utils/invite';
1919
20−import { useIssueChild } from 'views/IssueChild';
20+import { useIssueChild } from 'views/Point/IssueChild';
2121import View from 'components/View';
2222import L2BackHeader from 'components/L2/Headers/L2BackHeader';
2323import Window from 'components/L2/Window/Window';
src/views/Invite/Cohort.scss+3−3
@@ -12,7 +12,7 @@
1212
1313 .download-csv {
1414 padding: 6px 12px;
15− background-color: $washedGray;
15+ background-color: $washed-gray;
1616 border-radius: $medium-border-radius;
1717 display: flex;
1818 flex-direction: row;
@@ -72,7 +72,7 @@
7272 }
7373
7474 .invite-url {
75− background-color: $washedGray;
75+ background-color: $washed-gray;
7676 border-radius: $medium-border-radius;
7777 border: 1px solid $light-gray;
7878 width: 390px;
@@ -80,7 +80,7 @@
8080 }
8181
8282 .copy-invite {
83− background-color: $washedGray;
83+ background-color: $washed-gray;
8484 border-radius: $medium-border-radius;
8585 width: 32px;
8686 height: 32px;
src/views/IssueChild.js → src/views/Point/IssueChild.jsrenamed

The content is the same.

src/views/Point/MigrateL2.scssnew file+114
@@ -0,0 +1,114 @@
1+@import 'style/shared/variables.scss';
2+
3+.migrate-l2 {
4+ font-size: 14px;
5+
6+ .content {
7+ padding: 0 8px;
8+ line-height: 24px;
9+ display: flex;
10+ flex-direction: column;
11+ justify-content: space-between;
12+ min-height: 400px;
13+ width: 100%;
14+
15+ .bold {
16+ font-weight: 600;
17+ }
18+
19+ .info-list {
20+ margin: 40px 0;
21+
22+ .info-row {
23+ margin-bottom: 24px;
24+ width: 370px;
25+
26+ .icon-background {
27+ width: 24px;
28+ min-width: 24px;
29+ height: 24px;
30+ background-color: black;
31+ border-radius: 12px;
32+ display: flex;
33+ flex-direction: column;
34+ justify-content: center;
35+ align-items: center;
36+
37+ .icon {
38+ width: 14px;
39+ height: 14px;
40+ font-size: 14px;
41+ line-height: 14px;
42+ color: white;
43+ text-align: center;
44+ }
45+ }
46+
47+ .info-message {
48+ margin-left: 16px;
49+ }
50+
51+ .warning {
52+ color: $warning-red;
53+ font-weight: 600;
54+ }
55+ }
56+ }
57+
58+ .hide-row {
59+ display: flex;
60+ flex-direction: row;
61+ align-items: center;
62+
63+ .checkbox {
64+ height: 16px;
65+ width: 16px;
66+
67+ svg {
68+ width: 16px;
69+ height: 16px;
70+ color: white;
71+ }
72+ }
73+
74+ .dont-show {
75+ margin-left: 8px;
76+ font-weight: 600;
77+ }
78+ }
79+
80+ .buttons {
81+ display: flex;
82+ flex-direction: row;
83+ justify-content: flex-end;
84+ margin-top: 16px;
85+
86+ .cancel, .proceed {
87+ border-radius: $medium-border-radius;
88+ border: none;
89+ height: 32px;
90+ font-family: $default-font;
91+
92+ &:hover {
93+ opacity: 0.8;
94+ }
95+ }
96+
97+ .cancel {
98+ margin-right: 8px;
99+ background-color: $washed-gray;
100+ }
101+
102+ .proceed {
103+ background-color: black;
104+ color: white;
105+ }
106+ }
107+
108+ .ship-selector {
109+ .select-ship {
110+ color: $mid-gray;
111+ }
112+ }
113+ }
114+}
src/views/Point/MigrateL2.tsxnew file+198
@@ -0,0 +1,198 @@
1+import React, { useState, useEffect, useCallback } from 'react';
2+import { Grid } from 'indigo-react';
3+import * as azimuth from 'azimuth-js';
4+
5+import View from 'components/View';
6+import L2BackHeader from 'components/L2/Headers/L2BackHeader';
7+import BodyPane from 'components/L2/Window/BodyPane';
8+import HeaderPane from 'components/L2/Window/HeaderPane';
9+import Window from 'components/L2/Window/Window';
10+import { ReactComponent as StarIcon } from 'assets/star.svg';
11+
12+import { useLocalRouter } from 'lib/LocalRouter';
13+import * as need from 'lib/need';
14+
15+import { usePointCursor } from 'store/pointCursor';
16+
17+import './MigrateL2.scss';
18+import { Box, Button, Checkbox, Icon, Row } from '@tlon/indigo-react';
19+import {
20+ getHideMigrationMessage,
21+ storeHideMigrationMessage,
22+} from 'store/storage/roller';
23+import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
24+import { useNetwork } from 'store/network';
25+import { usePointCache } from 'store/pointCache';
26+import useEthereumTransaction from 'lib/useEthereumTransaction';
27+import { GAS_LIMITS } from 'lib/constants';
28+
29+const DUMMY_L2_ADDRESS = '0x1111111111111111111111111111111111111111';
30+
31+const useMigrate = () => {
32+ const { contracts }: any = useNetwork();
33+ const { syncDates }: any = usePointCache();
34+
35+ const _contracts = need.contracts(contracts);
36+
37+ const [selectedPoint, setSelectedPoint] = useState<number | null>(null);
38+
39+ return useEthereumTransaction(
40+ useCallback(
41+ (selectedPoint: number) => {
42+ setSelectedPoint(selectedPoint);
43+ return azimuth.ecliptic.setSpawnProxy(
44+ _contracts,
45+ selectedPoint,
46+ DUMMY_L2_ADDRESS
47+ );
48+ },
49+ [_contracts]
50+ ),
51+ useCallback(() => syncDates(selectedPoint), [selectedPoint, syncDates]),
52+ GAS_LIMITS.DEFAULT
53+ );
54+};
55+
56+export default function MigrateL2() {
57+ const { pop }: any = useLocalRouter();
58+
59+ const [proceed, setProceed] = useState(false);
60+ const [hideMessage, setHideMessage] = useState(false);
61+ const hideInfo = getHideMigrationMessage();
62+
63+ const { pointCursor }: any = usePointCursor();
64+ const point = need.point(pointCursor);
65+
66+ const { construct, unconstruct, completed, bind } = useMigrate();
67+
68+ useEffect(() => {
69+ if (point) {
70+ construct(point);
71+ } else {
72+ unconstruct();
73+ }
74+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
75+
76+ useEffect(() => {
77+ if (completed) {
78+ pop();
79+ }
80+ }, [completed, pop]);
81+
82+ const goBack = useCallback(() => {
83+ if (proceed) {
84+ setProceed(false);
85+ } else {
86+ pop();
87+ }
88+ }, [pop, proceed, setProceed]);
89+
90+ const goProceed = useCallback(() => {
91+ if (hideMessage) {
92+ storeHideMigrationMessage();
93+ }
94+
95+ setProceed(true);
96+ }, [hideMessage]);
97+
98+ const getContent = () => {
99+ if (proceed) {
100+ return (
101+ <Box className="content">
102+ <Box className="ship-selector">
103+ <Box>Ship</Box>
104+ <Box className="select-ship">Select one of your ships</Box>
105+
106+ </Box>
107+ <Grid.Item
108+ full
109+ as={InlineEthereumTransaction}
110+ label="Migrate"
111+ {...bind}
112+ onReturn={pop}
113+ />
114+ </Box>
115+ );
116+ }
117+
118+ return (
119+ <Box className="content">
120+ <Box className="message">
121+ You are about to migrate a node from Layer 1 to Layer 2. This will
122+ make transactions faster and cheaper. Here are some things you should
123+ know. <span className="bold">Learn More</span>
124+ </Box>
125+ {!hideInfo && (
126+ <Box className="info-list">
127+ <Row className="info-row">
128+ <Box className="icon-background">
129+ <StarIcon className="icon" />
130+ </Box>
131+ <Box className="info-message">
132+ <span className="warning">
133+ Migration to Layer 2 is irreversible
134+ </span>
135+ {'. '}
136+ You will not be able to revert back to Layer 1.
137+ </Box>
138+ </Row>
139+ <Row className="info-row">
140+ <Box className="icon-background">
141+ <Box className="icon">$</Box>
142+ </Box>
143+ <Box className="info-message">
144+ A migration is expensive, but a one-time fee. The estimated
145+ price is <span className="bold">$120</span>. Transaction fees
146+ will be subsidized on Layer 2.
147+ </Box>
148+ </Row>
149+ <Row className="info-row">
150+ <Box className="icon-background">
151+ <Icon icon="Clock" className="icon" color="white" />
152+ </Box>
153+ {/* <HistoryIcon className="icon" /> */}
154+ <Box className="info-message">
155+ All transactions will now be pushed at the end of the day. A
156+ timer will show when the next push is.
157+ </Box>
158+ </Row>
159+ </Box>
160+ )}
161+ {!hideInfo && (
162+ <Row className="hide-row">
163+ <Checkbox
164+ className="checkbox"
165+ selected={hideMessage}
166+ onClick={() => setHideMessage(!hideMessage)}
167+ />
168+ <Box className="dont-show">Do not show this again</Box>
169+ </Row>
170+ )}
171+ <Row className="buttons">
172+ <Button className="cancel" onClick={goBack}>
173+ Cancel
174+ </Button>
175+ <Button className="proceed" onClick={goProceed}>
176+ Proceed
177+ </Button>
178+ </Row>
179+ </Box>
180+ );
181+ };
182+
183+ return (
184+ <View
185+ className="migrate-l2"
186+ pop={pop}
187+ hideBack
188+ inset
189+ header={<L2BackHeader back={goBack} />}>
190+ <Window>
191+ <HeaderPane>
192+ <h5>Migrating to Layer 2</h5>
193+ </HeaderPane>
194+ <BodyPane>{getContent()}</BodyPane>
195+ </Window>
196+ </View>
197+ );
198+}
src/views/Point.js → src/views/Point/Point.jsrenamed+2−1
@@ -7,7 +7,7 @@ import { azimuth } from 'azimuth-js';
77
88import { usePointCursor } from 'store/pointCursor';
99import { useWallet } from 'store/wallet';
10−import { isL2, useRollerStore } from 'store/roller';
10+import { useRollerStore } from 'store/roller';
1111
1212import View from 'components/View';
1313import Greeting from 'components/Greeting';
@@ -30,6 +30,7 @@ import Inviter from 'views/Invite/Inviter';
3030import useRoller from 'lib/useRoller';
3131
3232import './Point.scss';
33+import { isL2 } from 'lib/utils/roller';
3334
3435function InviteForm({
3536 showInviteForm,
src/views/Point.scss → src/views/Point/Point.scssrenamed

The content is the same.

src/views/Residents.js → src/views/Point/Residents.jsrenamed

The content is the same.

src/views/Senate.js → src/views/Point/Senate.jsrenamed

The content is the same.

src/views/UrbitID.js → src/views/Point/UrbitID.jsrenamed+6−6
@@ -11,12 +11,12 @@ import View from 'components/View';
1111import Crumbs from 'components/Crumbs';
1212import NavHeader from 'components/NavHeader';
1313
14−import UrbitIDHome from './UrbitID/Home';
15−import SigilGenerator from './UrbitID/SigilGenerator';
16−import DownloadKeys from './UrbitID/DownloadKeys';
17−import SetProxy from './UrbitID/SetProxy';
18−import ResetKeys from './UrbitID/ResetKeys';
19−import Transfer from './UrbitID/Transfer';
14+import UrbitIDHome from '../UrbitID/Home';
15+import SigilGenerator from '../UrbitID/SigilGenerator';
16+import DownloadKeys from '../UrbitID/DownloadKeys';
17+import SetProxy from '../UrbitID/SetProxy';
18+import ResetKeys from '../UrbitID/ResetKeys';
19+import Transfer from '../UrbitID/Transfer';
2020
2121const NAMES = {
2222 HOME: 'HOME',
src/views/UrbitOS.js → src/views/Point/UrbitOS.jsrenamed+3−3
@@ -11,9 +11,9 @@ import View from 'components/View';
1111import Crumbs from 'components/Crumbs';
1212import NavHeader from 'components/NavHeader';
1313
14−import UrbitOSHome from './UrbitOS/Home';
15−import UrbitOSNetworkingKeys from './UrbitOS/NetworkingKeys';
16−import UrbitOSChangeSponsor from './UrbitOS/ChangeSponsor';
14+import UrbitOSHome from '../UrbitOS/Home';
15+import UrbitOSNetworkingKeys from '../UrbitOS/NetworkingKeys';
16+import UrbitOSChangeSponsor from '../UrbitOS/ChangeSponsor';
1717
1818const NAMES = {
1919 HOME: 'HOME',
src/views/Points.js+9−6
@@ -26,7 +26,7 @@ import CopiableAddress from 'components/copiable/CopiableAddress';
2626import NavHeader from 'components/NavHeader';
2727import L2PointHeader from 'components/L2/Headers/L2PointHeader';
2828import IncomingPoint from 'components/L2/Points/IncomingPoint';
29−import { CONDITIONAL_STAR_RELEASE, LINEAR_STAR_RELEASE } from 'lib/constants';
29+import { useNetwork } from 'store/network';
3030
3131export const maybeGetResult = (obj, key, defaultValue) =>
3232 obj.matchWith({
@@ -66,9 +66,9 @@ export const getOutgoingPoints = (controlledPoints, getDetails) => {
6666 .getOrElse([]);
6767};
6868
69−export const isLocked = details =>
70− details.owner === LINEAR_STAR_RELEASE ||
71− details.owner === CONDITIONAL_STAR_RELEASE;
69+export const isLocked = (details, contracts) =>
70+ details.owner === contracts.linearSR ||
71+ details.owner === contracts.conditionalSR;
7272
7373const PointList = function({
7474 points,
@@ -131,6 +131,7 @@ export default function Points() {
131131 const { pop, push, popAndPush, names } = useHistory();
132132 const { setPointCursor } = usePointCursor();
133133 const { controlledPoints, getDetails } = usePointCache();
134+ const { contracts } = useNetwork();
134135 const isEclipticOwner = useIsEclipticOwner();
135136 const [
136137 rejectedPoints,
@@ -143,6 +144,8 @@ export default function Points() {
143144 [getDetails, controlledPoints]
144145 );
145146
147+ const _contracts = need.contracts(contracts);
148+
146149 const maybeLockedPoints = useMemo(
147150 () =>
148151 controlledPoints.chain(points =>
@@ -151,7 +154,7 @@ export default function Points() {
151154 Ok: c => {
152155 const points = c.value.ownedPoints.map(point =>
153156 getDetails(point).chain(details =>
154− Just({ point, has: isLocked(details) })
157+ Just({ point, has: isLocked(details, _contracts) })
155158 )
156159 );
157160 // if we have details for every point,
@@ -167,7 +170,7 @@ export default function Points() {
167170 },
168171 })
169172 ),
170− [getDetails, controlledPoints]
173+ [getDetails, controlledPoints, _contracts]
171174 );
172175
173176 // if we can only interact with a single point, forget about the existence