Skip to content

Commit 130e4c1

Browse files
authored
581 market fees (bitshares#665)
* Update version # * Fix bitshares#498: Keep scrollbars visible, restore perfect scrollbar to main exchange div * Fix bitshares#589: Openledger deposit address shown as unknown * Only store valid deposit addresses bitshares#589 * Fix setting of max_market_fee in asset create/update * First pass at showing market fees in exchange bitshares#581 * Add a tooltip explaining the market fee
1 parent 0e64be4 commit 130e4c1

11 files changed

+146
-29
lines changed

app/assets/locales/locale-en.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181
"copy_password": "Click here to copy the password to your clipboard",
8282
"sync_yes": "The current node is in sync with the blockchain",
8383
"sync_no": "The current node is out of sync with the blockchain, try switching to another one",
84-
"disconnected": "You are not connected to an API node, try reloading or setting a new access point in the Settings"
84+
"disconnected": "You are not connected to an API node, try reloading or setting a new access point in the Settings",
85+
"market_fee": "The owner of %(asset)s charges a market fee of %(percent)s%% for buy orders. This fee will be subtracted from the amount you receive when your order fills, it is not paid when placing an order."
8586
},
8687
"propose": "Propose",
8788
"cancel": "Cancel",

app/assets/stylesheets/vendors/_perfect-scrollbar.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
display: none;
6161
position: absolute;
6262
/* please don't change 'position' */
63-
opacity: 0;
63+
opacity: 0.6;
6464
-webkit-transition: background-color .2s linear, opacity .2s linear;
6565
-o-transition: background-color .2s linear, opacity .2s linear;
6666
-moz-transition: background-color .2s linear, opacity .2s linear;

