import Maybe from 'folktale/maybe' import React from 'react' import * as azimuth from 'azimuth-js' import { Row, Col, H1, H3, P, InnerLabel, ShowBlockie, Anchor } from '../components/Base' import { AddressInput, Form, Warning } from '../components/Base' import * as ob from 'urbit-ob' import { PROXY_TYPE, renderProxyType } from '../lib/proxy' import { BRIDGE_ERROR } from '../lib/error' import StatelessTransaction from '../components/StatelessTransaction' import { ROUTE_NAMES } from '../lib/router' import { sendSignedTransaction, fromWei, } from '../lib/txn' import { isValidAddress, addressFromSecp256k1Public, } from '../lib/wallet' const SetManagementProxy = (props) => const SetSpawnProxy = (props) => const SetTransferProxy = (props) => class SetProxy extends React.Component { constructor(props) { super(props) const issuingPoint = props.pointCursor.matchWith({ Just: (shp) => shp.value, Nothing: () => { throw BRIDGE_ERROR.MISSING_POINT } }) this.state = { proxyAddress: '', txn: Maybe.Nothing(), txError: Maybe.Nothing(), issuingPoint: issuingPoint, userApproval: false, nonce: '', gasPrice: '5', chainId: '', gasLimit: '600000', stx: Maybe.Nothing(), } this.handleAddressInput = this.handleAddressInput.bind(this) // Transaction this.handleCreateUnsignedTxn = this.handleCreateUnsignedTxn.bind(this) this.handleSubmit = this.handleSubmit.bind(this) this.handleSetUserApproval = this.handleSetUserApproval.bind(this) this.handleSetTxn = this.handleSetTxn.bind(this) this.handleSetStx = this.handleSetStx.bind(this) this.handleSetNonce = this.handleSetNonce.bind(this) this.handleSetChainId = this.handleSetChainId.bind(this) this.handleSetGasPrice = this.handleSetGasPrice.bind(this) this.handleSetGasLimit = this.handleSetGasLimit.bind(this) } componentDidMount() { const { props } = this const addr = props.wallet.matchWith({ Just: wal => addressFromSecp256k1Public(wal.value.publicKey), Nothing: () => { throw BRIDGE_ERROR.MISSING_WALLET } }) props.web3.matchWith({ Nothing: () => {}, Just: (w3) => { const validWeb3 = w3.value const getTxMetadata = [ validWeb3.eth.getTransactionCount(addr), validWeb3.eth.net.getId(), validWeb3.eth.getGasPrice() ]; Promise.all(getTxMetadata).then(r => { const txMetadata = { nonce: r[0], chainId: r[1], gasPrice: fromWei(r[2], 'gwei'), }; this.setState({...txMetadata}) }) } }); } handleAddressInput(proxyAddress) { this.setState({ proxyAddress }) this.handleClearTxn() } handleCreateUnsignedTxn() { const txn = this.createUnsignedTxn() this.setState({ txn }) } handleSetUserApproval(){ const {state} = this this.setState({ userApproval: !state.userApproval }) } handleSetTxn(txn){ this.setState({ txn }) } handleSetStx(stx){ this.setState({ stx, userApproval: false, }) } handleSetNonce(nonce){ this.setState({ nonce }) this.handleClearStx() } handleSetChainId(chainId){ this.setState({ chainId }) this.handleClearStx() } handleSetGasPrice(gasPrice){ this.setState({ gasPrice }) this.handleClearStx() } handleSetGasLimit(gasLimit){ this.setState({ gasLimit }) this.handleClearStx() } handleClearStx() { this.setState({ userApproval: false, stx: Maybe.Nothing(), }) } handleClearTxn() { this.setState({ userApproval: false, txn: Maybe.Nothing(), stx: Maybe.Nothing(), }) } handleClearTransaction() { this.setState({ userApproval: false, txn: Maybe.Nothing(), stx: Maybe.Nothing(), }) } handleSubmit(){ const { props, state } = this sendSignedTransaction(props.web3.value, state.stx) .then(sent => { props.setTxnCursor(sent) props.popRoute() props.pushRoute(ROUTE_NAMES.SENT_TRANSACTION) }) .catch(err => { // Note that value.value is due to wrapped Maybe.Just + Result.Error this.setState({ txError: Maybe.Just(err.value.value) }) }) } createUnsignedTxn(proxyAddress) { const { state, props } = this const validContracts = props.contracts.matchWith({ Just: (cs) => cs.value, Nothing: () => { throw BRIDGE_ERROR.MISSING_CONTRACTS } }) const validPoint = props.pointCursor.matchWith({ Just: (shp) => shp.value, Nothing: () => { throw BRIDGE_ERROR.MISSING_POINT } }) const txArgs = [ validContracts, validPoint, state.proxyAddress ] if (props.proxyType === PROXY_TYPE.TRANSFER_PROXY) { return Maybe.Just(azimuth.ecliptic.setTransferProxy(...txArgs)) } if (props.proxyType === PROXY_TYPE.SPAWN_PROXY) { return Maybe.Just(azimuth.ecliptic.setSpawnProxy(...txArgs)) } if (props.proxyType === PROXY_TYPE.MANAGEMENT_PROXY) { return Maybe.Just(azimuth.ecliptic.setManagementProxy(...txArgs)) } return Maybe.Nothing() } render() { const { props, state } = this const renderedProxyType = renderProxyType(props.proxyType) const validAddress = isValidAddress(state.proxyAddress) const canGenerate = validAddress === true const canSign = !Maybe.Nothing.hasInstance(state.txn) const canApprove = !Maybe.Nothing.hasInstance(state.stx) const canSend = !Maybe.Nothing.hasInstance(state.stx) && state.userApproval === true const ucFirst = w => w.charAt(0).toUpperCase() + w.slice(1); return ( { `Set ${ucFirst(renderedProxyType)} Proxy For ` } { `${ob.patp(state.issuingPoint)}` } { 'Please provide an Ethereum address to act as the ' + `${renderedProxyType} proxy. You can also use Wallet ` + 'Generator to generate a keypair.' } this.handleAddressInput(v) }> { 'Proxy Address' } {'View on Etherscan ↗'} { Maybe.Nothing.hasInstance(state.txError) ? '' : { 'There was an error sending your transaction.' } { state.txError.value } } ) } } export { SetManagementProxy, SetSpawnProxy, SetTransferProxy }
{ `${ob.patp(state.issuingPoint)}` }
{ 'Please provide an Ethereum address to act as the ' + `${renderedProxyType} proxy. You can also use Wallet ` + 'Generator to generate a keypair.' }