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 { ROUTE_NAMES } from '../lib/router'
14 sendSignedTransaction,
20 addressFromSecp256k1Public
21 } from '../lib/wallet'
23class Transfer extends React.Component {
27 const issuingPoint = props.pointCursor.matchWith({
28 Just: (pt) => pt.value,
30 throw BRIDGE_ERROR.MISSING_POINT
35 txError: Maybe.Nothing(),
37 issuingPoint: issuingPoint,
46 this.handleAddressInput = this.handleAddressInput.bind(this)
48 this.handleCreateUnsignedTxn = this.handleCreateUnsignedTxn.bind(this)
49 this.handleSubmit = this.handleSubmit.bind(this)
50 this.handleSetUserApproval = this.handleSetUserApproval.bind(this)
51 this.handleSetTxn = this.handleSetTxn.bind(this)
52 this.handleSetStx = this.handleSetStx.bind(this)
53 this.handleSetNonce = this.handleSetNonce.bind(this)
54 this.handleSetChainId = this.handleSetChainId.bind(this)
55 this.handleSetGasPrice = this.handleSetGasPrice.bind(this)
56 this.handleSetGasLimit = this.handleSetGasLimit.bind(this)
61 const { props } = this
63 const addr = props.wallet.matchWith({
64 Just: wal => addressFromSecp256k1Public(wal.value.publicKey),
66 throw BRIDGE_ERROR.MISSING_WALLET
70 props.web3.matchWith({
73 const validWeb3 = w3.value
75 const getTxMetadata = [
76 validWeb3.eth.getTransactionCount(addr),
77 validWeb3.eth.net.getId(),
78 validWeb3.eth.getGasPrice()
81 Promise.all(getTxMetadata).then(r => {
85 gasPrice: fromWei(r[2], 'gwei'),
88 this.setState({...txMetadata})
98 handleAddressInput(receivingAddress) {
99 this.setState({ receivingAddress })
100 this.handleClearTxn()
105 handleConfirmAvailability() {
106 this.confirmPointAvailability().then(r => {
107 this.setState({ isAvailable: r })
113 handleCreateUnsignedTxn() {
114 const txn = this.createUnsignedTxn()
115 this.setState({ txn })
119 handleSetUserApproval(){
121 this.setState({ userApproval: !state.userApproval })
127 this.setState({ txn })
141 handleSetNonce(nonce){
142 this.setState({ nonce })
143 this.handleClearStx()
148 handleSetChainId(chainId){
149 this.setState({ chainId })
150 this.handleClearStx()
155 handleSetGasPrice(gasPrice){
156 this.setState({ gasPrice })
157 this.handleClearStx()
162 handleSetGasLimit(gasLimit){
163 this.setState({ gasLimit })
164 this.handleClearStx()
172 stx: Maybe.Nothing(),
181 txn: Maybe.Nothing(),
182 stx: Maybe.Nothing(),
188 handleClearTransaction() {
191 txn: Maybe.Nothing(),
192 stx: Maybe.Nothing(),
199 const { props, state } = this
200 sendSignedTransaction(props.web3.value, state.stx)
202 props.setTxnCursor(sent)
204 props.pushRoute(ROUTE_NAMES.SENT_TRANSACTION)
207 // Note that value.value is due to wrapped Maybe.Just + Result.Error
208 this.setState({ txError: Maybe.Just(err.value.value) })
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
257 { 'Transfer'} <code>{ ` ${ob.patp(state.issuingPoint)} ` }</code>
263 `Please provide the Ethereum address of the new owner. You own these
264 points until the recipient accepts the incoming transfer.
265 You may cancel the transfer until the transfer is accepted.`
270 className={'mono mt-8'}
272 prop-format='innerLabel'
273 value={ state.receivingAddress }
274 placeholder={ `e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f` }
275 onChange={ v => this.handleAddressInput(v) }>
276 <InnerLabel>{ 'New ownership address' }</InnerLabel>
277 <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
283 disabled={!isValidAddress(state.receivingAddress)}
285 href={`https://etherscan.io/address/${state.receivingAddress}`}>
286 {'View on Etherscan ↗'}
289 <StatelessTransaction
292 contracts={props.contracts}
293 wallet={props.wallet}
294 walletType={props.walletType}
295 walletHdPath={props.walletHdPath}
296 networkType={props.networkType}
302 gasPrice={state.gasPrice}
303 chainId={state.chainId}
304 gasLimit={state.gasLimit}
306 userApproval={state.userApproval}
307 canGenerate={ canGenerate }
309 canApprove={ canApprove }
312 createUnsignedTxn={this.handleCreateUnsignedTxn}
313 setUserApproval={this.handleSetUserApproval}
314 setTxn={this.handleSetTxn}
315 setStx={this.handleSetStx}
316 setNonce={this.handleSetNonce}
317 setChainId={this.handleSetChainId}
318 setGasPrice={this.handleSetGasPrice}
319 setGasLimit={this.handleSetGasLimit}
320 handleSubmit={this.handleSubmit} />
323 Maybe.Nothing.hasInstance(state.txError)
325 : <Warning className={'mt-8'}>
326 <H3 style={{marginTop: 0, paddingTop: 0}}>
328 'There was an error sending your transaction.'
331 { state.txError.value }
341export 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