fix(slab): decode PortfolioMatcherConfigV16 trailer in parsePortfolioV17 - #347
fix(slab): decode PortfolioMatcherConfigV16 trailer in parsePortfolioV17#347Morenikeoa wants to merge 1 commit into
Conversation
…olioV17 parsePortfolioV17 is the SDK's current, correct decoder for v17 standalone portfolio accounts, but it never read matcherProgram/matcherContext/ matcherDelegate/enabled even though every v17 portfolio account has this data: PortfolioMatcherConfigV16 (104 bytes: matcher_program[32] + matcher_context[32] + matcher_delegate[32] + enabled:u64) sits in a trailing region immediately after PortfolioAccountV16Account, per PORTFOLIO_MATCHER_CONFIG_OFF = HEADER_LEN + PORTFOLIO_STATE_LEN in v16_program.rs. The only function in this file that *does* decode matcherProgram/ matcherContext is parseAccount, the legacy pre-v16 shared-slab decoder — a completely different, no-longer-live account model. Anyone wanting a v17 portfolio's matcher config (which TradeCpi/BatchTradeCpi/ SetMatcherConfig all depend on) had no SDK function to call and would have to hand-roll the byte offset themselves, exactly the kind of duplication that produced the encodeMatcherInitPassive layout bug fixed in dcccrypto#336. Adds matcherProgram/matcherContext/matcherDelegate/matcherEnabled to PortfolioV17 and decodes them from V17_PORTFOLIO_ACCOUNT_LEN - 104, anchored from the end of the account rather than chaining through the intervening HealthCert/lock/CloseProgress/ResolvedPayoutReceipt regions (none of which parsePortfolioV17 decodes either, and whose sizes are already inconsistently commented in this file — 188 bytes labeled vs. 184 from the field breakdown directly below it). The same offset was independently confirmed via percolator-keeper's crank.ts, which derives and documents V17_PORTFOLIO_ACCOUNT_LEN = 9347 from the same struct for its own getProgramAccounts dataSize filter. Uses the same length-gated graceful-default pattern already established for every other field added to this function after the original v17 shape, so existing short-buffer callers are unaffected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 59 minutes and 13 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
parsePortfolioV17is the SDK's current, correct decoder for v17 standalone portfolio accounts — but it never decodesmatcherProgram/matcherContext/matcherDelegate/enabled, even though every v17 portfolio account contains this data. Perv16_program.rs,PortfolioMatcherConfigV16(104 bytes:matcher_program[32]+matcher_context[32]+matcher_delegate[32]+enabled:u64) sits in a trailing region immediately afterPortfolioAccountV16Account, atPORTFOLIO_MATCHER_CONFIG_OFF = HEADER_LEN + PORTFOLIO_STATE_LEN.The only function in
slab.tsthat does decodematcherProgram/matcherContextisparseAccount— the legacy pre-v16 shared-slab decoder, a completely different, no-longer-live account model (fixed-size accounts packed into one slab, vs. v17's one-account-per-portfolio). Anyone wanting a v17 portfolio's matcher config — whichTradeCpi/BatchTradeCpi/SetMatcherConfigall depend on — had no SDK function to call and would have to hand-roll the byte offset themselves. That's exactly the kind of duplication that produced theencodeMatcherInitPassivewire-layout bug fixed in #336.Fix
Adds
matcherProgram/matcherContext/matcherDelegate/matcherEnabledto thePortfolioV17interface and decodes them inparsePortfolioV17atV17_PORTFOLIO_ACCOUNT_LEN - 104.This offset is anchored from the end of the account rather than chained through the intervening HealthCert/lock/CloseProgress/ResolvedPayoutReceipt regions — none of which
parsePortfolioV17decodes either, and whose sizes are already inconsistently commented in this file (CloseProgressLedgerV16Accountis labeled 188 bytes in one comment, but its own field breakdown two lines below sums to 184). Anchoring from the end avoids depending on that chain at all.The same
V17_PORTFOLIO_ACCOUNT_LEN = 9347value (and the 184-byte correction) is independently confirmed bypercolator-keeper'scrank.ts, which derives it from the same struct for its owngetProgramAccountsdataSizefilter and explicitly notes "CloseProgressLedgerV16Account is 184 bytes, not 188."Uses the same length-gated graceful-default pattern already established for every other field added to this function after the original v17 shape (
data.length >= offset + size ? read(...) : default), so existing short-buffer callers are unaffected.Proof of Fix
V17_PORTFOLIO_ACCOUNT_LEN) buffer with sentinel pubkeys/enabled flag written at the matcher-config offset and assertsparsePortfolioV17decodes them correctly.PublicKey.default/false) rather than throw, matching existing behavior for other late-added fields.npm test→ 851 passed, 31 skipped (pre-existing, RPC-dependent).npm run lintclean.Related
Builds on the matcher-ABI audit in #336; no overlap — that PR fixes encoder-side wire bugs in
instructions.ts, this one fixes a decoder coverage gap inslab.ts.🤖 Generated with Claude Code