@@ -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+}