// Node 18+: save as top-holders.mjs and run `node top-holders.mjs`
const { ASSETS_URL, ASSET, LUMEUS_API_KEY } = process.env;
const url = new URL(`/assets/${ASSET}/holders`, ASSETS_URL);
url.searchParams.set('limit', '10');
const response = await fetch(url, { headers: { Authorization: `Bearer ${LUMEUS_API_KEY}` } });
const page = await response.json();
if (!response.ok) throw new Error(`${response.status} ${page.code}: ${page.error}`);
// Exact integer math: supply is a decimal string with `decimals` places.
const toRaw = (amount, decimals) => {
const [whole, fraction = ''] = amount.split('.');
return BigInt(whole + fraction.padEnd(decimals, '0'));
};
const supplyRaw = toRaw(page.supply, page.decimals ?? 0);
console.log(`${page.holder_count} holders, supply ${page.supply}`);
page._embedded.records.forEach((h, i) => {
// Share in basis points, rounded half up: the same rule as the Python version.
const bp = (BigInt(h.balance_raw) * 20000n + supplyRaw) / (2n * supplyRaw);
console.log(i + 1, h.holder, h.balance, `${bp / 100n}.${String(bp % 100n).padStart(2, '0')}%`);
});