1
0
mirror of https://github.com/kremalicious/blog.git synced 2025-01-03 02:15:08 +01:00
This commit is contained in:
Matthias Kretschmann 2018-10-30 18:08:07 +01:00
parent 86948a5340
commit 87f6f426c2
Signed by: m
GPG Key ID: 606EEEF3C479A91F
6 changed files with 135 additions and 160 deletions

View File

@ -94,7 +94,7 @@
"prettier": "^1.14.3",
"prettier-eslint-cli": "^4.7.1",
"prettier-stylelint": "^0.4.2",
"stylelint": "^9.6.0",
"stylelint": "^9.7.0",
"stylelint-config-css-modules": "^1.3.0",
"stylelint-config-standard": "^18.2.0",
"stylelint-scss": "^3.3.2"

View File

@ -2,65 +2,58 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import styles from './Alerts.module.scss'
const Message = ({ message, ...props }) => (
<div dangerouslySetInnerHTML={{ __html: message }} {...props} />
)
export const alertMessages = (networkName, transactionHash) => ({
noAccount:
'Web3 detected, but no account. Are you logged into your MetaMask account?',
noCorrectNetwork: `Please connect to <strong>Main</strong> network. You are on <strong>${networkName}</strong> right now.`,
noWeb3:
'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>.',
transaction: `<a href="https://etherscan.io/tx/${transactionHash}" target="_blank">See your transaction on etherscan.io.</a>`,
waitingForUser: 'Waiting for your confirmation',
waitingConfirmation: 'Waiting for network confirmation, hang on',
success: 'Confirmed. You are awesome, thanks!'
})
export default class Alerts extends PureComponent {
static propTypes = {
hasCorrectNetwork: PropTypes.bool.isRequired,
hasAccount: PropTypes.bool.isRequired,
networkName: PropTypes.string,
error: PropTypes.object,
transactionHash: PropTypes.string,
confirmationNumber: PropTypes.number,
receipt: PropTypes.object,
web3Connected: PropTypes.bool.isRequired
message: PropTypes.object,
transactionHash: PropTypes.string
}
alertMessages = (networkName, transactionHash) => ({
noAccount:
'Web3 detected, but no account. Are you logged into your MetaMask account?',
noCorrectNetwork: `Please connect to <strong>Main</strong> network. You are on <strong>${networkName}</strong> right now.`,
noWeb3:
'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>.',
transaction: `<a href="https://etherscan.io/tx/${transactionHash}" target="_blank">See your transaction on etherscan.io.</a>`
})
constructMessage = () => {
const { transactionHash, message } = this.props
let messageOutput
if (transactionHash) {
messageOutput =
message.text +
'<br />' +
alertMessages(null, transactionHash).transaction
} else {
messageOutput = message.text
}
return messageOutput
}
classes() {
const { status } = this.props.message
if (status === 'success') {
return styles.success
} else if (status === 'error') {
return styles.error
}
return styles.alert
}
render() {
const {
hasCorrectNetwork,
hasAccount,
networkName,
error,
transactionHash,
web3Connected
} = this.props
return (
<div className={styles.alert}>
{!web3Connected ? (
<Message message={this.alertMessages().noWeb3} />
) : (
<>
{!hasAccount && (
<Message message={this.alertMessages().noAccount} />
)}
{!hasCorrectNetwork && (
<Message
message={this.alertMessages(networkName).noCorrectNetwork}
/>
)}
{error && <Message message={error.message} />}
{transactionHash && (
<Message
message={this.alertMessages(null, transactionHash).transaction}
/>
)}
</>
)}
</div>
<div
className={this.classes()}
dangerouslySetInnerHTML={{ __html: this.constructMessage() }}
/>
)
}
}

View File

