From 9aecca522616650df099989826b8cad9fc6b6b78 Mon Sep 17 00:00:00 2001 From: Cesare Naldi <3353250+cesarenaldi@users.noreply.github.com> Date: Thu, 4 Jun 2026 18:46:13 +0200 Subject: [PATCH 1/2] fix account trades legacy timestamps --- .changeset/lazy-trades-fix.md | 2 +- packages/bindings/src/clob/account.test.ts | 14 +++-- packages/bindings/src/clob/account.ts | 48 +++++++++-------- packages/client/src/actions/account.ts | 60 ++++++++-------------- 4 files changed, 55 insertions(+), 69 deletions(-) diff --git a/.changeset/lazy-trades-fix.md b/.changeset/lazy-trades-fix.md index ea1170f..d21a350 100644 --- a/.changeset/lazy-trades-fix.md +++ b/.changeset/lazy-trades-fix.md @@ -3,4 +3,4 @@ "@polymarket/bindings": patch --- -Move account trade listing to the unified CLOB account trades endpoint. +Restore account trade listing to the legacy endpoint and parse legacy epoch-seconds timestamps correctly. diff --git a/packages/bindings/src/clob/account.test.ts b/packages/bindings/src/clob/account.test.ts index afcaad1..9f3de16 100644 --- a/packages/bindings/src/clob/account.test.ts +++ b/packages/bindings/src/clob/account.test.ts @@ -2,13 +2,14 @@ import { describe, expect, it } from 'vitest'; import { ClobTradeSchema } from './account'; const baseTrade = { - token_id: '1', + asset_id: '1', bucket_index: 7, fee_rate_bps: '0', id: 'trade-1', maker_address: `0x${'aa'.repeat(20)}`, maker_orders: [ { + asset_id: '1', fee_rate_bps: '0', maker_address: `0x${'bb'.repeat(20)}`, matched_amount: '1.5', @@ -17,10 +18,9 @@ const baseTrade = { owner: 'owner-1', price: '0.5', side: 'BUY', - token_id: '1', }, ], - market_id: `0x${'cc'.repeat(32)}`, + market: `0x${'cc'.repeat(32)}`, outcome: 'Yes', owner: 'owner-1', price: '0.5', @@ -33,15 +33,13 @@ const baseTrade = { }; describe('ClobTradeSchema', () => { - it('normalizes unified account trade responses', () => { + it('normalizes legacy epoch seconds timestamp strings', () => { const trade = ClobTradeSchema.parse({ ...baseTrade, - match_time: 1_777_996_829_000, - last_update: 1_777_996_840_000, + match_time: '1777996829', + last_update: '1777996840', }); - expect(trade.market).toBe(baseTrade.market_id); - expect(trade.tokenId).toBe(baseTrade.token_id); expect(trade.makerOrders[0]?.tokenId).toBe('1'); expect(trade.matchedAt).toBe('2026-05-05T16:00:29.000Z'); expect(trade.updatedAt).toBe('2026-05-05T16:00:40.000Z'); diff --git a/packages/bindings/src/clob/account.ts b/packages/bindings/src/clob/account.ts index d4ffe91..127d119 100644 --- a/packages/bindings/src/clob/account.ts +++ b/packages/bindings/src/clob/account.ts @@ -10,6 +10,7 @@ import { NotificationIdSchema, OptionalEpochMillisecondsToIsoDateTimeStringSchema, TokenIdSchema, + toIsoDateTimeString, } from '../shared'; function createCursorPageSchema(item: TItem) { @@ -91,6 +92,7 @@ export type OpenOrdersPage = z.infer; export const MakerOrderSchema = z .object({ + asset_id: TokenIdSchema, fee_rate_bps: DecimalStringSchema, maker_address: z.string(), matched_amount: DecimalStringSchema, @@ -99,19 +101,18 @@ export const MakerOrderSchema = z owner: z.string(), price: DecimalStringSchema, side: z.string(), - token_id: TokenIdSchema, }) .transform( ({ + asset_id, fee_rate_bps, maker_address, matched_amount, order_id, - token_id, ...rest }) => ({ ...rest, - tokenId: token_id, + tokenId: asset_id, feeRateBps: fee_rate_bps, makerAddress: maker_address, matchedAmount: matched_amount, @@ -119,17 +120,30 @@ export const MakerOrderSchema = z }), ); +const ClobTradeTimestampSchema = z.union([ + z + .union([z.number().int(), z.string().regex(/^\d+$/).transform(Number)]) + .transform((value) => + toIsoDateTimeString( + new Date( + value < 1_000_000_000_000 ? value * 1000 : value, + ).toISOString(), + ), + ), + z.string().transform(toIsoDateTimeString), +]); + export const ClobTradeSchema = z .object({ - token_id: TokenIdSchema, + asset_id: TokenIdSchema, bucket_index: z.number(), - fee_rate_bps: DecimalStringSchema.optional(), + fee_rate_bps: DecimalStringSchema, id: z.string(), - last_update: EpochMillisecondsToIsoDateTimeStringSchema, + last_update: ClobTradeTimestampSchema, maker_address: z.string(), maker_orders: z.array(MakerOrderSchema), - market_id: z.string(), - match_time: EpochMillisecondsToIsoDateTimeStringSchema, + market: z.string(), + match_time: ClobTradeTimestampSchema, outcome: z.string(), owner: z.string(), price: DecimalStringSchema, @@ -138,17 +152,16 @@ export const ClobTradeSchema = z status: z.string(), taker_order_id: z.string(), trader_side: z.enum(['TAKER', 'MAKER']), - transaction_hash: z.string().optional(), + transaction_hash: z.string(), }) .transform( ({ - token_id, + asset_id, bucket_index, fee_rate_bps, last_update, maker_address, maker_orders, - market_id, match_time, taker_order_id, trader_side, @@ -156,8 +169,7 @@ export const ClobTradeSchema = z ...rest }) => ({ ...rest, - market: market_id, - tokenId: token_id, + tokenId: asset_id, bucketIndex: bucket_index, feeRateBps: fee_rate_bps, updatedAt: last_update, @@ -172,15 +184,7 @@ export const ClobTradeSchema = z export type ClobTrade = z.infer; -export const ClobTradesPageSchema = z - .object({ - data: z.array(ClobTradeSchema), - has_more: z.boolean(), - }) - .transform(({ has_more, ...rest }) => ({ - ...rest, - hasMore: has_more, - })); +export const ClobTradesPageSchema = createCursorPageSchema(ClobTradeSchema); export type ClobTradesPage = z.infer; diff --git a/packages/client/src/actions/account.ts b/packages/client/src/actions/account.ts index cbd3ef0..668aba7 100644 --- a/packages/client/src/actions/account.ts +++ b/packages/client/src/actions/account.ts @@ -40,13 +40,7 @@ import { UserInputError, } from '../errors'; import { parseUserInput } from '../input'; -import { - decodeOffsetCursor, - encodeOffsetCursor, - PageSizeSchema, - type Paginated, - paginate, -} from '../pagination'; +import { PageSizeSchema, type Paginated, paginate } from '../pagination'; import { validateWith } from '../response'; import { toSignatureType } from '../wallet'; import { snakeCase, toSearchParams } from './params'; @@ -246,8 +240,6 @@ const ListAccountTradesRequestSchema = z .object(ListAccountTradesRequestFields) .default({}); -const ACCOUNT_TRADES_PAGE_SIZE = 50; - export type ListAccountTradesRequest = z.input< typeof ListAccountTradesRequestSchema >; @@ -311,35 +303,27 @@ export function listAccountTrades( ListAccountTradesRequestSchema, ); - return paginate((nextCursor) => { - const decoded = decodeOffsetCursor(nextCursor, ACCOUNT_TRADES_PAGE_SIZE); - - return client.secureClob - .get('/v1/account/trades', { - params: toSearchParams( - { ...params, offset: decoded.offset }, - snakeCase({ market: 'market_id', tokenId: 'token_id' }), - ), - }) - .andThen(validateWith(ClobTradesPageSchema)) - .map((response) => { - const items = response.data.slice(0, decoded.pageSize); - const hasMore = - items.length > 0 && - (response.hasMore || response.data.length > decoded.pageSize); - - return { - items, - hasMore, - nextCursor: hasMore - ? encodeOffsetCursor({ - offset: decoded.offset + items.length, - pageSize: decoded.pageSize, - }) - : undefined, - }; - }); - }, cursor); + return paginate( + (nextCursor) => + client.secureClob + .get('/data/trades', { + params: toSearchParams( + { ...params, nextCursor }, + snakeCase({ tokenId: 'asset_id' }), + ), + }) + .andThen(validateWith(ClobTradesPageSchema)) + .map((response) => ({ + items: response.data, + hasMore: response.nextCursor !== END_CURSOR, + nextCursor: + response.nextCursor === END_CURSOR + ? undefined + : toPaginationCursor(response.nextCursor), + totalCount: response.count, + })), + cursor, + ); } export type FetchNotificationsError = From 44f159b18059a8b46443a8d817aec09ad53a55d1 Mon Sep 17 00:00:00 2001 From: Cesare Naldi <3353250+cesarenaldi@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:20:13 +0200 Subject: [PATCH 2/2] share epoch-like timestamp schema --- packages/bindings/src/clob/account.ts | 19 +++---------------- packages/bindings/src/clob/builder.ts | 17 ++--------------- packages/bindings/src/shared.ts | 8 ++++++++ 3 files changed, 13 insertions(+), 31 deletions(-) diff --git a/packages/bindings/src/clob/account.ts b/packages/bindings/src/clob/account.ts index 127d119..e853294 100644 --- a/packages/bindings/src/clob/account.ts +++ b/packages/bindings/src/clob/account.ts @@ -4,13 +4,13 @@ import { ConditionIdSchema, DecimalishSchema, DecimalStringSchema, + EpochLikeToIsoDateTimeStringSchema, EpochMillisecondsSchema, EpochMillisecondsToIsoDateTimeStringSchema, EvmAddressSchema, NotificationIdSchema, OptionalEpochMillisecondsToIsoDateTimeStringSchema, TokenIdSchema, - toIsoDateTimeString, } from '../shared'; function createCursorPageSchema(item: TItem) { @@ -120,30 +120,17 @@ export const MakerOrderSchema = z }), ); -const ClobTradeTimestampSchema = z.union([ - z - .union([z.number().int(), z.string().regex(/^\d+$/).transform(Number)]) - .transform((value) => - toIsoDateTimeString( - new Date( - value < 1_000_000_000_000 ? value * 1000 : value, - ).toISOString(), - ), - ), - z.string().transform(toIsoDateTimeString), -]); - export const ClobTradeSchema = z .object({ asset_id: TokenIdSchema, bucket_index: z.number(), fee_rate_bps: DecimalStringSchema, id: z.string(), - last_update: ClobTradeTimestampSchema, + last_update: EpochLikeToIsoDateTimeStringSchema, maker_address: z.string(), maker_orders: z.array(MakerOrderSchema), market: z.string(), - match_time: ClobTradeTimestampSchema, + match_time: EpochLikeToIsoDateTimeStringSchema, outcome: z.string(), owner: z.string(), price: DecimalStringSchema, diff --git a/packages/bindings/src/clob/builder.ts b/packages/bindings/src/clob/builder.ts index e4d0b59..14f4083 100644 --- a/packages/bindings/src/clob/builder.ts +++ b/packages/bindings/src/clob/builder.ts @@ -1,25 +1,12 @@ import { z } from 'zod'; import { DecimalStringSchema, + EpochLikeToIsoDateTimeStringSchema, EpochMillisecondsToIsoDateTimeStringSchema, OrderSideSchema, TokenIdSchema, - toIsoDateTimeString, } from '../shared'; -const BuilderTradeMatchTimeSchema = z.union([ - z - .union([z.number().int(), z.string().regex(/^\d+$/).transform(Number)]) - .transform((value) => - toIsoDateTimeString( - new Date( - value < 1_000_000_000_000 ? value * 1000 : value, - ).toISOString(), - ), - ), - z.string().transform(toIsoDateTimeString), -]); - export const BuilderTradeSchema = z .object({ id: z.string(), @@ -38,7 +25,7 @@ export const BuilderTradeSchema = z owner: z.string(), maker: z.string(), transactionHash: z.string(), - matchTime: BuilderTradeMatchTimeSchema, + matchTime: EpochLikeToIsoDateTimeStringSchema, bucketIndex: z.number().int(), fee: DecimalStringSchema, feeUsdc: DecimalStringSchema, diff --git a/packages/bindings/src/shared.ts b/packages/bindings/src/shared.ts index b25b3d8..dd79ed7 100644 --- a/packages/bindings/src/shared.ts +++ b/packages/bindings/src/shared.ts @@ -283,6 +283,14 @@ export const DateLikeToIsoDateTimeStringSchema = z.union([ ), DateLikeStringToIsoDateTimeStringSchema, ]); +export const EpochLikeToIsoDateTimeStringSchema = z.union([ + EpochMillisecondsLikeSchema.transform((value) => + toIsoDateTimeString( + new Date(value < 1_000_000_000_000 ? value * 1000 : value).toISOString(), + ), + ), + DateLikeStringToIsoDateTimeStringSchema, +]); export const OptionalDateLikeToIsoDateTimeStringSchema = z.union([ EpochMillisecondsLikeSchema.transform((value) => value === 0