Skip to content

Commit

Permalink
vesting
Browse files Browse the repository at this point in the history
  • Loading branch information
dimakorzhovnik committed Jan 21, 2020
1 parent 944334f commit 268e9d8
Show file tree
Hide file tree
Showing 9 changed files with 707 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/components/web3/web3Vesting.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const injectWeb3Vesting = InnerComponent =>
contractVesting,
contractTokenManager,
contractToken,
accounts: accounts[0],
accounts: accounts[0].toLowerCase(),
networkId,
isCorrectNetwork: networkContract.indexOf(`${networkId}`) !== -1,
});
Expand Down
6 changes: 3 additions & 3 deletions src/containers/application/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ class App extends Component {
const { openMenu, story, home, valueSearchInput } = this.state;
const { children } = this.props;

if (!story) {
return <div>{children}</div>;
}
// if (!story) {
// return <div>{children}</div>;
// }

return (
<div>
Expand Down
289 changes: 289 additions & 0 deletions src/containers/vesting/actionBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
import React, { Component } from 'react';
import { ActionBar, Button, Input, Pane } from '@cybercongress/gravity';
import { AUCTION, PATTERN_CYBER, CYBER } from '../../utils/config';

function lament(error) {
if (error) {
document.querySelector('.before-error').outerHTML += `
<div class="error pane">
<h3>${error.message}</h3>
<pre>${error.stack}</pre>
</div>
`;
}
}

const hopefully = $ => (error, result) => {
if (error) {
lament(error);
} else {
$(result);
}
};

const ping = tx =>
new Promise((resolve, reject) => {
loop();
function loop() {
window.web3.eth.getTransactionReceipt(tx, async (error, receipt) => {
if (receipt == null) {
resolve(receipt);
} else {
setTimeout(loop, 1000);
}

if (receipt) {
resolve(receipt);
} else {
setTimeout(loop, 1000);
}
});
}
});

const ActionBarContentText = ({ children, ...props }) => (
<Pane
display="flex"
fontSize="20px"
justifyContent="center"
alignItems="center"
flexGrow={1}
marginRight="15px"
{...props}
>
{children}
</Pane>
);

const GenerateTx = ({ onClickBtn, valueAmount, account }) => (
<ActionBar>
<ActionBarContentText>
Vest {valueAmount}
{AUCTION.TOKEN_NAME}s till the end of action and create proposal to claim{' '}
{valueAmount}
{CYBER.DENOM_CYBER.toUpperCase()}s to account {account}
</ActionBarContentText>
<Button onClick={onClickBtn}>GenerateTx</Button>
</ActionBar>
);

const Succesfuuly = ({ onClickBtn, hash }) => (
<ActionBar>
<ActionBarContentText flexDirection="column">
<div className="text-default">
Your TX has been broadcast to the network. It is waiting to be mined &
confirned.
</div>
<div className="text-default">
Check TX status:{' '}
<a
className="hash"
href={`https://rinkeby.etherscan.io/tx/${hash}`}
target="_blank"
>
{hash}
</a>
</div>
</ActionBarContentText>
<Button onClick={onClickBtn}>OK</Button>
</ActionBar>
);

const CreateVesting = ({
onClickBtn,
valueAddr,
valueAmount,
onChangeAmount,
onChangeAddr,
disabledBtnCreateVesting,
validAmount,
validAddr,
messageAddr,
messageAmount,
}) => (
<ActionBar>
<ActionBarContentText>
Vest
<Input
value={valueAmount}
onChange={onChangeAmount}
isInvalid={validAmount}
message={messageAmount}
marginLeft={15}
marginRight={5}
width="11%"
textAlign="end"
/>
<span>{AUCTION.TOKEN_NAME}s to account</span>
<Input
value={valueAddr}
onChange={onChangeAddr}
isInvalid={validAddr}
message={messageAddr}
width="30%"
marginLeft={15}
marginRight={10}
/>
</ActionBarContentText>
<Button disabled={disabledBtnCreateVesting} onClick={onClickBtn}>
Create Vesting
</Button>
</ActionBar>
);

class ActionBarVesting extends Component {
constructor(props) {
super(props);
this.state = {
step: 'start',
valueAddr: '',
valueAmount: '',
tx: null,
};
this.smart = AUCTION.ADDR_SMART_CONTRACT;
}

onClickLook = async accounts => {
const { web3, contractVesting } = this.props;
const { valueAmount, valueAddr } = this.state;

// const accountsCyber = 'cyber1gw5kdey7fs9wdh05w66s0h4s24tjdvtcp5fhky';

const getData = await contractVesting.methods
.lock(valueAmount, valueAddr)
.encodeABI();

try {
web3.eth.sendTransaction(
{
from: accounts,
to: AUCTION.ADDR_VESTING,
data: getData,
},
hopefully(result =>
ping(result).then(() => {
this.setState({
step: 'succesfuuly',
tx: result,
});
})
)
);
} catch (e) {
console.log(e);
}
};

onClickGenerateTx = async () => {
const { web3 } = this.props;
if (web3.currentProvider.host) {
return console.log(
'Non-Ethereum browser detected. You should consider trying MetaMask!'
);
}
if (window.ethereum) {
try {
const accounts = await window.ethereum.enable();
if (accounts.length) {
this.onClickLook(accounts[0]);
}
} catch (error) {
console.log('You declined transaction', error);
}
} else if (window.web3) {
const accounts = await web3.eth.getAccounts();
if (accounts.length) {
this.onClickLook(accounts[0]);
}
} else {
return console.log('Your metamask is locked!');
}
};

onClickSaveAddress = () => {
const { update } = this.props;
this.setState({
step: 'start',
valueAddr: '',
valueAmount: '',
tx: null,
});
if (update) {
update();
}
};

onClickTransactionCost = () =>
this.setState({
step: 'succesfuuly',
});

onChangeAmount = e =>
this.setState({
valueAmount: e.target.value,
});

onChangeAddr = e =>
this.setState({
valueAddr: e.target.value,
});

onClickCreateVesting = () => {
this.setState({
step: 'generateTx',
});
};

render() {
const { step, tx, valueAmount, valueAddr } = this.state;
const { web3 } = this.props;
const btnCreateVesting = valueAmount > 0 && valueAddr.match(PATTERN_CYBER);

if (web3.givenProvider === null) {
return (
<ActionBar>
<ActionBarContentText>
<span>Please install</span>
&nbsp;
<a href="https://metamask.io/" target="_blank">
Metamask extension
</a>
&nbsp;
<span>and refresh the page</span>
</ActionBarContentText>
</ActionBar>
);
}

if (step === 'start') {
return (
<CreateVesting
valueAmount={valueAmount}
onClickBtn={this.onClickCreateVesting}
valueAddr={valueAddr}
onChangeAmount={e => this.onChangeAmount(e)}
onChangeAddr={e => this.onChangeAddr(e)}
disabledBtnCreateVesting={!btnCreateVesting}
/>
);
}

if (step === 'generateTx') {
return (
<GenerateTx
valueAmount={valueAmount}
account={valueAddr}
onClickBtn={this.onClickGenerateTx}
/>
);
}

if (step === 'succesfuuly') {
return <Succesfuuly hash={tx} onClickBtn={this.onClickSaveAddress} />;
}

return null;
}
}

export default ActionBarVesting;
65 changes: 65 additions & 0 deletions src/containers/vesting/balancePane.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import { Pane, Text, Avatar } from '@cybercongress/gravity';

import {
formatNumber,
formatValidatorAddress,
formatCurrency,
} from '../../utils/utils';

import { Tooltip } from '../../components';

import { AUCTION } from '../../utils/config';

const TextHeader = ({ children }) => (
<Text fontSize="18px" color="#fff" lineHeight="25px">
{children}
</Text>
);

const TextNumber = ({ children }) => (
<Text fontSize="22px" color="#fff" lineHeight="30px">
{children}
</Text>
);

const BalancePane = ({ spendableBalance, balance, accounts, ...props }) => (
<Pane
display="flex"
alignItems="center"
justifyContent="space-around"
width="100%"
padding="20px"
boxShadow="0 0 5px #3ab793"
{...props}
>
<Pane display="flex" alignItems="center" flexDirection="column">
<TextHeader>Total</TextHeader>
<TextNumber>{formatCurrency(balance)}</TextNumber>
</Pane>
<Pane display="flex" alignItems="center" flexDirection="column">
<TextHeader>Vested</TextHeader>
<TextNumber>{formatCurrency(balance - spendableBalance)}</TextNumber>
</Pane>
<Pane display="flex" alignItems="center" flexDirection="column">
<TextHeader>Available</TextHeader>
<Tooltip
placement="bottom"
tooltip={`${formatNumber(Math.floor(spendableBalance))} ${
AUCTION.TOKEN_NAME
}`}
>
<TextNumber>{formatCurrency(spendableBalance)}</TextNumber>
</Tooltip>
</Pane>
<Pane display="flex" alignItems="center" flexDirection="column">
<Avatar
style={{ width: 60, height: 60, marginBottom: 10 }}
hash={accounts}
/>
<Text color="#fff">{formatValidatorAddress(accounts, 6, 4)}</Text>
</Pane>
</Pane>
);

export default BalancePane;
Loading

0 comments on commit 268e9d8

Please sign in to comment.