import test from 'node:test'; import assert from 'node:assert/strict'; import { MAX_XMR_AMOUNT, XMR_ATOMIC_UNITS, XMR_RPC_UINT64_MAX, parseXmr, formatXmr, parseAtomicXmr, atomicXmrString, assertXmrRpcAmount, xmrCommission } from '../shared/xmr-amount.ts'; import { allocateXmrSale, assessXmrSaleBudget } from '../shared/xmr-pricing.ts'; import { atomicXmr, fiatCents } from '../server/market/xmr.ts'; import { xmrString, mockQuote } from '../server/market/payments.ts'; test('exact XMR decimal input preserves legacy bounds and canonicalizes without floats', () => { for (const [input, expected] of [['0', 0n], ['0.000000000001', 1n], ['1.2', 1_200_000_000_000n], ['9999999999.999999999999', MAX_XMR_AMOUNT]] as const) { assert.equal(parseXmr(input), expected); assert.equal(atomicXmr(input), expected); assert.equal(parseXmr(formatXmr(expected)), expected); assert.equal(xmrString(expected), formatXmr(expected)); } assert.equal(formatXmr(0n), '0.000000000000'); assert.equal(formatXmr(1n), '0.000000000001'); assert.equal(formatXmr(XMR_ATOMIC_UNITS), '1.000000000000'); for (const bad of ['', ' ', ' 1', '1 ', '\n1', '1\n', '+1', '-0', '-1', '01', '.1', '1.', '1e-12', '1_000', '1,000', 'NaN', 'Infinity', '12', '0.0000000000001', '10000000000', '9'.repeat(100_000), 1, 1n, null, {}, ['1']] as unknown[]) { assert.throws(() => parseXmr(bad as string)); assert.throws(() => atomicXmr(bad as string)); } }); test('atomic wire strings reject alternate spellings, coercion and unsafe numbers', () => { for (const value of [0n, 1n, BigInt(Number.MAX_SAFE_INTEGER) + 2n, XMR_RPC_UINT64_MAX, MAX_XMR_AMOUNT]) { const wire = atomicXmrString(value); assert.equal(parseAtomicXmr(JSON.parse(JSON.stringify(wire))), value); } for (const value of ['', '00', '01', '+1', '-1', '1.0', '1e12', '1\n', ' 1', (MAX_XMR_AMOUNT + 1n).toString(), '9'.repeat(100_000), 1, null, {}]) { assert.throws(() => parseAtomicXmr(value as string)); } for (const bad of [-1n, MAX_XMR_AMOUNT + 1n, 1, null] as unknown[]) { assert.throws(() => formatXmr(bad as bigint)); assert.throws(() => atomicXmrString(bad as bigint)); } assert.doesNotThrow(() => assertXmrRpcAmount(XMR_RPC_UINT64_MAX)); assert.throws(() => assertXmrRpcAmount(XMR_RPC_UINT64_MAX + 1n)); }); test('legacy processor USD parser also requires absolute end-of-input', () => { assert.equal(fiatCents('0'), 0); assert.equal(fiatCents('1.2'), 120); assert.equal(fiatCents('9999999.99'), 999999999); for (const value of ['1\n', '1\r', '1\r\n', '1\u2028', '1\u2029', '1.00\n', '01', '1e2', '10000000', '0.001', '9'.repeat(100_000), 1, null]) { assert.throws(() => fiatCents(value as string)); } }); test('tiny prices are representable and commissions round independently without a minimum charge', () => { assert.deepEqual(allocateXmrSale(1n, 5000), { gross: 1n, hosting: 0n, author: 0n, sellerBeforeNetworkCosts: 1n }); assert.equal(allocateXmrSale(99n, 0).author, 0n); assert.equal(allocateXmrSale(100n, 0).author, 1n); assert.deepEqual(allocateXmrSale(199n, 250), { gross: 199n, hosting: 4n, author: 1n, sellerBeforeNetworkCosts: 194n }); assert.throws(() => allocateXmrSale(0n, 0)); for (const bad of [-1, 5001, 0.5, NaN, Infinity, '100', null] as unknown[]) { assert.throws(() => allocateXmrSale(1n, bad as number)); } for (const bad of [-1, 10001, 0.5, NaN]) assert.throws(() => xmrCommission(1n, bad)); }); test('seller network budget preflight distinguishes positive net, exact exhaustion and fee spikes', () => { const gross = parseXmr('1'), available = allocateXmrSale(gross, 250).sellerBeforeNetworkCosts; const good = assessXmrSaleBudget(gross, 250, available - 1n); assert.equal(good.viable, true); assert.equal(good.sellerMinimumNet, 1n); assert.equal(good.fundingShortfall, 0n); for (const extra of [0n, 1n, 1_000_000n]) { const blocked = assessXmrSaleBudget(gross, 250, available + extra); assert.equal(blocked.viable, false); assert.equal(blocked.sellerMinimumNet, 0n); assert.equal(blocked.fundingShortfall, extra + 1n); } assert.equal(assessXmrSaleBudget(1n, 0, 0n).viable, true); assert.equal(assessXmrSaleBudget(1n, 0, 1n).viable, false); assert.throws(() => assessXmrSaleBudget(gross, 0, -1n)); assert.throws(() => assessXmrSaleBudget(gross, 0, MAX_XMR_AMOUNT + 1n)); }); test('deterministic generated amounts conserve value, bound rounding and round-trip exactly', () => { let seed = 0x584d52n; for (let i = 0; i < 4000; i++) { seed = (seed * 6364136223846793005n + 1442695040888963407n) % (1n << 96n); const gross = seed % MAX_XMR_AMOUNT + 1n, bps = i % 5001; assert.equal(parseXmr(formatXmr(gross)), gross); assert.equal(parseAtomicXmr(atomicXmrString(gross)), gross); const a = allocateXmrSale(gross, bps); assert.equal(a.hosting + a.author + a.sellerBeforeNetworkCosts, gross); for (const [fee, rate] of [[a.hosting, BigInt(bps)], [a.author, 100n]]) { assert.ok(fee * 10000n <= gross * rate); assert.ok((fee + 1n) * 10000n > gross * rate); } const budget = seed % (a.sellerBeforeNetworkCosts + 2n); const q = assessXmrSaleBudget(gross, bps, budget); assert.equal(q.viable, a.sellerBeforeNetworkCosts > budget); if (q.viable) assert.equal(q.hosting + q.author + budget + q.sellerMinimumNet, gross); } }); test('mock USD caller retains its original independently rounded amounts', () => { for (const cents of [1, 19, 1500, 100_000_000]) for (const bps of [0, 250, 5000]) { const quote = mockQuote(cents, bps, 19999); const gross = (BigInt(cents) * XMR_ATOMIC_UNITS + 19998n) / 19999n; assert.equal(parseXmr(quote.invoice.amountXmr), gross); assert.equal(parseXmr(quote.feeXmr), gross * BigInt(bps) / 10000n); assert.equal(parseXmr(quote.additionalFee.amountXmr), gross / 100n); assert.equal(parseXmr(quote.sellerNetXmr), gross - gross * BigInt(bps) / 10000n - gross / 100n); assert.equal(quote.invoice.address, null); } });