on master help sign in
Added more info for point transfer
dd5f6efWill Galebach
src/components/L2/Dropdowns/AccountsDropdown.tsx+4−1
@@ -8,6 +8,7 @@ import { Just } from 'folktale/maybe';
8import Sigil from 'components/Sigil';
8import Sigil from 'components/Sigil';
9import LayerIndicator from 'components/L2/LayerIndicator';
9import LayerIndicator from 'components/L2/LayerIndicator';
10import CopiableAddressWrap from 'components/copiable/CopiableAddressWrap';
10import CopiableAddressWrap from 'components/copiable/CopiableAddressWrap';
11+import { TooltipPosition } from 'components/WithTooltip';
11
12
12import { useWallet } from 'store/wallet';
13import { useWallet } from 'store/wallet';
13import { useHistory } from 'store/history';
14import { useHistory } from 'store/history';
@@ -88,7 +89,9 @@ const AccountsDropdown = ({ showMigrate = false }: AccountsDropdownProps) => {
88 open={open}
89 open={open}
89 value={currentAddress.slice(0, 6)}
90 value={currentAddress.slice(0, 6)}
90 toggleOpen={() => setOpen(!open)}>
91 toggleOpen={() => setOpen(!open)}>
92+ <CopiableAddressWrap
91− <CopiableAddressWrap className="current-address">
93+ className="current-address"
94+ position={TooltipPosition.Left}>
92 {displayAddress}
95 {displayAddress}
93 </CopiableAddressWrap>
96 </CopiableAddressWrap>
94 <Box className="divider" />
97 <Box className="divider" />
src/components/L2/Headers/L2PointHeader.tsx+3−5
@@ -1,5 +1,4 @@
1import React, { useEffect, useCallback } from 'react';
1import React, { useEffect, useCallback } from 'react';
2−import { azimuth } from 'azimuth-js';
3import { Box, Row } from '@tlon/indigo-react';
2import { Box, Row } from '@tlon/indigo-react';
4
3
5import useRoller from 'lib/useRoller';
4import useRoller from 'lib/useRoller';
@@ -12,6 +11,7 @@ import { useRollerStore } from 'store/roller';
12import './L2PointHeader.scss';
11import './L2PointHeader.scss';
13import { isDevelopment } from 'lib/flags';
12import { isDevelopment } from 'lib/flags';
14import { usePointCursor } from 'store/pointCursor';
13import { usePointCursor } from 'store/pointCursor';
14+import { isStar } from 'lib/utils/point';
15
15
16export interface L2PointHeaderProps {
16export interface L2PointHeaderProps {
17 numInvites: number;
17 numInvites: number;
@@ -47,15 +47,13 @@ const L2PointHeader = ({
47 push,
47 push,
48 ]);
48 ]);
49
49
50− const isStar =
51− pointCursor?.value &&
50+ const star = pointCursor?.value && isStar(pointCursor.value);
52− azimuth.getPointSize(pointCursor?.value) === azimuth.PointSize.Star;
53
51
54 return (
52 return (
55 <Row className="l2-point-header">
53 <Row className="l2-point-header">
56 <AccountsDropdown showMigrate={showMigrate} />
54 <AccountsDropdown showMigrate={showMigrate} />
57 <Row className="info">
55 <Row className="info">
58− {!hideInvites && isStar && (
56+ {!hideInvites && star && (
59 <Row onClick={goToInvites} className="invites">
57 <Row onClick={goToInvites} className="invites">
60 <InviteIcon />
58 <InviteIcon />
61 {numInvites}
59 {numInvites}
src/components/Passport.js+4−5
@@ -216,12 +216,11 @@ const Cell = props => {
216 */
216 */
217function MiniPassport({ point, inverted, locked = false, ...rest }) {
217function MiniPassport({ point, inverted, locked = false, ...rest }) {
218 useSyncDetails([point]);
218 useSyncDetails([point]);
219− const { wallet } = useWallet();
219+ // const { wallet } = useWallet();
220− const address = need.addressFromWallet(wallet);
220+ // const address = need.addressFromWallet(wallet);
221−
221+ // const permissions = usePermissionsForPoint(address, point);
222+ // const keyType = buildKeyType(permissions);
222 const patp = ob.patp(point);
223 const patp = ob.patp(point);
223− const permissions = usePermissionsForPoint(address, point);
224− const keyType = buildKeyType(permissions);
225
224
226 const contrast = locked ? '#666666' : 'black';
225 const contrast = locked ? '#666666' : 'black';
227
226
src/components/WithTooltip.tsx+3
@@ -4,6 +4,7 @@ import { useMemo } from 'react';
4export enum TooltipPosition {
4export enum TooltipPosition {
5 Top,
5 Top,
6 TopRight,
6 TopRight,
7+ Left,
7 // Add more as necessary here and in #positionStyle
8 // Add more as necessary here and in #positionStyle
8}
9}
9
10
@@ -30,6 +31,8 @@ export default function WithTooltip({
30 return { bottom: '100%' };
31 return { bottom: '100%' };
31 case TooltipPosition.TopRight:
32 case TooltipPosition.TopRight:
32 return { bottom: '90%', left: '90%' };
33 return { bottom: '90%', left: '90%' };
34+ case TooltipPosition.Left:
35+ return { bottom: '-67%', left: '-400%' };
33 default:
36 default:
34 return { bottom: '100%' };
37 return { bottom: '100%' };
35 }
38 }
src/components/copiable/CopiableAddress.js+2−1
@@ -3,9 +3,10 @@ import cn from 'classnames';
3
3
4import CopiableWithTooltip from './CopiableWithTooltip';
4import CopiableWithTooltip from './CopiableWithTooltip';
5
5
6−export default function CopiableAddress({ className, ...rest }) {
6+export default function CopiableAddress({ className, position, ...rest }) {
7 return (
7 return (
8 <CopiableWithTooltip
8 <CopiableWithTooltip
9+ position={position}
9 className={cn(className, 'mono', 'nowrap')}
10 className={cn(className, 'mono', 'nowrap')}
10 {...rest}
11 {...rest}
11 />
12 />
src/components/copiable/CopiableWithTooltip.js+2−1
@@ -9,6 +9,7 @@ export default function CopiableWithTooltip({
9 text,
9 text,
10 children,
10 children,
11 className,
11 className,
12+ position,
12 ...rest
13 ...rest
13}) {
14}) {
14 const [doCopy, didCopy] = useCopiable(text || children);
15 const [doCopy, didCopy] = useCopiable(text || children);
@@ -16,7 +17,7 @@ export default function CopiableWithTooltip({
16 return (
17 return (
17 <As className={className} {...rest}>
18 <As className={className} {...rest}>
18 {children}
19 {children}
19− <WithTooltip content={didCopy ? 'Copied!' : 'Copy'}>
20+ <WithTooltip position={position} content={didCopy ? 'Copied!' : 'Copy'}>
20 <Icon
21 <Icon
21 icon="Copy"
22 icon="Copy"
22 style={{ height: '1em', width: '1em' }}
23 style={{ height: '1em', width: '1em' }}
src/lib/utils/point.tsnew file+4
@@ -0,0 +1,4 @@
1+import { azimuth } from 'azimuth-js';
2+
3+export const isStar = (point: number) =>
4+ azimuth.getPointSize(point) === azimuth.PointSize.Star;
src/views/Point/MigrateL2.scss+30
@@ -143,6 +143,36 @@
143 }
143 }
144 }
144 }
145
145
146+ .transfer-spawn-selector {
147+ display: flex;
148+ flex-direction: row;
149+
150+ .transfer, .spawn {
151+ margin: 16px 0px;
152+ cursor: pointer;
153+ border-radius: $medium-border-radius;
154+ color: white;
155+ background-color: $light-gray;
156+ padding: 4px 8px;
157+
158+ &:hover {
159+ opacity: 0.8;
160+ }
161+
162+ &.selected {
163+ background-color: black;
164+
165+ &:hover {
166+ opacity: 1;
167+ }
168+ }
169+ }
170+
171+ .transfer {
172+ margin-right: 8px;
173+ }
174+ }
175+
146 .dropdown {
176 .dropdown {
147 margin-top: 4px;
177 margin-top: 4px;
148 &.migrate-selector .dropdown-content {
178 &.migrate-selector .dropdown-content {
src/views/Point/MigrateL2.tsx+58−15
@@ -1,6 +1,6 @@
1import React, { useState, useEffect, useCallback } from 'react';
1import React, { useState, useEffect, useCallback } from 'react';
2import { Grid } from 'indigo-react';
2import { Grid } from 'indigo-react';
3−import * as azimuth from 'azimuth-js';
3+import { azimuth, ecliptic } from 'azimuth-js';
4import * as ob from 'urbit-ob';
4import * as ob from 'urbit-ob';
5
5
6import View from 'components/View';
6import View from 'components/View';
@@ -29,6 +29,7 @@ import { GAS_LIMITS } from 'lib/constants';
29import Dropdown from 'components/L2/Dropdowns/Dropdown';
29import Dropdown from 'components/L2/Dropdowns/Dropdown';
30import { PointLayer } from 'lib/types/PointLayer';
30import { PointLayer } from 'lib/types/PointLayer';
31import Sigil from 'components/Sigil';
31import Sigil from 'components/Sigil';
32+import { isStar } from 'lib/utils/point';
32
33
33const DUMMY_L2_ADDRESS = '0x1111111111111111111111111111111111111111';
34const DUMMY_L2_ADDRESS = '0x1111111111111111111111111111111111111111';
34
35
@@ -61,13 +62,17 @@ const useMigrate = () => {
61
62
62 return useEthereumTransaction(
63 return useEthereumTransaction(
63 useCallback(
64 useCallback(
64− (selectedPoint: number) => {
65+ (selectedPoint: number, transfer: boolean) => {
65 setSelectedPoint(selectedPoint);
66 setSelectedPoint(selectedPoint);
67+ return transfer ||
68+ azimuth.getPointSize(selectedPoint) === azimuth.PointSize.Planet
69+ ? ecliptic.transferPoint(
70+ _contracts,
71+ selectedPoint,
72+ DUMMY_L2_ADDRESS,
73+ false
74+ )
66− return azimuth.ecliptic.setSpawnProxy(
75+ : ecliptic.setSpawnProxy(_contracts, selectedPoint, DUMMY_L2_ADDRESS);
67− _contracts,
68− selectedPoint,
69− DUMMY_L2_ADDRESS
70− );
71 },
76 },
72 [_contracts]
77 [_contracts]
73 ),
78 ),
@@ -86,12 +91,11 @@ export default function MigrateL2() {
86 const [hideMessage, setHideMessage] = useState(false);
91 const [hideMessage, setHideMessage] = useState(false);
87 const [selectedPoint, setSelectedPoint] = useState(point);
92 const [selectedPoint, setSelectedPoint] = useState(point);
88 const [showDropdown, setShowDropdown] = useState(false);
93 const [showDropdown, setShowDropdown] = useState(false);
94+ const [transfer, setTransfer] = useState(true);
89
95
90 const points = controlledPoints?.value?.value?.pointsWithLayers || [];
96 const points = controlledPoints?.value?.value?.pointsWithLayers || [];
91 const l1Points = points.filter(
97 const l1Points = points.filter(
92− ({ point, layer }: PointLayer) =>
98+ ({ point, layer }: PointLayer) => layer === 1 && isStar(point)
93− layer === 1 &&
94− azimuth.azimuth.getPointSize(point) === azimuth.azimuth.PointSize.Star
95 );
99 );
96
100
97 const hideInfo = getHideMigrationMessage();
101 const hideInfo = getHideMigrationMessage();
@@ -100,7 +104,7 @@ export default function MigrateL2() {
100
104
101 useEffect(() => {
105 useEffect(() => {
102 if (point) {
106 if (point) {
103− construct(point);
107+ construct(point, transfer);
104 } else {
108 } else {
105 unconstruct();
109 unconstruct();
106 }
110 }
@@ -132,12 +136,19 @@ export default function MigrateL2() {
132 (point: number) => {
136 (point: number) => {
133 setSelectedPoint(point);
137 setSelectedPoint(point);
134 setShowDropdown(false);
138 setShowDropdown(false);
135− construct(point);
139+ construct(point, transfer);
136 },
140 },
137− [setSelectedPoint, setShowDropdown, construct]
141+ [setSelectedPoint, setShowDropdown, construct, transfer]
138 );
142 );
139
143
144+ const toggleTransfer = useCallback(() => {
145+ construct(selectedPoint, !transfer);
146+ setTransfer(!transfer);
147+ }, [transfer, setTransfer, construct, selectedPoint]);
148+
140 const getContent = () => {
149 const getContent = () => {
150+ const star = isStar(selectedPoint);
151+
141 if (l1Points.length === 0) {
152 if (l1Points.length === 0) {
142 return (
153 return (
143 <Box className="content">
154 <Box className="content">
@@ -167,11 +178,36 @@ export default function MigrateL2() {
167 />
178 />
168 ))}
179 ))}
169 </Dropdown>
180 </Dropdown>
181+ {star && (
182+ <Box className="transfer-spawn-selector">
183+ <Box
184+ onClick={toggleTransfer}
185+ className={`transfer ${transfer ? 'selected' : ''}`}>
186+ Transfer Point
187+ </Box>
188+ <Box
189+ onClick={toggleTransfer}
190+ className={`spawn ${!transfer ? 'selected' : ''}`}>
191+ Set Spawn Proxy
192+ </Box>
193+ </Box>
194+ )}
195+ {star && (
196+ <Box>
197+ Transferring this point will allow you to conduct all
198+ transactions on Layer 2 and is irreversible. Setting the spawn
199+ proxy of a star to the Layer 2 contract is reversible, will
200+ allow you to create planet invites for free, but will require
201+ you to do all other transactions on Layer 1.
202+ </Box>
203+ )}
170 </Box>
204 </Box>
171 <Grid.Item
205 <Grid.Item
172 full
206 full
173 as={InlineEthereumTransaction}
207 as={InlineEthereumTransaction}
208+ label={`${
209+ transfer ? 'Transfer point' : 'Set spawn proxy'
174− label="Migrate to Layer 2"
210+ } to Layer 2`}
175 {...bind}
211 {...bind}
176 onReturn={pop}
212 onReturn={pop}
177 />
213 />
@@ -184,7 +220,14 @@ export default function MigrateL2() {
184 <Box className="message">
220 <Box className="message">
185 You are about to migrate a node from Layer 1 to Layer 2. This will
221 You are about to migrate a node from Layer 1 to Layer 2. This will
186 make transactions faster and cheaper. Here are some things you should
222 make transactions faster and cheaper. Here are some things you should
223+ know.{' '}
224+ <a
187− know. <span className="bold">Learn More</span>
225+ className="bold"
226+ target="_blank"
227+ rel="noreferrer"
228+ href="https://discord.com/channels/879614191672115260/879624035028324362">
229+ Learn More
230+ </a>
188 </Box>
231 </Box>
189 {!hideInfo && (
232 {!hideInfo && (
190 <Box className="info-list">
233 <Box className="info-list">
src/views/UrbitOS/ChangeSponsor.js+2−2
@@ -22,6 +22,7 @@ import * as need from 'lib/need';
22import { validateMinimumPatpByteLength } from 'lib/validators';
22import { validateMinimumPatpByteLength } from 'lib/validators';
23import { usePointCursor } from 'store/pointCursor';
23import { usePointCursor } from 'store/pointCursor';
24import useEthereumTransaction from 'lib/useEthereumTransaction';
24import useEthereumTransaction from 'lib/useEthereumTransaction';
25+import { isStar } from 'lib/utils/point';
25
26
26function useChangeSponsor() {
27function useChangeSponsor() {
27 const { contracts } = useNetwork();
28 const { contracts } = useNetwork();
@@ -73,8 +74,7 @@ function ChangeSponsor({ onDone }) {
73 );
74 );
74
75
75 const validate = useMemo(() => {
76 const validate = useMemo(() => {
76− const sponsorSize =
77+ const sponsorSize = isStar(point) ? 1 : 2;
77− azimuth.getPointSize(point) === azimuth.PointSize.Star ? 1 : 2;
78 return composeValidator(
78 return composeValidator(
79 {
79 {
80 sponsor: buildPointValidator(sponsorSize, [
80 sponsor: buildPointValidator(sponsorSize, [