Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions market-maker/configs/futures.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3001}

readBatchSize: 3
readBatchSize: 30
# Per-operation batch sizes for writes (futures: closeOrder limit / createOrders limit).
cancelBatchSize: 20
createBatchSize: 10
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/futures.local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ oracle:
health:
port: 3001

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes.
cancelBatchSize: 20
createBatchSize: 10
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/futures.prd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3001}

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes.
cancelBatchSize: 20
createBatchSize: 10
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/futures.stg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3001}

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes.
cancelBatchSize: 20
createBatchSize: 10
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/perps.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3002}

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes (perps: individual cancelOrder / createOrder).
cancelBatchSize: 30
createBatchSize: 30
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/perps.local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3001}

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes.
cancelBatchSize: 30
createBatchSize: 30
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/perps.prd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3001}

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes.
cancelBatchSize: 30
createBatchSize: 30
writeBatchSize: 20
5 changes: 2 additions & 3 deletions market-maker/configs/perps.stg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ oracle:
health:
port: ${MAKER_HEALTH_PORT:-3001}

readBatchSize: 10
readBatchSize: 100
# Per-operation batch sizes for writes.
cancelBatchSize: 30
createBatchSize: 30
writeBatchSize: 20
22 changes: 3 additions & 19 deletions market-maker/schemas/futures.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
"timing",
"health",
"readBatchSize",
"cancelBatchSize",
"createBatchSize"
"writeBatchSize"
],
"properties": {
"nodeEnv": {
Expand Down Expand Up @@ -924,7 +923,7 @@
"description": "Maximum number of contract calls bundled into a single Multicall3 read. Calls are chunked transparently; lower values reduce RPC timeouts on busy providers at the cost of more round-trips.",
"default": 10
},
"cancelBatchSize": {
"writeBatchSize": {
"anyOf": [
{
"minimum": 1,
Expand All @@ -936,23 +935,8 @@
"description": "Environment variable interpolation (resolved at startup)"
}
],
"description": "Maximum closeOrder calls per cancellation batch. The adapter groups cancels into chunks of this size before sending.",
"description": "Maximum qty per write batch. The adapter groups cancels into chunks of this size before sending.",
"default": 20
},
"createBatchSize": {
"anyOf": [
{
"minimum": 1,
"type": "number"
},
{
"type": "string",
"pattern": "^\\$\\{[A-Za-z_][A-Za-z0-9_]*(:-[^}]*)?\\}$",
"description": "Environment variable interpolation (resolved at startup)"
}
],
"description": "Maximum orders per createOrders call. The adapter packs creates into batches of this size.",
"default": 10
}
}
}
24 changes: 4 additions & 20 deletions market-maker/schemas/perps.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
"timing",
"health",
"readBatchSize",
"cancelBatchSize",
"createBatchSize"
"writeBatchSize"
],
"properties": {
"nodeEnv": {
Expand Down Expand Up @@ -901,7 +900,7 @@
"description": "Maximum number of contract calls bundled into a single Multicall3 read. Calls are chunked transparently; lower values reduce RPC timeouts.",
"default": 10
},
"cancelBatchSize": {
"writeBatchSize": {
"anyOf": [
{
"minimum": 1,
Expand All @@ -913,23 +912,8 @@
"description": "Environment variable interpolation (resolved at startup)"
}
],
"description": "Maximum cancelOrder calls per cancellation batch. Perps has no batch cancel — each cancel is one call.",
"default": 30
},
"createBatchSize": {
"anyOf": [
{
"minimum": 1,
"type": "number"
},
{
"type": "string",
"pattern": "^\\$\\{[A-Za-z_][A-Za-z0-9_]*(:-[^}]*)?\\}$",
"description": "Environment variable interpolation (resolved at startup)"
}
],
"description": "Maximum createOrder calls per creation batch. Perps has no batch create — each create is one call.",
"default": 30
"description": "Maximum qty per write batch. The adapter groups cancels into chunks of this size before sending.",
"default": 20
}
}
}
6 changes: 1 addition & 5 deletions market-maker/src/adapters/futures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ export interface CreateFuturesVenueOpts {
wallet: WalletContext;
address: `0x${string}`;
multicall3Address?: `0x${string}`;
/** Max calls per Multicall3 read batch. Default 100. */
readBatchSize: number;
/** Max closeOrder calls per cancellation batch. Default 20. */
cancelBatchSize: number;
/** Max orders per createOrders call. Default 10. */
createBatchSize: number;
writeBatchSize: number;
logger: pino.Logger;
}