app/components/Account/AccountAssetCreate.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ class AccountAssetCreate extends React.Component {
310310
break;
311311

312312
case "max_market_fee":
313-
if ((new big(inputValue)).times(Math.pow(10, precision)).gt(GRAPHENE_MAX_SHARE_SUPPLY)) {
313+
if ((new big(inputValue)).times(precision).gt(GRAPHENE_MAX_SHARE_SUPPLY)) {
314314
errors.max_market_fee = "The number you tried to enter is too large";
315315
return this.setState({errors});
316316
}

app/components/Account/AccountAssetUpdate.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class AccountAssetUpdate extends React.Component {
236236

237237
case "max_market_fee":
238238
let marketFee = e.amount.replace(/,/g, "");
239-
if ((new big(marketFee)).times(Math.pow(10, precision)).gt(GRAPHENE_MAX_SHARE_SUPPLY)) {
239+
if ((new big(marketFee)).times(precision).gt(GRAPHENE_MAX_SHARE_SUPPLY)) {
240240
updateState = false;
241241
return this.setState({errors: {max_market_fee: "The number you tried to enter is too large"}});
242242
}

app/components/DepositWithdraw/blocktrades/BlockTradesBridgeDepositRequest.jsx

+11-4
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ class BlockTradesBridgeDepositRequest extends React.Component {
575575
let conversion_limit = this.getCachedOrFreshDepositLimit("conversion", conversion_input_coin_type, conversion_output_coin_type);
576576

577577
if (this.unMounted) return;
578-
578+
579579
this.setState({
580580
coin_info_request_state: this.coin_info_request_states.request_complete,
581581
coins_by_type: coins_by_type,
@@ -719,14 +719,21 @@ class BlockTradesBridgeDepositRequest extends React.Component {
719719
// functions for managing input addresses
720720
getCachedInputAddress(input_coin_type, output_coin_type, memo)
721721
{
722-
let account_name = this.props.account.get('name');
722+
let account_name = this.props.account.get("name");
723723
return this.deposit_address_cache.getCachedInputAddress(this.props.gateway, account_name, input_coin_type, output_coin_type);
724724
}
725725

726726
cacheInputAddress(input_coin_type, output_coin_type, address, memo)
727727
{
728-
let account_name = this.props.account.get('name');
729-
this.deposit_address_cache.cacheInputAddress(this.props.gateway, account_name, input_coin_type, output_coin_type, address, memo);
728+
let account_name = this.props.account.get("name");
729+
this.deposit_address_cache.cacheInputAddress(
730+
this.props.gateway,
731+
account_name,
732+
input_coin_type,
733+
output_coin_type,
734+
address,
735+
memo
736+
);
730737
}
731738

732739
getCachedOrGeneratedInputAddress(input_coin_type, output_coin_type)

app/components/DepositWithdraw/blocktrades/BlockTradesGatewayDepositRequest.jsx

+15-6
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ class BlockTradesGatewayDepositRequest extends React.Component {
7878
componentWillMount() {
7979
let account_name = this.props.account.get("name");
8080
let receive_address = this.deposit_address_cache.getCachedInputAddress(this.props.gateway, account_name, this.props.deposit_coin_type, this.props.receive_coin_type);
81-
if (!receive_address) {
81+
if (!receive_address || receive_address.address === "unknown") {
8282
requestDepositAddress(this._getDepositObject());
83+
} else {
84+
this.setState({receive_address});
8385
}
8486
}
8587

@@ -89,7 +91,14 @@ class BlockTradesGatewayDepositRequest extends React.Component {
8991

9092
addDepositAddress( receive_address ) {
9193
let account_name = this.props.account.get("name");
92-
this.deposit_address_cache.cacheInputAddress(this.props.gateway, account_name, this.props.deposit_coin_type, this.props.receive_coin_type, receive_address.address, receive_address.memo);
94+
this.deposit_address_cache.cacheInputAddress(
95+
this.props.gateway,
96+
account_name,
97+
this.props.deposit_coin_type,
98+
this.props.receive_coin_type,
99+
receive_address.address,
100+
receive_address.memo
101+
);
93102
this.setState( {receive_address} );
94103
}
95104

@@ -114,7 +123,7 @@ class BlockTradesGatewayDepositRequest extends React.Component {
114123
}
115124

116125
render() {
117-
126+
const isDeposit = this.props.action === "deposit";
118127
let emptyRow = <div style={{display:"none", minHeight: 150}}></div>;
119128
if( !this.props.account || !this.props.issuer_account || !this.props.receive_asset )
120129
return emptyRow;
@@ -158,7 +167,7 @@ class BlockTradesGatewayDepositRequest extends React.Component {
158167
receive_address = this.deposit_address_cache.getCachedInputAddress(this.props.gateway, account_name, this.props.deposit_coin_type, this.props.receive_coin_type);
159168
}
160169

161-
if( !receive_address ) {
170+
if( !receive_address) {
162171
requestDepositAddress(this._getDepositObject());
163172
return <div style={{margin: "3rem"}}><LoadingIndicator type="three-bounce"/></div>;
164173
}
@@ -200,11 +209,11 @@ class BlockTradesGatewayDepositRequest extends React.Component {
200209
var withdraw_memo_prefix = "";
201210
}
202211

203-
if (!this.props.isAvailable) {
212+
if (!this.props.isAvailable || (isDeposit && !this.props.deposit_account && !this.state.receive_address)) {
204213
return <div><Translate className="txtlabel cancel" content="gateway.unavailable" component="h4" /></div>;
205214
}
206215

207-
if (this.props.action === "deposit") {
216+
if (isDeposit) {
208217
return (
209218
<div className="Blocktrades__gateway grid-block no-padding no-margin">
210219
<div className="small-12 medium-5">

app/components/Exchange/BuySell.jsx

+87
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import SimpleDepositWithdraw from "../Dashboard/SimpleDepositWithdraw";
1212
import SimpleDepositBlocktradesBridge from "../Dashboard/SimpleDepositBlocktradesBridge";
1313
import {Asset} from "common/MarketClasses";
1414
import ExchangeInput from "./ExchangeInput";
15+
import assetUtils from "common/asset_utils";
16+
import Icon from "../Icon/Icon";
1517

1618
class BuySell extends React.Component {
1719

@@ -80,10 +82,93 @@ class BuySell extends React.Component {
8082
if (this.props.total) total = this.props.total;
8183

8284
let balanceAmount = new Asset({amount: balance ? balance.get("balance") : 0, precision: balancePrecision, asset_id: this.props.balanceId});
85+
86+
const maxBaseMarketFee = new Asset({
87+
amount: base.getIn(["options", "max_market_fee"]),
88+
asset_id: base.get("asset_id"),
89+
precision: base.get("precision")
90+
});
91+
const maxQuoteMarketFee = new Asset({
92+
amount: quote.getIn(["options", "max_market_fee"]),
93+
asset_id: quote.get("asset_id"),
94+
precision: quote.get("precision")
95+
});
96+
const quoteFee = !amount ? 0 : Math.min(maxQuoteMarketFee.getAmount({real: true}), amount * quote.getIn(["options", "market_fee_percent"]) / 10000);
97+
const baseFee = !amount ? 0 : Math.min(maxBaseMarketFee.getAmount({real: true}), total * base.getIn(["options", "market_fee_percent"]) / 10000);
98+
const baseFlagBooleans = assetUtils.getFlagBooleans(base.getIn(["options", "flags"]), base.has("bitasset_data_id"));
99+
const quoteFlagBooleans = assetUtils.getFlagBooleans(quote.getIn(["options", "flags"]), quote.has("bitasset_data_id"));
100+
101+
102+
const hasMarketFee = baseFlagBooleans["charge_market_fee"] || quoteFlagBooleans["charge_market_fee"];
103+
var baseMarketFee = baseFlagBooleans["charge_market_fee"] ? (
104+
<div className="grid-block no-padding buy-sell-row">
105+
<div className="grid-block small-3 no-margin no-overflow buy-sell-label">
106+
<Translate content="explorer.asset.summary.market_fee" />:
107+
</div>
108+
<div className="grid-block small-5 no-margin no-overflow buy-sell-input">
109+
<input disabled type="text" id="baseMarketFee" value={baseFee} autoComplete="off"/>
110+
</div>
111+
<div className="grid-block small-4 no-margin no-overflow buy-sell-box">
112+
<AssetName noTip name={base.get("symbol")} />
113+
<span
114+
data-tip={counterpart.translate(
115+
"tooltip.market_fee",
116+
{
117+
percent: base.getIn(["options", "market_fee_percent"]) / 100,
118+
asset: base.get("symbol")
119+
}
120+
)
121+
}
122+
className="inline-block tooltip"
123+
>
124+
&nbsp;<Icon style={{position: "relative", top: 3}} name="question-circle" />
125+
</span>
126+
</div>
127+
</div>
128+
) : hasMarketFee ?
129+
<div className="grid-block no-padding buy-sell-row">
130+
<div style={{visibility: "hidden"}} className="grid-block small-3 no-margin no-overflow buy-sell-label">
131+
<Translate content="explorer.asset.summary.market_fee" />:
132+
</div>
133+
</div> : null;
134+
var quoteMarketFee = quoteFlagBooleans["charge_market_fee"] ? (
135+
<div className="grid-block no-padding buy-sell-row">
136+
<div className="grid-block small-3 no-margin no-overflow buy-sell-label">
137+
<Translate content="explorer.asset.summary.market_fee" />:
138+
</div>
139+
<div className="grid-block small-5 no-margin no-overflow buy-sell-input">
140+
<input disabled type="text" id="baseMarketFee" value={quoteFee} autoComplete="off"/>
141+
</div>
142+
<div className="grid-block small-4 no-margin no-overflow buy-sell-box">
143+
<AssetName noTip name={quote.get("symbol")} />
144+
<span
145+
data-tip={counterpart.translate(
146+
"tooltip.market_fee",
147+
{
148+
percent: quote.getIn(["options", "market_fee_percent"]) / 100,
149+
asset: quote.get("symbol")
150+
}
151+
)
152+
}
153+
className="inline-block tooltip"
154+
>
155+
&nbsp;<Icon style={{position: "relative", top: 3}} name="question-circle" />
156+
</span>
157+
</div>
158+
</div>
159+
) : hasMarketFee ?
160+
<div className="grid-block no-padding buy-sell-row">
161+
<div style={{visibility: "hidden"}} className="grid-block small-3 no-margin no-overflow buy-sell-label">
162+
<Translate content="explorer.asset.summary.market_fee" />:
163+
</div>
164+
</div> : null;
165+
83166
// if (!balanceAmount) {
84167
// balanceAmount = 0;
85168
// }
86169
const isBid = type === "bid";
170+
let marketFee = isBid && quoteMarketFee ? quoteMarketFee : !isBid && baseMarketFee ? baseMarketFee : null;
171+
console.log("isBid", isBid, "quoteMarketFee", !!quoteMarketFee, "baseMarketFee", !!baseMarketFee);
87172
let hasBalance = isBid ? balanceAmount.getAmount({real: true}) >= parseFloat(total) : balanceAmount.getAmount({real: true}) >= parseFloat(amount);
88173

89174
let buttonText = isPredictionMarket ? counterpart.translate("exchange.short") : isBid ? counterpart.translate("exchange.buy") : counterpart.translate("exchange.sell");
@@ -201,6 +286,8 @@ class BuySell extends React.Component {
201286
</select>
202287
</div>
203288
</div>
289+
290+
{marketFee}
204291
</div>
205292
<div>
206293
<div className="grid-content clear-fix no-padding">

app/components/Exchange/Exchange.jsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class Exchange extends React.Component {
6060

6161
this._getWindowSize = debounce(this._getWindowSize.bind(this), 150);
6262
this._checkFeeStatus = this._checkFeeStatus.bind(this);
63+
this.psInit = true;
6364
}
6465

6566
_initialState(props) {
@@ -148,10 +149,6 @@ class Exchange extends React.Component {
148149
}
149150

150151
componentDidMount() {
151-
let centerContainer = this.refs.center;
152-
if (centerContainer) {
153-
Ps.initialize(centerContainer);
154-
}
155152
SettingsActions.changeViewSetting.defer({
156153
[this._getLastMarketKey()]: this.props.quoteAsset.get("symbol") + "_" + this.props.baseAsset.get("symbol")
157154
});
@@ -191,10 +188,21 @@ class Exchange extends React.Component {
191188
height: innerHeight,
192189
width: innerWidth
193190
});
191+
let centerContainer = this.refs.center;
192+
if (centerContainer) {
193+
Ps.update(centerContainer);
194+
}
194195
}
195196
}
196197

197198
componentWillReceiveProps(nextProps) {
199+
if (this.refs.center && this.psInit) {
200+
let centerContainer = this.refs.center;
201+
if (centerContainer) {
202+
Ps.initialize(centerContainer);
203+
this.psInit = false;
204+
}
205+
}
198206
if (
199207
nextProps.quoteAsset !== this.props.quoteAsset ||
200208
nextProps.baseAsset !== this.props.baseAsset ||
@@ -1128,7 +1136,7 @@ class Exchange extends React.Component {
11281136
showVolumeChart={showVolumeChart}
11291137
/>
11301138

1131-
<div className="grid-block vertical no-padding" id="CenterContent" ref="center">
1139+
<div className="grid-block vertical no-padding ps-container" id="CenterContent" ref="center">
11321140
{!showDepthChart ? (
11331141
<div className="grid-block shrink no-overflow" id="market-charts" >
11341142
{/* Price history chart */}

app/components/Exchange/OrderBook.jsx

+12-8
Original file line numberDiff line numberDiff line change
@@ -401,10 +401,12 @@ class OrderBook extends React.Component {
401401
<span> (<AssetName name={quoteSymbol} />)</span>
402402
</div>
403403
</div>
404-
<table className="table order-table table-hover fixed-table text-right">
405-
{!this.state.flip ? rightHeader : leftHeader}
406-
</table>
407-
<div className="grid-block" ref="hor_asks" style={{paddingRight: !showAllAsks ? 0 : 15, overflow: "hidden", maxHeight: 210}}>
404+
<div style={{paddingRight: "0.6rem"}}>
405+
<table className="table order-table table-hover fixed-table text-right">
406+
{!this.state.flip ? rightHeader : leftHeader}
407+
</table>
408+
</div>
409+
<div className="grid-block" ref="hor_asks" style={{paddingRight: "0.6rem", overflow: "hidden", maxHeight: 210}}>
408410
<table style={{paddingBottom: 5}} className="table order-table table-hover fixed-table text-right no-overflow">
409411
<TransitionWrapper
410412
ref="askTransition"
@@ -442,10 +444,12 @@ class OrderBook extends React.Component {
442444
<span> (<AssetName name={baseSymbol} />)</span>
443445
</div>
444446
</div>
445-
<table className="table order-table table-hover fixed-table text-right">
446-
{this.state.flip ? rightHeader : leftHeader}
447-
</table>
448-
<div className="grid-block" ref="hor_bids" style={{paddingRight: !showAllBids ? 0 : 15, overflow: "hidden", maxHeight: 210}}>
447+
<div style={{paddingRight: "0.6rem"}}>
448+
<table className="table order-table table-hover fixed-table text-right">
449+
{this.state.flip ? rightHeader : leftHeader}
450+
</table>
451+
</div>
452+
<div className="grid-block" ref="hor_bids" style={{paddingRight: "0.6rem", overflow: "hidden", maxHeight: 210}}>
449453
<table style={{paddingBottom: 5}} className="table order-table table-hover fixed-table text-right no-overflow">
450454
<TransitionWrapper
451455
ref="bidTransition"

app/lib/common/BlockTradesDepositAddressCache.js

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class BlockTradesDepositAddressCache {
4949

5050
cacheInputAddress(exchange_name, account_name, input_coin_type, output_coin_type, address, memo)
5151
{
52+
if (!address) return;
5253
let wallet = WalletDb.getWallet();
5354
wallet = null;
5455

app/lib/common/blockTradesMethods.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ export function requestDepositAddress({inputCoinType, outputCoinType, outputAddr
7777
}, error => {
7878
// console.log( "error: ",error );
7979
delete depositRequests[body_string];
80-
if (stateCallback) stateCallback({"address": "unknown", "memo": null});
80+
if (stateCallback) stateCallback(null);
8181
});
8282
}, error => {
8383
// console.log( "error: ",error );
8484
delete depositRequests[body_string];
85-
if (stateCallback) stateCallback({"address": "unknown", "memo": null});
85+
if (stateCallback) stateCallback(null);
8686
}).catch(err => {
8787
console.log("fetch error:", err);
8888
delete depositRequests[body_string];

0 commit comments

Comments
 (0)