2018-10-09 23:48:25 +02:00
|
|
|
import React, { PureComponent } from 'react'
|
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
import Web3 from 'web3'
|
2018-10-13 15:40:05 +02:00
|
|
|
import Input from '../atoms/Input'
|
2018-10-09 23:48:25 +02:00
|
|
|
import styles from './Web3Donation.module.scss'
|
|
|
|
|
|
|
|
const ONE_SECOND = 1000
|
|
|
|
const ONE_MINUTE = ONE_SECOND * 60
|
|
|
|
|
2018-10-13 18:13:36 +02:00
|
|
|
const InputGroup = ({
|
|
|
|
networkId,
|
|
|
|
selectedAccount,
|
|
|
|
amount,
|
|
|
|
onAmountChange,
|
|
|
|
handleWeb3Button
|
|
|
|
}) => (
|
|
|
|
<div className={styles.inputGroup}>
|
|
|
|
<div className={styles.input}>
|
|
|
|
<Input
|
|
|
|
type="number"
|
|
|
|
disabled={!(networkId === '1') || !selectedAccount}
|
|
|
|
value={amount}
|
|
|
|
onChange={onAmountChange}
|
|
|
|
min="0"
|
|
|
|
step="0.01"
|
|
|
|
/>
|
|
|
|
<div className={styles.currency}>
|
|
|
|
<span>ETH</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<button
|
|
|
|
className="btn btn-primary"
|
|
|
|
onClick={handleWeb3Button}
|
|
|
|
disabled={!(networkId === '1') || !selectedAccount}
|
|
|
|
>
|
|
|
|
Make it rain
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
|
|
|
|
InputGroup.propTypes = {
|
|
|
|
networkId: PropTypes.string,
|
|
|
|
selectedAccount: PropTypes.string,
|
|
|
|
amount: PropTypes.number,
|
|
|
|
onAmountChange: PropTypes.func,
|
|
|
|
handleWeb3Button: PropTypes.func
|
|
|
|
}
|
|
|
|
|
|
|
|
const Alerts = ({ accounts, networkId, error, transactionHash }) => {
|
|
|
|
if (error || accounts.length === 0) {
|
|
|
|
return (
|
|
|
|
<div className={styles.alert}>
|
|
|
|
{accounts.length === 0 &&
|
|
|
|
'Web3 detected, but no account. Are you logged into your MetaMask account?'}
|
|
|
|
{networkId !== '1' && 'Please connect to Main network'}
|
|
|
|
{error && error.message}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (transactionHash) {
|
|
|
|
return (
|
|
|
|
<div className={styles.success}>
|
|
|
|
You are awesome, thanks!
|
|
|
|
<br />
|
|
|
|
<a href={`https://etherscan.io/tx/${transactionHash}`}>
|
|
|
|
See your transaction on etherscan.io.
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
Alerts.propTypes = {
|
|
|
|
accounts: PropTypes.array,
|
|
|
|
networkId: PropTypes.string,
|
|
|
|
error: PropTypes.object,
|
|
|
|
transactionHash: PropTypes.string
|
|
|
|
}
|
|
|
|
|
2018-10-09 23:48:25 +02:00
|
|
|
export default class Web3Donation extends PureComponent {
|
|
|
|
state = {
|
|
|
|
web3Connected: false,
|
|
|
|
networkError: null,
|
|
|
|
networkId: null,
|
|
|
|
accounts: [],
|
|
|
|
selectedAccount: null,
|
2018-10-13 15:40:05 +02:00
|
|
|
amount: 0.01,
|
2018-10-11 23:18:03 +02:00
|
|
|
receipt: null,
|
|
|
|
transactionHash: null,
|
2018-10-09 23:48:25 +02:00
|
|
|
loading: false,
|
|
|
|
error: null
|
|
|
|
}
|
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
address: PropTypes.string
|
|
|
|
}
|
|
|
|
|
2018-10-11 20:06:02 +02:00
|
|
|
web3 = null
|
2018-10-09 23:48:25 +02:00
|
|
|
interval = null
|
|
|
|
networkInterval = null
|
|
|
|
|
|
|
|
componentDidMount() {
|
2018-10-11 20:06:02 +02:00
|
|
|
if (typeof window.web3 === 'undefined') {
|
|
|
|
// no web3
|
|
|
|
this.setState({ web3Connected: false })
|
|
|
|
} else {
|
2018-10-11 23:18:03 +02:00
|
|
|
// this.web3 = new Web3(Web3.givenProvider || 'ws://localhost:8546')
|
|
|
|
this.web3 = new Web3(window.web3.currentProvider)
|
2018-10-09 23:48:25 +02:00
|
|
|
this.setState({ web3Connected: true })
|
|
|
|
|
|
|
|
this.fetchAccounts()
|
|
|
|
this.fetchNetwork()
|
|
|
|
this.initPoll()
|
|
|
|
this.initNetworkPoll()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
clearInterval(this.interval)
|
|
|
|
clearInterval(this.networkInterval)
|
|
|
|
this.setState({ web3Connected: false })
|
|
|
|
}
|
|
|
|
|
|
|
|
initPoll() {
|
|
|
|
if (!this.interval) {
|
|
|
|
this.interval = setInterval(this.fetchAccounts, ONE_SECOND)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
initNetworkPoll() {
|
|
|
|
if (!this.networkInterval) {
|
|
|
|
this.networkInterval = setInterval(this.fetchNetwork, ONE_MINUTE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchNetwork = () => {
|
|
|
|
const { web3 } = this
|
|
|
|
|
|
|
|
web3 &&
|
|
|
|
web3.eth &&
|
2018-10-11 23:18:03 +02:00
|
|
|
//web3.eth.net.getId((err, netId) => {
|
|
|
|
web3.version.getNetwork((err, netId) => {
|
2018-10-09 23:48:25 +02:00
|
|
|
if (err) {
|
2018-10-11 20:06:02 +02:00
|
|
|
this.setState({ networkError: err })
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netId != this.state.networkId) {
|
2018-10-09 23:48:25 +02:00
|
|
|
this.setState({
|
2018-10-11 20:06:02 +02:00
|
|
|
networkError: null,
|
|
|
|
networkId: netId
|
2018-10-09 23:48:25 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchAccounts = () => {
|
|
|
|
const { web3 } = this
|
|
|
|
|
|
|
|
web3 &&
|
|
|
|
web3.eth &&
|
|
|
|
web3.eth.getAccounts((err, accounts) => {
|
|
|
|
if (err) {
|
2018-10-11 20:06:02 +02:00
|
|
|
this.setState({ accountsError: err })
|
2018-10-09 23:48:25 +02:00
|
|
|
}
|
2018-10-11 20:06:02 +02:00
|
|
|
|
|
|
|
this.setState({
|
|
|
|
accounts,
|
|
|
|
selectedAccount: accounts[0]
|
|
|
|
})
|
2018-10-09 23:48:25 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
handleWeb3Button = () => {
|
|
|
|
const { web3 } = this
|
|
|
|
|
|
|
|
this.setState({ loading: true })
|
|
|
|
|
2018-10-11 23:18:03 +02:00
|
|
|
// web3.eth
|
|
|
|
// .sendTransaction({
|
|
|
|
// from: this.state.selectedAccount,
|
|
|
|
// to: this.props.address,
|
|
|
|
// value: '10000000000000000'
|
|
|
|
// })
|
|
|
|
// .then(receipt => {
|
|
|
|
// this.setState({ receipt, loading: false })
|
|
|
|
// })
|
|
|
|
// .catch(error => {
|
|
|
|
// this.setState({ error, loading: false })
|
|
|
|
// })
|
|
|
|
|
|
|
|
web3.eth.sendTransaction(
|
|
|
|
{
|
2018-10-09 23:48:25 +02:00
|
|
|
from: this.state.selectedAccount,
|
|
|
|
to: this.props.address,
|
2018-10-13 15:40:05 +02:00
|
|
|
value: this.state.amount * 1e18 // ETH -> Wei
|
2018-10-11 23:18:03 +02:00
|
|
|
},
|
|
|
|
(error, transactionHash) => {
|
|
|
|
if (error) this.setState({ error, loading: false })
|
|
|
|
if (!transactionHash) this.setState({ loading: true })
|
|
|
|
this.setState({ transactionHash, loading: false })
|
|
|
|
}
|
|
|
|
)
|
2018-10-09 23:48:25 +02:00
|
|
|
}
|
|
|
|
|
2018-10-13 15:40:05 +02:00
|
|
|
onAmountChange = ({ target }) => {
|
|
|
|
this.setState({ amount: target.value })
|
|
|
|
}
|
|
|
|
|
2018-10-09 23:48:25 +02:00
|
|
|
render() {
|
2018-10-11 20:06:02 +02:00
|
|
|
return (
|
|
|
|
<div className={styles.web3}>
|
2018-10-13 18:13:36 +02:00
|
|
|
<header>
|
|
|
|
<h4>web3</h4>
|
|
|
|
<p>Send Ether with MetaMask, Brave, or Mist.</p>
|
|
|
|
</header>
|
2018-10-11 20:06:02 +02:00
|
|
|
|
|
|
|
{this.state.web3Connected ? (
|
2018-10-13 18:13:36 +02:00
|
|
|
<div className={styles.web3Row}>
|
2018-10-11 20:06:02 +02:00
|
|
|
{this.state.loading ? (
|
|
|
|
'Hang on...'
|
|
|
|
) : (
|
2018-10-13 18:13:36 +02:00
|
|
|
<InputGroup
|
|
|
|
networkId={this.state.networkId}
|
|
|
|
selectedAccount={this.state.selectedAccount}
|
|
|
|
amount={this.state.amount}
|
|
|
|
onAmountChange={this.onAmountChange}
|
|
|
|
handleWeb3Button={this.handleWeb3Button}
|
|
|
|
/>
|
2018-10-11 20:06:02 +02:00
|
|
|
)}
|
|
|
|
|
2018-10-13 18:13:36 +02:00
|
|
|
<Alerts
|
|
|
|
accounts={this.state.accounts}
|
|
|
|
networkId={this.state.networkId}
|
|
|
|
error={this.state.error}
|
|
|
|
transactionHash={this.state.transactionHash}
|
|
|
|
/>
|
2018-10-11 20:06:02 +02:00
|
|
|
</div>
|
|
|
|
) : (
|
2018-10-13 18:13:36 +02:00
|
|
|
<small>
|
|
|
|
No Web3 detected. Install <a href="https://metamask.io">MetaMask</a>
|
|
|
|
, <a href="https://brave.com">Brave</a>, or{' '}
|
|
|
|
<a href="https://github.com/ethereum/mist">Mist</a>.
|
|
|
|
</small>
|
2018-10-11 20:06:02 +02:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)
|
2018-10-09 23:48:25 +02:00
|
|
|
}
|
|
|
|
}
|