@polymarket/clob-client-v2 1.0.2 → 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;
@@ -868,10 +877,13 @@ declare class ClobClient {
868
877
  private readonly tokenConditionMap;
869
878
  readonly useServerTime?: boolean;
870
879
  readonly builderConfig?: BuilderConfig;
880
+ readonly signatureType: SignatureTypeV2;
881
+ readonly funderAddress?: string;
871
882
  private cachedVersion?;
872
883
  readonly retryOnError?: boolean;
873
884
  readonly throwOnError?: boolean;
874
- 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);
875
887
  getOk(): Promise<any>;
876
888
  postHeartbeat(heartbeatId?: string): Promise<{
877
889
  heartbeat_id: string;
@@ -961,6 +973,8 @@ declare class ClobClient {
961
973
  private canL1Auth;
962
974
  private canL2Auth;
963
975
  private isBuilderOrder;
976
+ private getBuilderTakerFeeRate;
977
+ private adjustBuyAmountForBalance;
964
978
  private _ensureMarketInfoCached;
965
979
  private ensureBuilderFeeRateCached;
966
980
  private _resolveTickSize;
@@ -995,7 +1009,7 @@ declare class ApiError extends Error {
995
1009
  constructor(message: string, status?: number, data?: unknown);
996
1010
  }
997
1011
 
998
- declare const createL1Headers: (signer: ClobSigner, chainId: Chain, nonce?: number, timestamp?: number) => Promise<L1PolyHeader>;
1012
+ declare const createL1Headers: (signer: ClobSigner, chainId: Chain, nonce?: number, timestamp?: number, address?: string) => Promise<L1PolyHeader>;
999
1013
  declare const createL2Headers: (signer: ClobSigner, creds: ApiKeyCreds, l2HeaderArgs: L2HeaderArgs, timestamp?: number) => Promise<L2PolyHeader>;
1000
1014
 
1001
1015
  export { ApiError, type ApiKeyCreds, type ApiKeyRaw, type ApiKeysResponse, AssetType, type BalanceAllowanceParams, type BalanceAllowanceResponse, type BanStatus, type BookParams, type BuilderApiKey, type BuilderApiKeyResponse, type BuilderConfig, type BuilderFeeRates, type BuilderTrade, type BuilderTradeParams, type BuilderTradesResponse, COLLATERAL_TOKEN_DECIMALS, CONDITIONAL_TOKEN_DECIMALS, Chain, ClobClient, type ClobClientOptions, type ClobErrorResponseBody, type ClobToken, type ContractConfig, type CreateOrderOptions, type DropNotificationParams, type Earning, type FeeDetails, type FeeInfo, type FeeInfos, type FeeRates, type L1PolyHeader, L1_AUTH_UNAVAILABLE_ERROR, type L2HeaderArgs, type L2PolyHeader, L2_AUTH_NOT_AVAILABLE, type MakerOrder, type MarketDetails, type MarketPrice, type MarketReward, type MarketTradeEvent, type NegRisk, type NewOrderV1, type NewOrderV2, type Notification, type OpenOrder, type OpenOrderParams, type OpenOrdersResponse, type OrderBookSummary, OrderBuilder, type OrderMarketCancelParams, type OrderPayload, type OrderResponse, type OrderScoring, type OrderScoringParams, type OrderSummary, OrderType, type OrdersScoring, type OrdersScoringParams, type PaginationPayload, type PostOrdersArgs, type PostOrdersV1Args, type PostOrdersV2Args, type PreMigrationOrder, type PreMigrationOrdersResponse, type PriceHistoryFilterParams, PriceHistoryInterval, type ReadonlyApiKeyResponse, type RewardsConfig, type RewardsPercentages, type RoundConfig, Side, SignatureTypeV1, SignatureTypeV2, type SignedOrder, type SimpleHeaders, type TickSize, type TickSizes, type Token, type TokenConditionMap, type TotalUserEarning, type Trade, type TradeParams, type TradesPaginatedResponse, type UserEarning, type UserMarketOrderV1, type UserMarketOrderV2, type UserOrderV1, type UserOrderV2, type UserRewardsEarning, type VersionedPostOrdersArgs, type VersionedSignedOrder, type VersionedUserMarketOrder, type VersionedUserOrder, adjustBuyAmountForFees, createL1Headers, createL2Headers, getContractConfig, isV2Order, orderToJsonV1, orderToJsonV2 };
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;
@@ -868,10 +877,13 @@ declare class ClobClient {
868
877
  private readonly tokenConditionMap;
869
878
  readonly useServerTime?: boolean;
870
879
  readonly builderConfig?: BuilderConfig;
880
+ readonly signatureType: SignatureTypeV2;
881
+ readonly funderAddress?: string;
871
882
  private cachedVersion?;
872
883
  readonly retryOnError?: boolean;
873
884
  readonly throwOnError?: boolean;
874
- 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);
875
887
  getOk(): Promise<any>;
876
888
  postHeartbeat(heartbeatId?: string): Promise<{
877
889
  heartbeat_id: string;
@@ -961,6 +973,8 @@ declare class ClobClient {
961
973
  private canL1Auth;
962
974
  private canL2Auth;
963
975
  private isBuilderOrder;
976
+ private getBuilderTakerFeeRate;
977
+ private adjustBuyAmountForBalance;
964
978
  private _ensureMarketInfoCached;
965
979
  private ensureBuilderFeeRateCached;
966
980
  private _resolveTickSize;
@@ -995,7 +1009,7 @@ declare class ApiError extends Error {
995
1009
  constructor(message: string, status?: number, data?: unknown);
996
1010
  }
997
1011
 
998
- declare const createL1Headers: (signer: ClobSigner, chainId: Chain, nonce?: number, timestamp?: number) => Promise<L1PolyHeader>;
1012
+ declare const createL1Headers: (signer: ClobSigner, chainId: Chain, nonce?: number, timestamp?: number, address?: string) => Promise<L1PolyHeader>;
999
1013
  declare const createL2Headers: (signer: ClobSigner, creds: ApiKeyCreds, l2HeaderArgs: L2HeaderArgs, timestamp?: number) => Promise<L2PolyHeader>;
1000
1014
 
1001
1015
  export { ApiError, type ApiKeyCreds, type ApiKeyRaw, type ApiKeysResponse, AssetType, type BalanceAllowanceParams, type BalanceAllowanceResponse, type BanStatus, type BookParams, type BuilderApiKey, type BuilderApiKeyResponse, type BuilderConfig, type BuilderFeeRates, type BuilderTrade, type BuilderTradeParams, type BuilderTradesResponse, COLLATERAL_TOKEN_DECIMALS, CONDITIONAL_TOKEN_DECIMALS, Chain, ClobClient, type ClobClientOptions, type ClobErrorResponseBody, type ClobToken, type ContractConfig, type CreateOrderOptions, type DropNotificationParams, type Earning, type FeeDetails, type FeeInfo, type FeeInfos, type FeeRates, type L1PolyHeader, L1_AUTH_UNAVAILABLE_ERROR, type L2HeaderArgs, type L2PolyHeader, L2_AUTH_NOT_AVAILABLE, type MakerOrder, type MarketDetails, type MarketPrice, type MarketReward, type MarketTradeEvent, type NegRisk, type NewOrderV1, type NewOrderV2, type Notification, type OpenOrder, type OpenOrderParams, type OpenOrdersResponse, type OrderBookSummary, OrderBuilder, type OrderMarketCancelParams, type OrderPayload, type OrderResponse, type OrderScoring, type OrderScoringParams, type OrderSummary, OrderType, type OrdersScoring, type OrdersScoringParams, type PaginationPayload, type PostOrdersArgs, type PostOrdersV1Args, type PostOrdersV2Args, type PreMigrationOrder, type PreMigrationOrdersResponse, type PriceHistoryFilterParams, PriceHistoryInterval, type ReadonlyApiKeyResponse, type RewardsConfig, type RewardsPercentages, type RoundConfig, Side, SignatureTypeV1, SignatureTypeV2, type SignedOrder, type SimpleHeaders, type TickSize, type TickSizes, type Token, type TokenConditionMap, type TotalUserEarning, type Trade, type TradeParams, type TradesPaginatedResponse, type UserEarning, type UserMarketOrderV1, type UserMarketOrderV2, type UserOrderV1, type UserOrderV2, type UserRewardsEarning, type VersionedPostOrdersArgs, type VersionedSignedOrder, type VersionedUserMarketOrder, type VersionedUserOrder, adjustBuyAmountForFees, createL1Headers, createL2Headers, getContractConfig, isV2Order, orderToJsonV1, orderToJsonV2 };
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
 
@@ -146,8 +168,8 @@ var signTypedDataWithSigner = async ({
146
168
  };
147
169
 
148
170
  // src/signing/eip712.ts
149
- var buildClobEip712Signature = async (signer, chainId, timestamp, nonce) => {
150
- const address = await getSignerAddress(signer);
171
+ var buildClobEip712Signature = async (signer, chainId, timestamp, nonce, address) => {
172
+ const resolvedAddress = address ?? await getSignerAddress(signer);
151
173
  const ts = timestamp.toString();
152
174
  const domain = {
153
175
  name: "ClobAuthDomain",
@@ -163,7 +185,7 @@ var buildClobEip712Signature = async (signer, chainId, timestamp, nonce) => {
163
185
  ]
164
186
  };
165
187
  const value = {
166
- address,
188
+ address: resolvedAddress,
167
189
  timestamp: ts,
168
190
  nonce,
169
191
  message: MSG_TO_SIGN
@@ -196,7 +218,7 @@ var buildPolyHmacSignature = (secret, timestamp, method, requestPath, body) => {
196
218
  };
197
219
 
198
220
  // src/headers/index.ts
199
- var createL1Headers = async (signer, chainId, nonce, timestamp) => {
221
+ var createL1Headers = async (signer, chainId, nonce, timestamp, address) => {
200
222
  let ts = Math.floor(Date.now() / 1e3);
201
223
  if (timestamp !== void 0) {
202
224
  ts = timestamp;
@@ -205,10 +227,10 @@ var createL1Headers = async (signer, chainId, nonce, timestamp) => {
205
227
  if (nonce !== void 0) {
206
228
  n = nonce;
207
229
  }
208
- const sig = await buildClobEip712Signature(signer, chainId, ts, n);
209
- const address = await getSignerAddress(signer);
230
+ const sig = await buildClobEip712Signature(signer, chainId, ts, n, address);
231
+ const resolvedAddress = address ?? await getSignerAddress(signer);
210
232
  const headers = {
211
- POLY_ADDRESS: address,
233
+ POLY_ADDRESS: resolvedAddress,
212
234
  POLY_SIGNATURE: sig,
213
235
  POLY_TIMESTAMP: `${ts}`,
214
236
  POLY_NONCE: `${n}`
@@ -634,7 +656,7 @@ var ExchangeOrderBuilderV1 = class {
634
656
  };
635
657
 
636
658
  // src/order-utils/exchangeOrderBuilderV2.ts
637
- import { hashTypedData as hashTypedData2 } from "viem";
659
+ import { encodeAbiParameters, hashTypedData as hashTypedData2, keccak256, toHex } from "viem";
638
660
 
639
661
  // src/order-utils/model/ctfExchangeV2TypedData.ts
640
662
  var CTF_EXCHANGE_V2_DOMAIN_NAME = "Polymarket CTF Exchange";
@@ -663,22 +685,51 @@ var SignatureTypeV2 = /* @__PURE__ */ ((SignatureTypeV22) => {
663
685
  })(SignatureTypeV2 || {});
664
686
 
665
687
  // src/order-utils/exchangeOrderBuilderV2.ts
688
+ var ORDER_TYPE_STRING = "Order(uint256 salt,address maker,address signer,uint256 tokenId,uint256 makerAmount,uint256 takerAmount,uint8 side,uint8 signatureType,uint256 timestamp,bytes32 metadata,bytes32 builder)";
689
+ var ORDER_TYPE_HASH = keccak256(toHex(ORDER_TYPE_STRING));
690
+ var DOMAIN_TYPE_HASH = keccak256(
691
+ toHex("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
692
+ );
693
+ var TYPED_DATA_SIGN_STRUCT = [
694
+ { name: "contents", type: "Order" },
695
+ { name: "name", type: "string" },
696
+ { name: "version", type: "string" },
697
+ { name: "chainId", type: "uint256" },
698
+ { name: "verifyingContract", type: "address" },
699
+ { name: "salt", type: "bytes32" }
700
+ ];
701
+ var CTF_EXCHANGE_NAME_HASH = keccak256(toHex(CTF_EXCHANGE_V2_DOMAIN_NAME));
702
+ var CTF_EXCHANGE_VERSION_HASH = keccak256(toHex(CTF_EXCHANGE_V2_DOMAIN_VERSION));
666
703
  var ExchangeOrderBuilderV2 = class {
667
704
  constructor(contractAddress, chainId, signer, generateSalt = generateOrderSalt) {
668
705
  this.contractAddress = contractAddress;
669
706
  this.chainId = chainId;
670
707
  this.signer = signer;
671
708
  this.generateSalt = generateSalt;
709
+ this.appDomainSep = keccak256(
710
+ encodeAbiParameters(
711
+ [
712
+ { type: "bytes32" },
713
+ { type: "bytes32" },
714
+ { type: "bytes32" },
715
+ { type: "uint256" },
716
+ { type: "address" }
717
+ ],
718
+ [
719
+ DOMAIN_TYPE_HASH,
720
+ CTF_EXCHANGE_NAME_HASH,
721
+ CTF_EXCHANGE_VERSION_HASH,
722
+ BigInt(chainId),
723
+ contractAddress
724
+ ]
725
+ )
726
+ );
672
727
  }
673
728
  contractAddress;
674
729
  chainId;
675
730
  signer;
676
731
  generateSalt;
677
- /**
678
- * build an order object including the signature.
679
- * @param orderData
680
- * @returns a SignedOrder object (order + signature)
681
- */
732
+ appDomainSep;
682
733
  async buildSignedOrder(orderData) {
683
734
  const order = await this.buildOrder(orderData);
684
735
  const orderTypedData = this.buildOrderTypedData(order);
@@ -688,11 +739,6 @@ var ExchangeOrderBuilderV2 = class {
688
739
  signature: orderSignature
689
740
  };
690
741
  }
691
- /**
692
- * Creates an Order object from order data.
693
- * @param OrderData
694
- * @returns a Order object (not signed)
695
- */
696
742
  async buildOrder({
697
743
  maker,
698
744
  tokenId,
@@ -709,9 +755,11 @@ var ExchangeOrderBuilderV2 = class {
709
755
  if (!signer) {
710
756
  signer = maker;
711
757
  }
712
- const signerAddress = await getSignerAddress(this.signer);
713
- if (signer !== signerAddress) {
714
- throw new Error("signer does not match");
758
+ if (signatureType !== 3 /* POLY_1271 */) {
759
+ const signerAddress = await getSignerAddress(this.signer);
760
+ if (signer !== signerAddress) {
761
+ throw new Error("signer does not match");
762
+ }
715
763
  }
716
764
  return {
717
765
  salt: this.generateSalt(),
@@ -728,11 +776,6 @@ var ExchangeOrderBuilderV2 = class {
728
776
  expiration: expiration ?? "0"
729
777
  };
730
778
  }
731
- /**
732
- * Parses an Order object to EIP712 typed data
733
- * @param order
734
- * @returns a EIP712TypedData object
735
- */
736
779
  buildOrderTypedData(order) {
737
780
  return {
738
781
  primaryType: "Order",
@@ -761,29 +804,78 @@ var ExchangeOrderBuilderV2 = class {
761
804
  }
762
805
  };
763
806
  }
764
- /**
765
- * Generates order's signature from a EIP712TypedData object + the signer address
766
- * @param typedData
767
- * @returns a OrderSignature that is an string
768
- */
769
- buildOrderSignature(typedData) {
807
+ async buildOrderSignature(typedData) {
770
808
  delete typedData.types.EIP712Domain;
771
- return signTypedDataWithSigner({
809
+ const msg = typedData.message;
810
+ if (msg.signatureType !== 3 /* POLY_1271 */) {
811
+ return signTypedDataWithSigner({
812
+ signer: this.signer,
813
+ domain: typedData.domain,
814
+ types: typedData.types,
815
+ value: typedData.message,
816
+ primaryType: typedData.primaryType
817
+ });
818
+ }
819
+ const contentsHash = keccak256(
820
+ encodeAbiParameters(
821
+ [
822
+ { type: "bytes32" },
823
+ { type: "uint256" },
824
+ { type: "address" },
825
+ { type: "address" },
826
+ { type: "uint256" },
827
+ { type: "uint256" },
828
+ { type: "uint256" },
829
+ { type: "uint8" },
830
+ { type: "uint8" },
831
+ { type: "uint256" },
832
+ { type: "bytes32" },
833
+ { type: "bytes32" }
834
+ ],
835
+ [
836
+ ORDER_TYPE_HASH,
837
+ BigInt(msg.salt),
838
+ msg.maker,
839
+ msg.signer,
840
+ BigInt(msg.tokenId),
841
+ BigInt(msg.makerAmount),
842
+ BigInt(msg.takerAmount),
843
+ msg.side,
844
+ msg.signatureType,
845
+ BigInt(msg.timestamp),
846
+ msg.metadata,
847
+ msg.builder
848
+ ]
849
+ )
850
+ );
851
+ const innerSig = await signTypedDataWithSigner({
772
852
  signer: this.signer,
773
- domain: typedData.domain,
774
- types: typedData.types,
775
- value: typedData.message,
776
- primaryType: typedData.primaryType
853
+ domain: {
854
+ name: CTF_EXCHANGE_V2_DOMAIN_NAME,
855
+ version: CTF_EXCHANGE_V2_DOMAIN_VERSION,
856
+ chainId: this.chainId,
857
+ verifyingContract: this.contractAddress
858
+ },
859
+ types: {
860
+ TypedDataSign: TYPED_DATA_SIGN_STRUCT,
861
+ Order: CTF_EXCHANGE_V2_ORDER_STRUCT
862
+ },
863
+ primaryType: "TypedDataSign",
864
+ value: {
865
+ contents: typedData.message,
866
+ name: "DepositWallet",
867
+ version: "1",
868
+ chainId: this.chainId,
869
+ verifyingContract: msg.signer,
870
+ salt: bytes32Zero
871
+ }
777
872
  });
873
+ const ctLen = ORDER_TYPE_STRING.length;
874
+ const lenHex = ctLen.toString(16).padStart(4, "0");
875
+ return `0x${innerSig.slice(2)}${this.appDomainSep.slice(2)}${contentsHash.slice(2)}${toHex(ORDER_TYPE_STRING).slice(2)}${lenHex}`;
778
876
  }
779
- /**
780
- * Generates the hash of the order from a EIP712TypedData object.
781
- * @param orderTypedData
782
- * @returns a OrderHash that is an string
783
- */
784
877
  buildOrderHash(orderTypedData) {
785
- const digest = hashTypedData2(orderTypedData);
786
- return digest;
878
+ return hashTypedData2(orderTypedData);
787
879
  }
788
880
  };
789
881
 
@@ -1087,9 +1179,10 @@ var ROUNDING_CONFIG = {
1087
1179
  var createMarketOrder = async (eoaSigner, chainId, signatureType, funderAddress, userMarketOrder, options, version) => {
1088
1180
  const eoaSignerAddress = await getSignerAddress(eoaSigner);
1089
1181
  const maker = funderAddress === void 0 ? eoaSignerAddress : funderAddress;
1182
+ const signerForOrder = signatureType === 3 /* POLY_1271 */ ? maker : eoaSignerAddress;
1090
1183
  const contractConfig = getContractConfig(chainId);
1091
1184
  const orderData = await buildMarketOrderCreationArgs(
1092
- eoaSignerAddress,
1185
+ signerForOrder,
1093
1186
  maker,
1094
1187
  signatureType,
1095
1188
  userMarketOrder,
@@ -1117,9 +1210,10 @@ var createMarketOrder = async (eoaSigner, chainId, signatureType, funderAddress,
1117
1210
  var createOrder = async (eoaSigner, chainId, signatureType, funderAddress, userOrder, options, version) => {
1118
1211
  const eoaSignerAddress = await getSignerAddress(eoaSigner);
1119
1212
  const maker = funderAddress === void 0 ? eoaSignerAddress : funderAddress;
1213
+ const signerForOrder = signatureType === 3 /* POLY_1271 */ ? maker : eoaSignerAddress;
1120
1214
  const contractConfig = getContractConfig(chainId);
1121
1215
  const orderData = await buildOrderCreationArgs(
1122
- eoaSignerAddress,
1216
+ signerForOrder,
1123
1217
  maker,
1124
1218
  signatureType,
1125
1219
  userOrder,
@@ -1244,15 +1338,6 @@ var OrderBuilder = class {
1244
1338
  };
1245
1339
 
1246
1340
  // src/client.ts
1247
- function adjustBuyAmountForFees(amount, price, userUSDCBalance, feeRate, feeExponent, builderTakerFeeRate) {
1248
- const platformFeeRate = feeRate * (price * (1 - price)) ** feeExponent;
1249
- const platformFee = amount / price * platformFeeRate;
1250
- const totalCost = amount + platformFee + amount * builderTakerFeeRate;
1251
- if (userUSDCBalance <= totalCost) {
1252
- return userUSDCBalance / (1 + platformFeeRate / price + builderTakerFeeRate);
1253
- }
1254
- return amount;
1255
- }
1256
1341
  var ClobClient = class {
1257
1342
  host;
1258
1343
  chainId;
@@ -1270,9 +1355,12 @@ var ClobClient = class {
1270
1355
  tokenConditionMap;
1271
1356
  useServerTime;
1272
1357
  builderConfig;
1358
+ signatureType;
1359
+ funderAddress;
1273
1360
  cachedVersion;
1274
1361
  retryOnError;
1275
1362
  throwOnError;
1363
+ feeSlippage;
1276
1364
  constructor({
1277
1365
  host,
1278
1366
  chain,
@@ -1284,7 +1372,8 @@ var ClobClient = class {
1284
1372
  builderConfig,
1285
1373
  getSigner,
1286
1374
  retryOnError,
1287
- throwOnError
1375
+ throwOnError,
1376
+ feeSlippage
1288
1377
  }) {
1289
1378
  this.host = host.endsWith("/") ? host.slice(0, -1) : host;
1290
1379
  this.chainId = chain;
@@ -1301,6 +1390,8 @@ var ClobClient = class {
1301
1390
  funderAddress,
1302
1391
  getSigner
1303
1392
  );
1393
+ this.signatureType = signatureType ?? 0 /* EOA */;
1394
+ this.funderAddress = funderAddress;
1304
1395
  this.tickSizes = {};
1305
1396
  this.negRisk = {};
1306
1397
  this.feeRates = {};
@@ -1309,6 +1400,8 @@ var ClobClient = class {
1309
1400
  this.tokenConditionMap = {};
1310
1401
  this.retryOnError = retryOnError;
1311
1402
  this.throwOnError = throwOnError;
1403
+ this.feeSlippage = feeSlippage ?? 0;
1404
+ validateFeeSlippage(this.feeSlippage);
1312
1405
  this.useServerTime = useServerTime;
1313
1406
  if (builderConfig !== void 0) {
1314
1407
  this.builderConfig = builderConfig;
@@ -1806,8 +1899,19 @@ var ClobClient = class {
1806
1899
  `invalid price (${orderToSign.price}), min: ${parseFloat(tickSize)} - max: ${1 - parseFloat(tickSize)}`
1807
1900
  );
1808
1901
  }
1809
- const negRisk = options?.negRisk ?? await this.getNegRisk(tokenID);
1902
+ orderToSign.price = roundNormal(orderToSign.price, ROUNDING_CONFIG[tickSize].price);
1810
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);
1811
1915
  if (version === 1) {
1812
1916
  const userFeeRateBps = "feeRateBps" in orderToSign ? orderToSign.feeRateBps : void 0;
1813
1917
  const feeRateBps = await this._resolveFeeRateBps(tokenID, userFeeRateBps);
@@ -1847,15 +1951,12 @@ var ClobClient = class {
1847
1951
  await this.ensureBuilderFeeRateCached(orderToSign.builderCode);
1848
1952
  if (orderToSign.side === "BUY" /* BUY */ && "userUSDCBalance" in orderToSign && orderToSign.userUSDCBalance !== void 0) {
1849
1953
  const price = orderToSign.price;
1850
- const { userUSDCBalance } = orderToSign;
1851
- const builderTakerFeeRate = this.isBuilderOrder(orderToSign.builderCode) ? this.builderFeeRates[orderToSign.builderCode ?? ""]?.taker ?? 0 : 0;
1852
- orderToSign.amount = adjustBuyAmountForFees(
1954
+ orderToSign.amount = await this.adjustBuyAmountForBalance(
1955
+ tokenID,
1853
1956
  orderToSign.amount,
1854
1957
  price,
1855
- userUSDCBalance,
1856
- this.feeInfos[tokenID].rate,
1857
- this.feeInfos[tokenID].exponent,
1858
- builderTakerFeeRate
1958
+ orderToSign.userUSDCBalance,
1959
+ orderToSign.builderCode
1859
1960
  );
1860
1961
  }
1861
1962
  const negRisk = options?.negRisk ?? await this.getNegRisk(tokenID);
@@ -2315,6 +2416,24 @@ var ClobClient = class {
2315
2416
  isBuilderOrder(builderCode) {
2316
2417
  return builderCode !== void 0 && builderCode !== bytes32Zero;
2317
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
+ }
2318
2437
  async _ensureMarketInfoCached(tokenID) {
2319
2438
  if (tokenID in this.feeInfos) return;
2320
2439
  if (!(tokenID in this.tokenConditionMap)) {