Skip to content

Market orders: taker amount rounded to tick precision (5-6 decimals) but API caps it at 4 — orders rejected #87

Description

@furcabet

Package: @polymarket/clob-client-v2@1.0.8 (latest)
Affected code: getMarketOrderRawAmounts in src/order-builder/helpers (both BUY and SELL branches)

Summary

For market orders, getMarketOrderRawAmounts rounds the taker amount using the tick-size precision from ROUNDING_CONFIG (amount: 5 for tick 0.001, amount: 6 for 0.0001). But the CLOB API only accepts market-order amounts with maker ≤ 2 decimals and taker ≤ 4 decimals, so whenever the rounded taker ends up with a non-zero 5th/6th decimal the order is rejected server-side:

invalid amounts, the market buy orders maker amount supports a max accuracy of 2 decimals, taker amount a max of 4 decimals

The client itself produces the invalid payload, so there is nothing an SDK consumer can do about it short of patching the package (the rounding happens inside createMarketOrder/buildMarketOrderCreationArgs right before signing).

Reproduction

// node >= 18, after `npm i @polymarket/clob-client-v2@1.0.8`
const { buildMarketOrderCreationArgs } = await import(
  './node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/buildMarketOrderCreationArgs.js'
)
const { ROUNDING_CONFIG } = await import(
  './node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/roundingConfig.js'
)

// BUY $5 at 0.998 on a 0.001-tick market
const buy = await buildMarketOrderCreationArgs(
  '0x0000000000000000000000000000000000000001',
  '0x0000000000000000000000000000000000000001',
  0,
  { tokenID: '1', amount: 5, price: 0.998, side: 'BUY' },
  ROUNDING_CONFIG['0.001']
)
console.log(buy.takerAmount) // 5010020 = 5.01002 shares -> 5 decimals, rejected

// SELL 7.77 shares at 0.998
const sell = await buildMarketOrderCreationArgs(
  '0x0000000000000000000000000000000000000001',
  '0x0000000000000000000000000000000000000001',
  0,
  { tokenID: '1', amount: 7.77, price: 0.998, side: 'SELL' },
  ROUNDING_CONFIG['0.001']
)
console.log(sell.takerAmount) // 7754460 = 7.75446 USDC -> 5 decimals, rejected

Math: 5 / 0.998 = 5.010020… → roundDown(…, 5) = 5.01002 (5 decimals). Any price with 3+ significant decimals routinely produces this; it only slips through when the 5th decimal happens to be zero.

The 2/4-decimals cap appears to be specific to market orders (the server error says "the market buy orders …"): limit orders built by getOrderRawAmounts use the same tick precision (5–6 decimals) and are accepted fine.

Suggested fix

Cap the taker amount at 4 decimals (round down, so the order stays marketable and never asks for more than the fair amount) in both branches of getMarketOrderRawAmounts:

if (decimalPlaces(rawTakerAmt) > 4) rawTakerAmt = roundDown(rawTakerAmt, 4);

We are running exactly this as a local patch on top of 1.0.8 and rejections disappeared. Happy to open a PR if useful.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions