@polymarket/clob-client-v2 1.0.3-canary.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -585,6 +585,13 @@ interface UserOrderV2 {
585
585
  * Expiration timestamp (unix seconds). Defaults to 0 (no expiration).
586
586
  */
587
587
  expiration?: number;
588
+ /**
589
+ * User's USDC balance. If provided and sufficient to cover amount + fees, the order
590
+ * size is used as-is. Otherwise fees are deducted from the order notional and size is reduced.
591
+ * If this field is left empty, the default flow is to use the order size as-is.
592
+ * This is used for marketable limit orders
593
+ */
594
+ userUSDCBalance?: number;
588
595
  }
589
596
  interface UserMarketOrderV2 {
590
597
  /**
@@ -840,7 +847,8 @@ declare class OrderBuilder {
840
847
  private resolveSigner;
841
848
  }
842
849
 
843
- declare function adjustBuyAmountForFees(amount: number, price: number, userUSDCBalance: number, feeRate: number, feeExponent: number, builderTakerFeeRate: number): number;
850
+ declare function adjustBuyAmountForFees(amount: number, price: number, userUSDCBalance: number, feeRate: number, feeExponent: number, builderTakerFeeRate: number, feeSlippage?: number): number;
851
+
844
852
  interface ClobClientOptions {
845
853
  host: string;
846
854
  chain: Chain;
@@ -853,6 +861,7 @@ interface ClobClientOptions {
853
861
  getSigner?: () => Promise<ClobSigner> | ClobSigner;
854
862
  retryOnError?: boolean;
855
863
  throwOnError?: boolean;
864
+ feeSlippage?: number;
856
865
  }
857
866
  declare class ClobClient {
858
867
  readonly host: string;
@@ -873,7 +882,8 @@ declare class ClobClient {
873
882
  private cachedVersion?;
874
883
  readonly retryOnError?: boolean;
875
884
  readonly throwOnError?: boolean;
876
- constructor({ host, chain, signer, creds, signatureType, funderAddress, useServerTime, builderConfig, getSigner, retryOnError, throwOnError, }: ClobClientOptions);
885
+ readonly feeSlippage: number;
886
+ constructor({ host, chain, signer, creds, signatureType, funderAddress, useServerTime, builderConfig, getSigner, retryOnError, throwOnError, feeSlippage, }: ClobClientOptions);
877
887
  getOk(): Promise<any>;
878
888
  postHeartbeat(heartbeatId?: string): Promise<{
879
889
  heartbeat_id: string;
@@ -963,6 +973,8 @@ declare class ClobClient {
963
973
  private canL1Auth;
964
974
  private canL2Auth;
965
975
  private isBuilderOrder;
976
+ private getBuilderTakerFeeRate;
977
+ private adjustBuyAmountForBalance;
966
978
  private _ensureMarketInfoCached;
967
979
  private ensureBuilderFeeRateCached;
968
980
  private _resolveTickSize;
package/dist/index.d.ts CHANGED
@@ -585,6 +585,13 @@ interface UserOrderV2 {
585
585
  * Expiration timestamp (unix seconds). Defaults to 0 (no expiration).
586
586
  */
587
587
  expiration?: number;
588
+ /**
589
+ * User's USDC balance. If provided and sufficient to cover amount + fees, the order
590
+ * size is used as-is. Otherwise fees are deducted from the order notional and size is reduced.
591
+ * If this field is left empty, the default flow is to use the order size as-is.
592
+ * This is used for marketable limit orders
593
+ */
594
+ userUSDCBalance?: number;
588
595
  }
