Skip to content

Commit

Permalink
Merge pull request #849 from swaponline/partialClosure
Browse files Browse the repository at this point in the history
Partial closure
  • Loading branch information
noxonsu committed Nov 8, 2018
2 parents 8db4c7c + c61807e commit ed010d6
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 7 deletions.
9 changes: 8 additions & 1 deletion shared/components/modals/OfferModal/AddOffer/AddOffer.js
Expand Up @@ -63,6 +63,7 @@ export default class AddOffer extends Component {
isSellFieldInteger: false,
isBuyFieldInteger: false,
manualRate: false,
isPartialClosure: false,
}
}

Expand Down Expand Up @@ -350,7 +351,7 @@ export default class AddOffer extends Component {
render() {
const { currencies, tokenItems } = this.props
const { exchangeRate, buyAmount, sellAmount, buyCurrency, sellCurrency,
balance, isBuyFieldInteger, isSellFieldInteger, ethBalance, manualRate } = this.state
balance, isBuyFieldInteger, isSellFieldInteger, ethBalance, manualRate, isPartialClosure } = this.state
const linked = Link.all(this, 'exchangeRate', 'buyAmount', 'sellAmount')
const isDisabled = !exchangeRate || !buyAmount && !sellAmount
|| sellAmount > balance || sellAmount < minAmount[sellCurrency]
Expand All @@ -359,6 +360,8 @@ export default class AddOffer extends Component {
linked.sellAmount.check((value) => value > minAmount[sellCurrency], `Amount must be greater than ${minAmount[sellCurrency]} `)
linked.sellAmount.check((value) => value <= balance, `Amount must be bigger than on your balance`)

console.log('this state', isPartialClosure)

return (
<div styleName="wrapper">
{ this.isEthOrERC20() &&
Expand Down Expand Up @@ -410,6 +413,10 @@ export default class AddOffer extends Component {
<Toggle checked={manualRate} onChange={this.handleManualRate} /> Custom exchange rate
<Tooltip text="To change the exchange rate" />
</div>
<div>
<Toggle checked={isPartialClosure} onChange={() => this.setState((state) => ({ isPartialClosure: !state.isPartialClosure }))} /> Enabled to partial closure
<Tooltip text="To change the exchange rate" />
</div>
<Button styleName="button" fullWidth brand disabled={isDisabled} onClick={this.handleNext}>
<FormattedMessage id="AddOffer396" defaultMessage="Next" />
</Button>
Expand Down
Expand Up @@ -39,16 +39,15 @@ export default class ConfirmOffer extends Component {
}

createOrder = () => {
const { offer: { buyAmount, sellAmount, buyCurrency, sellCurrency, exchangeRate } } = this.props

console.log('order id', this.getUniqId())
const { offer: { buyAmount, sellAmount, buyCurrency, sellCurrency, exchangeRate, isPartialClosure } } = this.props

const data = {
buyCurrency: `${buyCurrency}`,
sellCurrency: `${sellCurrency}`,
buyAmount: Number(buyAmount),
sellAmount: Number(sellAmount),
exchangeRate: Number(exchangeRate),
isPartialClosure,
}

actions.analytics.dataEvent('orderbook-addoffer-click-confirm-button')
Expand Down
1 change: 0 additions & 1 deletion shared/components/ui/CurrencySelect/CurrencySelect.js
Expand Up @@ -8,7 +8,6 @@ import DropDown from 'components/ui/DropDown/DropDown'


const CurrencySelect = ({ className, selectedValue, onSelect, currencies }) => {

// remove null values in object map
const nonNullCurrencies = currencies.filter(currency => !!currency !== false)
// TODO: Add debug logger message to see if some currency have been dropped
Expand Down
11 changes: 11 additions & 0 deletions shared/containers/Core/Core.js
Expand Up @@ -43,10 +43,14 @@ export default class Core extends Component {
this.updateOrders()
console.log('swap app', SwapApp)

SwapApp.services.room
.on('request partial closure', this.createOrder)

SwapApp.services.room.connection
.on('peer joined', actions.ipfs.userJoined)
.on('peer left', actions.ipfs.userLeft)
.on('accept swap request', this.updateOrders)
.on('request partial closure', this.createOrder)
.on('decline swap request', this.updateOrders)

setTimeout(() => {
Expand All @@ -66,6 +70,13 @@ export default class Core extends Component {
actions.core.updateCore(orders)
}

createOrder = async ({ fromPeer, order, ...rest }) => {
console.log('rest', ...rest)
// TODO add check exchange rate and format order
const createdOrder = await actions.core.createOrder(order)
actions.core.requestToPeer('accept request', fromPeer, { orderId: createdOrder.id })
}

render() {
return null
}
Expand Down
1 change: 1 addition & 0 deletions shared/helpers/links.js
Expand Up @@ -10,6 +10,7 @@ export default {
test: 'https://testnet.swap.online',
main: 'https://swap.online/',
coins: '/coins',
partial: '/partial',

// social networks
medium: 'https://medium.com/swaponline',
Expand Down
2 changes: 1 addition & 1 deletion shared/pages/Home/Orders/Row/Row.js
Expand Up @@ -9,7 +9,7 @@ import { Link, Redirect } from 'react-router-dom'

import Avatar from 'components/Avatar/Avatar'
import InlineLoader from 'components/loaders/InlineLoader/InlineLoader'
import RemoveButton from 'components/controls/RemoveButton/RemoveButton'
import { Button, RemoveButton } from 'components/controls'

import Pair from '../Pair'
import PAIR_TYPES from 'helpers/constants/PAIR_TYPES'
Expand Down
162 changes: 162 additions & 0 deletions shared/pages/PartialClosure/PartialClosure.js
@@ -0,0 +1,162 @@
import React, { Component, Fragment } from 'react'

import Link from 'sw-valuelink'
import { links } from 'helpers'

import CSSModules from 'react-css-modules'
import styles from './PartialClosure.scss'

import { connect } from 'redaction'
import actions from 'redux/actions'
import { BigNumber } from 'bignumber.js'

import SelectGroup from './SelectGroup/SelectGroup'
import { Button, Toggle } from 'components/controls'
import { Redirect } from 'react-router-dom'


const filterIsPartial = (orders) => orders
.filter(order => order.isPartialClosure)


@connect(({ currencies, core: { orders } }) => ({
currencies: currencies.items,
orders: filterIsPartial(orders),
}))
@CSSModules(styles)
export default class PartialClosure extends Component {

static defaultProps = {
orders: [],
}

constructor() {
super()

this.state = {
haveCurrency: 'btc',
getCurrency: 'eth',
haveAmount: '',
getAmount: '',
peer: '',
filteredOrders: [],
isNonOffers: false,
isDeclinedOffer: false,
}
}

static getDerivedStateFromProps({ orders }, { haveCurrency }) {
if (!Array.isArray(orders)) { return }

const filteredOrders = orders.filter(order =>
order.sellCurrency === haveCurrency.toUpperCase())

return {
filteredOrders,
}
}

sendRequest = () => {
const { getAmount, haveAmount, haveCurrency, getCurrency, peer, orderId } = this.state

if (!String(getAmount) || !peer || !orderId || !String(haveAmount)) {
return
}

const order = {
buyCurrency: getCurrency,
sellCurrency: haveCurrency,
sellAmount: haveAmount,
buyAmount: getAmount,
}

actions.core.requestToPeer('request partial closure', peer, { order, orderId }, (orderId) => {
console.log('orderId', orderId)
// TODO change callback on boolean type
if (orderId) {
actions.core.sendRequest(orderId, (isAccept) => {
if (isAccept) {
this.setState(() => ({
redirect: true,
orderId,
}))
}
})
} else {
this.setState(() => ({ isDeclinedOffer: true, haveAmount: '' }))
}
})
}

setAmount = (value) => {
this.setState(() => ({ haveAmount: new BigNumber(String(value)) }))

const { filteredOrders } = this.state

console.log('value', value)
console.log('filteredOrders', filteredOrders)

if (filteredOrders.length === 0) {
this.setState(() => ({ isNonOffers: true }))
return
}

// TODO add check orders and view
const sortedOrder = filteredOrders.sort((a, b) => a.exchangeRate - b.exchangeRate)
const exRate = new BigNumber(String(sortedOrder[0].exchangeRate))

console.log('exRate', exRate)
console.log('sortedOrder', sortedOrder)

this.setState(() => ({
isNonOffers: false,
getAmount: exRate.multipliedBy(new BigNumber(String(value))),
peer: sortedOrder[0].owner.peer,
orderId: sortedOrder[0].id,
}))
}

render() {
const { currencies } = this.props
const { haveCurrency, getCurrency, isNonOffers, redirect, orderId, isDeclinedOffer, type } = this.state

const linked = Link.all(this, 'haveAmount', 'getAmount')

if (redirect) {
return <Redirect push to={`${links.swap}/${getCurrency}-${haveCurrency}/${orderId}`} />
}

return (
<Fragment>
<h1>Partial Closure</h1>
<div style={{ width: '400px', margin: '0 auto' }}>
<SelectGroup
inputValueLink={linked.haveAmount.pipe(this.setAmount)}
selectedValue={haveCurrency}
onSelect={({ value }) => this.setState(() => ({ haveCurrency: value }))}
label="You have"
placeholder="Enter amount"
currencies={currencies}
/>
<SelectGroup
inputValueLink={linked.getAmount}
selectedValue={getCurrency}
onSelect={({ value }) => this.setState(() => ({ getCurrency: value }))}
label="You get"
disabled
currencies={currencies}
/>
{
isDeclinedOffer && (<p>Offer is declined</p>)
}
{
isNonOffers && (<p style={{ color: 'red' }}>No offers </p>)
}
<Button styleName="button" brand fullWidth onClick={this.sendRequest} disabled={isNonOffers}>
Start
</Button>
</div>
</Fragment>
)
}
}
3 changes: 3 additions & 0 deletions shared/pages/PartialClosure/PartialClosure.scss
@@ -0,0 +1,3 @@
.button {
margin-top: 20px;
}
34 changes: 34 additions & 0 deletions shared/pages/PartialClosure/SelectGroup/SelectGroup.js
@@ -0,0 +1,34 @@
import React from 'react'

import CSSModules from 'react-css-modules'
import styles from './SelectGroup.scss'

import Input from 'components/forms/Input/Input'
import FieldLabel from 'components/forms/FieldLabel/FieldLabel'
import CurrencySelect from 'components/ui/CurrencySelect/CurrencySelect'

// TODO to split data and view this component
const SelectGroup = ({ selectedValue, onSelect, currencies, placeholder, label, disabled, className, inputValueLink }) => (
<div>
<FieldLabel inRow>{label}</FieldLabel>
<div styleName="groupField" className={className}>
<Input
styleName="inputRoot"
inputContainerClassName="inputContainer"
valueLink={inputValueLink}
type="number"
placeholder={placeholder}
pattern="0-9."
disabled={disabled}
/>
<CurrencySelect
styleName="currencySelect"
selectedValue={selectedValue}
onSelect={onSelect}
currencies={currencies}
/>
</div>
</div>
)

export default CSSModules(SelectGroup, styles)
27 changes: 27 additions & 0 deletions shared/pages/PartialClosure/SelectGroup/SelectGroup.scss
@@ -0,0 +1,27 @@
.groupField {
width: 100%;
display: inline-flex;
height: 60px;
margin-bottom: 10px;
box-shadow: rgba(#000, 0.08) 0 3px 9px 0;
border-radius: 6px;
text-align: center;
}

.inputRoot {
min-width: 0;
flex: auto 1 1;
}

.inputContainer {
border-radius: 6px 0 0 6px !important;
box-shadow: none !important;
}

input:disabled {
background-color:#eee;
}

.currencySelect {
border-radius: 0 6px 6px 0 !important;
}
7 changes: 6 additions & 1 deletion shared/redux/actions/core.js
Expand Up @@ -35,7 +35,11 @@ const sendRequest = (orderId, callback) => {
}

const createOrder = (data) => {
SwapApp.services.orders.create(data)
return SwapApp.services.orders.create(data)
}

const requestToPeer = (event, peer, data, callback) => {
SwapApp.services.orders.requestToPeer(event, peer, data, callback)
}

const updateCore = () => {
Expand Down Expand Up @@ -86,4 +90,5 @@ export default {
removeOrder,
markCoinAsHidden,
markCoinAsVisible,
requestToPeer,
}
2 changes: 2 additions & 0 deletions shared/routes/index.js
Expand Up @@ -11,6 +11,7 @@ import History from 'pages/History/History'
import NotFound from 'pages/NotFound/NotFound'
import Affiliate from 'pages/Affiliate/Affiliate'
import Currency from 'pages/Currency/Currency'
import PartialClosure from 'pages/PartialClosure/PartialClosure'
import CurrencyWallet from 'pages/CurrencyWallet/CurrencyWallet'


Expand All @@ -24,6 +25,7 @@ const routes = (
<Route path={`${links.home}:buy-:sell`} component={Home} />
<Route path={links.exchange} component={Home} />

<Route path={links.partial} component={PartialClosure} />
<Route path={links.affiliate} component={Affiliate} />
<Route path={links.listing} component={Listing} />
<Route path={links.history} component={History} />
Expand Down

0 comments on commit ed010d6

Please sign in to comment.