118 lines
4.0 KiB
JavaScript
118 lines
4.0 KiB
JavaScript
// Generated, do not edit. sha256:20efe63e56f8374f20930043f99fa07bae78df1e6fc48a984d3f6364d25853bf
|
|
import { CONFIG } from './config.js';
|
|
import { fail } from './app-error.js';
|
|
|
|
const M = CONFIG.METALS;
|
|
|
|
export const isMetal = asset => !!asset && asset.kind === 'metal';
|
|
|
|
export function metalFactor(code) {
|
|
const f = M.UNITS[code];
|
|
if (!f) throw new Error(`Unknown metal unit: '${code}'.`);
|
|
return f;
|
|
}
|
|
|
|
export function metalPrimary(asset) {
|
|
return asset.displayUnit === 'subunit' && asset.subunit ? asset.subunit : asset.unit;
|
|
}
|
|
export function metalSecondary(asset) {
|
|
return asset.displayUnit === 'subunit' && asset.subunit ? asset.unit : asset.subunit;
|
|
}
|
|
|
|
export function toBaseByFactor(value, code) {
|
|
const n = Number(value);
|
|
if (!Number.isFinite(n)) fail('common.invalidAmount', null, 'Invalid amount.');
|
|
return Math.round(n * metalFactor(code) * Math.pow(10, M.BASE_DECIMALS));
|
|
}
|
|
export function fromBaseByFactor(amount, code) {
|
|
return (Number(amount) / Math.pow(10, M.BASE_DECIMALS)) / metalFactor(code);
|
|
}
|
|
|
|
export function mainToSub(main, decimals) {
|
|
return Math.round(Number(main) * Math.pow(10, decimals || 0));
|
|
}
|
|
export function subToMain(sub, decimals) {
|
|
const d = decimals || 0;
|
|
return Number((Number(sub) / Math.pow(10, d)).toFixed(d));
|
|
}
|
|
|
|
export function toSubunit(value, asset) {
|
|
if (isMetal(asset)) return toBaseByFactor(value, metalPrimary(asset));
|
|
const n = Number(value);
|
|
if (!Number.isFinite(n)) fail('common.invalidAmount', null, 'Invalid amount.');
|
|
const dec = asset.decimals ?? 0;
|
|
return asset.displayUnit === 'subunit' ? Math.round(n) : mainToSub(n, dec);
|
|
}
|
|
|
|
export function fromSubunit(amount, asset) {
|
|
if (isMetal(asset)) return fromBaseByFactor(amount, metalPrimary(asset));
|
|
const dec = asset.decimals ?? 0;
|
|
if (asset.displayUnit === 'subunit') return amount;
|
|
return subToMain(amount, dec);
|
|
}
|
|
|
|
export function unitToSubunit(value, asset) {
|
|
if (isMetal(asset)) return toBaseByFactor(value, asset.unit);
|
|
const n = Number(value);
|
|
if (!Number.isFinite(n)) fail('common.invalidAmount', null, 'Invalid amount.');
|
|
return mainToSub(n, asset.decimals ?? 0);
|
|
}
|
|
|
|
export function priceToBase(price, asset) {
|
|
const n = Number(price);
|
|
return isMetal(asset) ? n / metalFactor(metalPrimary(asset)) : n;
|
|
}
|
|
export function priceFromBase(stored, asset) {
|
|
const n = Number(stored);
|
|
return isMetal(asset) ? n * metalFactor(metalPrimary(asset)) : n;
|
|
}
|
|
|
|
export function unitPriceToBase(price, asset) {
|
|
const n = Number(price);
|
|
if (!Number.isFinite(n)) throw new Error('Invalid price.');
|
|
return isMetal(asset) ? n / metalFactor(asset.unit) : n;
|
|
}
|
|
|
|
function getal(v) {
|
|
if (v === null || v === undefined) return null;
|
|
if (typeof v === 'string' && v.trim() === '') return null;
|
|
const n = Number(v);
|
|
return Number.isFinite(n) ? n : null;
|
|
}
|
|
|
|
function feeSigned(fee, type) {
|
|
const f = getal(fee) ?? 0;
|
|
return type === 'sell' ? -f : f;
|
|
}
|
|
|
|
export function totalFromPrice(amountBase, decimals, priceBase, fee = 0, type = 'buy') {
|
|
const a = getal(amountBase), p = getal(priceBase);
|
|
if (a === null || p === null) return null;
|
|
return (a / Math.pow(10, decimals ?? 0)) * p + feeSigned(fee, type);
|
|
}
|
|
|
|
export function priceFromTotal(total, amountBase, decimals, fee = 0, type = 'buy') {
|
|
const tot = getal(total), a = getal(amountBase);
|
|
if (tot === null || a === null) return null;
|
|
const eenheden = a / Math.pow(10, decimals ?? 0);
|
|
const netto = tot - feeSigned(fee, type);
|
|
if (netto < 0) return null;
|
|
return eenheden > 0 ? netto / eenheden : null;
|
|
}
|
|
|
|
export function amountFromTotal(total, priceBase, decimals, fee = 0, type = 'buy') {
|
|
const tot = getal(total), p = getal(priceBase);
|
|
if (tot === null || p === null || p <= 0) return null;
|
|
const netto = tot - feeSigned(fee, type);
|
|
if (netto < 0) return null;
|
|
return (netto / p) * Math.pow(10, decimals ?? 0);
|
|
}
|
|
|
|
export function priceUnitLabel(asset) {
|
|
return isMetal(asset) ? metalPrimary(asset) : asset?.unit;
|
|
}
|
|
|
|
export function hasSubunit(asset) {
|
|
return !!(asset && typeof asset.subunit === 'string' && asset.subunit.trim() !== '');
|
|
}
|