[MET-570] Extend circulating supply: exclude non-circulating holders#18
Draft
metajinglun wants to merge 6 commits into
Draft
[MET-570] Extend circulating supply: exclude non-circulating holders#18metajinglun wants to merge 6 commits into
metajinglun wants to merge 6 commits into
Conversation
Add a config-driven mechanism to exclude external/vesting/encumbered wallet holdings from circulating supply. EXCLUDED_CIRCULATING_WALLETS lists per-mint (mint:wallet[:label]) holders whose live on-chain balance is subtracted from that mint's circulating supply and echoed under allocation.excludedHolders. Mirrors the existing daoTreasuryTokens path (derive ATA -> live balance -> subtract) and its error contract: an absent token account is 0, any RPC failure propagates (never a silent 0 that overstates circulating supply). No behavior change and no extra RPC when no holders are configured for the mint. Meteora DAMM v2 fractional pool-ownership and DB persistence are deferred (see PLAN.md); a protocol pool-position holder can be excluded via config today. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Sum ALL of a holder's token accounts for the mint via getParsedTokenAccountsByOwner (not just the ATA) so multiple/non-associated accounts can't under-subtract and overstate circulating supply. - Fail fast: malformed EXCLUDED_CIRCULATING_WALLETS entries now throw at startup instead of being silently skipped (a dropped exclusion overstates circulating). - Add direct getExcludedHolderBalances coverage: multi-account sum, zero balance, RPC-failure propagation, and cross-mint skip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Throw on an unreadable parsed token-account shape (missing/non-numeric tokenAmount.amount) instead of silently counting it as 0, which would overstate circulating supply. - Include per-holder address/amount/label in the getSupplyInfo cache key so two distinct holder sets sharing an aggregate total can't return stale allocation.excludedHolders detail. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A duplicated EXCLUDED_CIRCULATING_WALLETS entry would resolve and subtract the same live balance twice, understating circulating supply. Dedupe on mint:wallet (first occurrence wins); per-mint scoping is preserved so the same wallet can still be listed for different mints. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ts (MET-570)
- Route test now captures the allocation forwarded to getSupplyInfo and asserts
the mapped {amount,address,label}, guarding the supplyWithLaunchpadAllocation
wiring against regressions.
- Reset config.circulating.excludedHolders in a file-level beforeEach so the
no-launch/incomplete-launch cases never depend on ambient env config.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…havior The circulating endpoint subtracts the additional-token allocation as the code currently does (regardless of claimed); drop the "unclaimed" qualifier so the docs don't assert behavior the pre-existing code doesn't implement. The claimed-vs-unclaimed correction is tracked as a separate pre-existing follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Package Protection
Repository GuardExact dependency versions
Package minimum age
Sensitive wallet / program changes
Overall status: pass Transitive supply-chain threats are covered by the Socket scanner (via |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the circulating-supply calculation with a dynamic, config-driven mechanism to
exclude operator-vetted non-circulating holders — external wallets (e.g. Laso),
vesting contracts, and other encumbered/protocol-owned holdings that are not "in the
hands of others."
Ticket asks addressed:
daoTreasuryTokens), unchangedteamPerformancePackage), unchangedHow it works
New env var
EXCLUDED_CIRCULATING_WALLETS: comma-separatedmint:walletormint:wallet:label. For the queried mint, each configured holder's live on-chainbalance (summed across all of the owner's token accounts for that mint, via
getParsedTokenAccountsByOwner) is subtracted from circulating supply and echoed backunder
allocation.excludedHolderson/api/supply/:mint/circulating.Scoped per-mint so only the vetted
(mint, wallet)balance is ever excluded — a walletholding a circulating balance of an unrelated token is never wrongly subtracted.
Design invariants (match the existing supply path)
unreadable parsed account throws rather than counting as 0. A silent 0 would overstate
circulating supply — the exact mispricing this codebase guards against.
RPC, identical output.
EXCLUDED_CIRCULATING_WALLETSentries throw atstartup (a dropped exclusion would overstate circulating); exact
mint:walletduplicates are de-duped to avoid double-subtraction.
Tests
bun run typecheck,bun test(136 pass),bun run deps:checkall green. New coverage:config parsing (valid/malformed/dedupe),
getExcludedHolderBalances(multi-account sum,zero, RPC-failure propagation, fail-loud on bad shape, cross-mint skip),
getSupplyInfosubtraction/clamp, and the route mapping/response.Deferred / follow-ups (not blockers for this increment)
@metadaoproject/programsSDK shipsno DAMM v2 position decoder, and concentrated-liquidity share ≠ simple liquidity ratio.
Hand-decoding position NFTs for a financial calc is too risky to land autonomously
without live verification. Interim lever: list a protocol pool-position holder in
EXCLUDED_CIRCULATING_WALLETS.getSupplyInfosubtractsadditionalTokenAllocationregardless of itsclaimedflag, whilelaunchpadService.totalNonCirculatingonly counts it when!claimed. Correcting italso requires reworking the RNGR add-back (project memory records the RNGR hardcode as
intentionally correct), which depends on RNGR's on-chain
additionalTokensClaimedvalue — not verifiable here. Left untouched; this feature does not double-subtract on
its own.
🤖 Generated with Claude Code