From 177d279d98edd9b744b6ca92cc7a5b82dfdda5bd Mon Sep 17 00:00:00 2001 From: Trevor Miller Date: Fri, 15 May 2026 15:12:19 -0400 Subject: [PATCH] =?UTF-8?q?sdk:=20round-5=20CLI=20follow-ups=20=E2=80=94?= =?UTF-8?q?=20close=20the=20last=20two=20producer=E2=86=94recognizer=20dri?= =?UTF-8?q?ft=20guards=20(#0434)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round-4 audit converged: doc/code drift, numeric/units, untested helpers, tautologies, zero-coverage commands, CLI DRY all CLEAN. Only genuine remaining finding = the last two instances of the #0425/#0407 producer↔recognizer-drift class: - buildQuests output → isQuestApproval + doesCollectionFollowQuestProtocol - buildPredictionMarket output → isPredictionMarketValid + validatePredictionMarketCollection Both run through normalizeForReview (the indexer's bigint normalization) then asserted against their own recognizer — mirrors the closed subscription #0425 guard. Both pass (no actual drift; the guards now lock it in against future field renames / added recognizer constraints that would otherwise make CLI-built quests/PMs unrecognizable on the FE with a green suite). Test-only, no source change. Build clean (no circular deps); unit 143 suites / 3110 tests; integration 20 suites / 186 tests. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/core/builders/builders.spec.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/bitbadgesjs-sdk/src/core/builders/builders.spec.ts b/packages/bitbadgesjs-sdk/src/core/builders/builders.spec.ts index 1111cb0619..ceb4fad857 100644 --- a/packages/bitbadgesjs-sdk/src/core/builders/builders.spec.ts +++ b/packages/bitbadgesjs-sdk/src/core/builders/builders.spec.ts @@ -30,9 +30,11 @@ import { buildBid } from './bid.js'; import { buildPmSellIntent } from './pm-sell-intent.js'; import { buildPmBuyIntent } from './pm-buy-intent.js'; import { resolveCoin, parseDuration, toBaseUnits, sanitizeCosmosPathName, resolveExpiration } from './shared.js'; -import { buildPredictionMarketBuyIntent, buildPredictionMarketSellIntent } from '../prediction-markets.js'; +import { buildPredictionMarketBuyIntent, buildPredictionMarketSellIntent, isPredictionMarketValid, validatePredictionMarketCollection } from '../prediction-markets.js'; import { buildIntentApproval } from '../intents.js'; import { UintRangeArray } from '../uintRanges.js'; +import { isQuestApproval, doesCollectionFollowQuestProtocol } from '../quests.js'; +import { normalizeForReview } from '../review-normalize.js'; import { buildOrderbookBidApproval, buildOrderbookListingApproval } from '../bids.js'; // ── Helpers ────────────────────────────────────────────────────────────────── @@ -589,6 +591,13 @@ describe('prediction-market builder', () => { buildPredictionMarket({ verifier: 'bb1verifier', ...META }) ); }); + test('producer↔recognizer drift guard — built collection satisfies isPredictionMarketValid (#0434)', () => { + const built = normalizeForReview(buildPredictionMarket({ verifier: 'bb1verifier', ...META })); + const res = validatePredictionMarketCollection(built); + expect(res.valid).toBe(true); + expect(res.errors).toEqual([]); + expect(isPredictionMarketValid(built)).toBe(true); + }); test('seven distinct pm-- approval ids, stable across calls', () => { const ids = r.collectionApprovals.map((a: any) => a.approvalId); expect(ids.length).toBe(7); @@ -712,6 +721,13 @@ describe('quests builder', () => { const p = { reward: 10, denom: 'BADGE', maxClaims: 100, ...META }; expect(buildQuests(p)).toEqual(buildQuests(p)); }); + test('producer↔recognizer drift guard — built quest is recognized by isQuestApproval (#0434)', () => { + const built = normalizeForReview(buildQuests({ reward: 10, denom: 'BADGE', maxClaims: 100, ...META })); + const questApproval = built.collectionApprovals.find((a: any) => a.approvalId === 'quests-approval'); + expect(questApproval).toBeTruthy(); + expect(isQuestApproval(questApproval)).toBe(true); + expect(doesCollectionFollowQuestProtocol(built as any)).toBe(true); + }); test('passes verification with zero violations', () => { expectCleanVerification(msg); });