@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.cjs +182 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +183 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
230
|
+
const sig = await buildClobEip712Signature(signer, chainId, ts, n, address);
|
|
231
|
+
const resolvedAddress = address ?? await getSignerAddress(signer);
|
|
210
232
|
const headers = {
|
|
211
|
-
POLY_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
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
-
|
|
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:
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1851
|
-
|
|
1852
|
-
orderToSign.amount = adjustBuyAmountForFees(
|
|
1954
|
+
orderToSign.amount = await this.adjustBuyAmountForBalance(
|
|
1955
|
+
tokenID,
|
|
1853
1956
|
orderToSign.amount,
|
|
1854
1957
|
price,
|
|
1855
|
-
userUSDCBalance,
|
|
1856
|
-
|
|
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)) {
|