// ==UserScript==
// @name GDax Display Gross Order Costs/Yields
// @version 1.10
// @author Simonthebrit
// @description Adds a button to the GDax crypto-exchange main view that calculates gross costs and yields of existing orders.
// @namespace GDaxTweaks
// @grant none
// @include *.gdax.com*
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// ==/UserScript==
// Specs
var delay = 5000; // 5-second delay while gdax interface loads
var grossPreText = 'GRS'; // Label to use to indicate our added gross values
var buttonText = 'CALCULATE GROSS (' + grossPreText + ')';
var buttonCSS = {
"display" : "flex",
"justify-content" : "center",
"align-items" : "center",
"margin-left" : "20px",
"padding" : "3px 7px",
"border" : "2px solid #788085",
"border-radius" : "40px",
"font-size" : "9px",
"font-weight" : "bold",
"color" : "#ced2d5",
"cursor" : "pointer",
"transition" : "background .2s ease-out"
};
// Start when main view is loaded
var checkExist = setInterval(function() {
if ($('div:acp("PanelHeader_title-and-children")').length) {
// Button for main view
$(':acp("UserPanel_user-panel") :acp("UserPanel_user-history") :acp("PanelHeader_title-and-children")')
.append('<div class="calcGrossButton">' + buttonText + '</div>');
$('.calcGrossButton').css(buttonCSS);
doIt();
clearInterval(checkExist);
}
}, 100); // check every 100ms
// Start when order/fill view is loaded
var checkExist2 = setInterval(function() {
if ($('div:acp("ListView_header")').length) {
// Button for "All Order" view
$(':acp("ListView_header") :acp("OrderListHeader_title")')
.after('<div class="calcGrossButton">' + buttonText + '</div>');
$('.calcGrossButton').css(buttonCSS);
// Button for "All Fills" page (this doesn't work yet)
$(':acp("FillListHeader_fill-list-header") :acp("FillListHeader_download")')
.after('<div class="calcGrossButton">' + buttonText + '</div>');
$('.calcGrossButton').css(buttonCSS);
doIt();
clearInterval(checkExist2);
}
}, 100); // check every 100ms
function doIt() {
// When clicked
$('.calcGrossButton').click(function(){
var grs = [], addVal = 0, currentUSD = 0, net = 0;
// Do 'orders' list ------------------
$('ul:acp("OrderList_list") li:acp("OrderList_row")').each( function() {
var $this = $(this);
var market = $this.find(':acp("OrderList_order-price") span.whole').text() +
'.' + $this.find(':acp("OrderList_order-price") span.part').text();
var wholeBTC = $this.find(':acp("OrderList_split-number") span.whole:first').text();
var subNum = (wholeBTC.substr(0,1) == '≈') ? 2 : 0;
var btc = $this.find(':acp("OrderList_order-size") :acp("OrderList_split-number") span.whole:first').text().substr(subNum) +
'.' + $this.find(':acp("OrderList_order-size") :acp("OrderList_split-number") span.part').text();
var net = roundTo(market * btc, 2);
//alert('market: ' + market + ', btc: ' + btc + ', multiplied: ' + (market * btc) + ', net: ' + net); //debug
var color = $this.find(':acp("OrderList_order-tag")').is('[class*="buy"]') ? "rgba(255,105,57,.85)" : "rgba(132,247,102,.85)";
var buyOrSell = $this.find(':acp("OrderList_order-tag")').is('[class*="buy"]') ? "-" : "+";
if (!$this.hasClass('NetDone')){
$this.find('div:acp("OrderList_order-price"):acp("OrderList_column") :acp("OrderList_split-number")')
.append(" <br>(" + grossPreText + " <span style='color:" + color + ";'>" + buyOrSell + "</span> $<span style='color:" + color + "'>" + net + "</span>)");
}
$this.addClass('NetDone');
net = parseFloat(net);
var addVal = (buyOrSell == '+') ? net : (net - (net*2));
grs.push(addVal);
});
// Do 'fills' list ------------------
$('ul:acp("FillList_list") li:acp("FillList_row")').each( function() {
var $this = $(this);
var market = $this.find(':acp("FillList_fill-price") span.whole').text() +
'.' + $this.find(':acp("FillList_fill-price") span.part').text();
var wholeBTC = $this.find(':acp("FillList_split-number") span.whole:first').text();
var subNum = (wholeBTC.substr(0,1) == '≈') ? 2 : 0;
var btc = $this.find(':acp("FillList_fill-size") :acp("FillList_split-number") span.whole:first').text().substr(subNum) +
'.' + $this.find(':acp("FillList_fill-size") :acp("FillList_split-number") span.part').text();
$this.find(':acp("FillList_fill-price")').css('white-space','inherit');
var net = roundTo(market * btc, 2);
//alert('market: ' + market + ', btc: ' + btc + ', multiplied: ' + (market * btc) + ', net: ' + net); //debug
var color = $this.find(':acp("FillList_fill-tag")').is('[class*="buy"]') ? "rgba(255,105,57,.85)" : "rgba(132,247,102,.85)";
var buyOrSell = $this.find(':acp("FillList_fill-tag")').is('[class*="buy"]') ? "-" : "+";
if (!$this.hasClass('NetDone')){
$this.find(':acp("FillList_fill-price"):acp("FillList_column") :acp("FillList_split-number")')
.append(" <br>(" + grossPreText + " <span style='color:" + color + ";'>" + buyOrSell + "</span> $<span style='color:" + color + ";'>" + net + "</span>)");
}
$this.addClass('NetDone');
});
// Tweak some styles for better display with the added info
$(':acp("FillList_fill-list") :acp("FillList_row") :acp("FillList_fill-price")')
.css('width','25%');
$(':acp("FillList_fill-list") :acp("FillList_row") :acp("FillList_fill-time")')
.css('width','20%');
$(':acp("OrderList_order-list") :acp("OrderList_list") :acp("OrderList_order") :acp("OrderList_order-tag") :acp("OrderList_tag")')
.css('height','27px');
$(':acp("FillList_fill-list") :acp("FillList_list") :acp("FillList_fill") :acp("FillList_fill-tag") span')
.css('height','27px');
// Do total gross
if (!$('.totalGRS').length) {
$(':acp("BalanceInfo_currencies") :acp("BalanceInfo_spacer")').clone().appendTo(':acp("BalanceInfo_currencies")');
$(':acp("BalanceInfo_currencies")').append('<div class="totalLabel" style="color:yellow">+ ORDERS</div>');
$(':acp("BalanceInfo_balances") :acp("BalanceInfo_spacer")').clone().appendTo(':acp("BalanceInfo_balances")');
$(':acp("BalanceInfo_balances") :acp("Tooltip_wrapper"):first').clone().addClass('totalGRS').appendTo(':acp("BalanceInfo_balances")');
}
var currentUSD = $(':acp("BalanceInfo_balances") span:acp("BalanceInfo_term-description"):first').text();
currentUSD = parseFloat(currentUSD);
$('.totalGRS span:acp("BalanceInfo_term-description")').css('color','yellow').html(currentUSD + grs.reduce(add, 0));
});
}
function add(a, b) {
return a + b;
}
// Declare :acp() custom jQuery selector. It finds individual class names beginning with 'string'
$(function(){
$.expr[":"].acp = function(elem, index, m){
var regString = '\\b' + m[3];
var reg = new RegExp(regString, "g");
return elem.className.match(reg);
}
});
// Rounding
function roundTo(n, digits) {
var negative = false;
if (digits === undefined) {
digits = 0;
}
if ( n < 0) {
negative = true;
n = n * -1;
}
var multiplicator = Math.pow(10, digits);
n = parseFloat((n * multiplicator).toFixed(11));
n = (Math.round(n) / multiplicator).toFixed(2);
if ( negative ) {
n = (n * -1).toFixed(2);
}
return n;
}