Expand Down
60 changes: 28 additions & 32 deletions market-maker/src/adapters/futures/instrument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ import { FuturesOwnOrders } from "./ownOrders.ts";

const FUTURES_INSTRUMENT_ID = "futures";

/** Maximum encoded calls per multicall write tx (safety net for block gas limit). */
const WRITE_BATCH_SIZE = 50;

export class FuturesInstrumentAdapter implements InstrumentAdapter {
readonly id = FUTURES_INSTRUMENT_ID;
readonly venue: FuturesVenueAdapter;
Expand All @@ -34,9 +31,8 @@ export class FuturesInstrumentAdapter implements InstrumentAdapter {

constructor(venue: FuturesVenueAdapter, logger: pino.Logger) {
this.venue = venue;
const batchSize = venue.readBatchSize;
this.book = new FuturesBook(this, batchSize);
this.ownOrders = new FuturesOwnOrders(venue, logger, batchSize);
this.book = new FuturesBook(this, venue.readBatchSize);
this.ownOrders = new FuturesOwnOrders(venue, logger, venue.readBatchSize);
}

async getIndexPrice(): Promise<bigint> {
Expand Down Expand Up @@ -147,18 +143,12 @@ export class FuturesInstrumentAdapter implements InstrumentAdapter {
): Promise<ExecuteOrdersResult> {
// 1. Build the ordered call list: cancels first, then creates.
const calls = this.buildCallList(intent);
if (calls.length === 0) {
return { receipts: [], errors: [] };
}

if (intent.dryRun) {
const totalBatches = Math.ceil(calls.length / WRITE_BATCH_SIZE);
logger.info(
{
cancels: intent.cancels.length,
creates: intent.creates.length,
calls: calls.length,
batches: totalBatches,
},
"DRY RUN: would send multicall batches",
);
Expand All @@ -168,12 +158,11 @@ export class FuturesInstrumentAdapter implements InstrumentAdapter {
// 2. Chunk into tx-sized groups and broadcast sequentially.
const receipts: { gasUsed: bigint; effectiveGasPrice: bigint }[] = [];
const errors: Error[] = [];
const totalBatches = Math.ceil(calls.length / WRITE_BATCH_SIZE);

for (let offset = 0; offset < calls.length; offset += WRITE_BATCH_SIZE) {
const chunk = calls.slice(offset, offset + WRITE_BATCH_SIZE);
const batchNum = Math.floor(offset / WRITE_BATCH_SIZE) + 1;
const totalBatches = calls.length;

console.log(calls);
for (let batchNum = 0; batchNum < totalBatches; batchNum++) {
const chunk = calls[batchNum];
try {
const hash = await this.venue.multicall(chunk, {
maxFeePerGas: intent.maxFeePerGas,
Expand Down Expand Up @@ -211,26 +200,33 @@ export class FuturesInstrumentAdapter implements InstrumentAdapter {
}

/** Build the ordered call list: cancels (individual closeOrder) then creates (createOrders). */
private buildCallList(intent: ExecuteOrdersIntent): `0x${string}`[] {
const cancelSize = this.venue.cancelBatchSize;
const createSize = this.venue.createBatchSize;
const calls: `0x${string}`[] = [];

// Cancels: chunk by cancelBatchSize, each = one closeOrder call.
for (let i = 0; i < intent.cancels.length; i += cancelSize) {
const batch = intent.cancels.slice(i, i + cancelSize);
for (const c of batch) {
calls.push(this.encodeCancel(c));
private buildCallList(intent: ExecuteOrdersIntent): `0x${string}`[][] {
const batchSize = this.venue.writeBatchSize;

let batchN = 0;
let qtyCount = 0; // we limit batch by qty count, since gas cost of one cancel approx eq one create order qty=1
const batch: `0x${string}`[][] = [];
function addTx(tx: `0x${string}`, qty: number) {
if (!batch[batchN]) {
batch[batchN] = new Array();
}
batch[batchN].push(tx);
qtyCount += qty;
if (batch[batchN].length >= batchSize) {
batchN++;
qtyCount = 0;
}
}

for (const c of intent.cancels) {
addTx(this.encodeCancel(c), 1);
}

// Creates: chunk by createBatchSize, each chunk = one createOrders call.
for (let i = 0; i < intent.creates.length; i += createSize) {
const batch = intent.creates.slice(i, i + createSize);
calls.push(this.encodeCreateOrders(batch));
for (const c of intent.creates) {
addTx(this.encodeCreate(c), Number(c.size));
}

return calls;
return batch;
}

/** Encode a batch of creates via the `createOrders` contract function. */
Expand Down
10 changes: 3 additions & 7 deletions market-maker/src/adapters/futures/venue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ export interface FuturesVenueOptions {
/** Max calls per Multicall3 read batch. Default 100. */
readBatchSize: number;
/** Max closeOrder calls per cancellation batch. Default 20. */
cancelBatchSize: number;
/** Max orders per createOrders call. Default 10. */
createBatchSize: number;
writeBatchSize: number;
logger: pino.Logger;
}

Expand Down Expand Up @@ -61,8 +59,7 @@ export class FuturesVenueAdapter implements VenueAdapter {
private readonly logger: pino.Logger;
private readonly multicall3Address: `0x${string}`;
readonly readBatchSize: number;
readonly cancelBatchSize: number;
readonly createBatchSize: number;
readonly writeBatchSize: number;
private instrumentSingleton: FuturesInstrumentAdapter | null = null;

private vaultAddressCache: `0x${string}` | null = null;
Expand All @@ -87,8 +84,7 @@ export class FuturesVenueAdapter implements VenueAdapter {
throw new Error(`chain ${this.chain.name} has no multicall3 address`);
this.multicall3Address = mc3;
this.readBatchSize = opts.readBatchSize;
this.cancelBatchSize = opts.cancelBatchSize;
this.createBatchSize = opts.createBatchSize;
this.writeBatchSize = opts.writeBatchSize;

this.events = new FuturesVenueEvents(this.publicClient, this.address);
this.account = new FuturesCollateralAccount(this);
Expand Down
11 changes: 2 additions & 9 deletions market-maker/src/apps/futures/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,20 +168,13 @@ export const futuresRootSchema = Type.Object(
"Calls are chunked transparently; lower values reduce RPC timeouts on busy providers " +
"at the cost of more round-trips.",
}),
cancelBatchSize: Type.Number({
writeBatchSize: Type.Number({
minimum: 1,
default: 20,
description:
"Maximum closeOrder calls per cancellation batch. " +
"Maximum qty per write batch. " +
"The adapter groups cancels into chunks of this size before sending.",
}),
createBatchSize: Type.Number({
minimum: 1,
default: 10,
description:
"Maximum orders per createOrders call. " +
"The adapter packs creates into batches of this size.",
}),
},
{ ...Closed, description: "Titan Market Maker — Futures app config." },
);
Expand Down
3 changes: 1 addition & 2 deletions market-maker/src/apps/futures/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ async function main(): Promise<void> {
wallet,
address: config.venue.address,
readBatchSize: config.readBatchSize,
cancelBatchSize: config.cancelBatchSize,
createBatchSize: config.createBatchSize,
writeBatchSize: config.writeBatchSize,
logger,
});
const instrument = await venue.getInstrument();
Expand Down
17 changes: 4 additions & 13 deletions market-maker/src/apps/perps/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,21 +155,12 @@ export const perpsRootSchema = Type.Object(
"Maximum number of contract calls bundled into a single Multicall3 read. " +
"Calls are chunked transparently; lower values reduce RPC timeouts.",
}),

cancelBatchSize: Type.Number({
minimum: 1,
default: 30,
description:
"Maximum cancelOrder calls per cancellation batch. " +
"Perps has no batch cancel — each cancel is one call.",
}),

createBatchSize: Type.Number({
writeBatchSize: Type.Number({
minimum: 1,
default: 30,
default: 20,
description:
"Maximum createOrder calls per creation batch. " +
"Perps has no batch create — each create is one call.",
"Maximum qty per write batch. " +
"The adapter groups cancels into chunks of this size before sending.",
}),
},
{ ...Closed, description: "Titan Market Maker — Perps app config." },
Expand Down
4 changes: 2 additions & 2 deletions market-maker/src/apps/perps/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ async function main(): Promise<void> {
wallet,
address: config.venue.address,
readBatchSize: config.readBatchSize,
cancelBatchSize: config.cancelBatchSize,
createBatchSize: config.createBatchSize,
cancelBatchSize: config.writeBatchSize,
createBatchSize: config.writeBatchSize,
logger,
});
const instrument = await venue.getInstrument();
Expand Down
Loading