fix: an address holding only unpriced tokens is no longer totalled at $0.00 (closes #261)
Some checks failed
check / check (push) Has been cancelled
Some checks failed
check / check (push) Has been cancelled
This commit was merged in pull request #298.
This commit is contained in:
@@ -55,42 +55,77 @@ function formatUsd(amount) {
|
||||
);
|
||||
}
|
||||
|
||||
function getAddressValueUsd(addr) {
|
||||
// What an address is worth, as { usd, partial }.
|
||||
//
|
||||
// Prices are fetched for the top 25 tokens only, so an address can hold real
|
||||
// assets this code has no price for. Adding up the priced ones and calling the
|
||||
// result the total states a number the holdings do not support: an address
|
||||
// holding nothing but unpriced tokens comes out at $0.00, which tells the user
|
||||
// their address is worth nothing when it may hold a great deal. Worth zero and
|
||||
// worth an unknown amount are separate facts and get separate fields, the same
|
||||
// way an absent holders_count is not a count of zero.
|
||||
//
|
||||
// usd: the value of the holdings a price is known for, or null when
|
||||
// nothing is knowable at all — testnet, or before the first fetch.
|
||||
// partial: the address also holds a token with no price, so usd is a floor
|
||||
// and not the total.
|
||||
//
|
||||
// Render it through formatAddressTotal() rather than reading usd alone.
|
||||
function getAddressValue(addr) {
|
||||
const { currentNetwork } = require("./state");
|
||||
if (currentNetwork().isTestnet) return null;
|
||||
if (!prices.ETH) return null;
|
||||
let total = 0;
|
||||
const ethBal = parseFloat(addr.balance || "0");
|
||||
total += ethBal * prices.ETH;
|
||||
if (currentNetwork().isTestnet) return { usd: null, partial: false };
|
||||
if (!prices.ETH) return { usd: null, partial: false };
|
||||
let usd = parseFloat(addr.balance || "0") * prices.ETH;
|
||||
let partial = false;
|
||||
for (const token of addr.tokenBalances || []) {
|
||||
const tokenBal = parseFloat(token.balance || "0");
|
||||
if (tokenBal > 0 && prices[token.symbol]) {
|
||||
total += tokenBal * prices[token.symbol];
|
||||
// A balance of zero is not a holding: it can neither add to the total
|
||||
// nor make it incomplete.
|
||||
if (!(tokenBal > 0)) continue;
|
||||
if (prices[token.symbol]) {
|
||||
usd += tokenBal * prices[token.symbol];
|
||||
} else {
|
||||
partial = true;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
return { usd, partial };
|
||||
}
|
||||
|
||||
function getWalletValueUsd(wallet) {
|
||||
const { currentNetwork } = require("./state");
|
||||
if (currentNetwork().isTestnet) return null;
|
||||
if (!prices.ETH) return null;
|
||||
let total = 0;
|
||||
for (const addr of wallet.addresses) {
|
||||
total += getAddressValueUsd(addr);
|
||||
}
|
||||
return total;
|
||||
// The same pair for a whole wallet, and for every wallet at once. One
|
||||
// unpriced holding anywhere makes the sum a floor, so partial carries up.
|
||||
function getWalletValue(wallet) {
|
||||
return sumValues(wallet.addresses.map(getAddressValue));
|
||||
}
|
||||
|
||||
function getTotalValueUsd(wallets) {
|
||||
const { currentNetwork } = require("./state");
|
||||
if (currentNetwork().isTestnet) return null;
|
||||
if (!prices.ETH) return null;
|
||||
let total = 0;
|
||||
for (const wallet of wallets) {
|
||||
total += getWalletValueUsd(wallet);
|
||||
function getTotalValue(wallets) {
|
||||
return sumValues(wallets.map(getWalletValue));
|
||||
}
|
||||
|
||||
function sumValues(values) {
|
||||
let usd = null;
|
||||
let partial = false;
|
||||
for (const value of values) {
|
||||
if (value.usd === null) continue;
|
||||
usd = (usd === null ? 0 : usd) + value.usd;
|
||||
partial = partial || value.partial;
|
||||
}
|
||||
return total;
|
||||
return { usd, partial };
|
||||
}
|
||||
|
||||
// The one rendering of an address total, so no screen says it differently.
|
||||
//
|
||||
// A partial total is shown and named as partial: the figure is the ETH and
|
||||
// priced tokens the user does hold, which is worth having, and suppressing it
|
||||
// would throw away a number that is correct as far as it goes. What is never
|
||||
// shown is a figure covering no holdings at all — the $0.00 sum of an empty
|
||||
// set beside a list of tokens is the bug this replaces.
|
||||
function formatAddressTotal(value) {
|
||||
if (!value || value.usd === null) return "";
|
||||
if (!value.partial) return "Total: " + formatUsd(value.usd);
|
||||
if (value.usd > 0) {
|
||||
return "Total: " + formatUsd(value.usd) + " plus unpriced tokens";
|
||||
}
|
||||
return "Total: unpriced tokens only";
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@@ -99,7 +134,8 @@ module.exports = {
|
||||
clearPrices,
|
||||
getPrice,
|
||||
formatUsd,
|
||||
getAddressValueUsd,
|
||||
getWalletValueUsd,
|
||||
getTotalValueUsd,
|
||||
formatAddressTotal,
|
||||
getAddressValue,
|
||||
getWalletValue,
|
||||
getTotalValue,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user