@ -2,16 +2,44 @@
@import 'mixins';
.alert {
margin-top: $spacer / 2;
font-size: $font-size-small;
color: darken($alert-error, 60%);
display: inline-block;
&:empty {
display: none;
}
&::after {
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis steps(4, end) 1s infinite;
content: '\2026'; // ascii code for the ellipsis character
width: 0;
position: absolute;
}
}
.error {
composes: alert;
color: darken($alert-error, 60%);
&::after {
display: none;
}
}
.success {
composes: alert;
color: darken($alert-success, 60%);
&::after {
display: none;
}
}
@keyframes ellipsis {
to {
width: .75rem;
}
}

View File

@ -7,21 +7,17 @@ import styles from './InputGroup.module.scss'
export default class InputGroup extends PureComponent {
static propTypes = {
isCorrectNetwork: PropTypes.bool.isRequired,
hasAccount: PropTypes.bool.isRequired,
amount: PropTypes.string.isRequired,
onAmountChange: PropTypes.func.isRequired,
handleButton: PropTypes.func.isRequired,
sendTransaction: PropTypes.func.isRequired,
selectedAccount: PropTypes.string
}
render() {
const {
isCorrectNetwork,
hasAccount,
amount,
onAmountChange,
handleButton,
sendTransaction,
selectedAccount
} = this.props
@ -30,7 +26,6 @@ export default class InputGroup extends PureComponent {
<div className={styles.input}>
<Input
type="number"
disabled={!isCorrectNetwork || !hasAccount}
value={amount}
onChange={onAmountChange}
min="0"
@ -40,20 +35,13 @@ export default class InputGroup extends PureComponent {
<span>ETH</span>
</div>
</div>
<button
className="btn btn-primary"
onClick={handleButton}
disabled={!isCorrectNetwork || !hasAccount}
>
<button className="btn btn-primary" onClick={sendTransaction}>
Make it rain
</button>
{isCorrectNetwork &&
hasAccount && (
<div className={styles.infoline}>
<Conversion amount={amount} />
{selectedAccount && <Account account={selectedAccount} />}
</div>
)}
<div className={styles.infoline}>
<Conversion amount={amount} />
{selectedAccount && <Account account={selectedAccount} />}
</div>
</div>
)
}

View File

@ -1,29 +1,25 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import InputGroup from './InputGroup'
import Alerts from './Alerts'
import Alerts, { alertMessages } from './Alerts'
import styles from './index.module.scss'
import { getWeb3, getAccounts, getNetwork } from './utils'
const ONE_SECOND = 1000
const ONE_MINUTE = ONE_SECOND * 60
const correctNetwork = 1
export default class Web3Donation extends PureComponent {
state = {
web3Connected: false,
netId: null,
networkName: null,
isCorrectNetwork: false,
loading: true,
accounts: [],
selectedAccount: null,
amount: '0.01',
transactionHash: null,
receipt: null,
inTransaction: false,
error: null,
message: 'Hang on',
success: false
message: null,
inTransaction: false
}
static propTypes = {
@ -43,22 +39,24 @@ export default class Web3Donation extends PureComponent {
}
initWeb3 = async () => {
this.setState({ message: { text: 'Checking' } })
try {
this.web3 = await getWeb3()
this.setState({ web3Connected: this.web3 ? true : false })
this.web3 ? this.initAllTheTings() : this.setState({ loading: false })
this.web3
? this.initAllTheTings()
: this.setState({
message: { status: 'error', text: alertMessages().noWeb3 }
})
} catch (error) {
this.setState({ error })
this.setState({ web3Connected: false })
this.setState({ message: { status: 'error', text: error } })
}
}
async initAllTheTings() {
await this.fetchAccounts()
await this.fetchNetwork()
this.setState({ loading: false })
this.fetchAccounts()
this.fetchNetwork()
this.initAccountsPoll()
this.initNetworkPoll()
@ -67,7 +65,6 @@ export default class Web3Donation extends PureComponent {
resetAllTheThings() {
clearInterval(this.interval)
clearInterval(this.networkInterval)
this.setState({ web3Connected: false })
}
initAccountsPoll() {
@ -84,40 +81,44 @@ export default class Web3Donation extends PureComponent {
fetchNetwork = async () => {
const { web3 } = this
const { netId, networkName } = await getNetwork(web3)
try {
const { netId, networkName } = await getNetwork(web3)
if (netId === correctNetwork) {
this.setState({ netId, networkName })
} else {
this.setState({
error: null,
netId,
networkName,
isCorrectNetwork: netId === 1
message: {
status: 'error',
text: alertMessages(networkName).noCorrectNetwork
}
})
} catch (error) {
this.setState({ error })
}
}
fetchAccounts = async () => {
const { web3 } = this
const accounts = await getAccounts(web3)
try {
const accounts = await getAccounts(web3)
if (accounts[0]) {
this.setState({
error: null,
accounts,
selectedAccount: accounts[0] ? accounts[0].toLowerCase() : null
selectedAccount: accounts[0].toLowerCase()
})
} else {
this.setState({
message: { status: 'error', text: alertMessages().noAccount }
})
} catch (error) {
this.setState({ error })
}
}
sendTransaction() {
sendTransaction = () => {
const { web3 } = this
this.setState({
inTransaction: true,
message: { text: alertMessages().waitingForUser }
})
web3.eth
.sendTransaction({
from: this.state.selectedAccount,
@ -127,50 +128,32 @@ export default class Web3Donation extends PureComponent {
.once('transactionHash', transactionHash => {
this.setState({
transactionHash,
message: 'Waiting for network confirmation, hang on'
message: { text: alertMessages().waitingConfirmation }
})
})
.on('error', error => this.setState({ error, inTransaction: false }))
.on('error', error =>
this.setState({ message: { status: 'error', text: error } })
)
.then(() => {
this.setState({
message: 'Confirmed. You are awesome, thanks!',
success: true
message: { status: 'success', text: alertMessages().success }
})
})
}
handleButton = () => {
this.setState({
inTransaction: true,
message: 'Waiting for your confirmation'
})
this.sendTransaction()
}
onAmountChange = ({ target }) => {
this.setState({ amount: target.value })
}
render() {
const {
isCorrectNetwork,
accounts,
selectedAccount,
web3Connected,
inTransaction,
loading,
amount,
networkName,
error,
transactionHash,
confirmationNumber,
message,
success
inTransaction
} = this.state
const hasAccount = accounts.length !== 0
return (
<div className={styles.web3}>
<header>
@ -179,38 +162,21 @@ export default class Web3Donation extends PureComponent {
</header>
<div className={styles.web3Row}>
{loading ? (
<div className={styles.message}>Checking</div>
) : inTransaction ? (
<div className={success ? styles.success : styles.message}>
{message}
</div>
{selectedAccount &&
this.state.netId === correctNetwork &&
!inTransaction ? (
<InputGroup
selectedAccount={selectedAccount}
amount={amount}
onAmountChange={this.onAmountChange}
sendTransaction={this.sendTransaction}
/>
) : (
web3Connected && (
<InputGroup
isCorrectNetwork={isCorrectNetwork}
hasAccount={hasAccount}
selectedAccount={selectedAccount}
amount={amount}
onAmountChange={this.onAmountChange}
handleButton={this.handleButton}
message={message}
/>
message && (
<Alerts message={message} transactionHash={transactionHash} />
)
)}
</div>
{!loading && (
<Alerts
hasCorrectNetwork={isCorrectNetwork}
hasAccount={hasAccount}
networkName={networkName}
error={error}
transactionHash={transactionHash}
web3Connected={web3Connected}
confirmationNumber={confirmationNumber}
/>
)}
</div>
)
}

View File

@ -37,7 +37,7 @@ class ModalThanks extends PureComponent {
<Web3Donation address={author.ether} />
<header>
<h4>Other wallets</h4>
<h4>Any other wallets</h4>
<p>Send Bitcoin or Ether from any wallet.</p>
</header>