Skip to content

fix: add Polymarket V2 balance cache endpoint#460

Merged
realfishsam merged 3 commits into
pmxt-dev:mainfrom
peterxing:fix/issue-436-polymarket-v2-balance-allowance
May 22, 2026
Merged

fix: add Polymarket V2 balance cache endpoint#460
realfishsam merged 3 commits into
pmxt-dev:mainfrom
peterxing:fix/issue-436-polymarket-v2-balance-allowance

Conversation

@peterxing
Copy link
Copy Markdown
Contributor

Summary

  • add Polymarket CLOB V2 GET /balance-allowance/update to the bundled OpenAPI spec
  • expose it through the generated polymarketClobSpec so the implicit API creates updateBalanceAllowance()
  • add regression coverage for the V2 pUSD balance/allowance cache endpoint and for avoiding the legacy USDC.e balance token

Verification

  • npm test --workspace=pmxt-core -- polymarket-v2-spec.test.ts --runInBand
  • node_modules\\.bin\\tsc.cmd -p core\\tsconfig.json --noEmit
  • git diff --check (passed with existing Windows LF/CRLF warnings only)

Notes

  • npm run build --workspace=pmxt-core is blocked on Windows by the existing POSIX rm -rf dist clean script before TypeScript runs, so I ran tsc --noEmit directly.

Fixes #436

Copy link
Copy Markdown
Contributor

@realfishsam realfishsam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (tsc clean, 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 any introduced
  • 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/update against clob.polymarket.com was not smoke-tested.
  • The hand-edited api-clob.ts will silently drift from what npm run fetch:openapi produces (specifically: loses the description field on next regeneration). Low risk in practice since the endpoint itself is anchored in the YAML.

Generated by Claude Code

peterxing and others added 3 commits May 22, 2026 21:48
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
@realfishsam realfishsam force-pushed the fix/issue-436-polymarket-v2-balance-allowance branch from d221808 to 203b287 Compare May 22, 2026 18:50
@realfishsam realfishsam merged commit ba46541 into pmxt-dev:main May 22, 2026
1 check passed
@peterxing
Copy link
Copy Markdown
Contributor Author

peterxing commented May 22, 2026

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spec drift: polymarket — V2 exchange contracts and pUSD collateral token not reflected in spec (live April 28, 2026)

2 participants