feat(vibewatch-sentiment): --asset sBTC|STX picks the 402 option to pay - #431
Open
sonic-mast wants to merge 2 commits into
Open
sonic-mast wants to merge 2 commits into
sonic-mast wants to merge 2 commits into
Conversation
The engine's interceptor always paid the first `stacks:` option of a 402 challenge. The Vibewatch Stacks Vibe Index lists sBTC first and STX second, so a wallet holding only STX signed an sBTC transfer it could not fund, and there was no way to pay the advertised STX price short of bypassing the interceptor (Vibewatch-io/vibewatch-mcp#16). - x402.service: `createApiClient(baseUrl, tool, { preferredAsset })` selects the first Stacks option carrying that asset (`STX` literally, sBTC by the same contract-id test the builders use). No preference keeps the old first-option rule byte for byte. A preference the challenge does not offer fails before anything is signed and names the offered assets; an invalid value fails when the client is created. Applies to sponsored and direct modes alike. - vibewatch-sentiment: `--asset sBTC|STX` (default sBTC) on `project`, `evidence`, `delta`, validated before the free preflight. - SKILL.md / AGENT.md: how to pay in STX, that the 402 lists sBTC first, and observed settlement latency (<60 s from broadcast to paid payload). - Tests: pure selection rules plus fake-server runs for both assets in both modes, the unoffered-asset refusal, and the invalid-value refusal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CI typechecks test files; getStacksChainId returns string, not NetworkV2. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 17, 2026
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.
Why
Four Tier 1 winners of the Stacks Vibe Index paid-query bounties (aibtc board
mtt3jjrgcf0aa8fb225c,mttjxw940faa8df06de7,mtwd0kcs90cb2cfcf830,mtwd0cet93a16ab82498) and Vibewatch-io/vibewatch-mcp#16 asked for the same two things: a way to pay the index's advertised STX price, and docs saying that the 402 lists sBTC first. The engine's interceptor always paid the firststacks:option, so a wallet holding STX but no sBTC signed an sBTC transfer it could not fund, and the only way to pay in STX was to bypass the interceptor.What
src/lib/services/x402.service.ts—createApiClient(baseUrl, tool, { preferredAsset }). New exportedselectStacksPaymentOption(accepts, preferredAsset?): no preference keeps the old first-Stacks-option rule;"STX"picks the first Stacks option whose asset is literallySTX;"sBTC"picks the first one passing the builders' contract-id test. A preference the challenge does not offer rejects before anything is signed and names the offered assets; an invalid value rejects when the client is created (same place the payment mode is validated). Works in sponsored and direct modes; the selected option flows into the existing builders unchanged.vibewatch-sentiment—--asset sBTC|STX(defaultsBTC) onproject,evidence,delta, validated before the free preflight and before any wallet access.--asset STXto pay the STX option, selectaccepts[]byassetnot by position), an error-table row for the unoffered-asset refusal, and one line on settlement latency (winners observed the paid payload under 60 s after broadcast).Default behaviour is unchanged: without
preferredAssetevery existing caller pays exactly what it paid before.Verification
bun run typecheck,bun run validate(204/204) — pass.bun test src/lib— 160 pass, 0 fail, including 10 new tests: the pure selection rules, fake-server runs paying sBTC and STX in both orders and both modes (decoded tx is a ContractCall for sBTC and a TokenTransfer for STX,accepted.assetmatches), the unoffered-asset refusal (no paid request, no Stacks API hit), and the invalid-value refusal at client creation.scripts/gemini-review.py --base origin/main): no findings.Related: a server-side change in vibewatch-app refuses an unscored panel slug with a free 422 before the 402, so the client-side
--allow-unscoredguard here stops being the only protection once that deploys.🤖 Generated with Claude Code