Загрузка данных
Размещение ордеров (POST /api/trade)
Ключевые решения:
А) FOK с щедрой ценой (generous price)
typescript
const generousPrice = side === Side.BUY ? 0.99 : 0.01;
await client.createAndPostMarketOrder(
{
tokenID: tokenId,
side: orderSide,
amount: size, // $$$ — доллары (для BUY) или акции (для SELL)
price: generousPrice, // щедрая цена — как на сайте Polymarket
},
undefined, // НЕ передаём options — библиотека сама определяет negRisk + tickSize
OrderType.FOK,
);
Почему щедрая цена:
* Без price библиотека вычисляет цену из стакана — получается слишком точная (tight) цена
* Между получением стакана и отправкой подписанного ордера ликвидность сдвигается → FOK не заполняется ("order couldn't be fully filled")
* С price: 0.99 для BUY: CLOB всё равно заполняет по лучшим доступным ценам, но takerAmount даёт зазор
* С price: 0.01 для SELL: аналогично, продаём по лучшим бидам
Б) НЕ передавать { negRisk, tickSize } в options
typescript
// ❌ НЕ ДЕЛАТЬ ТАК — ломает EIP-712 домен подписи:
await client.createAndPostMarketOrder({...}, { tickSize: "0.01", negRisk: true }, OrderType.FOK);
// ✅ Правильно — библиотека сама определяет:
await client.createAndPostMarketOrder({...}, undefined, OrderType.FOK);
Передача negRisk и tickSize в options меняет EIP-712 signing domain → сервер возвращает "invalid signature".
В) Переопределение feeRateBps
typescript
const DEFAULT_FEE_RATE_BPS = 1000; // 10% для 5-минутных рынков
const originalGetFeeRateBps = client.getFeeRateBps.bind(client);
const feeOverride = async (tokenID: string) => {
try { const f = await originalGetFeeRateBps(tokenID); if (f > 0) return f; } catch {}
return DEFAULT_FEE_RATE_BPS;
};
client.getFeeRateBps = feeOverride;
client._resolveFeeRateBps = async (tokenID, userFeeRateBps) => {
if (userFeeRateBps !== undefined && userFeeRateBps > 0) return userFeeRateBps;
return feeOverride(tokenID);
};
5-минутные рынки имеют fee 1000 bps (10%). Без этого хака CLOB возвращал ошибки "error parsing fee rate bps ()" или "invalid fee rate (0)".
Г) Предварительное определение версии сервера
typescript
try { await client.resolveVersion(); } catch { client.cachedVersion = 1; }
Без этого клиент мог отправить V2 payload на V1 сервер.
Д) Исправление signatureType
typescript
if (wallet.signatureType === 2) walРазмещение ордеров (POST /api/trade)
Файл: src/app/api/trade/route.ts
Ключевые решения:
А) FOK с щедрой ценой (generous price)
typescript
const generousPrice = side === Side.BUY ? 0.99 : 0.01;
await client.createAndPostMarketOrder(
{
tokenID: tokenId,
side: orderSide,
amount: size, // $$$ — доллары (для BUY) или акции (для SELL)
price: generousPrice, // щедрая цена — как на сайте Polymarket
},
undefined, // НЕ передаём options — библиотека сама определяет negRisk + tickSize
OrderType.FOK,
);
Почему щедрая цена:
Без price библиотека вычисляет цену из стакана — получается слишком точная (tight) цена
Между получением стакана и отправкой подписанного ордера ликвидность сдвигается → FOK не заполняется ("order couldn't be fully filled")
С price: 0.99 для BUY: CLOB всё равно заполняет по лучшим доступным ценам, но takerAmount даёт зазор
С price: 0.01 для SELL: аналогично, продаём по лучшим бидам
Б) НЕ передавать { negRisk, tickSize } в options
typescript
// ❌ НЕ ДЕЛАТЬ ТАК — ломает EIP-712 домен подписи:
await client.createAndPostMarketOrder({...}, { tickSize: "0.01", negRisk: true }, OrderType.FOK);
// ✅ Правильно — библиотека сама определяет:
await client.createAndPostMarketOrder({...}, undefined, OrderType.FOK);
Передача negRisk и tickSize в options меняет EIP-712 signing domain → сервер возвращает "invalid signature".
В) Переопределение feeRateBps
typescript
const DEFAULT_FEE_RATE_BPS = 1000; // 10% для 5-минутных рынков
const originalGetFeeRateBps = client.getFeeRateBps.bind(client);
const feeOverride = async (tokenID: string) => {
try { const f = await originalGetFeeRateBps(tokenID); if (f > 0) return f; } catch {}
return DEFAULT_FEE_RATE_BPS;
};
client.getFeeRateBps = feeOverride;
client._resolveFeeRateBps = async (tokenID, userFeeRateBps) => {
if (userFeeRateBps !== undefined && userFeeRateBps > 0) return userFeeRateBps;
return feeOverride(tokenID);
};
5-минутные рынки имеют fee 1000 bps (10%). Без этого хака CLOB возвращал ошибки "error parsing fee rate bps ()" или "invalid fee rate (0)".
Г) Предварительное определение версии сервера
typescript
try { await client.resolveVersion(); } catch { client.cachedVersion = 1; }
Без этого клиент мог отправить V2 payload на V1 сервер.
Д) Исправление signatureType
typescript
let.signatureType = 1;