@bzxnetwork/portal
Version:
Frontend demo portal for bZx
398 lines (347 loc) • 12.1 kB
JSX
import { Fragment } from "react";
import styled from "styled-components";
import MuiButton from "@material-ui/core/Button";
import BZxComponent from "../common/BZxComponent";
import { COLORS } from "../styles/constants";
import { fromBigNumber, toBigNumber } from "../common/utils";
import { Input, InputLabel, InputAdornment, FormControl, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@material-ui/core";
const IsSaleLive = true;
const InfoContainer = styled.div`
display: flex;
align-items: center;
`;
const ShowInfo = styled.div`
display: inline-block;
margin: 6px;
`;
const Button = styled(MuiButton)`
margin: 6px !important;
`;
const DataPointContainer = styled.div`
display: flex;
justify-content: flex-start;
align-items: center;
margin-bottom: 6px;
`;
const DataPoint = styled.span`
margin-left: 16px;
`;
const Label = styled.span`
font-weight: 600;
color: ${COLORS.gray};
`;
const AddressLink = styled.a.attrs({
target: `_blank`,
rel: `noopener noreferrer`
})`
//display: inline-block;
font-family: monospace;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 20ch;
`;
const TxHashLink = styled.a.attrs({
target: `_blank`,
rel: `noopener noreferrer`
})`
font-family: monospace;
display: block;
text-overflow: ellipsis;
overflow: auto;
}
`;
function stringToHex (tmp) {
if (!tmp)
return '';
var str = '',
i = 0,
tmp_len = tmp.length,
c;
for (; i < tmp_len; i += 1) {
c = tmp.charCodeAt(i);
str += c.toString(16);
}
return str;
}
export default class Tokensale extends BZxComponent {
state = {
loading: false,
error: false,
tokenBalance: null,
//totalTokens: 0,
//totalTokenBonus: 0,
//ethRate: 0,
tokensaleContract: null,
tokenContract: null,
bzrxTokenAddress: null,
showBuyDialog: false,
buyAmount: 0,
affiliateHex: stringToHex(this.props.affiliate),
ethRaised: null
};
async componentDidMount() {
const tokensaleContract = await this.props.bZx.getWeb3Contract(`BZRxTokenSale`);
const tokenContract = await this.props.bZx.getWeb3Contract(`BZxToken`);
console.log(`Token contract:`, tokenContract._address);
let currentTokenBonus;
switch (this.props.bZx.networkId) {
case 1: {
//bzrxTokenAddress = `0x1c74cFF0376FB4031Cd7492cD6dB2D66c3f2c6B9`;
currentTokenBonus = `107`;
break;
}
case 3: {
//bzrxTokenAddress = `0xF8b0B6Ee32a617beca665b6c5B241AC15b1ACDD5`;
currentTokenBonus = `107`;
break;
}
default: {
//bzrxTokenAddress = await this.wrapAndRun(tokensaleContract.methods.bZRxTokenContractAddress().call());
currentTokenBonus = await this.wrapAndRun(tokensaleContract.methods.bonusMultiplier().call());
break;
}
}
//console.log(`BZRX Token:`, bzrxTokenAddress);
await this.setState({
tokensaleContract,
tokenContract,
currentTokenBonus: toBigNumber(currentTokenBonus).minus(100).toString()
});
await this.refreshTokenData();
}
refreshTokenData = async () => {
const { accounts } = this.props;
const { tokenContract, tokensaleContract } = this.state;
await this.setState({ loading: true, tokenBalance: null, ethRaised: null });
console.log(`Token contract:`, tokenContract._address);
try {
const tokenBalance = await window.pqueueGeneral.add(() => this.wrapAndRun(tokenContract.methods.balanceOf(accounts[0]).call()));
//const tokenData = await this.wrapAndRun(tokensaleContract.methods.purchases(accounts[0]).call());
//console.log(tokenData);
//const ethRate = await this.wrapAndRun(tokensaleContract.methods.getEthRate().call());
//console.log(ethRate);
const ethRaised = await window.pqueueGeneral.add(() => this.wrapAndRun(tokensaleContract.methods.ethRaised().call()));
//console.log(ethRaised);
this.setState({
tokenBalance: tokenBalance,
ethRaised: ethRaised,
loading: false,
error: false
});
} catch(e) {
console.log(e);
this.setState({
error: true,
loading: false,
tokenBalance: 0,
});
}
}
setBuyAmount = e => this.setState({ buyAmount: e.target.value });
toggleBuyDialog = () =>
this.setState(p => ({ showBuyDialog: !p.showBuyDialog }));
buyToken = async () => {
const { web3, bZx, accounts } = this.props;
const { buyAmount, tokensaleContract } = this.state;
if (bZx.portalProviderName !== `MetaMask`) {
alert(`Please confirm this transaction on your device.`);
}
const txOpts = {
from: accounts[0],
gas: 2000000,
gasPrice: window.defaultGasPrice.toString(),
value: toBigNumber(buyAmount, 1e18)
};
const txObj = await tokensaleContract.methods.buyToken();
try {
await txObj
.estimateGas(txOpts)
.then(gas => {
console.log(gas);
txOpts.gas = window.gasValue(gas)+10000;
txOpts.data = `0xa4821719` + this.state.affiliateHex;
console.log(txOpts);
web3.eth.sendTransaction(txOpts)
.once(`transactionHash`, hash => {
alert(`Transaction submitted, transaction hash:`, {
component: () => (
<TxHashLink href={`${bZx.etherscanURL}tx/${hash}`}>
{hash}
</TxHashLink>
)
});
this.setState({ buyAmount: ``, showBuyDialog: false });
})
.then(async () => {
alert(`Your purchase is complete. It may take a few minutes for this page to update.`);
this.refreshTokenData();
})
.catch(error => {
console.error(error.message);
alert(`The purchase did not complete. Please try again.`);
this.setState({ buyAmount: ``, showBuyDialog: false });
});
})
.catch(error => {
console.error(error.message);
alert(`The purchase did not complete. Please try again.`);
this.setState({ buyAmount: ``, showBuyDialog: false });
});
} catch (error) {
console.error(error.message);
alert(`The purchase did not complete. Please try again.`);
this.setState({ buyAmount: ``, showBuyDialog: false });
}
};
render() {
const {
loading,
error,
tokenBalance,
tokensaleContract,
tokenContract,
currentTokenBonus,
ethRaised
} = this.state;
/*if (error) {
return (
<div>
<InfoContainer>
<ShowInfo>Web3 error loading. Please refresh in a few minutes.</ShowInfo>
<Button onClick={this.refreshTokenData} variant="raised" disabled={false}>
Refresh
</Button>
</InfoContainer>
</div>
);
}*/
const tokensaleContractAddress = tokensaleContract ? tokensaleContract._address : null;
const tokensaleContractLink = `${this.props.bZx.etherscanURL}address/${tokensaleContractAddress}`;
const bzrxTokenAddress = tokenContract ? tokenContract._address : null;
const bzrxTokenAddressLink = `${this.props.bZx.etherscanURL}address/${bzrxTokenAddress}`;
return (
<div>
<InfoContainer>
<Button
onClick={this.refreshTokenData}
variant="raised"
disabled={loading}
>
{loading ? `Refreshing...` : `Refresh`}
</Button>
</InfoContainer>
<br/>
<InfoContainer>
<ShowInfo>
{!IsSaleLive ? (
<Fragment>
<div style={{ fontWeight: `900` }}>*** The token sale is temporarily paused and will resume shortly. Please check back later. ***</div>
<br/>
</Fragment>
) : ``}
<DataPointContainer>
<Label>Tokensale Contract</Label>
<DataPoint>
<AddressLink href={tokensaleContractLink}>
{tokensaleContractAddress}
</AddressLink>
</DataPoint>
</DataPointContainer>
<DataPointContainer>
<Label>bZx Protocol Token (BZRX)</Label>
<DataPoint>
<AddressLink href={bzrxTokenAddressLink}>
{bzrxTokenAddress}
</AddressLink>
</DataPoint>
</DataPointContainer>
<br/>
<DataPointContainer>
<Label>Current Token Price (locked)</Label>
<DataPoint>
0.000073 ETH
</DataPoint>
</DataPointContainer>
<DataPointContainer>
<Label>ETH Raised in Current Sale</Label>
<DataPoint>
{loading || ethRaised == null ?
`Loading...` :
fromBigNumber(
ethRaised,
10 ** 18
)+` ETH`
}
</DataPoint>
</DataPointContainer>
<br/>
<DataPointContainer>
<Label>Your Token Balance</Label>
<DataPoint>
{loading || tokenBalance == null ?
`Loading...` :
fromBigNumber(
tokenBalance,
10 ** 18
)+` BZRX`
}
</DataPoint>
</DataPointContainer>
<br/>
<DataPointContainer>
<Button
variant="raised"
color="primary"
onClick={this.toggleBuyDialog}
disabled={!IsSaleLive}
style={{ marginLeft: `12px` }}
>
Purchase BZRX Token
</Button>
</DataPointContainer>
</ShowInfo>
</InfoContainer>
<Dialog
open={this.state.showBuyDialog}
onClose={this.toggleBuyDialog}
>
<DialogTitle>Purchase BZRX Tokens</DialogTitle>
<DialogContent>
<DialogContentText>
{this.state.affiliateHex ? (
<Fragment>
BZRX tokens cost 0.000073 ETH each. Please specify the amount of Ether you want
to send for your purchase. Your purchase will include an additional token bonus of {currentTokenBonus}%.
</Fragment>
) : (
<Fragment>
BZRX tokens cost 0.000073 ETH each. Please specify the amount of Ether you want
to send for your purchase. Your purchase will include an additional token bonus of {currentTokenBonus}%.
</Fragment>
)}
</DialogContentText>
<br/>
<FormControl fullWidth>
<InputLabel>Purchase Amount</InputLabel>
<Input
value={this.state.buyAmount}
type="number"
onChange={this.setBuyAmount}
endAdornment={
<InputAdornment position="end">ETH</InputAdornment>
}
/>
</FormControl>
</DialogContent>
<DialogActions>
<Button onClick={this.toggleBuyDialog}>Cancel</Button>
<Button onClick={this.buyToken} color="primary">
Buy
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}