on cbb04ce help sign in
bridge/src/views/CreateGalaxy.js
159 lines 4.1 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 { usePointCache } from 'store/pointCache';
10import * as need from 'lib/need';
11import { useAddressInput, useGalaxyInput } from 'lib/useInputs';
12import useEthereumTransaction from 'lib/useEthereumTransaction';
13import { GAS_LIMITS } from 'lib/constants';
14import patp2dec from 'lib/patp2dec';
15import { isZeroAddress } from 'lib/wallet';
16import { useLocalRouter } from 'lib/LocalRouter';
18import ViewHeader from 'components/ViewHeader';
19import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
20import View from 'components/View';
22function useCreateGalaxy() {
23 const { contracts } = useNetwork();
24 const { syncKnownPoint } = usePointCache();
26 const _contracts = need.contracts(contracts);
28 const [galaxy, setGalaxy] = useState();
30 return useEthereumTransaction(
31 useCallback(
32 (galaxy, owner) => {
33 setGalaxy(galaxy);
34 return azimuth.ecliptic.createGalaxy(_contracts, galaxy, owner);
35 },
36 [_contracts]
37 ),
38 useCallback(() => syncKnownPoint(galaxy), [galaxy, syncKnownPoint]),
39 GAS_LIMITS.DEFAULT
40 );
43export default function CreateGalaxy() {
44 const { pop } = useLocalRouter();
45 const { contracts } = useNetwork();
46 const _contracts = need.contracts(contracts);
48 const [error, setError] = useState();
49 const [isAvailable, setIsAvailable] = useState(Nothing());
51 const {
52 construct,
53 unconstruct,
54 completed,
55 inputsLocked,
56 bind,
57 } = useCreateGalaxy();
59 const [
60 galaxyNameInput,
61 { pass: validGalaxyName, syncPass: syncValidGalaxyName, value: galaxyName },
62 // ^ we use value: here so our effect runs onChange
63 ] = useGalaxyInput({
64 name: 'galaxy',
65 disabled: inputsLocked,
66 autoFocus: true,
67 error:
68 error ||
69 isAvailable.matchWith({
70 Nothing: () => 'Loading availability...', // TODO: make async loading?
71 Just: p => (p.value ? undefined : 'This galaxy is already owned.'),
72 }),
73 });
75 const [ownerInput, { pass: validOwner, data: owner }] = useAddressInput({
76 name: 'owner',
77 label: `Ethereum Address`,
78 disabled: inputsLocked,
79 });
81 useEffect(() => {
82 if (validGalaxyName && validOwner) {
83 construct(patp2dec(galaxyName), owner);
84 } else {
85 unconstruct();
86 }
87 }, [owner, construct, unconstruct, validGalaxyName, validOwner, galaxyName]);
89 useEffect(() => {
90 if (!syncValidGalaxyName || inputsLocked) {
91 return;
92 }
94 setError();
95 setIsAvailable(Nothing());
97 let cancelled = false;
99 (async () => {
100 try {
101 const currentOwner = await azimuth.azimuth.getOwner(
102 _contracts,
103 patp2dec(galaxyName)
104 );
106 const isAvailable = isZeroAddress(currentOwner);
108 if (cancelled) {
109 return;
110 }
112 setIsAvailable(Just(isAvailable));
113 } catch (error) {
114 console.error(error);
115 setError(error.message);
116 setIsAvailable(Just(false));
117 }
118 })();
120 return () => (cancelled = true);
121 }, [
122 _contracts,
123 galaxyName,
124 inputsLocked,
125 setIsAvailable,
126 syncValidGalaxyName,
127 ]);
129 return (
130 <View pop={pop} inset>
131 <Grid>
132 <Grid.Item full as={ViewHeader}>
133 Create a Galaxy
134 </Grid.Item>
136 {completed && (
137 <Grid.Item
138 full
139 as={Text}
140 className={cn('f5', {
141 green3: completed,
142 })}>
143 {galaxyName} has been created and can be claimed by {owner}.
144 </Grid.Item>
145 )}
147 <Grid.Item full as={Input} {...galaxyNameInput} className="mt4" />
148 <Grid.Item full as={Input} {...ownerInput} className="mb4" />
150 <Grid.Item
151 full
152 as={InlineEthereumTransaction}
153 {...bind}
154 onReturn={() => pop()}
155 />
156 </Grid>
157 </View>
158 );