1import React, { useState, useEffect, useCallback } from 'react';
2import { Grid } from 'indigo-react';
3import { ecliptic } from 'azimuth-js';
4import * as ob from 'urbit-ob';
7 getHideMigrationMessage,
8 storeHideMigrationMessage,
9} from 'store/storage/roller';
10import { useNetwork } from 'store/network';
11import { usePointCache } from 'store/pointCache';
12import { useRollerStore } from 'store/rollerStore';
14import { useLocalRouter } from 'lib/LocalRouter';
15import * as need from 'lib/need';
16import Point, { PointField } from 'lib/types/Point';
17import useRoller from 'lib/useRoller';
18import { L1TxnType } from 'lib/types/PendingL1Transaction';
19import useEthereumTransaction from 'lib/useEthereumTransaction';
20import { DUMMY_L2_ADDRESS, GAS_LIMITS } from 'lib/constants';
21import { isPlanet } from 'lib/utils/point';
23import View from 'components/View';
24import L2BackHeader from 'components/L2/Headers/L2BackHeader';
25import BodyPane from 'components/L2/Window/BodyPane';
26import HeaderPane from 'components/L2/Window/HeaderPane';
27import Window from 'components/L2/Window/Window';
28import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
29import Dropdown from 'components/L2/Dropdowns/Dropdown';
30import Sigil from 'components/Sigil';
31import { ReactComponent as StarIcon } from 'assets/star.svg';
40} from '@tlon/indigo-react';
42import './MigrateL2.scss';
53 <Row className="entry" onClick={select}>
54 <Box>Select a point</Box>
59 const patp = ob.patp(point);
62 <Row className="entry" onClick={select}>
63 <Box className="sigil">
64 <Sigil patp={patp} size={1} colors={['#000000', '#FFFFFF']} />
66 <Box className="mono">{patp}</Box>
71const useMigrate = () => {
72 const { contracts }: any = useNetwork();
73 const { syncDates }: any = usePointCache();
75 const _contracts = need.contracts(contracts);
77 const [selectedPoint, setSelectedPoint] = useState<number | null>(null);
79 return useEthereumTransaction(
81 (selectedPoint: number, transfer: boolean) => {
82 if (selectedPoint < 0) {
85 setSelectedPoint(selectedPoint);
86 return transfer || isPlanet(selectedPoint)
87 ? ecliptic.transferPoint(
93 : ecliptic.setSpawnProxy(_contracts, selectedPoint, DUMMY_L2_ADDRESS);
97 useCallback(() => syncDates(selectedPoint), [selectedPoint, syncDates]),
102export default function MigrateL2() {
103 const { pop }: any = useLocalRouter();
104 const { point, pointList } = useRollerStore();
105 const { checkForUpdates } = useRoller();
106 const l1Points = pointList.filter(({ canMigrate }) => canMigrate);
108 const [proceed, setProceed] = useState(false);
109 const [hideMessage, setHideMessage] = useState(false);
110 const [showDropdown, setShowDropdown] = useState(false);
111 const [transfer, setTransfer] = useState(true);
113 const [selectedPoint, setSelectedPoint] = useState(
114 point.isL1 ? point : l1Points[0]
116 const hideInfo = getHideMigrationMessage();
118 const { construct, unconstruct, bind, completed, txHashes } = useMigrate();
121 if (point.isGalaxy && point.isL1) {
123 construct(point.value, false);
124 } else if (point.isL1) {
125 construct(point.value, transfer);
129 }, []); // eslint-disable-line react-hooks/exhaustive-deps
133 const message = transfer
134 ? `${selectedPoint.patp} has been migrated to Layer 2!`
135 : `${selectedPoint.patp}'s spawn proxy has been set to Layer 2!`;
138 point: selectedPoint,
141 field: PointField.layer,
143 id: `${DUMMY_L2_ADDRESS}-${selectedPoint.value}`,
144 point: selectedPoint.value,
145 type: transfer ? L1TxnType.migrate : L1TxnType.migrateSpawn,
147 time: new Date().getTime(),
153 }, [completed, pop]); // eslint-disable-line react-hooks/exhaustive-deps
155 const goBack = useCallback(() => {
161 }, [pop, proceed, setProceed]);
163 const goProceed = useCallback(() => {
165 storeHideMigrationMessage();
171 const selectPoint = useCallback(
173 if (point.isPlanet || (point.isStar && point.isL2Spawn)) {
175 } else if (point.isGalaxy) {
178 setSelectedPoint(point);
179 setShowDropdown(false);
181 construct(point.value, transfer);
183 [setSelectedPoint, setShowDropdown, bind, construct, transfer]
186 const toggleTransfer = useCallback(() => {
187 construct(selectedPoint.value, !transfer);
188 setTransfer(!transfer);
189 }, [transfer, setTransfer, construct, selectedPoint]);
191 const getContent = () => {
192 if (l1Points.length === 0) {
194 <Box className="content">
195 <Box className="ship-selector">
196 <Box>All of your eligible ships are already on Layer 2.</Box>
202 const isStar = Boolean(selectedPoint?.isStar);
203 const isGalaxy = Boolean(selectedPoint?.isGalaxy);
207 <Box className="content">
208 <Box className="ship-selector">
210 <Box className="select-ship">Select one of your ships</Box>
213 toggleOpen={() => setShowDropdown(!showDropdown)}
214 value={<PointEntry point={selectedPoint.value} />}
215 className="migrate-selector">
216 {l1Points.map((p: Point) => (
220 select={() => selectPoint(p)}
224 {isStar && !selectedPoint?.isL2Spawn && (
225 <Box className="transfer-spawn-selector">
226 <Row onClick={toggleTransfer} className="transfer">
228 color="rgba(0,0,0,0.3)"
229 className={`radio ${transfer ? 'selected' : ''}`}
235 <Row onClick={toggleTransfer} className="transfer">
237 color="rgba(0,0,0,0.3)"
238 className={`radio ${!transfer ? 'selected' : ''}`}
247 <Box className="mt4">
248 Transferring this point will allow you to conduct all
249 transactions on Layer 2. Setting the spawn proxy of a star to
250 Layer 2 will allow you to create planet invites for free, but
251 will require you to do all other transactions on Layer 1.
255 <Box className="mt4">
256 Setting the spawn proxy of this galaxy to Layer 2 will allow you
257 to spawn stars on Layer 2 for free, but will still require you
258 to do all other transactions on Layer 1.
264 as={InlineEthereumTransaction}
266 transfer ? 'Transfer ship' : 'Set spawn proxy'
269 onReturn={() => pop()}
276 <Box className="content">
277 <Box className="message">
278 You are about to migrate a node from Layer 1 to Layer 2. This will
279 make transactions faster and cheaper. Here are some things you should
285 href="https://urbit.org/docs/azimuth/l2/layer2">
290 <Box className="info-list">
291 <Row className="info-row">
292 <Box className="icon-background">
293 <StarIcon className="icon" />
295 <Box className="info-message">
296 <span className="warning">
297 Migration to Layer 2 is irreversible
300 You will not be able to revert back to Layer 1.
303 <Row className="info-row">
304 <Box className="icon-background">
305 <Box className="icon">$</Box>
307 <Box className="info-message">
308 A migration is expensive, but a one-time fee. The estimated
309 price is <span className="bold">$120</span>. Transaction fees
310 will be subsidized on Layer 2.
313 <Row className="info-row">
314 <Box className="icon-background">
315 <Icon icon="Clock" className="icon" color="white" />
317 {/* <HistoryIcon className="icon" /> */}
318 <Box className="info-message">
319 All transactions will now be pushed at the end of the day. A
320 timer will show when the next push is.
326 <Row className="hide-row">
329 selected={hideMessage}
330 onClick={() => setHideMessage(!hideMessage)}
332 <Box className="dont-show">Do not show this again</Box>
335 <Row className="buttons">
336 <Button className="cancel" onClick={goBack}>
339 <Button className="proceed" onClick={goProceed}>
349 className="migrate-l2"
353 header={<L2BackHeader back={goBack} />}>
356 <h5>Migrating to Layer 2</h5>
358 <BodyPane>{getContent()}</BodyPane>
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list