Skip to content

fix(amounts): handle vault and milestone amounts as exact 7-decimal v… - #1763

Merged
1nonlypiece merged 2 commits into
Disciplr-Org:mainfrom
Viccodes11:fix/exact-amounts-and-milestone-sum
Oct 24, 2026
Merged

1nonlypiece merged 2 commits into
Disciplr-Org:mainfrom
Viccodes11:fix/exact-amounts-and-milestone-sum

Conversation

@Viccodes11

Copy link
Copy Markdown
Contributor

Closes #1685

Summary

This PR introduces exact 7-decimal stroop parsing, storage, and formatting across the API and store layers, preventing floating-point precision loss and enforcing that milestone amounts sum exactly to the vault stake amount.

Changes

  1. apilib/amount.mjs:

    • Implemented parseAmount(input) to convert amounts (JSON strings or safe numbers) into exact bigint stroops (1 unit = 10,000,000 stroops).
    • Rejects negative amounts, exponent / scientific notation, NaN, Infinity, non-numeric strings, and numbers with more than 7 decimal places.
    • Implemented formatAmount(bigint) to output canonical decimal strings without redundant trailing zeros.
  2. api/index.mjs:

    • In POST /vaults, parsed vault and milestone amounts into exact stroops.
    • Enforced that each milestone amount is strictly positive (> 0) and sum(milestones.amount) === vault.amount.
    • In GET /stats, aggregated totals using bigint stroops instead of floating-point arithmetic and serialized totals (totalLocked, totalReleased, totalRedirected) as exact decimal strings.
  3. apilib/store.mjs:

    • Updated read paths in PgStore (rowToVault and actRow) to read numeric values without Number() casts, normalizing them with formatAmount(parseAmount(...)).
  4. apilib/openapi.mjs:

    • Updated OpenAPI Amount schema to pattern: '^\d+(\.\d{1,7})?$'.
    • Updated CreateMilestoneRequest and CreateVaultRequest amount schemas to accept strings or numbers for backward compatibility.
    • Updated Stats amount schemas and examples to reflect string amounts.
  5. Tests:

    • apilib/__tests__/amount.test.mjs: Unit and property-based tests verifying formatAmount(parseAmount(s)) === canonical(s) for random 0–7-decimal strings as well as boundary values.
    • api/__tests__/vaults.amounts.test.mjs: HTTP tests verifying milestone sum invariant, 0 amount rejection, rejection table (1e3, -1, abc, "", null, Infinity), and /stats exact string sums.
    • api/__tests__/postgres.amounts.test.mjs: Asserting exact round-trip preservation of boundary values ("922337203685.4775807" near i64::MAX in stroops) through PostgreSQL numeric(36,7).

Viccodes11 and others added 2 commits October 24, 2026 19:17
…icts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1nonlypiece
1nonlypiece merged commit c70dc18 into Disciplr-Org:main Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[amounts] Handle vault and milestone amounts as exact 7-decimal values and enforce the milestone sum

2 participants