on 8aed2cb help sign in
bridge/src/views/CreateGalaxy.js
162 lines 4.2 kB history raw
1import React, { useCallback, useEffect, useState } from 'react';
2import { Nothing, Just } from 'folktale/maybe';
3import cn from 'classnames';
4import { Grid, Text, Input } from 'indigo-react';
5import * as azimuth from 'azimuth-js';
7import { useNetwork } from 'store/network';
8import { useHistory } from 'store/history';
9import { usePointCache } from 'store/pointCache';
11import * as need from 'lib/need';
12import { useAddressInput, useGalaxyInput } from 'lib/useInputs';
13import useEthereumTransaction from 'lib/useEthereumTransaction';
14import { GAS_LIMITS } from 'lib/constants';
15import patp2dec from 'lib/patp2dec';
17import ViewHeader from 'components/ViewHeader';
18import MiniBackButton from 'components/MiniBackButton';
19import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
20import View from 'components/View';
21import { isZeroAddress } from 'lib/wallet';
23function useCreateGalaxy() {
24 const { contracts } = useNetwork();
25 const { syncKnownPoint } = usePointCache();
27 const _contracts = need.contracts(contracts);
29 const [galaxy, setGalaxy] = useState();
31 return useEthereumTransaction(
32 useCallback(
33 (galaxy, owner) => {
34 setGalaxy(galaxy);
35 return azimuth.ecliptic.createGalaxy(_contracts, galaxy, owner);
36 },
37 [_contracts]
38 ),
39 useCallback(() => syncKnownPoint(galaxy), [galaxy, syncKnownPoint]),
40 GAS_LIMITS.DEFAULT
41 );
44export default function CreateGalaxy() {
45 const { pop } = useHistory();
46 const { contracts } = useNetwork();
47 const _contracts = need.contracts(contracts);
49 const [error, setError] = useState();
50 const [isAvailable, setIsAvailable] = useState(Nothing());
52 const {
53 construct,
54 unconstruct,
55 completed,
56 inputsLocked,
57 bind,
58 } = useCreateGalaxy();
60 const [
61 galaxyNameInput,
62 { pass: validGalaxyName, syncPass: syncValidGalaxyName, value: galaxyName },
63 // ^ we use value: here so our effect runs onChange
64 ] = useGalaxyInput({
65 name: 'galaxy',
66 disabled: inputsLocked,
67 autoFocus: true,
68 error:
69 error ||
70 isAvailable.matchWith({
71 Nothing: () => 'Loading availability...', // TODO: make async loading?
72 Just: p => (p.value ? undefined : 'This galaxy is already owned.'),
73 }),
74 });
76 const [ownerInput, { pass: validOwner, data: owner }] = useAddressInput({
77 name: 'owner',
78 label: `Ethereum Address`,
79 disabled: inputsLocked,
80 });
82 useEffect(() => {
83 if (validGalaxyName && validOwner) {
84 construct(patp2dec(galaxyName), owner);
85 } else {
86 unconstruct();
87 }
88 }, [owner, construct, unconstruct, validGalaxyName, validOwner, galaxyName]);
90 useEffect(() => {
91 if (!syncValidGalaxyName || inputsLocked) {
92 return;
93 }
95 setError();
96 setIsAvailable(Nothing());
98 let cancelled = false;
100 (async () => {
101 try {
102 const currentOwner = await azimuth.azimuth.getOwner(
103 _contracts,
104 patp2dec(galaxyName)
105 );
107 const isAvailable = isZeroAddress(currentOwner);
109 if (cancelled) {
110 return;
111 }
113 setIsAvailable(Just(isAvailable));
114 } catch (error) {
115 console.error(error);
116 setError(error.message);
117 setIsAvailable(Just(false));
118 }
119 })();
121 return () => (cancelled = true);
122 }, [
123 _contracts,
124 galaxyName,
125 inputsLocked,
126 setIsAvailable,
127 syncValidGalaxyName,
128 ]);
130 return (
131 <View inset>
132 <Grid>
133 <Grid.Item full as={MiniBackButton} onClick={() => pop()} />
135 <Grid.Item full as={ViewHeader}>
136 Create a Galaxy
137 </Grid.Item>
139 {completed && (
140 <Grid.Item
141 full
142 as={Text}
143 className={cn('f5', {
144 green3: completed,
145 })}>
146 {galaxyName} has been created and can be claimed by {owner}.
147 </Grid.Item>
148 )}
150 <Grid.Item full as={Input} {...galaxyNameInput} className="mt4" />
151 <Grid.Item full as={Input} {...ownerInput} className="mb4" />
153 <Grid.Item
154 full
155 as={InlineEthereumTransaction}
156 {...bind}
157 onReturn={() => pop()}
158 />
159 </Grid>
160 </View>
161 );