fix: add Polymarket V2 balance cache endpoint#460
Conversation
realfishsam
left a comment
There was a problem hiding this comment.
PR Review: PASS (NOT VERIFIED)
What This Does
Adds the Polymarket CLOB V2 GET /balance-allowance/update endpoint to the bundled spec so the implicit API exposes updateBalanceAllowance() as an L2-authenticated method. SDK consumers who need to sync the exchange's pUSD collateral cache before placing orders can now call callApi('updateBalanceAllowance') on a credentialed PolymarketExchange instance.
Blast Radius
core/specs/polymarket/PolymarketClobAPI.yaml— YAML source spec only (Polymarket CLOB, no other exchanges)core/src/exchanges/polymarket/api-clob.ts— hand-edited generated file (see Finding 1)core/test/pipeline/polymarket-v2-spec.test.ts— new test file- No unified types, no sidecar
openapi.yaml, no router, no SDKs touched
Consumer Verification
Before (main branch):
callApi('updateBalanceAllowance') throws Implicit API method "updateBalanceAllowance" not found on Polymarket because the method is not registered. Verified: descriptor.endpoints.updateBalanceAllowance is undefined on main.
After (PR branch):
parseOpenApiSpec(polymarketClobSpec) returns:
descriptor.endpoints.updateBalanceAllowance == {
method: 'GET',
path: '/balance-allowance/update',
isPrivate: true,
operationId: 'updateBalanceAllowance'
}The method is registered on the exchange instance via defineImplicitApi, sign() correctly fires (L2Auth), and the implicit method routes remaining params as query string (GET path, handled by createImplicitMethod). Full live-wire verification was not performed as it requires L2 credentials.
Test Results
- Build: PASS (
tscclean,dist/produced) - Unit tests (main): PASS — 505 passed, 8 suites
- Unit tests (PR branch): PASS — 507 passed, 9 suites (+2 tests, new suite)
- Server starts: not tested (no live credentials)
- E2E smoke: N/A (private endpoint, no test credentials available)
Findings
1. api-clob.ts was hand-edited instead of regenerated — process violation, low functional impact.
core/src/exchanges/polymarket/api-clob.ts carries the header:
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
The script (core/scripts/fetch-openapi-specs.js) reads from the local YAML file and generates the TypeScript. The PR edits both files manually instead of running the script after editing the YAML.
I ran npm run fetch:openapi against the PR's updated YAML and diffed the output:
- "description": "Refresh the CLOB backend's cached pUSD balance...\n",The script intentionally strips description, responses, and other verbose fields (see stripVerboseFields). The generated output is otherwise identical to the PR's hand-edit: same operationId, path, tags, security, parameters. All 507 tests still pass after running the generation script.
Concrete risk: a future contributor running npm run fetch:openapi would overwrite the hand-edited file, removing the description field — but the endpoint itself would survive because the YAML (the source of truth) is correctly updated. The functional difference is zero since parseOpenApiSpec never reads description.
Recommended fix: revert the api-clob.ts change and run npm run fetch:openapi to regenerate it from the updated YAML. The output will be identical minus the description comment.
2. Second test ('keeps the Polymarket on-chain balance lookup on pUSD...') tests code not changed by this PR.
// core/test/pipeline/polymarket-v2-spec.test.ts:19-27
test('keeps the Polymarket on-chain balance lookup on pUSD instead of legacy USDC.e', () => {
expect(source).toContain('0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB');
expect(source).not.toContain('0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174');
});index.ts:getAddressOnChainBalance already hardcodes pusdAddress = '0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB' and has never referenced the USDC.e address. This test passes on main too. It's a reasonable regression guard, but it's not testing anything introduced by this PR. That's fine — defensive tests are good — but it shouldn't be cited as evidence that the PR's change is correct.
No other blocking findings. isPrivate detection is correct (security: [{L2Auth: []}] → non-empty → true in parseOpenApiSpec:63). No auth credential logging. No financial arithmetic. No any types introduced. No router impact.
PMXT Pipeline Check
- Field propagation (3-layer): N/A — no unified types changed
- OpenAPI sync (
core/src/server/openapi.yaml): N/A — new method is implicit API only, not a sidecar endpoint - Financial precision: N/A
- Type safety: OK — no
anyintroduced - Auth safety: OK — L2Auth correctly required,
sign()called for private endpoints, credentials not logged - Generated file hand-edited: ISSUE (see Finding 1)
Semver Impact
patch — adds an implicit API method callable via callApi('updateBalanceAllowance'). No changes to unified types, sidecar contract, or SDK-generated files. No existing behavior altered.
Risk
- Live endpoint behavior unverified (requires L2 credentials). The method wiring is structurally correct but
GET /balance-allowance/updateagainstclob.polymarket.comwas not smoke-tested. - The hand-edited
api-clob.tswill silently drift from whatnpm run fetch:openapiproduces (specifically: loses thedescriptionfield on next regeneration). Low risk in practice since the endpoint itself is anchored in the YAML.
Generated by Claude Code
Co-authored-by: peterxing <peterxing@users.noreply.github.com>
- SDK fetchOrderBook return type widened to OrderBook | OrderBook[] (array when both since and until are provided in params) - Args construction forwards limit and params to hosted API - Changelog for v2.43.0
d221808 to
203b287
Compare
|
Thanks for merging this focused V2 spec slice. I packaged the remaining no-spend Polymarket V2 migration readback as a fixed A$390 follow-on here: https://farmbot-platform-mvp.pages.dev/hire-agent/pmxt-polymarket-v2-readback/ Scope: V2 contract/signing-domain checklist, pUSD wrap/cache-sync flow, approval/trading failure matrix, and copy-paste regression checks against current PMXT code paths. No wallet signing, live trading, token approval, transfer, swap, bridge, or paid call. Contact if useful: info@transhumanism.com.au. Settlement after scope confirmation can be invoice or USDC on Base/Polygon. |
Summary
GET /balance-allowance/updateto the bundled OpenAPI specpolymarketClobSpecso the implicit API createsupdateBalanceAllowance()Verification
npm test --workspace=pmxt-core -- polymarket-v2-spec.test.ts --runInBandnode_modules\\.bin\\tsc.cmd -p core\\tsconfig.json --noEmitgit diff --check(passed with existing Windows LF/CRLF warnings only)Notes
npm run build --workspace=pmxt-coreis blocked on Windows by the existing POSIXrm -rf distclean script before TypeScript runs, so I rantsc --noEmitdirectly.Fixes #436