Skip to content

ClobClient.create_order() returns invalid SignedOrderRequest fields #9

@M4DF135H

Description

@M4DF135H

Description

When using ClobClient.create_order() to sign orders (EOA path), the returned SignedOrderRequest contains incorrect field values that cause API rejection with HTTP 400 errors.

Environment

Problem

ClobClient.create_order() Issues:

When calling:

let signed_order = self.client.create_order(
    args,           // &OrderArgs
    Some(nonce),    // Option<u64> - nonce in milliseconds
    None,
    Some(&options)  // &OrderOptions
).await?;

The returned SignedOrderRequest contains:

  • nonce: "0" (expected: "1770035966841" - the nonce_ms we passed)
  • fee_rate_bps: "0" (expected: "1000" from OrderOptions)
  • expiration: "1770035650105" (in milliseconds, expected: "1770036250" in seconds)

This causes Polymarket API to reject all orders with HTTP 400 "Failed to post order".

OrderBuilder.create_order() Works Better:

When using OrderBuilder (Gnosis Safe path) with same parameters:

builder.create_order(
    chain_id,
    args,
    expiration,     // in seconds
    &extras,        // ExtraOrderArgs with proper fee_rate_bps
    &options
)?;

The returned SignedOrderRequest contains correct values:

  • nonce: "1770035544133" ✓
  • fee_rate_bps: "1000" ✓
  • expiration: "1770035470" (seconds) ✓

However, even with correct OrderBuilder output, the API still rejects with HTTP 400, suggesting a deeper authentication or API compatibility issue.

Expected Behavior

  1. ClobClient.create_order() should return SignedOrderRequest with:
    - nonce field set to the provided nonce value (in milliseconds as string)
    - fee_rate_bps field set to the value from OrderOptions.fee_rate_bps
    - expiration field in seconds (not milliseconds)
  2. The returned order should be accepted by Polymarket API without HTTP 400 errors

Steps to Reproduce

  1. Initialize ClobClient with L1 headers
  2. Create or derive API key
  3. Call client.create_order(args, Some(nonce_ms), None, Some(&options))
  4. Log the returned SignedOrderRequest fields
  5. Compare with expected values

Workaround Applied

Currently working around by manually fixing the fields after signing:
signed_order.nonce = nonce.to_string();
signed_order.fee_rate_bps = "1000".to_string();
signed_order.expiration = (current_secs + 600).to_string();

Questions

  1. Is ClobClient.create_order() the correct method for EOA signing, or should we use a different approach?
  2. Does polyfill-rs 0.2.3 support Polymarket's current API format?
  3. Are there any authentication headers or additional parameters required for successful order posting?

Additional Context

  • All workarounds applied (correct time sync, proper nonce generation, fee_rate_bps matching)
  • Both Gnosis Safe and EOA paths tested
  • API credentials working (confirmed via log output)
  • Order structure validated against Polymarket API spec

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions