UNPKG

@bzxnetwork/portal

Version:
440 lines (411 loc) 13.9 kB
import { Fragment } from "react"; import styled from "styled-components"; import Button from "@material-ui/core/Button"; import { fromBigNumber, toBigNumber, getInitialCollateralRequired } from "../../common/utils"; import Section, { SectionLabel, Divider } from "../../common/FormSection"; import { getDecimals } from "../../common/tokens"; import Tokens from "./Tokens"; import Details from "./Details"; import Expiration from "./Expiration"; import Inputs from "./Inputs"; import CancelInputs from "./CancelInputs"; import BZxComponent from "../../common/BZxComponent"; import { validateFillOrder, validateCancelOrder, submitFillOrder, submitFillOrderWithHash, submitCancelOrder, submitCancelOrderWithHash } from "./utils"; import { getOrderHash } from "../GenerateOrder/utils"; const SubmitBtn = styled(Button)` width: 100%; max-width: 480px; margin-bottom: 24px; `; const Hash = styled.a` font-family: monospace; `; const defaultToken = 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 FillOrder extends BZxComponent { state = { fillOrderAmount: 0, collateralTokenAddress: defaultToken(this.props.tokens).address, collateralTokenAmount: `(finish form then refresh)`, loanTokenAvailable: 0, overCollateralize: false }; async componentDidMount() { // console.log(this.props.order); if (this.props.order.makerRole !== `0`) { this.refreshCollateralAmountNoEvent(); } try { const orderHash = this.props.order.loanOrderHash ? this.props.order.loanOrderHash : getOrderHash(this.props.order); // console.log("orderHash: "+orderHash); const orderDetail = await this.getSingleOrder(orderHash); console.log(orderDetail); if (Object.keys(orderDetail).length !== 0) { let loanTokenAvailable = orderDetail.loanTokenAmount - (this.props.order.makerAddress.toLowerCase() !== this.props.accounts[0].toLowerCase() ? orderDetail.orderFilledAmount : 0) - orderDetail.orderCancelledAmount; if (loanTokenAvailable < 0) loanTokenAvailable = 0; this.setState({ loanTokenAvailable }); } else { const cancelledAmount = await this.props.bZx.orderCancelledAmount( orderHash ); this.setState({ loanTokenAvailable: this.props.order.loanTokenAmount-cancelledAmount }); } } catch (e) {} // eslint-disable-line no-empty } /* State setters */ setStateForCollateralAmount = async ( loanTokenAddress, collateralTokenAddress, oracleAddress, loanTokenAmount, initialMarginAmount ) => { let collateralRequired = `(finish form then refresh)`; if ( loanTokenAddress && collateralTokenAddress && oracleAddress && loanTokenAmount && initialMarginAmount ) { if (toBigNumber(loanTokenAmount).gt(0) && collateralTokenAddress && collateralTokenAddress !== `0x0000000000000000000000000000000000000000`) { this.setState({ [`collateralTokenAmount`]: `loading...` }); collateralRequired = toBigNumber(await getInitialCollateralRequired( loanTokenAddress, collateralTokenAddress, oracleAddress, toBigNumber(loanTokenAmount).toFixed(0), toBigNumber(initialMarginAmount).toFixed(0), this.props.bZx )); let overCollateralize = this.props.order.makerRole === `0` ? this.state.overCollateralize : !!+this.props.order.withdrawOnOpen; if (overCollateralize) { collateralRequired = collateralRequired.plus(collateralRequired.times(10 ** 20).div(initialMarginAmount)); } collateralRequired = fromBigNumber( collateralRequired, 10 ** getDecimals(this.props.tokens, collateralTokenAddress) ); } else { collateralRequired = `0`; } // console.log(`collateralRequired: ${collateralRequired}`); if (collateralRequired === 0) { collateralRequired = `(unsupported)`; } } this.setState({ [`collateralTokenAmount`]: collateralRequired }); }; setStateFor = key => value => this.setState({ [key]: value }); setCollateralTokenAddress = async value => { await this.setState({ [`collateralTokenAddress`]: value }); await this.refreshCollateralAmountNoEvent(); }; setOverCollateralize = async (e, value) => { await this.setState({ [`overCollateralize`]: value }); await this.refreshCollateralAmountNoEvent(); }; getSingleOrder = async loanOrderHash => { const { bZx } = this.props; const order = await this.wrapAndRun(bZx.getSingleOrder({ loanOrderHash })); return order; }; refreshCollateralAmountNoEvent = async () => { await this.setStateForCollateralAmount( this.props.order.loanTokenAddress, this.props.order.makerRole === `0` ? this.state.collateralTokenAddress : this.props.order.collateralTokenAddress, this.props.order.oracleAddress, this.props.order.makerRole === `0` ? toBigNumber( this.state.fillOrderAmount, 10 ** getDecimals(this.props.tokens, this.props.order.loanTokenAddress) ) : this.props.order.loanTokenAmount, this.props.order.initialMarginAmount ); }; refreshCollateralAmount = async event => { event.preventDefault(); await this.refreshCollateralAmountNoEvent(); }; handleSubmit = async () => { const { order, tokens, oracles, web3, bZx, accounts, changeOrderTab, resetOrder } = this.props; await this.setState({ isSubmitted: true }); await this.refreshCollateralAmountNoEvent(); const { fillOrderAmount, loanTokenAvailable, collateralTokenAddress, collateralTokenAmount, overCollateralize } = this.state; const isFillOrderValid = await validateFillOrder( order, fillOrderAmount, loanTokenAvailable, collateralTokenAddress, collateralTokenAmount, tokens, oracles, bZx, accounts ); if (isFillOrderValid) { if (!order.loanOrderHash) { submitFillOrder( order, fillOrderAmount, collateralTokenAddress, overCollateralize, tokens, web3, bZx, accounts, resetOrder ); } else { submitFillOrderWithHash( order.loanOrderHash, order.makerRole === `0`, order.loanTokenAddress, fillOrderAmount, collateralTokenAddress, overCollateralize, tokens, web3, bZx, accounts, changeOrderTab ); } } else { await this.setState({ isSubmitted: false }); } }; handleCancelSubmit = async () => { const { order, tokens, web3, bZx, accounts, changeOrderTab, resetOrder } = this.props; await this.setState({ isSubmitted: true }); await this.refreshCollateralAmountNoEvent(); const { fillOrderAmount, loanTokenAvailable } = this.state; const isCancelOrderValid = await validateCancelOrder( order, fillOrderAmount, // cancelOrderAmount loanTokenAvailable, tokens, bZx, accounts ); if (isCancelOrderValid) { if (!order.loanOrderHash) { submitCancelOrder( order, fillOrderAmount, tokens, web3, bZx, accounts, resetOrder ); } else { submitCancelOrderWithHash( order.loanOrderHash, order.loanTokenAddress, fillOrderAmount, tokens, web3, bZx, accounts, changeOrderTab ); } } else { await this.setState({ isSubmitted: false }); } }; render() { const { order, tokens, bZx, accounts } = this.props; const isMaker = order.makerAddress.toLowerCase() === accounts[0].toLowerCase(); const makerRole = order.makerRole === `0` ? `lender` : `trader`; const counterRole = order.makerRole !== `0` ? `lender` : `trader`; return ( <Fragment> <Section> <SectionLabel>1. Review order info</SectionLabel> <p> {isMaker ? ( <Fragment> This order was created by you for a{` `} {counterRole} to fill. </Fragment> ) : ( <Fragment> This order was created by {` `} <Hash href={`${bZx.etherscanURL}address/${order.makerAddress}`} target="_blank" rel="noopener noreferrer" > {order.makerAddress} </Hash> {` `} for a{` `} {counterRole} to fill. </Fragment> )} </p> <Tokens bZx={bZx} tokens={tokens} role={makerRole} loanTokenAddress={order.loanTokenAddress} loanTokenAvailable={fromBigNumber( this.state.loanTokenAvailable, 10 ** getDecimals(tokens, order.loanTokenAddress) )} interestTokenAddress={order.interestTokenAddress} interestAmount={fromBigNumber( order.interestAmount, 10 ** getDecimals(tokens, order.interestAmount) )} collateralTokenAddress={order.collateralTokenAddress} collateralTokenAmount={this.state.collateralTokenAmount} isMaker={isMaker} /> <Details bZx={bZx} oracles={this.props.oracles} initialMarginAmount={order.initialMarginAmount} maintenanceMarginAmount={order.maintenanceMarginAmount} oracleAddress={order.oracleAddress} signature={order.signature} feeRecipientAddress={order.feeRecipientAddress} lenderRelayFee={fromBigNumber(order.lenderRelayFee, 1e18)} traderRelayFee={fromBigNumber(order.traderRelayFee, 1e18)} /> <Expiration expirationUnixTimestampSec={order.expirationUnixTimestampSec} /> </Section> {this.state.loanTokenAvailable ? ( <Fragment> <Divider /> <Section> {isMaker ? ( <Fragment> <SectionLabel> 2. Choose cancel amount and submit </SectionLabel> <CancelInputs bZx={bZx} tokens={tokens} fillOrderAmount={this.state.fillOrderAmount} loanTokenAddress={order.loanTokenAddress} setFillOrderAmount={this.setStateFor(`fillOrderAmount`)} /> <SubmitBtn variant="raised" color="primary" onClick={this.handleCancelSubmit} disabled={this.state.isSubmitted} > {this.state.isSubmitted ? `Please Wait` : `Cancel Order`} </SubmitBtn> </Fragment> ) : ( <Fragment> <SectionLabel> {makerRole === `lender` ? `2. Choose parameters and submit` : `2. Submit fill order transaction`} </SectionLabel> {makerRole === `lender` && ( <Inputs bZx={bZx} tokens={tokens} fillOrderAmount={this.state.fillOrderAmount} collateralTokenAddress={this.state.collateralTokenAddress} loanTokenAddress={order.loanTokenAddress} setFillOrderAmount={this.setStateFor(`fillOrderAmount`)} setCollateralTokenAddress={this.setCollateralTokenAddress} collateralTokenAmount={this.state.collateralTokenAmount} collateralRefresh={this.refreshCollateralAmount} setOverCollateralize={this.setOverCollateralize} overCollateralize={this.state.overCollateralize} /> )} <SubmitBtn variant="raised" color="primary" onClick={this.handleSubmit} disabled={this.state.isSubmitted} > {this.state.isSubmitted ? `Please Wait` : `Fill Order`} </SubmitBtn> </Fragment> )} </Section> </Fragment> ) : ( <Fragment> <Section> <p> This order is completely filled or cancelled. There is no loan token remaining. </p> </Section> </Fragment> )} </Fragment> ); } }