Skip to content

Instantly share code, notes, and snippets.

@QuantBits
Created February 8, 2019 17:55
Show Gist options
  • Star 52 You must be signed in to star a gist
  • Fork 25 You must be signed in to fork a gist
  • Save QuantBits/6b8315f93969ee7caf6c3d66e70ec721 to your computer and use it in GitHub Desktop.
Save QuantBits/6b8315f93969ee7caf6c3d66e70ec721 to your computer and use it in GitHub Desktop.
BitMex USD Converter - For TemperMonkey
// ==UserScript==
// @name BitMex USD Converter
// @namespace https://bitmex.com/
// @version 0.11
// @description Get some sanity into your gambling.
// @author koinkraft
// @grant none
// @include https://bitmex.com/*
// @include https://www.bitmex.com/*
// @require https://code.jquery.com/jquery-2.1.4.min.js
// ==/UserScript==
(function() {
'use strict';
// Script vars
let indexPrice = 0;
let currentBalance = {total: 0, avail: 0};
// Extract BitMex price
const updateIndexPrice = () => {
$('.instrument').each(function() {
let obj = this;
if($(obj).children('.symbol').length > 0 && $(obj).children('.symbol').html() == '.BXBT') {
indexPrice = $(obj).children('.price').html();
}
});
setTimeout(function() {
updateIndexPrice();
}, 1000);
};
// Extract Wallet Balance
const extractWalletBalance = (callback) => {
let balances = currentBalance;
$('a[href="/app/wallet"] > span > table > tbody > tr').each(function() {
let currentLabel = '';
$(this).children('td').each(function() {
if($(this).html() == 'Total' || $(this).html() == 'Avail') {
currentLabel = $(this).html();
} else {
if(currentLabel == 'Total') {
let balanceTotal = formatXBTString($(this).html());
if(balanceTotal !== false) balances.total = balanceTotal;
} else if(currentLabel == 'Avail') {
let balanceAvail = formatXBTString($(this).html());
if(balanceAvail !== false) balances.avail = balanceAvail;
}
}
});
});
currentBalance = balances;
callback(balances);
};
// Set USD Wallet Balance
const setWalletBalance = (updatedBalances) => {
if(updatedBalances.total + ' USD' != $('.balance-usd-total').html()) $('.balance-usd-total').html(updatedBalances.total + ' USD');
if(updatedBalances.avail + ' USD' != $('.balance-usd-avail').html()) $('.balance-usd-avail').html(updatedBalances.avail + ' USD');
};
// Convert XBT String
const formatXBTString = (string) => {
let parts = string.split(" ");
if(parts.length == 2) {
if(parts[1] == 'XBT') {
return parts[0].replace(",",".");
} else if(parts[1] == 'mXBT') {
return parts[0].replace(",",".")*0.001;
} else if(parts[1] == 'XBt') {
return parts[0].replace(".","")*0.00001;
} else if(parts[1] == 'μXBT') {
return parts[0].replace(".","").replace(",",".")*0.000001;
}
}
return false;
};
// Update Wallet Balances
const updateWalletBalances = () => {
setTimeout(function() {
if(indexPrice != 0) {
extractWalletBalance(function(balances) {
let updatedBalances = {total: (balances.total*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}), avail: (balances.avail*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})};
setWalletBalance(updatedBalances);
});
}
updateWalletBalances();
}, 1000);
};
// Update PNLs
const updatePNLs = (setTimeoutCycle) => {
if(indexPrice != 0) {
// Unrealized PNL
$('td.unrealisedPnl').each(function() {
let obj = this;
let content;
let isSpan = false;
if($(this).children('div:first-child').children('span').length > 0) {
content = $(this).children('div:first-child').children('span:first-child').html();
isSpan = true;
} else {
content = $(this).children('div:first-child').html();
}
let parts = content.split(" ");
if(parts[1] == 'XBT' || parts[1] == 'mXBT' || parts[1] == 'XBt' || parts[1] == 'μXBT') {
let formatUnrealizedPNL = formatXBTString(parts[0] + ' ' + parts[1]);
let unrealizedPNLUSD = (formatUnrealizedPNL*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
let newDivContent;
if(!isSpan) {
newDivContent = unrealizedPNLUSD + ' USD ' + parts[2];
} else {
newDivContent = '<span style="background:rgba(86,188,118,0.25);" class="' + ( formatUnrealizedPNL*indexPrice < 0 ? 'neg' : 'pos' ) + ' tooltipWrapper hovered">' + unrealizedPNLUSD + ' USD ' + parts[2] + '</span>';
}
if(newDivContent != $(obj).children('div.unrealizedPnlUSD').html()) {
$(obj).children('div.unrealizedPnlUSD').html(newDivContent);
if(formatUnrealizedPNL*indexPrice < 0) {
if(!$(obj).children('div.unrealizedPnlUSD').hasClass('neg')) {
$(obj).children('div.unrealizedPnlUSD').addClass('neg').removeClass('pos');
}
} else {
if(!$(obj).children('div.unrealizedPnlUSD').hasClass('pos')) {
$(obj).children('div.unrealizedPnlUSD').addClass('pos').removeClass('neg');
}
}
}
}
});
// Realized PNL
$('td.combinedRealisedPnl').each(function() {
let obj = this;
let realizedPNLhover = formatXBTString($(obj).children('.hoverContainer:first-child').children('.hoverVisible').children('.tooltipWrapper').children('span').html());
let realizedPNL = formatXBTString($(obj).children('.hoverContainer:first-child').children('.hoverHidden').children('span').html());
let realizedPNLUSDhoverContent = (realizedPNLhover*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USD';
let realizedPNLUSDContent = (realizedPNL*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USD';
if($(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').html() != realizedPNLUSDhoverContent) {
$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').html(realizedPNLUSDhoverContent);
if(realizedPNLhover*indexPrice < 0) {
if(!$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').hasClass('neg')) {
$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').addClass('neg').removeClass('pos');
}
} else {
if(!$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').hasClass('pos')) {
$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').addClass('pos').removeClass('neg');
}
}
}
if($(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').html() != realizedPNLUSDContent) {
$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').html(realizedPNLUSDContent);
if(realizedPNL*indexPrice < 0) {
if(!$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').hasClass('neg')) {
$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').addClass('neg').removeClass('pos');
}
} else {
if(!$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').hasClass('pos')) {
$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').addClass('pos').removeClass('neg');
}
}
}
});
}
if(setTimeoutCycle) {
setTimeout(function() {
updatePNLs(true);
}, 50);
}
};
// Initialize PNL wrapper
const initPNLWrapper = (setTimeoutCycle) => {
if($('td.unrealisedPnl').length > 0 && $('.unrealizedPnlUSD').length == 0) {
// Unrealized PNL
$('td.unrealisedPnl').css('position', 'relative');
$('td.unrealisedPnl > div').css('opacity', '0').css('position','absolute').css('left','0').css('top','0').css('right','0').css('bottom','0');
$('td.unrealisedPnl > div').after('<div class="unrealizedPnl unrealizedPnlUSD">0.00 USD (0.00%)</div>');
// Realized PNL
$('td.combinedRealisedPnl > .hoverContainer').hide();
$('td.combinedRealisedPnl > .hoverContainer').after('<span class="hoverContainer realizedPNLContainer"><span class="hoverVisible"><span class="tooltipWrapper"><span>0.00 USD</span></span></span><span class="hoverHidden"><span>0.00 USD</span></span></span>');
}
if(setTimeoutCycle) {
setTimeout(function() {
initPNLWrapper(true);
}, 100);
}
};
// Wait for window to load
$(window).load(function() {
// Hide BTC balance box
$('._1mNCXSUh:first').hide();
$('._2UCMYPbC > ._2wx45MYS:first').hide();
// Init PNL Wrapper
initPNLWrapper(true);
$(window).resize(function() {
initPNLWrapper(false);
});
// Insert USD Balance div
$('.announcementsDropdown').before('<a class="_1mNCXSUh usdBalance noHover" href="/app/wallet"><span class="noBorder tooltipWrapper"><table class="visible-lg visible-md"><tbody><tr><td class="_39qDSUxb">Total</td><td class="balance-usd-total">0.00 USD</td></tr><tr><td class="_39qDSUxb">Avail</td><td class="balance-usd-avail">0.00 USD</td></tr></tbody></table></span></a><span class="_2wx45MYS visible-lg visible-md"></span>');
// Update Functions
setInterval(() => {
console.log('Updating....');
updateIndexPrice();
updateWalletBalances();
updatePNLs(true);
$('td.unrealisedPnl > div').hover(function() {
updatePNLs(false);
});
}, 30000);
});
})();
@JayWiseFree
Copy link

Hey fantastic script mate! I have one major request: can you please also add this to convert 'Order Value' and 'Cost' for orders in USD as well? Cheers mate! Great work. :)

@Sapiensinfomatics
Copy link

Hey, is there any information how I can set this up please? I have zero knowledge of coding.

@ILoveMexKetchup
Copy link

Install Tampermonkey (available for Chrome, Microsoft Edge, Safari, Opera Next, and Firefox)

  1. go to https://www.tampermonkey.net
  2. click the download button, this will redirect you to the according addon page for your browser
  3. click the "add to your browsers name" button
  4. you will now see a new red icon in your browser.

Install the userscript

  1. click on the new red Tampermonkey icon, then click "Create a new script"
  2. replace the script template that opens with the bitmex usd script
  3. click on file, save
  4. refresh the bitmex.com page, wait 30 seconds to let the display updating, voila

you can always enable or disable any installed script by clicking on the red tampermonkey icon and then clicking the switch in the row of the according script.

@unclescroogeJR
Copy link

This second script works on FIREFOX? String error on lines 112 114 on second script and with first to much lag.. What i need to do?

@cmer
Copy link

cmer commented May 29, 2019

Is this script still working? It doesn't seem to do anything for me (macOS, Safari).

@fr4z3n
Copy link

fr4z3n commented Jun 17, 2019

thank you for this neat script. was searching for it a long time :)

@nateflanders
Copy link

It was working fine for weeks for me... now all the sudden displays no conversion data, can't seem to reset it back to working... any suggestions?

Copy link

ghost commented Jun 25, 2019

I just tested this script on testnet.bitmex.com (you have to edit the script to include this site). When I entered the trade it didn't work, but now after 1 minute or so it works. Try hard refreshing the page and wait a minute or two.

@cataseven
Copy link

cataseven commented Jul 2, 2019

When I copy and past this code into Tampermonkey. I get a ('$' is not defined) on every line there is '$'.

Guys, I know next to nothing about programming. What do you think the issue is? Thanks!

Add the bold one to line 19
....
// Script vars
let currentBalance = {total: 0, avail: 0};
let indexPrice = 0;
var $ = window.jQuery;
...

@cmer
Copy link

cmer commented Jul 2, 2019

Make sure jquery is present

@theodoroswhite
Copy link

Lines 112 and 114 both say "Unexpected String Concatenation of Literals"?

Both around ' + ' part of each line

@cataseven
Copy link

Lines 112 and 114 both say "Unexpected String Concatenation of Literals"?

Both around ' + ' part of each line

I have same errors but it is working.

Did you refresh Bitmex page after saving your code?
Did you wait for 45 seconds after refresh?

@theodoroswhite
Copy link

Ya I have. Still nothing. Are you using BitcoinMolester's code?

@cataseven
Copy link

// ==UserScript==
// @name BitMex USD Converter
// @namespace https://bitmex.com/
// @Version 0.11
// @description Get some sanity into your gambling.
// @author koinkraft
// @grant none
// @include https://bitmex.com/*
// @include https://www.bitmex.com/*
// @require https://code.jquery.com/jquery-2.1.4.min.js
// ==/UserScript==

(function() {
'use strict';

// Script vars
let indexPrice = 0;
let currentBalance = {total: 0, avail: 0};
var $ = window.jQuery;

// Extract BitMex price
const updateIndexPrice = () => {
    $('.instrument').each(function() {
        let obj = this;
        if($(obj).children('.symbol').length > 0 && $(obj).children('.symbol').html() == '.BXBT') {
            indexPrice = $(obj).children('.price').html();
        }
    });
    setTimeout(function() {
        updateIndexPrice();
    }, 1000);
};

// Extract Wallet Balance
const extractWalletBalance = (callback) => {
    let balances = currentBalance;
    $('a[href="/app/wallet"] > span > table > tbody > tr').each(function() {
        let currentLabel = '';
        $(this).children('td').each(function() {
            if($(this).html() == 'Total' || $(this).html() == 'Avail') {
                currentLabel = $(this).html();
            } else {
                if(currentLabel == 'Total') {
                    let balanceTotal = formatXBTString($(this).html());
                    if(balanceTotal !== false) balances.total = balanceTotal;
                } else if(currentLabel == 'Avail') {
                    let balanceAvail = formatXBTString($(this).html());
                    if(balanceAvail !== false) balances.avail = balanceAvail;
                }
            }
        });
    });
    currentBalance = balances;
    callback(balances);
};

// Set USD Wallet Balance
const setWalletBalance = (updatedBalances) => {
    if(updatedBalances.total + ' USD' != $('.balance-usd-total').html()) $('.balance-usd-total').html(updatedBalances.total + ' USD');
    if(updatedBalances.avail + ' USD' != $('.balance-usd-avail').html()) $('.balance-usd-avail').html(updatedBalances.avail + ' USD');
};

// Convert XBT String
const formatXBTString = (string) => {
    let parts = string.split(" ");
    if(parts.length == 2) {
        if(parts[1] == 'XBT') {
            return parts[0].replace(",",".");
        } else if(parts[1] == 'mXBT') {
            return parts[0].replace(",",".")*0.001;
        } else if(parts[1] == 'XBt') {
            return parts[0].replace(".","")*0.00001;
        } else if(parts[1] == 'μXBT') {
            return parts[0].replace(".","").replace(",",".")*0.000001;
        }
    }
    return false;
};

// Update Wallet Balances
const updateWalletBalances = () => {
    setTimeout(function() {
        if(indexPrice != 0) {
            extractWalletBalance(function(balances) {
                let updatedBalances = {total: (balances.total*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}), avail: (balances.avail*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})};
                setWalletBalance(updatedBalances);
            });
        }
        updateWalletBalances();
    }, 1000);
};

// Update PNLs
const updatePNLs = (setTimeoutCycle) => {
    if(indexPrice != 0) {
        // Unrealized PNL
        $('td.unrealisedPnl').each(function() {
            let obj = this;
            let content;
            let isSpan = false;
            if($(this).children('div:first-child').children('span').length > 0) {
                content = $(this).children('div:first-child').children('span:first-child').html();
                isSpan = true;
            } else {
                content = $(this).children('div:first-child').html();
            }
            let parts = content.split(" ");
            if(parts[1] == 'XBT' || parts[1] == 'mXBT' || parts[1] == 'XBt' || parts[1] == 'μXBT') {
                let formatUnrealizedPNL = formatXBTString(parts[0] + ' ' + parts[1]);
                let unrealizedPNLUSD = (formatUnrealizedPNL*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
                let newDivContent;
                if(!isSpan) {
                    newDivContent = unrealizedPNLUSD + ' USD | ' + ' BTC ' + formatUnrealizedPNL + ' ' + parts[2];
                } else {
                    newDivContent = '<span style="background:rgba(86,188,118,0.25);" class="' + ( formatUnrealizedPNL*indexPrice < 0 ? 'neg' : 'pos' ) + ' tooltipWrapper hovered">' + unrealizedPNLUSD + ' USD | ' + ' BTC ' + formatUnrealizedPNL + ' ' + parts[2] + '</span>';
                }
                if(newDivContent != $(obj).children('div.unrealizedPnlUSD').html()) {
                    $(obj).children('div.unrealizedPnlUSD').html(newDivContent);
                    if(formatUnrealizedPNL*indexPrice < 0) {
                        if(!$(obj).children('div.unrealizedPnlUSD').hasClass('neg')) {
                            $(obj).children('div.unrealizedPnlUSD').addClass('neg').removeClass('pos');
                        }
                    } else {
                        if(!$(obj).children('div.unrealizedPnlUSD').hasClass('pos')) {
                            $(obj).children('div.unrealizedPnlUSD').addClass('pos').removeClass('neg');
                        }
                    }
                }
            }
        });

        // Realized PNL
        $('td.combinedRealisedPnl').each(function() {
            let obj = this;
            let realizedPNLhover = formatXBTString($(obj).children('.hoverContainer:first-child').children('.hoverVisible').children('.tooltipWrapper').children('span').html());
            let realizedPNL = formatXBTString($(obj).children('.hoverContainer:first-child').children('.hoverHidden').children('span').html());
            let realizedPNLUSDhoverContent = (realizedPNLhover*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USD';
            let realizedPNLUSDContent = (realizedPNL*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USD';
            if($(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').html() != realizedPNLUSDhoverContent) {
                $(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').html(realizedPNLUSDhoverContent);
                if(realizedPNLhover*indexPrice < 0) {
                    if(!$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').hasClass('neg')) {
                        $(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').addClass('neg').removeClass('pos');
                    }
                } else {
                    if(!$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').hasClass('pos')) {
                       $(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').addClass('pos').removeClass('neg');
                    }
                }
            }
            if($(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').html() != realizedPNLUSDContent) {
                $(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').html(realizedPNLUSDContent);
                if(realizedPNL*indexPrice < 0) {
                    if(!$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').hasClass('neg')) {
                        $(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').addClass('neg').removeClass('pos');
                    }
                } else {
                    if(!$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').hasClass('pos')) {
                       $(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').addClass('pos').removeClass('neg');
                    }
                }
            }
        });
    }
    if(setTimeoutCycle) {
        setTimeout(function() {
            updatePNLs(true);
        }, 50);
    }
};

// Initialize PNL wrapper
const initPNLWrapper = (setTimeoutCycle) => {
    if($('td.unrealisedPnl').length > 0 && $('.unrealizedPnlUSD').length == 0) {
        // Unrealized PNL
        $('td.unrealisedPnl').css('position', 'relative');
        $('td.unrealisedPnl > div').css('opacity', '0').css('position','absolute').css('left','0').css('top','0').css('right','0').css('bottom','0');
        $('td.unrealisedPnl > div').after('<div class="unrealizedPnl unrealizedPnlUSD">0.00 USD (0.00%)</div>');

        // Realized PNL
        $('td.combinedRealisedPnl > .hoverContainer').hide();
        $('td.combinedRealisedPnl > .hoverContainer').after('<span class="hoverContainer realizedPNLContainer"><span class="hoverVisible"><span class="tooltipWrapper"><span>0.00 USD</span></span></span><span class="hoverHidden"><span>0.00 USD</span></span></span>');
    }
    if(setTimeoutCycle) {
        setTimeout(function() {
            initPNLWrapper(true);
        }, 100);
    }
};

// Wait for window to load
$(window).load(function() {

    // Hide BTC balance box
    $('._1mNCXSUh:first').hide();
    $('._2UCMYPbC > ._2wx45MYS:first').hide();

    // Init PNL Wrapper
    initPNLWrapper(true);
    $(window).resize(function() {
        initPNLWrapper(false);
    });

    // Insert USD Balance div
    $('.announcementsDropdown').before('<a class="_1mNCXSUh usdBalance noHover" href="/app/wallet"><span class="noBorder tooltipWrapper"><table class="visible-lg visible-md"><tbody><tr><td class="_39qDSUxb">Total</td><td class="balance-usd-total">0.00 USD</td></tr><tr><td class="_39qDSUxb">Avail</td><td class="balance-usd-avail">0.00 USD</td></tr></tbody></table></span></a><span class="_2wx45MYS visible-lg visible-md"></span>');

    // Update Functions
    setInterval(() => {
        console.log('Updating....');
        updateIndexPrice();
        updateWalletBalances();
        updatePNLs(true);
        $('td.unrealisedPnl > div').hover(function() {
            updatePNLs(false);
        });
    }, 30000);
});

})();

@cmer
Copy link

cmer commented Jul 5, 2019 via email

@pauloec
Copy link

pauloec commented Jul 8, 2019

Yeah it's not working on Safari. I guess some issue with parsing the HTML, i have no time to check though :D

@grant
Copy link

grant commented Jul 8, 2019

Hi there. Please don't @grant unless I can contribute to the conversation. :)

@bafferbox
Copy link

how to set realised pnl in both usd | btc ?

@cryptochuso
Copy link

Good job!

Would it be possible to add all these fields with the two values, usd and xbt?

That would be great!

image

@nateflanders
Copy link

This still isn't working for me. Using latest code, not getting any errors in the code, but never updates price on bitmex. I'm on chrome, have tried it all.

It used to work fine, now the UPNL field shows 0.00 USD (0.00%) no matter what, when the script is enabled, of course.

@Shaifff
Copy link

Shaifff commented Sep 3, 2019

anyone know a revision I can do to @cataseven's version so that my balances at the top show both the usd and btc balance instead of just the usd one?

@nikolaos83
Copy link

It does not work if you set the currency to Satoshi (XBt).

@bejanj
Copy link

bejanj commented Sep 20, 2019

@nateflanders @Shaifff This version works for me on Chrome (with what you want)

// ==UserScript==
// @name         BitMex USD Converter
// @namespace    https://bitmex.com/
// @version      0.11
// @description  Get some sanity into your gambling.
// @author       koinkraft
// @grant        none
// @include      https://bitmex.com/*
// @include      https://www.bitmex.com/*
// @require      https://code.jquery.com/jquery-2.1.4.min.js
// ==/UserScript==

(function() {
    'use strict';

    // Script vars
    let indexPrice = 0;
    let currentBalance = {total: 0, avail: 0};

    // Extract BitMex price
    const updateIndexPrice = () => {
        $('.instrument').each(function() {
            let obj = this;
            if($(obj).children('.symbol').length > 0 && $(obj).children('.symbol').html() == '.BXBT') {
                indexPrice = $(obj).children('.price').html();
            }
        });
        setTimeout(function() {
            updateIndexPrice();
        }, 1000);
    };

    // Extract Wallet Balance
    const extractWalletBalance = (callback) => {
        let balances = currentBalance;
        $('a[href="/app/wallet"] > span > table > tbody > tr').each(function() {
            let currentLabel = '';
            $(this).children('td').each(function() {
                if($(this).html() == 'Total' || $(this).html() == 'Avail') {
                    currentLabel = $(this).html();
                } else {
                    if(currentLabel == 'Total') {
                        let balanceTotal = formatXBTString($(this).html());
                        if(balanceTotal !== false) balances.total = balanceTotal;
                    } else if(currentLabel == 'Avail') {
                        let balanceAvail = formatXBTString($(this).html());
                        if(balanceAvail !== false) balances.avail = balanceAvail;
                    }
                }
            });
        });
        currentBalance = balances;
        callback(balances);
    };

    // Set USD Wallet Balance
    const setWalletBalance = (updatedBalances) => {
        if(updatedBalances.total + ' USD' != $('.balance-usd-total').html()) $('.balance-usd-total').html(updatedBalances.total + ' USD');
        if(updatedBalances.avail + ' USD' != $('.balance-usd-avail').html()) $('.balance-usd-avail').html(updatedBalances.avail + ' USD');
    };

    // Convert XBT String
    const formatXBTString = (string) => {
        let parts = string.split(" ");
        if(parts.length == 2) {
            if(parts[1] == 'XBT') {
                return parts[0].replace(",",".");
            } else if(parts[1] == 'mXBT') {
                return parts[0].replace(",",".")*0.001;
            } else if(parts[1] == 'XBt') {
                return parts[0].replace(".","")*0.00001;
            } else if(parts[1] == 'μXBT') {
                return parts[0].replace(".","").replace(",",".")*0.000001;
            }
        }
        return false;
    };

    // Update Wallet Balances
    const updateWalletBalances = () => {
        setTimeout(function() {
            if(indexPrice != 0) {
                extractWalletBalance(function(balances) {
                    let updatedBalances = {total: (balances.total*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}), avail: (balances.avail*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})};
                    setWalletBalance(updatedBalances);
                });
            }
            updateWalletBalances();
        }, 1000);
    };

    // Update PNLs
    const updatePNLs = (setTimeoutCycle) => {
        if(indexPrice != 0) {
            // Unrealized PNL
            $('td.unrealisedPnl').each(function() {
                let obj = this;
                let content;
                let isSpan = false;
                if($(this).children('div:first-child').children('span').length > 0) {
                    content = $(this).children('div:first-child').children('span:first-child').html();
                    isSpan = true;
                } else {
                    content = $(this).children('div:first-child').html();
                }
                let parts = content.split(" ");
                if(parts[1] == 'XBT' || parts[1] == 'mXBT' || parts[1] == 'XBt' || parts[1] == 'μXBT') {
                    let formatUnrealizedPNL = formatXBTString(parts[0] + ' ' + parts[1]);
                    let unrealizedPNLUSD = (formatUnrealizedPNL*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
                    let newDivContent;
                    if(!isSpan) {
                        newDivContent = unrealizedPNLUSD + ' USD | ' + ' BTC ' + formatUnrealizedPNL + ' ' + parts[2];
                    } else {
                        newDivContent = '<span style="background:rgba(86,188,118,0.25);" class="' + ( formatUnrealizedPNL*indexPrice < 0 ? 'neg' : 'pos' ) + ' tooltipWrapper hovered">' + unrealizedPNLUSD + ' USD | ' + ' BTC ' + formatUnrealizedPNL + ' ' + parts[2] + '</span>';
                    }
                    if(newDivContent != $(obj).children('div.unrealizedPnlUSD').html()) {
                        $(obj).children('div.unrealizedPnlUSD').html(newDivContent);
                        if(formatUnrealizedPNL*indexPrice < 0) {
                            if(!$(obj).children('div.unrealizedPnlUSD').hasClass('neg')) {
                                $(obj).children('div.unrealizedPnlUSD').addClass('neg').removeClass('pos');
                            }
                        } else {
                            if(!$(obj).children('div.unrealizedPnlUSD').hasClass('pos')) {
                                $(obj).children('div.unrealizedPnlUSD').addClass('pos').removeClass('neg');
                            }
                        }
                    }
                }
            });

            // Realized PNL
            $('td.combinedRealisedPnl').each(function() {
                let obj = this;
                let realizedPNLhover = formatXBTString($(obj).children('.hoverContainer:first-child').children('.hoverVisible').children('.tooltipWrapper').children('span').html());
                let realizedPNL = formatXBTString($(obj).children('.hoverContainer:first-child').children('.hoverHidden').children('span').html());
                let realizedPNLUSDhoverContent = (realizedPNLhover*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USD';
                let realizedPNLUSDContent = (realizedPNL*indexPrice).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USD';
                if($(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').html() != realizedPNLUSDhoverContent) {
                    $(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').html(realizedPNLUSDhoverContent);
                    if(realizedPNLhover*indexPrice < 0) {
                        if(!$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').hasClass('neg')) {
                            $(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').addClass('neg').removeClass('pos');
                        }
                    } else {
                        if(!$(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').hasClass('pos')) {
                           $(obj).children('.realizedPNLContainer').children('.hoverVisible').children('.tooltipWrapper').children('span').addClass('pos').removeClass('neg');
                        }
                    }
                }
                if($(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').html() != realizedPNLUSDContent) {
                    $(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').html(realizedPNLUSDContent);
                    if(realizedPNL*indexPrice < 0) {
                        if(!$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').hasClass('neg')) {
                            $(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').addClass('neg').removeClass('pos');
                        }
                    } else {
                        if(!$(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').hasClass('pos')) {
                           $(obj).children('.realizedPNLContainer').children('.hoverHidden').children('span').addClass('pos').removeClass('neg');
                        }
                    }
                }
            });
        }
        if(setTimeoutCycle) {
            setTimeout(function() {
                updatePNLs(true);
            }, 50);
        }
    };

    // Initialize PNL wrapper
    const initPNLWrapper = (setTimeoutCycle) => {
        if($('td.unrealisedPnl').length > 0 && $('.unrealizedPnlUSD').length == 0) {
            // Unrealized PNL
            $('td.unrealisedPnl').css('position', 'relative');
            $('td.unrealisedPnl > div').css('opacity', '0').css('position','absolute').css('left','0').css('top','0').css('right','0').css('bottom','0');
            $('td.unrealisedPnl > div').after('<div class="unrealizedPnl unrealizedPnlUSD">0.00 USD (0.00%)</div>');

            // Realized PNL
            $('td.combinedRealisedPnl > .hoverContainer').hide();
            $('td.combinedRealisedPnl > .hoverContainer').after('<span class="hoverContainer realizedPNLContainer"><span class="hoverVisible"><span class="tooltipWrapper"><span>0.00 USD</span></span></span><span class="hoverHidden"><span>0.00 USD</span></span></span>');
        }
        if(setTimeoutCycle) {
            setTimeout(function() {
                initPNLWrapper(true);
            }, 100);
        }
    };

    // Wait for window to load
    $(window).load(function() {

        // Hide BTC balance box
        $('._1mNCXSUh:first').hide();
        $('._2UCMYPbC > ._2wx45MYS:first').hide();

        // Init PNL Wrapper
        initPNLWrapper(true);
        $(window).resize(function() {
            initPNLWrapper(false);
        });

        // Insert USD Balance div
        $('.announcementsDropdown').before('<a class="_1mNCXSUh usdBalance noHover" href="/app/wallet"><span class="noBorder tooltipWrapper"><table class="visible-lg visible-md"><tbody><tr><td class="_39qDSUxb">Total</td><td class="balance-usd-total">0.00 USD</td></tr><tr><td class="_39qDSUxb">Avail</td><td class="balance-usd-avail">0.00 USD</td></tr></tbody></table></span></a><span class="_2wx45MYS visible-lg visible-md"></span>');

        // Update Functions
        setInterval(() => {
            console.log('Updating....');
            updateIndexPrice();
            updateWalletBalances();
            updatePNLs(true);
            $('td.unrealisedPnl > div').hover(function() {
                updatePNLs(false);
            });
        }, 30000);
    });

})();

@nateflanders
Copy link

@bigbdude - thank you! That worked!

@kvck
Copy link

kvck commented Oct 12, 2019

PNL field shows 0.00 USD (0.00%) after I tried the codes above. can anyone check again? I am using chrome. XBT is used as currency, not satoshi. I also refreshed a couple of time

@braulioholtz
Copy link

A small improvement on the last script, I decided to limit the number of decimal places in BTC profit.
let formatUnrealizedPNL = formatXBTString(parts[0] + ' ' + parts[1]);
to
let formatUnrealizedPNL = formatXBTString(parts[0] + ' ' + parts[1]).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 5});
I think the result gets bug if Satoshi option is selected, using other units looks ok

@chriseomi
Copy link

anyone get this to work in Firefox?

@braulioholtz
Copy link

anyone get this to work in Firefox?

Works normal for me, I just need to wait I believe 1 minute to update the data

@andriytkachiv
Copy link

Stopped working for me. Probably because of hard coding dom elements identifiers

@TradingJoe
Copy link

Ladies and gentlemen. I'm sure you'll all appreciate this extension:

icon-256
https://github.com/TradingJoe/bitmeeex-usd-display

It has a different logic and a much more resilient functionality. It will just work. 😎

screenshot1_1280x800
screenshot2_1280x800

The code is open source. If you don't trust me, check the source code from the zip first. It's pretty short. You like this extension? Consider a donation! 👍

Tested with

  • Chrome (Desktop)
  • Firefox (Desktop)
  • Kiwi (Android Tablet)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment