import { ADDITIONAL_MARKET_FEE } from './market.ts'; import { assertXmrAmount, xmrCommission } from './xmr-amount.ts'; /** Allocation only, not proof of payment or an instruction to send/retain funds. */ export function allocateXmrSale(gross: bigint, hostingBps: number) { assertXmrAmount(gross); if (gross === 0n) throw new Error('Sale price must be positive; use a free transfer for gifts'); if (!Number.isSafeInteger(hostingBps) || hostingBps < 0 || hostingBps > 5000) { throw new Error('Hosting commission must be between 0 and 5000 basis points'); } const hosting = xmrCommission(gross, hostingBps); const author = xmrCommission(gross, ADDITIONAL_MARKET_FEE.bps); return { gross, hosting, author, sellerBeforeNetworkCosts: gross - hosting - author }; } /** * Evaluate an explicitly supplied total seller-funded network-cost budget, including * every applicable leg. Does not choose who funds an author leg or approve a quote. * The budget is a maximum, not revenue; actual costs/unused budget need accounting. */ export function assessXmrSaleBudget(gross: bigint, hostingBps: number, sellerNetworkBudget: bigint) { const allocation = allocateXmrSale(gross, hostingBps); assertXmrAmount(sellerNetworkBudget); const available = allocation.sellerBeforeNetworkCosts; const viable = sellerNetworkBudget < available; return { ...allocation, sellerNetworkBudget, viable, sellerMinimumNet: viable ? available - sellerNetworkBudget : 0n, // Additional gross-independent funding required to retain at least one atomic unit. fundingShortfall: viable ? 0n : sellerNetworkBudget - available + 1n }; }