UNPKG

@bzxnetwork/portal

Version:
428 lines (368 loc) 13.1 kB
import moment from "moment"; import { Divider } from "../../common/FormSection"; import RoleSection from "./Role"; import TokensSection from "./Tokens"; import MarginAmountsSection from "./MarginAmounts"; import ExpirationSection from "./Expiration"; import OracleSection from "./Oracle"; import RelayExchangeSection from "./RelayExchange"; import Submission from "./Submission"; import Result from "./Result"; import { getDecimals } from "../../common/tokens"; import validateInputs from "./validate"; import { fromBigNumber, toBigNumber, getInitialCollateralRequired, getTokenConversionAmount } from "../../common/utils"; import { compileObject, addSalt, signOrder, getOrderHash, addNetworkId, pushOrderOnChain } from "./utils"; const defaultLoanToken = tokens => { let token = tokens.filter(t => t.symbol === `KNC`); if (token.length > 0) { token = token[0]; // eslint-disable-line prefer-destructuring } else { token = tokens[0]; // eslint-disable-line prefer-destructuring } return token; }; const defaultInterestToken = tokens => { let token = tokens.filter(t => t.symbol === `WETH`); if (token.length > 0) { token = token[0]; // eslint-disable-line prefer-destructuring } else { token = tokens[0]; // eslint-disable-line prefer-destructuring } return token; }; const defaultCollateralToken = tokens => { let token = tokens.filter(t => t.symbol === `DAI`); if (token.length > 0) { token = token[0]; // eslint-disable-line prefer-destructuring } else { token = tokens[0]; // eslint-disable-line prefer-destructuring } return token; }; export default class GenerateOrder extends React.Component { state = { role: `lender`, // token addresses loanTokenAddress: defaultLoanToken(this.props.tokens).address, interestTokenAddress: defaultInterestToken(this.props.tokens).address, collateralTokenAddress: defaultCollateralToken(this.props.tokens).address, // token amounts loanTokenAmount: ``, interestAmount: ``, collateralTokenAmount: `(finish form then refresh)`, interestTotalAmount: 0, interestRate: 0.0006, // margin amounts initialMarginAmount: toBigNumber(50, 10 ** 18).toString(), maintenanceMarginAmount: toBigNumber(25, 10 ** 18).toString(), maxDuration: 2419200, // 28 days // expiration date/time expirationDate: moment().add(7, `days`), // oracles oracles: this.props.oracles, oracleAddress: this.props.oracles[0].address, // relay/exchange settings sendToRelayExchange: false, feeRecipientAddress: `0x0000000000000000000000000000000000000000`, lenderRelayFee: 0, traderRelayFee: 0, takerAddress: `0x0000000000000000000000000000000000000000`, oracleData: `0x`, pushOnChain: false, withdrawOnOpen: false, tradeTokenToFillAddress: `0x0000000000000000000000000000000000000000`, orderHash: `0x_temp_order_hash`, finalOrder: null }; /* State setters */ setStateForCollateralAmount = async ( loanTokenAddress, collateralTokenAddress, oracleAddress, loanTokenAmount, initialMarginAmount ) => { let collateralRequired = `(finish form then refresh)`; if ( loanTokenAddress && collateralTokenAddress && oracleAddress && loanTokenAmount && initialMarginAmount ) { this.setState({ [`collateralTokenAmount`]: `loading...` }); collateralRequired = toBigNumber(await getInitialCollateralRequired( loanTokenAddress, collateralTokenAddress, oracleAddress, toBigNumber(loanTokenAmount).toFixed(0), toBigNumber(initialMarginAmount).toFixed(0), this.props.bZx )); console.log(`collateralRequired`,collateralRequired); if (this.state.withdrawOnOpen) { collateralRequired = collateralRequired.plus(collateralRequired.times(10 ** 20).div(initialMarginAmount)); } collateralRequired = fromBigNumber( collateralRequired, 10 ** getDecimals(this.props.tokens, collateralTokenAddress) ); console.log(`collateralRequired: ${collateralRequired}`); if (collateralRequired === 0) { collateralRequired = `(unsupported)`; } } this.setState({ [`collateralTokenAmount`]: collateralRequired }); }; setStateFor = key => async value => { await this.setState({ [key]: value }); if ( key === `loanTokenAddress` || key === `collateralTokenAddress` || key === `interestTokenAddress` ) { await this.refreshValuesAsync(); } }; setStateForInput = key => event => this.setState({ [key]: event.target.value }); setStateForMarginAmounts = key => event => { const { value } = event.target; this.setState({ [key]: toBigNumber(value, 10 ** 18) }); }; setStateForTotalInterest = (interestAmount, maxDuration) => { let totalInterest = 0; if (maxDuration > 0) { totalInterest = (maxDuration / 86400) * interestAmount; } this.setState({ interestTotalAmount: Math.round(totalInterest * 10 ** 8) / 10 ** 8 }); }; setStateForInterestRate = async event => { const { value } = event.target; this.setState({ interestRate: value / 100 }); }; setStateForMaxDuration = async event => { let value = toBigNumber(event.target.value) .times(86400) .toNumber(); if (!value) value = 0; this.setState({ maxDuration: value }); }; setRole = (e, value) => { this.setState({ role: value }); }; setRelayCheckbox = (e, value) => { if (!value || !this.props.web3.utils.isAddress(this.state.feeRecipientAddress)) this.setState({ feeRecipientAddress: `0x0000000000000000000000000000000000000000` }); this.setState(p => ({ sendToRelayExchange: value, pushOnChain: value ? !value : p.pushOnChain })); } setwithdrawOnOpenCheckbox = async (e, value) => { await this.setState(p => ({ withdrawOnOpen: value })); await this.refreshCollateralAmount(); } setPushOnChainCheckbox = (e, value) => this.setState(p => ({ pushOnChain: value, sendToRelayExchange: value ? !value : p.sendToRelayExchange })); refreshCollateralAmount = async () => { if (this.state.role === `trader` && this.state.loanTokenAmount) { await this.setStateForCollateralAmount( this.state.loanTokenAddress, this.state.collateralTokenAddress, this.state.oracleAddress, toBigNumber( this.state.loanTokenAmount, 10 ** getDecimals(this.props.tokens, this.state.loanTokenAddress) ), this.state.initialMarginAmount ); } }; refreshCollateralAmountEvent = async event => { event.preventDefault(); await this.refreshCollateralAmount(); }; refreshValuesAsync = async () => { await this.refreshInterestAmount(); await this.refreshCollateralAmount(); }; refreshInterestAmount = async () => { let interestAmount = 0; if ( this.state.loanTokenAmount && this.state.interestRate && this.state.loanTokenAddress && this.state.interestTokenAddress ) { const loanToInterestAmount = toBigNumber( await getTokenConversionAmount( this.state.loanTokenAddress, this.state.interestTokenAddress, toBigNumber( this.state.loanTokenAmount, 10 ** getDecimals(this.props.tokens, this.state.loanTokenAddress) ), this.state.oracleAddress, this.props.bZx ) ); if (!loanToInterestAmount.eq(0)) { interestAmount = fromBigNumber( loanToInterestAmount.times(this.state.interestRate), 10 ** getDecimals(this.props.tokens, this.state.interestTokenAddress) ); } } this.setState({ interestAmount }); this.setStateForTotalInterest(interestAmount, this.state.maxDuration); }; refreshInterestAmountEvent = async event => { event.preventDefault(); await this.refreshInterestAmount(); }; /* Submission handler */ handleSubmit = async () => { await this.refreshValuesAsync(); const isValid = await validateInputs( this.props.bZx, this.props.accounts, this.state, this.props.tokens, this.props.web3 ); this.setState({ orderHash: null, finalOrder: null }); if (isValid) { const orderObject = await compileObject( this.props.web3, this.state, this.props.accounts[0], this.props.bZx, this.props.tokens ); const saltedOrderObj = addSalt(orderObject); console.log(saltedOrderObj); const orderHash = getOrderHash(saltedOrderObj); try { if (this.state.pushOnChain) { // console.log(finalOrder); pushOrderOnChain( saltedOrderObj, this.props.web3, this.props.bZx, this.props.accounts ); } else { const signature = await signOrder( orderHash, this.props.accounts, this.props.bZx ); const orderWithSignature = { ...saltedOrderObj, signature }; console.log(`orderHash`, orderHash); const finalOrder = await addNetworkId( orderWithSignature, this.props.web3 ); const isSigValid = await this.props.bZx.isValidSignatureAsync({ account: this.props.accounts[0].toLowerCase(), orderHash, signature }); console.log(`isSigValid`, isSigValid); this.setState({ orderHash, finalOrder }); } } catch (e) { console.log(e); } } }; render() { return ( <div> <RoleSection role={this.state.role} setRole={this.setRole} /> <Divider /> <OracleSection oracleAddress={this.state.oracleAddress} setOracleAddress={this.setStateForInput(`oracleAddress`)} oracles={this.state.oracles} etherscanURL={this.props.bZx.etherscanURL} /> <Divider /> <TokensSection tokens={this.props.tokens} role={this.state.role} // state setters setStateForAddress={this.setStateFor} setStateForInput={this.setStateForInput} setStateForInterestRate={this.setStateForInterestRate} // address states loanTokenAddress={this.state.loanTokenAddress} interestTokenAddress={this.state.interestTokenAddress} collateralTokenAddress={this.state.collateralTokenAddress} // token amounts loanTokenAmount={this.state.loanTokenAmount} collateralTokenAmount={this.state.collateralTokenAmount} interestRate={this.state.interestRate} interestTotalAmount={this.state.interestTotalAmount} collateralRefresh={this.refreshCollateralAmountEvent} etherscanURL={this.props.bZx.etherscanURL} maxDuration={this.state.maxDuration} interestRefresh={this.refreshInterestAmountEvent} /> <Divider /> <MarginAmountsSection setStateForInput={this.setStateForMarginAmounts} initialMarginAmount={this.state.initialMarginAmount} maintenanceMarginAmount={this.state.maintenanceMarginAmount} role={this.state.role} setwithdrawOnOpenCheckbox={this.setwithdrawOnOpenCheckbox} withdrawOnOpen={this.state.withdrawOnOpen} /> <Divider /> <ExpirationSection setMaxDuration={this.setStateForMaxDuration} maxDuration={this.state.maxDuration} setStateForInput={this.setStateForInput} expirationDate={this.state.expirationDate} /> <Divider /> <RelayExchangeSection // state setters setStateForInput={this.setStateForInput} setRelayCheckbox={this.setRelayCheckbox} // form states sendToRelayExchange={this.state.sendToRelayExchange} feeRecipientAddress={this.state.feeRecipientAddress} pushOnChain={this.state.pushOnChain} lenderRelayFee={this.state.lenderRelayFee} traderRelayFee={this.state.traderRelayFee} /> <Divider /> <Submission setPushOnChainCheckbox={this.setPushOnChainCheckbox} pushOnChain={this.state.pushOnChain} sendToRelayExchange={this.state.sendToRelayExchange} onSubmit={this.handleSubmit} /> <Result orderHash={this.state.orderHash} signedOrderObject={this.state.finalOrder} /> </div> ); } }