1import Maybe from 'folktale/maybe'
2import React from 'react'
3import * as azimuth from 'azimuth-js'
4import * as ob from 'urbit-ob'
6import { Row, Col, H1, InnerLabel, ShowBlockie, P, Anchor } from '../components/Base'
7import { AddressInput, Warning, H3 } from '../components/Base'
8import StatelessTransaction from '../components/StatelessTransaction'
10import { BRIDGE_ERROR } from '../lib/error'
11import { NETWORK_NAMES } from '../lib/network'
12import { ROUTE_NAMES } from '../lib/router'
15 sendSignedTransaction,
21 addressFromSecp256k1Public
22 } from '../lib/wallet'
24class Transfer extends React.Component {
28 const issuingPoint = props.pointCursor.matchWith({
29 Just: (pt) => pt.value,
31 throw BRIDGE_ERROR.MISSING_POINT
36 txError: Maybe.Nothing(),
38 issuingPoint: issuingPoint,
47 this.handleAddressInput = this.handleAddressInput.bind(this)
49 this.handleCreateUnsignedTxn = this.handleCreateUnsignedTxn.bind(this)
50 this.handleSubmit = this.handleSubmit.bind(this)
51 this.handleSetUserApproval = this.handleSetUserApproval.bind(this)
52 this.handleSetTxn = this.handleSetTxn.bind(this)
53 this.handleSetStx = this.handleSetStx.bind(this)
54 this.handleSetNonce = this.handleSetNonce.bind(this)
55 this.handleSetChainId = this.handleSetChainId.bind(this)
56 this.handleSetGasPrice = this.handleSetGasPrice.bind(this)
57 this.handleSetGasLimit = this.handleSetGasLimit.bind(this)
62 const { props } = this
64 const addr = props.wallet.matchWith({
65 Just: wal => addressFromSecp256k1Public(wal.value.publicKey),
67 throw BRIDGE_ERROR.MISSING_WALLET
71 props.web3.matchWith({
74 const validWeb3 = w3.value
76 const getTxMetadata = [
77 validWeb3.eth.getTransactionCount(addr),
78 validWeb3.eth.net.getId(),
79 validWeb3.eth.getGasPrice()
82 Promise.all(getTxMetadata).then(r => {
86 gasPrice: fromWei(r[2], 'gwei'),
89 this.setState({...txMetadata})
99 handleAddressInput(receivingAddress) {
100 this.setState({ receivingAddress })
101 this.handleClearTxn()
106 handleConfirmAvailability() {
107 this.confirmPointAvailability().then(r => {
108 this.setState({ isAvailable: r })
114 handleCreateUnsignedTxn() {
115 const txn = this.createUnsignedTxn()
116 this.setState({ txn })
120 handleSetUserApproval(){
122 this.setState({ userApproval: !state.userApproval })
128 this.setState({ txn })
142 handleSetNonce(nonce){
143 this.setState({ nonce })
144 this.handleClearStx()
149 handleSetChainId(chainId){
150 this.setState({ chainId })
151 this.handleClearStx()
156 handleSetGasPrice(gasPrice){
157 this.setState({ gasPrice })
158 this.handleClearStx()
163 handleSetGasLimit(gasLimit){
164 this.setState({ gasLimit })
165 this.handleClearStx()
173 stx: Maybe.Nothing(),
182 txn: Maybe.Nothing(),
183 stx: Maybe.Nothing(),
189 handleClearTransaction() {
192 txn: Maybe.Nothing(),
193 stx: Maybe.Nothing(),
200 const { props, state } = this
201 sendSignedTransaction(props.web3.value, state.stx)
203 props.setTxnHashCursor(sent)
205 props.pushRoute(ROUTE_NAMES.SENT_TRANSACTION)
208 this.setState({ txError: err.map(val => val.merge()) })
214 createUnsignedTxn() {
215 const { state, props } = this
217 const validContracts = props.contracts.matchWith({
218 Just: (cs) => cs.value,
220 throw BRIDGE_ERROR.MISSING_CONTRACTS
224 const validPoint = props.pointCursor.matchWith({
225 Just: (shp) => shp.value,
227 throw BRIDGE_ERROR.MISSING_POINTs
231 const txn = azimuth.ecliptic.setTransferProxy(
234 state.receivingAddress
237 return Maybe.Just(txn)
243 const { props, state } = this
245 const validAddress = isValidAddress(state.receivingAddress)
247 const canGenerate = validAddress === true
249 const canSign = !Maybe.Nothing.hasInstance(state.txn)
250 const canApprove = !Maybe.Nothing.hasInstance(state.stx)
251 const canSend = !Maybe.Nothing.hasInstance(state.stx) && state.userApproval === true
254 props.networkType === NETWORK_NAMES.ROPSTEN ||
255 props.networkType === NETWORK_NAMES.MAINNET
258 props.networkType === NETWORK_NAMES.ROPSTEN
259 ? "ropsten.etherscan.io"
266 { 'Transfer'} <code>{ ` ${ob.patp(state.issuingPoint)} ` }</code>
272 `Please provide the Ethereum address of the new owner. You own these
273 points until the recipient accepts the incoming transfer.
274 You may cancel the transfer until the transfer is accepted.`
279 className={'mono mt-8'}
281 prop-format='innerLabel'
282 value={ state.receivingAddress }
283 placeholder={ `e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f` }
284 onChange={ v => this.handleAddressInput(v) }>
285 <InnerLabel>{ 'New ownership address' }</InnerLabel>
286 <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
292 prop-disabled={!isValidAddress(state.receivingAddress) || !esvisible}
294 href={`https://${esdomain}/address/${state.receivingAddress}`}>
295 {'View on Etherscan ↗'}
298 <StatelessTransaction
301 contracts={props.contracts}
302 wallet={props.wallet}
303 walletType={props.walletType}
304 walletHdPath={props.walletHdPath}
305 networkType={props.networkType}
311 gasPrice={state.gasPrice}
312 chainId={state.chainId}
313 gasLimit={state.gasLimit}
315 userApproval={state.userApproval}
316 canGenerate={ canGenerate }
318 canApprove={ canApprove }
321 createUnsignedTxn={this.handleCreateUnsignedTxn}
322 setUserApproval={this.handleSetUserApproval}
323 setTxn={this.handleSetTxn}
324 setStx={this.handleSetStx}
325 setNonce={this.handleSetNonce}
326 setChainId={this.handleSetChainId}
327 setGasPrice={this.handleSetGasPrice}
328 setGasLimit={this.handleSetGasLimit}
329 handleSubmit={this.handleSubmit} />
332 Maybe.Nothing.hasInstance(state.txError)
334 : <Warning className={'mt-8'}>
335 <H3 style={{marginTop: 0, paddingTop: 0}}>
337 'There was an error sending your transaction.'
340 { state.txError.value }
350export default Transfer
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