on 616e621 help sign in
bridge/src/views/CreateGalaxy.js
291 lines 8.2 kB history raw
1import React from 'react'
2import Maybe from 'folktale/maybe'
3import * as azimuth from 'azimuth-js'
4import * as ob from 'urbit-ob'
6import { Button, } from '../components/Base'
7import { Row, Col, H1, P, Anchor } from '../components/Base'
8import { InnerLabel, GalaxyInput, AddressInput, ValidatedSigil, ShowBlockie, Form } from '../components/Base'
9import StatelessTransaction from '../components/StatelessTransaction'
11import { BRIDGE_ERROR } from '../lib/error'
13import {
14 sendSignedTransaction,
15 getTxnInfo,
16 canDecodePatp
17} from '../lib/txn'
19import { ROUTE_NAMES } from '../lib/router'
21import {
22 addressFromSecp256k1Public,
23 ETH_ZERO_ADDR,
24 isValidAddress,
25 eqAddr
26} from '../lib/wallet'
28import {
29 isValidGalaxy
30} from '../lib/lib'
33const buttonTriState = status => {
34 if (status === null) return 'blue'
35 if (status === false) return 'yellow'
36 if (status === true) return 'green'
39const buttonTriStateText = status => {
40 if (status === null) return 'Confirm Galaxy Availablility'
41 if (status === false) return 'Galaxy is Not Available'
42 if (status === true) return 'Galaxy is Available'
47class CreateGalaxy extends React.Component {
48 constructor(props) {
49 super(props)
51 const galaxyOwner = props.wallet.matchWith({
52 Just: (wal) => addressFromSecp256k1Public(wal.value.publicKey),
53 Nothing: () => {
54 throw BRIDGE_ERROR.MISSING_WALLET
55 }
56 })
58 this.state = {
59 galaxyOwner: galaxyOwner,
60 galaxyName: '',
61 isAvailable: null,
62 txApproval: false,
63 nonce: '',
64 gasPrice: '5',
65 chainId: '',
66 txInfo: '',
67 gasLimit: '600000',
68 txn: Maybe.Nothing(),
69 stx: Maybe.Nothing(),
70 }
72 this.handleAddressInput = this.handleAddressInput.bind(this)
73 this.handleGalaxyNameInput = this.handleGalaxyNameInput.bind(this)
74 this.confirmAvailability = this.confirmAvailability.bind(this)
75 this.handleSubmit = this.handleSubmit.bind(this)
76 }
78 componentDidMount() {
79 const { props } = this
80 const addr = props.wallet.matchWith({
81 Just: wal => addressFromSecp256k1Public(wal.value.publicKey),
82 Nothing: () => {
83 throw BRIDGE_ERROR.MISSING_WALLET
84 }
85 })
87 // getTxnInfo(props.web3.value, addr).then(txInfo => this.setState(txInfo))
88 props.web3.map(w3 => getTxnInfo(w3, addr)
89 .then(txInfo => this.setState(txInfo))
90 )
91 }
94 handleGalaxyNameInput = (galaxyName) => {
95 this.setState({ galaxyName, isAvailable: null })
96 this.clearTransaction()
97 }
99 handleAddressInput = (galaxyOwner) => {
100 this.setState({ galaxyOwner })
101 this.clearTransaction()
102 }
104 createUnsignedTxn = () => {
105 const { state, props } = this
106 if (isValidAddress(state.galaxyOwner) === false) return Maybe.Nothing()
107 if (state.isAvailable === false) return Maybe.Nothing()
108 if (canDecodePatp(state.galaxyName) === false) return Maybe.Nothing()
109 if (isValidGalaxy(state.galaxyName) === false) return Maybe.Nothing()
111 const validContracts = props.contracts.matchWith({
112 Just: (cs) => cs.value,
113 Nothing: () => {
114 throw BRIDGE_ERROR.MISSING_CONTRACTS
115 }
116 })
118 const galaxyDec = parseInt(ob.patp2dec(state.galaxyName), 10)
120 const txn = azimuth.ecliptic.createGalaxy(
121 validContracts,
122 galaxyDec,
123 state.galaxyOwner
124 )
126 this.setState({ txn: Maybe.Just(txn) })
127 }
130 handleSubmit = () => {
131 const { props, state } = this
132 sendSignedTransaction(props.web3.value, state.stx)
133 .then(sent => {
134 props.setTxnCursor(sent)
135 props.popRoute()
136 props.pushRoute(ROUTE_NAMES.SENT_TRANSACTION)
137 })
138 }
140 confirmAvailability = async () => {
141 const { state, props } = this
143 if (canDecodePatp(state.galaxyName) === false) {
144 this.setState({ isAvailable: false })
145 return
146 }
148 const validContracts = props.contracts.matchWith({
149 Just: (cs) => cs.value,
150 Nothing: () => {
151 throw BRIDGE_ERROR.MISSING_CONTRACTS
152 }
153 })
155 const galaxyDec = ob.patp2dec(state.galaxyName)
157 const currentOwner = await azimuth.azimuth.getOwner(
158 validContracts,
159 galaxyDec
160 )
162 const available = eqAddr(currentOwner, ETH_ZERO_ADDR)
164 this.setState({ isAvailable: available })
165 }
168 clearTransaction = () => {
169 this.setState({
170 txApproval: false,
171 txn: Maybe.Nothing(),
172 stx: Maybe.Nothing(),
173 })
174 }
176 render() {
177 const { props, state } = this
179 const validAddress = isValidAddress(state.galaxyOwner)
180 const validGalaxy = isValidGalaxy(state.galaxyName)
183 return (
184 <Row>
185 <Col>
186 <H1> { 'Create a Galaxy' } </H1>
188 <P>
189 {
190 'Enter the galaxy to create and the address that will own ' +
191 'it (defaulting to this account, if not provided).'
192 }
193 </P>
195 <Form>
197 <GalaxyInput
198 className='mono'
199 prop-size='lg'
200 prop-format='innerLabel'
201 autoFocus
202 placeholder='e.g. ~zod'
203 value={state.galaxyName}
204 onChange={v => this.handleGalaxyNameInput(v)}>
205 <InnerLabel>{ 'Galaxy Name' }</InnerLabel>
206 <ValidatedSigil
207 className='tr-0 mt-05 mr-0 abs'
208 patp={state.galaxyName}
209 size={76}
210 margin={8} />
211 </GalaxyInput>
213 <AddressInput
214 className='mono mt-8'
215 prop-size='lg'
216 prop-format='innerLabel'
217 value={ state.galaxyOwner }
218 onChange={ v => this.handleAddressInput(v) }>
219 <InnerLabel>
220 { 'Address that will own this galaxy' }
221 </InnerLabel>
222 <ShowBlockie
223 className={'mt-1'}
224 address={state.galaxyOwner} />
225 </AddressInput>
227 <Anchor
228 className={'mt-1'}
229 prop-size={'sm'}
230 prop-disabled={!validAddress}
231 target={'_blank'}
232 href={`https://etherscan.io/address/${state.galaxyOwner}`}>
233 {'View on Etherscan ↗'}
234 </Anchor>
236 <Button
237 prop-size='lg wide'
238 className='mt-8'
239 prop-color={buttonTriState(state.isAvailable)}
240 disabled={!validGalaxy}
241 onClick={() => this.confirmAvailability()}>
242 {buttonTriStateText(state.isAvailable)}
243 </Button>
245 <StatelessTransaction
246 address={state.galaxyOwner}
247 shipName={state.galaxyName}
248 isAvailable={state.isAvailable}
249 web3={props.web3}
250 contracts={props.contracts}
251 wallet={props.wallet}
252 walletType={props.walletType}
253 walletHdPath={props.walletHdPath}
254 // Tx
255 txApproval={state.txApproval}
256 txn={state.txn}
257 stx={state.stx}
258 nonce={state.nonce}
259 gasPrice={state.gasPrice}
260 chainId={state.chainId}
261 gasLimit={state.gasLimit}
262 canGenerate={
263 validAddress === true &&
264 validGalaxy === true &&
265 state.isAvailable === true
266 }
267 canSign={!Maybe.Nothing.hasInstance(state.txn)}
268 canSend={!Maybe.Nothing.hasInstance(state.stx)}
269 // Methods
270 createUnsignedTxn={() => this.createUnsignedTxn()}
271 clearTransaction={() => this.clearTransaction()}
272 setApproval={() => this.setState({txApproval: !state.txApproval})}
273 setTxn={txn => this.setState({txn})}
274 setStx={stx => this.setState({stx})}
275 setNonce={nonce => this.setState({nonce})}
276 setChainId={chainId => this.setState({chainId})}
277 setGasPrice={gasPrice => this.setState({gasPrice})}
278 setGasLimit={gasLimit => this.setState({gasLimit})}
279 handleSubmit={this.handleSubmit} />
281 </Form>
282 </Col>
283 </Row>
284 )
285 }
291export default CreateGalaxy