From fc8b683adc157bec9dc475735d7b8107abd79d4d Mon Sep 17 00:00:00 2001 From: Anmol Agrawal Date: Mon, 2 Mar 2026 14:26:57 -0500 Subject: [PATCH 1/4] add createdAt field to index orders table --- .../20260302120000_add_created_at_to_orders.ts | 13 +++++++++++++ indexer/packages/postgres/src/models/order-model.ts | 4 ++++ .../packages/postgres/src/types/db-model-types.ts | 3 ++- indexer/packages/postgres/src/types/order-types.ts | 4 +++- indexer/services/comlink/public/swagger.json | 3 +++ .../src/request-helpers/request-transformer.ts | 1 + .../handlers/dydx_stateful_order_handler.sql | 13 +++++++------ .../dydx_liquidation_fill_handler_per_order.sql | 10 ++++++---- .../helpers/dydx_order_fill_handler_per_order.sql | 10 ++++++---- 9 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 indexer/packages/postgres/src/db/migrations/migration_files/20260302120000_add_created_at_to_orders.ts diff --git a/indexer/packages/postgres/src/db/migrations/migration_files/20260302120000_add_created_at_to_orders.ts b/indexer/packages/postgres/src/db/migrations/migration_files/20260302120000_add_created_at_to_orders.ts new file mode 100644 index 0000000000..f296c1930b --- /dev/null +++ b/indexer/packages/postgres/src/db/migrations/migration_files/20260302120000_add_created_at_to_orders.ts @@ -0,0 +1,13 @@ +import * as Knex from 'knex'; + +export async function up(knex: Knex): Promise { + return knex.schema.alterTable('orders', (table) => { + table.timestamp('createdAt').nullable(); + }); +} + +export async function down(knex: Knex): Promise { + return knex.schema.alterTable('orders', (table) => { + table.dropColumn('createdAt'); + }); +} diff --git a/indexer/packages/postgres/src/models/order-model.ts b/indexer/packages/postgres/src/models/order-model.ts index 22ae83b018..632eed175e 100644 --- a/indexer/packages/postgres/src/models/order-model.ts +++ b/indexer/packages/postgres/src/models/order-model.ts @@ -96,6 +96,7 @@ export default class OrderModel extends BaseModel { goodTilBlock: { type: ['string', 'null'], default: null, pattern: IntegerPattern }, goodTilBlockTime: { type: ['string', 'null'], default: null, format: 'date-time' }, createdAtHeight: { type: ['string', 'null'], default: null, pattern: IntegerPattern }, + createdAt: { type: ['string', 'null'], default: null, format: 'date-time' }, clientMetadata: { type: 'string', pattern: IntegerPattern }, triggerPrice: { type: ['string', 'null'], default: null, pattern: NonNegativeNumericPattern }, updatedAt: { type: 'string', format: 'date-time' }, @@ -134,6 +135,7 @@ export default class OrderModel extends BaseModel { goodTilBlock: 'string', goodTilBlockTime: 'date-time', createdAtHeight: 'string', + createdAt: 'date-time', clientMetadata: 'string', triggerPrice: 'string', updatedAt: 'date-time', @@ -181,6 +183,8 @@ export default class OrderModel extends BaseModel { createdAtHeight?: string; + createdAt?: IsoString; + clientMetadata!: string; triggerPrice?: string; diff --git a/indexer/packages/postgres/src/types/db-model-types.ts b/indexer/packages/postgres/src/types/db-model-types.ts index a3d69aada6..25b6753a03 100644 --- a/indexer/packages/postgres/src/types/db-model-types.ts +++ b/indexer/packages/postgres/src/types/db-model-types.ts @@ -72,8 +72,9 @@ export interface OrderFromDatabase extends IdBasedModelFromDatabase { updatedAtHeight: string, goodTilBlock?: string, goodTilBlockTime?: string, - // createdAtHeight is optional because short term orders do not have a createdAtHeight. + // createdAtHeight and createdAt are optional because short term orders do not have them. createdAtHeight?: string, + createdAt?: IsoString, clientMetadata: string, triggerPrice?: string, builderAddress?: string, diff --git a/indexer/packages/postgres/src/types/order-types.ts b/indexer/packages/postgres/src/types/order-types.ts index 239bedf280..40a597b902 100644 --- a/indexer/packages/postgres/src/types/order-types.ts +++ b/indexer/packages/postgres/src/types/order-types.ts @@ -62,8 +62,9 @@ export interface OrderCreateObject { updatedAtHeight: string, goodTilBlock?: string, goodTilBlockTime?: string, - // createdAtHeight is optional because short term orders do not have a createdAtHeight. + // createdAtHeight and createdAt are optional because short term orders do not have them. createdAtHeight?: string, + createdAt?: IsoString, clientMetadata: string, triggerPrice?: string, builderAddress?: string, @@ -119,6 +120,7 @@ export enum OrderColumns { updatedAt = 'updatedAt', updatedAtHeight = 'updatedAtHeight', createdAtHeight = 'createdAtHeight', + createdAt = 'createdAt', clientMetadata = 'clientMetadata', triggerPrice = 'triggerPrice', duration = 'duration', diff --git a/indexer/services/comlink/public/swagger.json b/indexer/services/comlink/public/swagger.json index e5616990c7..3ad8a53e14 100644 --- a/indexer/services/comlink/public/swagger.json +++ b/indexer/services/comlink/public/swagger.json @@ -1108,6 +1108,9 @@ "createdAtHeight": { "type": "string" }, + "createdAt": { + "$ref": "#/components/schemas/IsoString" + }, "clientMetadata": { "type": "string" }, diff --git a/indexer/services/comlink/src/request-helpers/request-transformer.ts b/indexer/services/comlink/src/request-helpers/request-transformer.ts index d8b0a928ee..24b4e48f4a 100644 --- a/indexer/services/comlink/src/request-helpers/request-transformer.ts +++ b/indexer/services/comlink/src/request-helpers/request-transformer.ts @@ -494,6 +494,7 @@ export function postgresOrderToResponseObject( goodTilBlock: order.goodTilBlock ?? undefined, goodTilBlockTime: order.goodTilBlockTime ?? undefined, createdAtHeight: order.createdAtHeight ?? undefined, + createdAt: order.createdAt ?? undefined, ticker: perpetualMarketRefresher.getPerpetualMarketTicker(order.clobPairId)!, triggerPrice: order.triggerPrice ?? undefined, builderAddress: order.builderAddress ?? undefined, diff --git a/indexer/services/ender/src/scripts/handlers/dydx_stateful_order_handler.sql b/indexer/services/ender/src/scripts/handlers/dydx_stateful_order_handler.sql index 3bf21c48f7..ecf5fc6cd8 100644 --- a/indexer/services/ender/src/scripts/handlers/dydx_stateful_order_handler.sql +++ b/indexer/services/ender/src/scripts/handlers/dydx_stateful_order_handler.sql @@ -60,6 +60,7 @@ BEGIN order_record."goodTilBlockTime" = to_timestamp((order_->'goodTilBlockTime')::double precision); order_record."clientMetadata" = (order_->'clientMetadata')::bigint; order_record."createdAtHeight" = block_height; + order_record."createdAt" = block_time; order_record."updatedAt" = block_time; order_record."updatedAtHeight" = block_height; order_record."orderRouterAddress" = order_->>'orderRouterAddress'; @@ -99,7 +100,7 @@ BEGIN INSERT INTO orders ( "id", "subaccountId", "clientId", "clobPairId", "side", "size", "totalFilled", "price", "timeInForce", "reduceOnly", "orderFlags", "goodTilBlockTime", - "clientMetadata", "createdAtHeight", "updatedAt", "updatedAtHeight", + "clientMetadata", "createdAtHeight", "createdAt", "updatedAt", "updatedAtHeight", "orderRouterAddress", "type", "status", "triggerPrice", "builderAddress", "feePpm", "duration", "interval", "priceTolerance" ) VALUES ( @@ -107,11 +108,11 @@ BEGIN order_record."clobPairId", order_record."side", order_record."size", order_record."totalFilled", order_record."price", order_record."timeInForce", order_record."reduceOnly", order_record."orderFlags", order_record."goodTilBlockTime", - order_record."clientMetadata", order_record."createdAtHeight", order_record."updatedAt", - order_record."updatedAtHeight", order_record."orderRouterAddress", order_record."type", - order_record."status", order_record."triggerPrice", order_record."builderAddress", - order_record."feePpm", order_record."duration", order_record."interval", - order_record."priceTolerance" + order_record."clientMetadata", order_record."createdAtHeight", order_record."createdAt", + order_record."updatedAt", order_record."updatedAtHeight", order_record."orderRouterAddress", + order_record."type", order_record."status", order_record."triggerPrice", + order_record."builderAddress", order_record."feePpm", order_record."duration", + order_record."interval", order_record."priceTolerance" ) ON CONFLICT ("id") DO UPDATE SET "subaccountId" = order_record."subaccountId", diff --git a/indexer/services/ender/src/scripts/helpers/dydx_liquidation_fill_handler_per_order.sql b/indexer/services/ender/src/scripts/helpers/dydx_liquidation_fill_handler_per_order.sql index 34ec5ac8aa..a4f7c3f883 100644 --- a/indexer/services/ender/src/scripts/helpers/dydx_liquidation_fill_handler_per_order.sql +++ b/indexer/services/ender/src/scripts/helpers/dydx_liquidation_fill_handler_per_order.sql @@ -184,6 +184,7 @@ BEGIN order_record."totalFilled" = fill_amount; order_record."status" = dydx_get_order_status(fill_amount, order_size, 'NOT_CANCELED', order_record."orderFlags", order_record."timeInForce"); order_record."createdAtHeight" = block_height; + order_record."createdAt" = block_time; IF jsonb_extract_path(order_, 'orderId', 'orderFlags')::bigint = constants.order_flag_twap_suborder() THEN -- This is a handled case but is not expected for twap. Parent orders should always exist @@ -200,16 +201,17 @@ BEGIN INSERT INTO orders ("id", "subaccountId", "clientId", "clobPairId", "side", "size", "totalFilled", "price", "type", "status", "timeInForce", "reduceOnly", "orderFlags", "goodTilBlock", "goodTilBlockTime", "createdAtHeight", - "clientMetadata", "triggerPrice", "updatedAt", "updatedAtHeight", "builderAddress", "feePpm", + "createdAt", "clientMetadata", "triggerPrice", "updatedAt", "updatedAtHeight", "builderAddress", "feePpm", "orderRouterAddress", "duration", "interval", "priceTolerance") VALUES ( order_record."id", order_record."subaccountId", order_record."clientId", order_record."clobPairId", order_record."side", order_record."size", order_record."totalFilled", order_record."price", order_record."type", order_record."status", order_record."timeInForce", order_record."reduceOnly", order_record."orderFlags", order_record."goodTilBlock", order_record."goodTilBlockTime", order_record."createdAtHeight", - order_record."clientMetadata", order_record."triggerPrice", order_record."updatedAt", order_record."updatedAtHeight", - order_record."builderAddress", order_record."feePpm", order_record."orderRouterAddress", order_record."duration", - order_record."interval", order_record."priceTolerance" + order_record."createdAt", order_record."clientMetadata", order_record."triggerPrice", + order_record."updatedAt", order_record."updatedAtHeight", + order_record."builderAddress", order_record."feePpm", order_record."orderRouterAddress", + order_record."duration", order_record."interval", order_record."priceTolerance" ); END IF; END IF; diff --git a/indexer/services/ender/src/scripts/helpers/dydx_order_fill_handler_per_order.sql b/indexer/services/ender/src/scripts/helpers/dydx_order_fill_handler_per_order.sql index 7247b487d8..99b0a29221 100644 --- a/indexer/services/ender/src/scripts/helpers/dydx_order_fill_handler_per_order.sql +++ b/indexer/services/ender/src/scripts/helpers/dydx_order_fill_handler_per_order.sql @@ -174,6 +174,7 @@ BEGIN order_record."totalFilled" = fill_amount; order_record."status" = dydx_get_order_status(fill_amount, order_size, order_canceled_status, order_record."orderFlags", order_record."timeInForce"); order_record."createdAtHeight" = block_height; + order_record."createdAt" = block_time; order_record."duration" = NULL; order_record."interval" = NULL; @@ -190,16 +191,17 @@ BEGIN INSERT INTO orders ("id", "subaccountId", "clientId", "clobPairId", "side", "size", "totalFilled", "price", "type", "status", "timeInForce", "reduceOnly", "orderFlags", "goodTilBlock", "goodTilBlockTime", "createdAtHeight", - "clientMetadata", "triggerPrice", "updatedAt", "updatedAtHeight", "builderAddress", "feePpm", + "createdAt", "clientMetadata", "triggerPrice", "updatedAt", "updatedAtHeight", "builderAddress", "feePpm", "orderRouterAddress", "duration", "interval", "priceTolerance") VALUES ( order_record."id", order_record."subaccountId", order_record."clientId", order_record."clobPairId", order_record."side", order_record."size", order_record."totalFilled", order_record."price", order_record."type", order_record."status", order_record."timeInForce", order_record."reduceOnly", order_record."orderFlags", order_record."goodTilBlock", order_record."goodTilBlockTime", order_record."createdAtHeight", - order_record."clientMetadata", order_record."triggerPrice", order_record."updatedAt", order_record."updatedAtHeight", - order_record."builderAddress", order_record."feePpm", order_record."orderRouterAddress", order_record."duration", - order_record."interval", order_record."priceTolerance" + order_record."createdAt", order_record."clientMetadata", order_record."triggerPrice", + order_record."updatedAt", order_record."updatedAtHeight", + order_record."builderAddress", order_record."feePpm", order_record."orderRouterAddress", + order_record."duration", order_record."interval", order_record."priceTolerance" ); END IF; From 6ccfda0c05b05afe2679e431c139eed90bdf8534 Mon Sep 17 00:00:00 2001 From: Anmol Agrawal Date: Mon, 2 Mar 2026 15:02:47 -0500 Subject: [PATCH 2/4] fix tests and deploy --- .github/workflows/indexer-build-and-push-dev-staging.yml | 1 + .../stateful-order/conditional-order-placement-handler.test.ts | 2 ++ .../stateful-order/stateful-order-placement-handler.test.ts | 3 +++ 3 files changed, 6 insertions(+) diff --git a/.github/workflows/indexer-build-and-push-dev-staging.yml b/.github/workflows/indexer-build-and-push-dev-staging.yml index 87b597c0a6..8b4039b538 100644 --- a/.github/workflows/indexer-build-and-push-dev-staging.yml +++ b/.github/workflows/indexer-build-and-push-dev-staging.yml @@ -6,6 +6,7 @@ on: # yamllint disable-line rule:truthy - main - 'release/indexer/v[0-9]+.[0-9]+.x' # e.g. release/indexer/v0.1.x - 'release/indexer/v[0-9]+.x' # e.g. release/indexer/v1.x + - 'anmol*' # TODO(DEC-837): Customize github build and push to ECR by service with paths jobs: diff --git a/indexer/services/ender/__tests__/handlers/stateful-order/conditional-order-placement-handler.test.ts b/indexer/services/ender/__tests__/handlers/stateful-order/conditional-order-placement-handler.test.ts index 4cc6972e2a..29472bcbd4 100644 --- a/indexer/services/ender/__tests__/handlers/stateful-order/conditional-order-placement-handler.test.ts +++ b/indexer/services/ender/__tests__/handlers/stateful-order/conditional-order-placement-handler.test.ts @@ -157,6 +157,7 @@ describe('conditionalOrderPlacementHandler', () => { goodTilBlock: null, goodTilBlockTime: protocolTranslations.getGoodTilBlockTime(defaultOrder), createdAtHeight: '3', + createdAt: defaultDateTime.toISO(), clientMetadata: '0', triggerPrice: getTriggerPrice(defaultOrder, testConstants.defaultPerpetualMarket), updatedAt: defaultDateTime.toISO(), @@ -225,6 +226,7 @@ describe('conditionalOrderPlacementHandler', () => { goodTilBlock: null, goodTilBlockTime: protocolTranslations.getGoodTilBlockTime(defaultOrder), createdAtHeight: '3', + createdAt: defaultDateTime.toISO(), clientMetadata: '0', triggerPrice: getTriggerPrice(defaultOrder, testConstants.defaultPerpetualMarket), updatedAt: defaultDateTime.toISO(), diff --git a/indexer/services/ender/__tests__/handlers/stateful-order/stateful-order-placement-handler.test.ts b/indexer/services/ender/__tests__/handlers/stateful-order/stateful-order-placement-handler.test.ts index 0ee6a48661..984ff8236a 100644 --- a/indexer/services/ender/__tests__/handlers/stateful-order/stateful-order-placement-handler.test.ts +++ b/indexer/services/ender/__tests__/handlers/stateful-order/stateful-order-placement-handler.test.ts @@ -215,6 +215,7 @@ describe('statefulOrderPlacementHandler', () => { goodTilBlock: null, goodTilBlockTime: protocolTranslations.getGoodTilBlockTime(testOrder), createdAtHeight: '3', + createdAt: defaultDateTime.toISO(), clientMetadata: '0', triggerPrice: null, updatedAt: defaultDateTime.toISO(), @@ -299,6 +300,7 @@ describe('statefulOrderPlacementHandler', () => { goodTilBlock: null, goodTilBlockTime: protocolTranslations.getGoodTilBlockTime(testOrder), createdAtHeight: '3', + createdAt: defaultDateTime.toISO(), clientMetadata: '0', triggerPrice: null, updatedAt: defaultDateTime.toISO(), @@ -367,6 +369,7 @@ describe('statefulOrderPlacementHandler', () => { goodTilBlock: null, goodTilBlockTime: protocolTranslations.getGoodTilBlockTime(defaultOrder), createdAtHeight: '3', + createdAt: defaultDateTime.toISO(), clientMetadata: '0', triggerPrice: null, updatedAt: defaultDateTime.toISO(), From e0e326b9c249ff448feddc958b0be9cd98395791 Mon Sep 17 00:00:00 2001 From: Anmol Agrawal Date: Wed, 4 Mar 2026 13:27:36 -0500 Subject: [PATCH 3/4] remove anmol* --- .github/workflows/indexer-build-and-push-dev-staging.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/indexer-build-and-push-dev-staging.yml b/.github/workflows/indexer-build-and-push-dev-staging.yml index 8b4039b538..87b597c0a6 100644 --- a/.github/workflows/indexer-build-and-push-dev-staging.yml +++ b/.github/workflows/indexer-build-and-push-dev-staging.yml @@ -6,7 +6,6 @@ on: # yamllint disable-line rule:truthy - main - 'release/indexer/v[0-9]+.[0-9]+.x' # e.g. release/indexer/v0.1.x - 'release/indexer/v[0-9]+.x' # e.g. release/indexer/v1.x - - 'anmol*' # TODO(DEC-837): Customize github build and push to ECR by service with paths jobs: From 4330c3eaffc2a1251ead7f31bdc94bfde0f73f65 Mon Sep 17 00:00:00 2001 From: Anmol Agrawal Date: Wed, 4 Mar 2026 13:43:46 -0500 Subject: [PATCH 4/4] update docs --- indexer/services/comlink/public/api-documentation.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/indexer/services/comlink/public/api-documentation.md b/indexer/services/comlink/public/api-documentation.md index 24b937a528..232a7358b3 100644 --- a/indexer/services/comlink/public/api-documentation.md +++ b/indexer/services/comlink/public/api-documentation.md @@ -2382,6 +2382,7 @@ fetch(`${baseURL}/orders?address=string&subaccountNumber=0.1`, "goodTilBlock": "string", "goodTilBlockTime": "string", "createdAtHeight": "string", + "createdAt": "string", "clientMetadata": "string", "triggerPrice": "string", "builderAddress": "string", @@ -2428,6 +2429,7 @@ Status Code **200** |» goodTilBlock|string|false|none|none| |» goodTilBlockTime|string|false|none|none| |» createdAtHeight|string|false|none|none| +|» createdAt|[IsoString](#schemaisostring)|false|none|none| |» clientMetadata|string|true|none|none| |» triggerPrice|string|false|none|none| |» builderAddress|string|false|none|none| @@ -2615,6 +2617,7 @@ fetch(`${baseURL}/orders/parentSubaccountNumber?address=string&parentSubaccountN "goodTilBlock": "string", "goodTilBlockTime": "string", "createdAtHeight": "string", + "createdAt": "string", "clientMetadata": "string", "triggerPrice": "string", "builderAddress": "string", @@ -2661,6 +2664,7 @@ Status Code **200** |» goodTilBlock|string|false|none|none| |» goodTilBlockTime|string|false|none|none| |» createdAtHeight|string|false|none|none| +|» createdAt|[IsoString](#schemaisostring)|false|none|none| |» clientMetadata|string|true|none|none| |» triggerPrice|string|false|none|none| |» builderAddress|string|false|none|none| @@ -2798,6 +2802,7 @@ fetch(`${baseURL}/orders/{orderId}`, "goodTilBlock": "string", "goodTilBlockTime": "string", "createdAtHeight": "string", + "createdAt": "string", "clientMetadata": "string", "triggerPrice": "string", "builderAddress": "string", @@ -6513,6 +6518,7 @@ or "goodTilBlock": "string", "goodTilBlockTime": "string", "createdAtHeight": "string", + "createdAt": "string", "clientMetadata": "string", "triggerPrice": "string", "builderAddress": "string", @@ -6550,6 +6556,7 @@ or |goodTilBlock|string|false|none|none| |goodTilBlockTime|string|false|none|none| |createdAtHeight|string|false|none|none| +|createdAt|[IsoString](#schemaisostring)|false|none|none| |clientMetadata|string|true|none|none| |triggerPrice|string|false|none|none| |builderAddress|string|false|none|none|