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,
42 showGasDetails: false,
48 this.handleAddressInput = this.handleAddressInput.bind(this)
50 this.handleCreateUnsignedTxn = this.handleCreateUnsignedTxn.bind(this)
51 this.handleSubmit = this.handleSubmit.bind(this)
52 this.handleSetUserApproval = this.handleSetUserApproval.bind(this)
53 this.handleSetTxn = this.handleSetTxn.bind(this)
54 this.handleSetStx = this.handleSetStx.bind(this)
55 this.handleSetNonce = this.handleSetNonce.bind(this)
56 this.handleSetChainId = this.handleSetChainId.bind(this)
57 this.handleSetGasPrice = this.handleSetGasPrice.bind(this)
58 this.handleSetGasLimit = this.handleSetGasLimit.bind(this)
59 this.toggleGasDetails = this.toggleGasDetails.bind(this)
64 showGasDetails: !this.state.showGasDetails
69 const { props } = this
71 const addr = props.wallet.matchWith({
72 Just: wal => addressFromSecp256k1Public(wal.value.publicKey),
74 throw BRIDGE_ERROR.MISSING_WALLET
78 props.web3.matchWith({
81 const validWeb3 = w3.value
83 const getTxMetadata = [
84 validWeb3.eth.getTransactionCount(addr),
85 validWeb3.eth.net.getId(),
86 validWeb3.eth.getGasPrice()
89 Promise.all(getTxMetadata).then(r => {
93 gasPrice: fromWei(r[2], 'gwei'),
96 this.setState({...txMetadata})
106 handleAddressInput(receivingAddress) {
107 this.setState({ receivingAddress })
108 this.handleClearTxn()
113 handleConfirmAvailability() {
114 this.confirmPointAvailability().then(r => {
115 this.setState({ isAvailable: r })
121 handleCreateUnsignedTxn() {
122 const txn = this.createUnsignedTxn()
123 this.setState({ txn })
127 handleSetUserApproval(){
129 this.setState({ userApproval: !state.userApproval })
135 this.setState({ txn })
149 handleSetNonce(nonce){
150 this.setState({ nonce })
151 this.handleClearStx()
156 handleSetChainId(chainId){
157 this.setState({ chainId })
158 this.handleClearStx()
163 handleSetGasPrice(gasPrice){
164 this.setState({ gasPrice })
165 this.handleClearStx()
170 handleSetGasLimit(gasLimit){
171 this.setState({ gasLimit })
172 this.handleClearStx()
180 stx: Maybe.Nothing(),
189 txn: Maybe.Nothing(),
190 stx: Maybe.Nothing(),
196 handleClearTransaction() {
199 txn: Maybe.Nothing(),
200 stx: Maybe.Nothing(),
207 const { props, state } = this
208 sendSignedTransaction(props.web3.value, state.stx)
210 props.setTxnHashCursor(sent)
212 props.pushRoute(ROUTE_NAMES.SENT_TRANSACTION)
215 this.setState({ txError: err.map(val => val.merge()) })
221 createUnsignedTxn() {
222 const { state, props } = this
224 const validContracts = props.contracts.matchWith({
225 Just: (cs) => cs.value,
227 throw BRIDGE_ERROR.MISSING_CONTRACTS
231 const validPoint = props.pointCursor.matchWith({
232 Just: (shp) => shp.value,
234 throw BRIDGE_ERROR.MISSING_POINTs
238 const txn = azimuth.ecliptic.setTransferProxy(
241 state.receivingAddress
244 return Maybe.Just(txn)
250 const { props, state } = this
252 const validAddress = isValidAddress(state.receivingAddress)
254 const canGenerate = validAddress === true
256 const canSign = Maybe.Just.hasInstance(state.txn)
257 const canApprove = Maybe.Just.hasInstance(state.stx)
258 const canSend = Maybe.Just.hasInstance(state.stx) && state.userApproval === true
261 props.networkType === NETWORK_NAMES.ROPSTEN ||
262 props.networkType === NETWORK_NAMES.MAINNET
265 props.networkType === NETWORK_NAMES.ROPSTEN
266 ? "ropsten.etherscan.io"
273 { 'Transfer'} <code>{ ` ${ob.patp(state.issuingPoint)} ` }</code>
279 `Please provide the Ethereum address of the new owner. You own these
280 points until the recipient accepts the incoming transfer.
281 You may cancel the transfer until the transfer is accepted.`
286 className={'mono mt-8'}
288 prop-format='innerLabel'
289 value={ state.receivingAddress }
290 placeholder={ `e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f` }
291 onChange={ v => this.handleAddressInput(v) }>
292 <InnerLabel>{ 'New ownership address' }</InnerLabel>
293 <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
299 prop-disabled={!isValidAddress(state.receivingAddress) || !esvisible}
301 href={`https://${esdomain}/address/${state.receivingAddress}`}>
302 {'View on Etherscan ↗'}
305 <StatelessTransaction
308 contracts={props.contracts}
309 wallet={props.wallet}
310 walletType={props.walletType}
311 walletHdPath={props.walletHdPath}
312 networkType={props.networkType}
318 gasPrice={state.gasPrice}
319 chainId={state.chainId}
320 gasLimit={state.gasLimit}
321 showGasDetails={state.showGasDetails}
322 toggleGasDetails={this.toggleGasDetails}
324 userApproval={state.userApproval}
325 canGenerate={ canGenerate }
327 canApprove={ canApprove }
330 createUnsignedTxn={this.handleCreateUnsignedTxn}
331 setUserApproval={this.handleSetUserApproval}
332 setTxn={this.handleSetTxn}
333 setStx={this.handleSetStx}
334 setNonce={this.handleSetNonce}
335 setChainId={this.handleSetChainId}
336 setGasPrice={this.handleSetGasPrice}
337 setGasLimit={this.handleSetGasLimit}
338 handleSubmit={this.handleSubmit} />
341 Maybe.Nothing.hasInstance(state.txError)
343 : <Warning className={'mt-8'}>
344 <H3 style={{marginTop: 0, paddingTop: 0}}>
346 'There was an error sending your transaction.'
349 { state.txError.value }
359export 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