-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
944334f
commit 268e9d8
Showing
9 changed files
with
707 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
| ||
<a href="https://metamask.io/" target="_blank"> | ||
Metamask extension | ||
</a> | ||
| ||
<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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.