589
596
  interface UserMarketOrderV2 {
590
597
  /**
@@ -840,7 +847,8 @@ declare class OrderBuilder {
840
847
  private resolveSigner;
841
848
  }
842
849
 
843
- declare function adjustBuyAmountForFees(amount: number, price: number, userUSDCBalance: number, feeRate: number, feeExponent: number, builderTakerFeeRate: number): number;
850
+ declare function adjustBuyAmountForFees(amount: number, price: number, userUSDCBalance: number, feeRate: number, feeExponent: number, builderTakerFeeRate: number, feeSlippage?: number): number;
851
+
844
852
  interface ClobClientOptions {
845
853
  host: string;
846
854
  chain: Chain;
@@ -853,6 +861,7 @@ interface ClobClientOptions {
853
861
  getSigner?: () => Promise<ClobSigner> | ClobSigner;
854
862
  retryOnError?: boolean;
855
863
  throwOnError?: boolean;
864
+ feeSlippage?: number;
856
865
  }
857
866
  declare class ClobClient {
858
867
  readonly host: string;
@@ -873,7 +882,8 @@ declare class ClobClient {
873
882
  private cachedVersion?;
874
883
  readonly retryOnError?: boolean;
875
884
  readonly throwOnError?: boolean;
876
- constructor({ host, chain, signer, creds, signatureType, funderAddress, useServerTime, builderConfig, getSigner, retryOnError, throwOnError, }: ClobClientOptions);
885
+ readonly feeSlippage: number;
886
+ constructor({ host, chain, signer, creds, signatureType, funderAddress, useServerTime, builderConfig, getSigner, retryOnError, throwOnError, feeSlippage, }: ClobClientOptions);
877
887
  getOk(): Promise<any>;
878
888
  postHeartbeat(heartbeatId?: string): Promise<{
879
889
  heartbeat_id: string;
@@ -963,6 +973,8 @@ declare class ClobClient {
963
973
  private canL1Auth;
964
974
  private canL2Auth;
965
975
  private isBuilderOrder;
976
+ private getBuilderTakerFeeRate;
977
+ private adjustBuyAmountForBalance;
966
978
  private _ensureMarketInfoCached;
967
979
  private ensureBuilderFeeRateCached;
968
980
  private _resolveTickSize;
package/dist/index.js CHANGED
@@ -85,6 +85,28 @@ var ApiError = class extends Error {
85
85
  }
86
86
  };
87
87
 
88
+ // src/fees/index.ts
89
+ var MIN_FEE_SLIPPAGE_PERCENTAGE = 1;
90
+ var MAX_FEE_SLIPPAGE_PERCENTAGE = 100;
91
+ function validateFeeSlippage(feeSlippage) {
92
+ if (!Number.isFinite(feeSlippage) || feeSlippage < 0 || feeSlippage > MAX_FEE_SLIPPAGE_PERCENTAGE || feeSlippage > 0 && feeSlippage < MIN_FEE_SLIPPAGE_PERCENTAGE) {
93
+ throw new Error("feeSlippage must be 0 or a percentage between 1 and 100");
94
+ }
95
+ }
96
+ function adjustBuyAmountForFees(amount, price, userUSDCBalance, feeRate, feeExponent, builderTakerFeeRate, feeSlippage = 0) {
97
+ validateFeeSlippage(feeSlippage);
98
+ const platformFeeRate = feeRate * (price * (1 - price)) ** feeExponent;
99
+ const effectivePlatformFeeRate = platformFeeRate * (1 + feeSlippage / 100);
100
+ const feeBaseAmount = Math.min(amount, userUSDCBalance);
101
+ const platformFee = feeBaseAmount / price * effectivePlatformFeeRate;
102
+ const builderFee = feeBaseAmount * builderTakerFeeRate;
103
+ const totalCost = amount + platformFee + builderFee;
104
+ if (userUSDCBalance <= totalCost) {
105
+ return Math.max(userUSDCBalance - platformFee - builderFee, 0);
106
+ }
107
+ return amount;
108
+ }
109
+
88
110
  // src/signing/constants.ts
89
111
  var MSG_TO_SIGN = "This message attests that I control the given wallet";
90
112
 
@@ -1316,15 +1338,6 @@ var OrderBuilder = class {
1316
1338
  };
1317
1339
 
1318
1340
  // src/client.ts
1319
- function adjustBuyAmountForFees(amount, price, userUSDCBalance, feeRate, feeExponent, builderTakerFeeRate) {
1320
- const platformFeeRate = feeRate * (price * (1 - price)) ** feeExponent;
1321
- const platformFee = amount / price * platformFeeRate;
1322
- const totalCost = amount + platformFee + amount * builderTakerFeeRate;
1323
- if (userUSDCBalance <= totalCost) {
1324
- return userUSDCBalance / (1 + platformFeeRate / price + builderTakerFeeRate);
1325
- }
1326
- return amount;
1327
- }
1328
1341
  var ClobClient = class {
1329
1342
  host;
1330
1343
  chainId;
@@ -1347,6 +1360,7 @@ var ClobClient = class {
1347
1360
  cachedVersion;
1348
1361
  retryOnError;
1349
1362
  throwOnError;
1363
+ feeSlippage;
1350
1364
  constructor({
1351
1365
  host,
1352
1366
  chain,
@@ -1358,7 +1372,8 @@ var ClobClient = class {
1358
1372
  builderConfig,
1359
1373
  getSigner,
1360
1374
  retryOnError,
1361
- throwOnError
1375
+ throwOnError,
1376
+ feeSlippage
1362
1377
  }) {
1363
1378
  this.host = host.endsWith("/") ? host.slice(0, -1) : host;
1364
1379
  this.chainId = chain;
@@ -1385,6 +1400,8 @@ var ClobClient = class {
1385
1400
  this.tokenConditionMap = {};
1386
1401
  this.retryOnError = retryOnError;
1387
1402
  this.throwOnError = throwOnError;
1403
+ this.feeSlippage = feeSlippage ?? 0;
1404
+ validateFeeSlippage(this.feeSlippage);
1388
1405
  this.useServerTime = useServerTime;
1389
1406
  if (builderConfig !== void 0) {
1390
1407
  this.builderConfig = builderConfig;
@@ -1882,8 +1899,19 @@ var ClobClient = class {
1882
1899
  `invalid price (${orderToSign.price}), min: ${parseFloat(tickSize)} - max: ${1 - parseFloat(tickSize)}`
1883
1900
  );
1884
1901
  }
1885
- const negRisk = options?.negRisk ?? await this.getNegRisk(tokenID);
1902
+ orderToSign.price = roundNormal(orderToSign.price, ROUNDING_CONFIG[tickSize].price);
1886
1903
  const version = await this.resolveVersion();
1904
+ if (version === 2 && orderToSign.side === "BUY" /* BUY */ && "userUSDCBalance" in orderToSign && orderToSign.userUSDCBalance !== void 0) {
1905
+ const adjustedAmount = await this.adjustBuyAmountForBalance(
1906
+ tokenID,
1907
+ orderToSign.size * orderToSign.price,
1908
+ orderToSign.price,
1909
+ orderToSign.userUSDCBalance,
1910
+ orderToSign.builderCode
1911
+ );
1912
+ orderToSign.size = adjustedAmount / orderToSign.price;
1913
+ }
1914
+ const negRisk = options?.negRisk ?? await this.getNegRisk(tokenID);
1887
1915
  if (version === 1) {
1888
1916
  const userFeeRateBps = "feeRateBps" in orderToSign ? orderToSign.feeRateBps : void 0;
1889
1917
  const feeRateBps = await this._resolveFeeRateBps(tokenID, userFeeRateBps);
@@ -1923,15 +1951,12 @@ var ClobClient = class {
1923
1951
  await this.ensureBuilderFeeRateCached(orderToSign.builderCode);
1924
1952
  if (orderToSign.side === "BUY" /* BUY */ && "userUSDCBalance" in orderToSign && orderToSign.userUSDCBalance !== void 0) {
1925
1953
  const price = orderToSign.price;
1926
- const { userUSDCBalance } = orderToSign;
1927
- const builderTakerFeeRate = this.isBuilderOrder(orderToSign.builderCode) ? this.builderFeeRates[orderToSign.builderCode ?? ""]?.taker ?? 0 : 0;
1928
- orderToSign.amount = adjustBuyAmountForFees(
1954
+ orderToSign.amount = await this.adjustBuyAmountForBalance(
1955
+ tokenID,
1929
1956
  orderToSign.amount,
1930
1957
  price,
1931
- userUSDCBalance,
1932
- this.feeInfos[tokenID].rate,
1933
- this.feeInfos[tokenID].exponent,
1934
- builderTakerFeeRate
1958
+ orderToSign.userUSDCBalance,
1959
+ orderToSign.builderCode
1935
1960
  );
1936
1961
  }
1937
1962
  const negRisk = options?.negRisk ?? await this.getNegRisk(tokenID);
@@ -2391,6 +2416,24 @@ var ClobClient = class {
2391
2416
  isBuilderOrder(builderCode) {
2392
2417
  return builderCode !== void 0 && builderCode !== bytes32Zero;
2393
2418
  }
2419
+ async getBuilderTakerFeeRate(builderCode) {
2420
+ if (!this.isBuilderOrder(builderCode)) return 0;
2421
+ await this.ensureBuilderFeeRateCached(builderCode);
2422
+ return this.builderFeeRates[builderCode ?? ""]?.taker ?? 0;
2423
+ }
2424
+ async adjustBuyAmountForBalance(tokenID, amount, price, userUSDCBalance, builderCode) {
2425
+ await this._ensureMarketInfoCached(tokenID);
2426
+ const builderTakerFeeRate = await this.getBuilderTakerFeeRate(builderCode);
2427
+ return adjustBuyAmountForFees(
2428
+ amount,
2429
+ price,
2430
+ userUSDCBalance,
2431
+ this.feeInfos[tokenID].rate,
2432
+ this.feeInfos[tokenID].exponent,
2433
+ builderTakerFeeRate,
2434
+ this.feeSlippage
2435
+ );
2436
+ }
2394
2437
  async _ensureMarketInfoCached(tokenID) {
2395
2438
  if (tokenID in this.feeInfos) return;
2396
2439
  if (!(tokenID in this.tokenConditionMap)) {