Repository navigation
Description
Problem
x402Serve() has no way to declare the extensions.bazaar field on a route. Every route it builds is just { description?, accepts } - there's no extensions key anywhere in X402ServeConfig or in the per-route spec, and no passthrough for one.
Consequence: a seller using x402Serve() as documented cannot get their endpoint listed in any x402 Bazaar - not 57Blocks' (reserved, not built yet), not Rail402's (live on testnet today, testnet.rail402.dev/discovery/resources), not Coinbase's CDP Bazaar when that applies here. This isn't specific to one Bazaar implementation - the SDK just never emits the key any of them key off of.
Reference - the correct shape already exists in this repo
packages/agent/src/middleware/x402.ts does this right today, on its own 3 Premium routes (not through x402Serve()):
'GET /signals': {
description: 'Nirium premium arbitrage signals (x402)',
mimeType: 'application/json',
accepts: { scheme: 'exact', price: '$0.02', network, payTo },
extensions: declareDiscoveryExtension({
input: { count: 20 },
inputSchema: { properties: { count: { type: 'integer', maximum: 100 } } },
output: { example: { signals: [...], meta: {...} } },
}),
},declareDiscoveryExtension() comes from @x402/extensions/bazaar and already returns the extension in the right shape ({ bazaar: {...} }) - it's spread into extensions as-is, same level as description/accepts, never nested inside accepts.
Minimal change
In packages/sdk/src/index.ts's x402Serve():
- Let each route's spec object in
X402ServeConfig.routesaccept optionalinput,inputSchema, andoutput. - Load
@x402/extensions/bazaarthe same way the other@x402/*packages are already lazily loaded (dynamicimport(), notrequire- see the existingload()helper and its ESM/CJS note). - When any of
input/inputSchema/outputis present on a route, calldeclareDiscoveryExtension({ input, inputSchema, output, bodyType? })and set the result as that route'sextensions. - Without those fields, behavior must not change at all - routes that don't opt in stay exactly as they are today (no
extensionskey, no new required dependency, no behavior change for existing callers).
Done when
- Tests cover both cases: a route with discovery fields (gets
extensions.bazaar) and a route without them (noextensionskey, unchanged behavior from today). - A real testnet run against Rail402's facilitator (
testnet.rail402.dev) where the route actually appears inGET https://testnet.rail402.dev/discovery/resourcesafter a settled payment, with the payment's tx hash included in the PR. - The test endpoint for that run uses
x402Serve()itself (the fix under test) - not a hand-rolled@x402/expressmiddleware bypassing it. Proving the fix means provingx402Serve()can do this, not that Nirium's internal middleware already could.
Order
After packages/sdk 0.17.0 ships (#213, currently open - don't stack this on top of an unpublished version).
🤖 Generated with Claude Code
Activity
grantfox-oss commentedon Nov 7, 2026
🎉 This issue has been marked as completed on GrantFox!
@M0nsxx's PR #262 was approved and merged by @Eras256.
🏆 @M0nsxx: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (468 total points). Track your full progress on GrantFox.
👏 Great work, @M0nsxx! Keep contributing to nirium-protocol.
release(sdk): cut 0.18.0 - x402Serve() Bazaar discovery extension (#217…
grantfox-oss commentedon Nov 7, 2026
🎉 This issue has been marked as completed on GrantFox!
@M0nsxx's PR #267 was approved and merged by @Eras256.
🏆 @M0nsxx: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (573 total points). Track your full progress on GrantFox.
👏 Great work, @M0nsxx! Keep contributing to nirium-protocol.