@theliem/xmarket-sdk 3.5.0 → 3.6.0
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.mts +89 -2
- package/dist/index.d.ts +89 -2
- package/dist/index.js +163 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +161 -90
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -596,7 +596,7 @@ declare class ClobClient {
|
|
|
596
596
|
buildMatchComplementaryIxs(takerSigned: SignedOrder, makersSigned: SignedOrder[], collateralMint: PublicKey, feeRecipient: PublicKey, operator: PublicKey, opts?: {
|
|
597
597
|
marketOracleVault?: PublicKey;
|
|
598
598
|
fillAmount?: anchor.BN;
|
|
599
|
-
}): Promise<TransactionInstruction[]>;
|
|
599
|
+
}, useTakerPrice?: boolean): Promise<TransactionInstruction[]>;
|
|
600
600
|
/**
|
|
601
601
|
* COMPLEMENTARY: 1 taker (BUY) + N makers (SELL), same tokenId.
|
|
602
602
|
* Phase 1: register taker + all makers in parallel.
|
|
@@ -646,6 +646,48 @@ declare class ClobClient {
|
|
|
646
646
|
matchOrders(taker: SignedOrder, makers: SignedOrder[], opts?: {
|
|
647
647
|
marketOracleVault?: PublicKey;
|
|
648
648
|
}): Promise<TxResult>;
|
|
649
|
+
/**
|
|
650
|
+
* High-level match: caller passes price + quantity + keypair — SDK builds,
|
|
651
|
+
* signs, and submits in one call. No manual amount calculation needed.
|
|
652
|
+
*
|
|
653
|
+
* Amounts are computed from each order's own limit `price` (percentage, e.g. 51 for 51%).
|
|
654
|
+
* NEVER pass averageMatchedPrice — that is an engine output, not an order input.
|
|
655
|
+
*
|
|
656
|
+
* @param taker { keypair, condition, tokenId, side, price, quantity, nonce?, expiry? }
|
|
657
|
+
* @param makers Array of same shape
|
|
658
|
+
* @param decimals Collateral decimals (default 9 for USDS)
|
|
659
|
+
*/
|
|
660
|
+
matchOrdersFromPrice(taker: {
|
|
661
|
+
keypair: {
|
|
662
|
+
publicKey: PublicKey;
|
|
663
|
+
secretKey: Uint8Array;
|
|
664
|
+
};
|
|
665
|
+
condition: PublicKey;
|
|
666
|
+
tokenId: number;
|
|
667
|
+
side: 0 | 1;
|
|
668
|
+
price: number;
|
|
669
|
+
quantity: number;
|
|
670
|
+
nonce?: BN;
|
|
671
|
+
expiry?: BN;
|
|
672
|
+
fee?: BN;
|
|
673
|
+
taker?: PublicKey;
|
|
674
|
+
}, makers: Array<{
|
|
675
|
+
keypair: {
|
|
676
|
+
publicKey: PublicKey;
|
|
677
|
+
secretKey: Uint8Array;
|
|
678
|
+
};
|
|
679
|
+
condition: PublicKey;
|
|
680
|
+
tokenId: number;
|
|
681
|
+
side: 0 | 1;
|
|
682
|
+
price: number;
|
|
683
|
+
quantity: number;
|
|
684
|
+
nonce?: BN;
|
|
685
|
+
expiry?: BN;
|
|
686
|
+
fee?: BN;
|
|
687
|
+
taker?: PublicKey;
|
|
688
|
+
}>, decimals?: number, opts?: {
|
|
689
|
+
marketOracleVault?: PublicKey;
|
|
690
|
+
}): Promise<TxResult>;
|
|
649
691
|
fetchConfig(): Promise<ClobConfig | null>;
|
|
650
692
|
fetchOrderStatus(maker: PublicKey, nonce: anchor.BN): Promise<OrderStatus | null>;
|
|
651
693
|
fetchOrderRecord(maker: PublicKey, nonce: anchor.BN): Promise<{
|
|
@@ -947,6 +989,51 @@ declare function buildOrder(params: {
|
|
|
947
989
|
fee?: BN;
|
|
948
990
|
taker?: PublicKey;
|
|
949
991
|
}): Order;
|
|
992
|
+
/**
|
|
993
|
+
* Compute makerAmount / takerAmount from a limit price and quantity.
|
|
994
|
+
*
|
|
995
|
+
* ALWAYS use the order's own limit price (e.g., 51 for a 51% limit order).
|
|
996
|
+
* NEVER pass `averageMatchedPrice` — that is an output of the matching engine,
|
|
997
|
+
* not an order input. Using avgPrice here causes crossing checks to fail
|
|
998
|
+
* for any maker whose price equals the limit price exactly.
|
|
999
|
+
*
|
|
1000
|
+
* BUY YES (side=0): makerAmount = USDS spent = qty × price/100
|
|
1001
|
+
* takerAmount = YES received = qty
|
|
1002
|
+
* SELL YES (side=1): makerAmount = YES given = qty
|
|
1003
|
+
* takerAmount = USDS received = qty × price/100
|
|
1004
|
+
*
|
|
1005
|
+
* @param side 0 = BUY, 1 = SELL
|
|
1006
|
+
* @param price Limit price in percentage cents (e.g., 51 for 51% = $0.51/token)
|
|
1007
|
+
* @param quantity Whole token count (e.g., 11 for 11 YES tokens)
|
|
1008
|
+
* @param decimals Collateral token decimals (default 9 for USDS)
|
|
1009
|
+
*/
|
|
1010
|
+
declare function orderAmountsFromPrice(side: 0 | 1, price: number, quantity: number, decimals?: number): {
|
|
1011
|
+
makerAmount: BN;
|
|
1012
|
+
takerAmount: BN;
|
|
1013
|
+
};
|
|
1014
|
+
/**
|
|
1015
|
+
* Build a fully-populated Order from human-readable price + quantity.
|
|
1016
|
+
* Amounts are computed using the limit price — never use averageMatchedPrice.
|
|
1017
|
+
*
|
|
1018
|
+
* @param params.side 0 = BUY, 1 = SELL
|
|
1019
|
+
* @param params.price Limit price in percentage (e.g., 51 for 51%)
|
|
1020
|
+
* @param params.quantity Whole token count (e.g., 11 for 11 YES tokens)
|
|
1021
|
+
* @param params.decimals Collateral decimals (default 9 for USDS)
|
|
1022
|
+
*/
|
|
1023
|
+
declare function buildOrderFromPrice(params: {
|
|
1024
|
+
maker: PublicKey;
|
|
1025
|
+
condition: PublicKey;
|
|
1026
|
+
tokenId: number;
|
|
1027
|
+
side: 0 | 1;
|
|
1028
|
+
price: number;
|
|
1029
|
+
quantity: number;
|
|
1030
|
+
decimals?: number;
|
|
1031
|
+
nonce?: BN;
|
|
1032
|
+
expiry?: BN;
|
|
1033
|
+
createdAt?: BN;
|
|
1034
|
+
fee?: BN;
|
|
1035
|
+
taker?: PublicKey;
|
|
1036
|
+
}): Order;
|
|
950
1037
|
/**
|
|
951
1038
|
* Sign an order with a Keypair.
|
|
952
1039
|
* Uses Ed25519 (nacl.sign.detached) over the 178-byte canonical message.
|
|
@@ -1013,4 +1100,4 @@ declare function buildApproveCollateralTx(collateralMint: PublicKey, signer: Pub
|
|
|
1013
1100
|
*/
|
|
1014
1101
|
declare function buildApproveAllOutcomeTokensTx(condition: PublicKey, signer: PublicKey, payer: PublicKey, delegate: PublicKey, programIds: ProgramIds, amount?: BN): Transaction;
|
|
1015
1102
|
|
|
1016
|
-
export { AccountNotFoundError, AdminClient, type AdminConfigInfo, type ClaimRecordInfo, ClobClient, type ClobConfig, type CollateralConfig, type CollateralVault, type Condition, type CreateQuestionParams, CtfClient, type CtfConfig, FEE_DENOMINATOR, FeeManagementClient, HookClient, type HookConfig, IX_SYSVAR, InvalidParamError, MAX_APPROVE_AMOUNT, MarketClient, MarketOracleClient, type MarketOracleInfo, type MatchType, type NetworkConfig, type NetworkName, OracleClient, type OracleConfig, type Order, type OrderStatus, PDA, type Position, PresaleClient, type PresaleInfo, type ProgramIds, type Question, type QuestionFee, type QuestionMarketConfig, type QuestionResult, QuestionStatus, SEEDS, type SignedOrder, type TxResult, UnauthorizedError, type UserBuyRecord, type UserClaimRecord, XMarketError, XMarketSDK, buildApproveAllOutcomeTokensTx, buildApproveCollateralTx, buildBatchedEd25519Instruction, buildOrder, deserializeSignedOrder, detectMatchType, generateContentHash, generateQuestionId, getOrderSignBytes, serializeOrderToBytes, serializeSignedOrder, signOrder, signOrderWithKeypair, verifySignedOrder };
|
|
1103
|
+
export { AccountNotFoundError, AdminClient, type AdminConfigInfo, type ClaimRecordInfo, ClobClient, type ClobConfig, type CollateralConfig, type CollateralVault, type Condition, type CreateQuestionParams, CtfClient, type CtfConfig, FEE_DENOMINATOR, FeeManagementClient, HookClient, type HookConfig, IX_SYSVAR, InvalidParamError, MAX_APPROVE_AMOUNT, MarketClient, MarketOracleClient, type MarketOracleInfo, type MatchType, type NetworkConfig, type NetworkName, OracleClient, type OracleConfig, type Order, type OrderStatus, PDA, type Position, PresaleClient, type PresaleInfo, type ProgramIds, type Question, type QuestionFee, type QuestionMarketConfig, type QuestionResult, QuestionStatus, SEEDS, type SignedOrder, type TxResult, UnauthorizedError, type UserBuyRecord, type UserClaimRecord, XMarketError, XMarketSDK, buildApproveAllOutcomeTokensTx, buildApproveCollateralTx, buildBatchedEd25519Instruction, buildOrder, buildOrderFromPrice, deserializeSignedOrder, detectMatchType, generateContentHash, generateQuestionId, getOrderSignBytes, orderAmountsFromPrice, serializeOrderToBytes, serializeSignedOrder, signOrder, signOrderWithKeypair, verifySignedOrder };
|
package/dist/index.d.ts
CHANGED
|
@@ -596,7 +596,7 @@ declare class ClobClient {
|
|
|
596
596
|
buildMatchComplementaryIxs(takerSigned: SignedOrder, makersSigned: SignedOrder[], collateralMint: PublicKey, feeRecipient: PublicKey, operator: PublicKey, opts?: {
|
|
597
597
|
marketOracleVault?: PublicKey;
|
|
598
598
|
fillAmount?: anchor.BN;
|
|
599
|
-
}): Promise<TransactionInstruction[]>;
|
|
599
|
+
}, useTakerPrice?: boolean): Promise<TransactionInstruction[]>;
|
|
600
600
|
/**
|
|
601
601
|
* COMPLEMENTARY: 1 taker (BUY) + N makers (SELL), same tokenId.
|
|
602
602
|
* Phase 1: register taker + all makers in parallel.
|
|
@@ -646,6 +646,48 @@ declare class ClobClient {
|
|
|
646
646
|
matchOrders(taker: SignedOrder, makers: SignedOrder[], opts?: {
|
|
647
647
|
marketOracleVault?: PublicKey;
|
|
648
648
|
}): Promise<TxResult>;
|
|
649
|
+
/**
|
|
650
|
+
* High-level match: caller passes price + quantity + keypair — SDK builds,
|
|
651
|
+
* signs, and submits in one call. No manual amount calculation needed.
|
|
652
|
+
*
|
|
653
|
+
* Amounts are computed from each order's own limit `price` (percentage, e.g. 51 for 51%).
|
|
654
|
+
* NEVER pass averageMatchedPrice — that is an engine output, not an order input.
|
|
655
|
+
*
|
|
656
|
+
* @param taker { keypair, condition, tokenId, side, price, quantity, nonce?, expiry? }
|
|
657
|
+
* @param makers Array of same shape
|
|
658
|
+
* @param decimals Collateral decimals (default 9 for USDS)
|
|
659
|
+
*/
|
|
660
|
+
matchOrdersFromPrice(taker: {
|
|
661
|
+
keypair: {
|
|
662
|
+
publicKey: PublicKey;
|
|
663
|
+
secretKey: Uint8Array;
|
|
664
|
+
};
|
|
665
|
+
condition: PublicKey;
|
|
666
|
+
tokenId: number;
|
|
667
|
+
side: 0 | 1;
|
|
668
|
+
price: number;
|
|
669
|
+
quantity: number;
|
|
670
|
+
nonce?: BN;
|
|
671
|
+
expiry?: BN;
|
|
672
|
+
fee?: BN;
|
|
673
|
+
taker?: PublicKey;
|
|
674
|
+
}, makers: Array<{
|
|
675
|
+
keypair: {
|
|
676
|
+
publicKey: PublicKey;
|
|
677
|
+
secretKey: Uint8Array;
|
|
678
|
+
};
|
|
679
|
+
condition: PublicKey;
|
|
680
|
+
tokenId: number;
|
|
681
|
+
side: 0 | 1;
|
|
682
|
+
price: number;
|
|
683
|
+
quantity: number;
|
|
684
|
+
nonce?: BN;
|
|
685
|
+
expiry?: BN;
|
|
686
|
+
fee?: BN;
|
|
687
|
+
taker?: PublicKey;
|
|
688
|
+
}>, decimals?: number, opts?: {
|
|
689
|
+
marketOracleVault?: PublicKey;
|
|
690
|
+
}): Promise<TxResult>;
|
|
649
691
|
fetchConfig(): Promise<ClobConfig | null>;
|
|
650
692
|
fetchOrderStatus(maker: PublicKey, nonce: anchor.BN): Promise<OrderStatus | null>;
|
|
651
693
|
fetchOrderRecord(maker: PublicKey, nonce: anchor.BN): Promise<{
|
|
@@ -947,6 +989,51 @@ declare function buildOrder(params: {
|
|
|
947
989
|
fee?: BN;
|
|
948
990
|
taker?: PublicKey;
|
|
949
991
|
}): Order;
|
|
992
|
+
/**
|
|
993
|
+
* Compute makerAmount / takerAmount from a limit price and quantity.
|
|
994
|
+
*
|
|
995
|
+
* ALWAYS use the order's own limit price (e.g., 51 for a 51% limit order).
|
|
996
|
+
* NEVER pass `averageMatchedPrice` — that is an output of the matching engine,
|
|
997
|
+
* not an order input. Using avgPrice here causes crossing checks to fail
|
|
998
|
+
* for any maker whose price equals the limit price exactly.
|
|
999
|
+
*
|
|
1000
|
+
* BUY YES (side=0): makerAmount = USDS spent = qty × price/100
|
|
1001
|
+
* takerAmount = YES received = qty
|
|
1002
|
+
* SELL YES (side=1): makerAmount = YES given = qty
|
|
1003
|
+
* takerAmount = USDS received = qty × price/100
|
|
1004
|
+
*
|
|
1005
|
+
* @param side 0 = BUY, 1 = SELL
|
|
1006
|
+
* @param price Limit price in percentage cents (e.g., 51 for 51% = $0.51/token)
|
|
1007
|
+
* @param quantity Whole token count (e.g., 11 for 11 YES tokens)
|
|
1008
|
+
* @param decimals Collateral token decimals (default 9 for USDS)
|
|
1009
|
+
*/
|
|
1010
|
+
declare function orderAmountsFromPrice(side: 0 | 1, price: number, quantity: number, decimals?: number): {
|
|
1011
|
+
makerAmount: BN;
|
|
1012
|
+
takerAmount: BN;
|
|
1013
|
+
};
|
|
1014
|
+
/**
|
|
1015
|
+
* Build a fully-populated Order from human-readable price + quantity.
|
|
1016
|
+
* Amounts are computed using the limit price — never use averageMatchedPrice.
|
|
1017
|
+
*
|
|
1018
|
+
* @param params.side 0 = BUY, 1 = SELL
|
|
1019
|
+
* @param params.price Limit price in percentage (e.g., 51 for 51%)
|
|
1020
|
+
* @param params.quantity Whole token count (e.g., 11 for 11 YES tokens)
|
|
1021
|
+
* @param params.decimals Collateral decimals (default 9 for USDS)
|
|
1022
|
+
*/
|
|
1023
|
+
declare function buildOrderFromPrice(params: {
|
|
1024
|
+
maker: PublicKey;
|
|
1025
|
+
condition: PublicKey;
|
|
1026
|
+
tokenId: number;
|
|
1027
|
+
side: 0 | 1;
|
|
1028
|
+
price: number;
|
|
1029
|
+
quantity: number;
|
|
1030
|
+
decimals?: number;
|
|
1031
|
+
nonce?: BN;
|
|
1032
|
+
expiry?: BN;
|
|
1033
|
+
createdAt?: BN;
|
|
1034
|
+
fee?: BN;
|
|
1035
|
+
taker?: PublicKey;
|
|
1036
|
+
}): Order;
|
|
950
1037
|
/**
|
|
951
1038
|
* Sign an order with a Keypair.
|
|
952
1039
|
* Uses Ed25519 (nacl.sign.detached) over the 178-byte canonical message.
|
|
@@ -1013,4 +1100,4 @@ declare function buildApproveCollateralTx(collateralMint: PublicKey, signer: Pub
|
|
|
1013
1100
|
*/
|
|
1014
1101
|
declare function buildApproveAllOutcomeTokensTx(condition: PublicKey, signer: PublicKey, payer: PublicKey, delegate: PublicKey, programIds: ProgramIds, amount?: BN): Transaction;
|
|
1015
1102
|
|
|
1016
|
-
export { AccountNotFoundError, AdminClient, type AdminConfigInfo, type ClaimRecordInfo, ClobClient, type ClobConfig, type CollateralConfig, type CollateralVault, type Condition, type CreateQuestionParams, CtfClient, type CtfConfig, FEE_DENOMINATOR, FeeManagementClient, HookClient, type HookConfig, IX_SYSVAR, InvalidParamError, MAX_APPROVE_AMOUNT, MarketClient, MarketOracleClient, type MarketOracleInfo, type MatchType, type NetworkConfig, type NetworkName, OracleClient, type OracleConfig, type Order, type OrderStatus, PDA, type Position, PresaleClient, type PresaleInfo, type ProgramIds, type Question, type QuestionFee, type QuestionMarketConfig, type QuestionResult, QuestionStatus, SEEDS, type SignedOrder, type TxResult, UnauthorizedError, type UserBuyRecord, type UserClaimRecord, XMarketError, XMarketSDK, buildApproveAllOutcomeTokensTx, buildApproveCollateralTx, buildBatchedEd25519Instruction, buildOrder, deserializeSignedOrder, detectMatchType, generateContentHash, generateQuestionId, getOrderSignBytes, serializeOrderToBytes, serializeSignedOrder, signOrder, signOrderWithKeypair, verifySignedOrder };
|
|
1103
|
+
export { AccountNotFoundError, AdminClient, type AdminConfigInfo, type ClaimRecordInfo, ClobClient, type ClobConfig, type CollateralConfig, type CollateralVault, type Condition, type CreateQuestionParams, CtfClient, type CtfConfig, FEE_DENOMINATOR, FeeManagementClient, HookClient, type HookConfig, IX_SYSVAR, InvalidParamError, MAX_APPROVE_AMOUNT, MarketClient, MarketOracleClient, type MarketOracleInfo, type MatchType, type NetworkConfig, type NetworkName, OracleClient, type OracleConfig, type Order, type OrderStatus, PDA, type Position, PresaleClient, type PresaleInfo, type ProgramIds, type Question, type QuestionFee, type QuestionMarketConfig, type QuestionResult, QuestionStatus, SEEDS, type SignedOrder, type TxResult, UnauthorizedError, type UserBuyRecord, type UserClaimRecord, XMarketError, XMarketSDK, buildApproveAllOutcomeTokensTx, buildApproveCollateralTx, buildBatchedEd25519Instruction, buildOrder, buildOrderFromPrice, deserializeSignedOrder, detectMatchType, generateContentHash, generateQuestionId, getOrderSignBytes, orderAmountsFromPrice, serializeOrderToBytes, serializeSignedOrder, signOrder, signOrderWithKeypair, verifySignedOrder };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var anchor5 = require('@coral-xyz/anchor');
|
|
|
4
4
|
var web3_js = require('@solana/web3.js');
|
|
5
5
|
var crypto = require('crypto');
|
|
6
6
|
var splToken = require('@solana/spl-token');
|
|
7
|
-
var
|
|
7
|
+
var BN4 = require('bn.js');
|
|
8
8
|
var nacl = require('tweetnacl');
|
|
9
9
|
|
|
10
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -28,7 +28,7 @@ function _interopNamespace(e) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
var anchor5__namespace = /*#__PURE__*/_interopNamespace(anchor5);
|
|
31
|
-
var
|
|
31
|
+
var BN4__default = /*#__PURE__*/_interopDefault(BN4);
|
|
32
32
|
var nacl__namespace = /*#__PURE__*/_interopNamespace(nacl);
|
|
33
33
|
|
|
34
34
|
// src/sdk.ts
|
|
@@ -1338,6 +1338,108 @@ function buildBatchedEd25519Instruction(orders) {
|
|
|
1338
1338
|
});
|
|
1339
1339
|
}
|
|
1340
1340
|
var IX_SYSVAR = web3_js.SYSVAR_INSTRUCTIONS_PUBKEY;
|
|
1341
|
+
function buildOrder(params) {
|
|
1342
|
+
return {
|
|
1343
|
+
maker: params.maker,
|
|
1344
|
+
condition: params.condition,
|
|
1345
|
+
tokenId: params.tokenId,
|
|
1346
|
+
side: params.side,
|
|
1347
|
+
makerAmount: params.makerAmount,
|
|
1348
|
+
takerAmount: params.takerAmount,
|
|
1349
|
+
nonce: params.nonce ?? new BN4__default.default(Date.now()),
|
|
1350
|
+
expiry: params.expiry ?? new BN4__default.default(0),
|
|
1351
|
+
createdAt: params.createdAt ?? new BN4__default.default(Math.floor(Date.now() / 1e3)),
|
|
1352
|
+
fee: params.fee ?? new BN4__default.default(0),
|
|
1353
|
+
taker: params.taker ?? new web3_js.PublicKey(new Uint8Array(32)),
|
|
1354
|
+
signer: params.maker
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
function orderAmountsFromPrice(side, price, quantity, decimals = 9) {
|
|
1358
|
+
const PRICE_PRECISION = new BN4__default.default(1e6);
|
|
1359
|
+
const DENOM = new BN4__default.default(100).mul(PRICE_PRECISION);
|
|
1360
|
+
const base = new BN4__default.default(10).pow(new BN4__default.default(decimals));
|
|
1361
|
+
const priceScaled = new BN4__default.default(Math.round(price * 1e6));
|
|
1362
|
+
const quantityBase = new BN4__default.default(quantity).mul(base);
|
|
1363
|
+
const collateral = quantityBase.mul(priceScaled).div(DENOM);
|
|
1364
|
+
return side === 0 ? { makerAmount: collateral, takerAmount: quantityBase } : { makerAmount: quantityBase, takerAmount: collateral };
|
|
1365
|
+
}
|
|
1366
|
+
function buildOrderFromPrice(params) {
|
|
1367
|
+
const { makerAmount, takerAmount } = orderAmountsFromPrice(
|
|
1368
|
+
params.side,
|
|
1369
|
+
params.price,
|
|
1370
|
+
params.quantity,
|
|
1371
|
+
params.decimals ?? 9
|
|
1372
|
+
);
|
|
1373
|
+
return buildOrder({ ...params, makerAmount, takerAmount });
|
|
1374
|
+
}
|
|
1375
|
+
function signOrderWithKeypair(order, keypair) {
|
|
1376
|
+
const message = serializeOrderToBytes(order);
|
|
1377
|
+
const signature = nacl__namespace.sign.detached(message, keypair.secretKey);
|
|
1378
|
+
return { order, signature };
|
|
1379
|
+
}
|
|
1380
|
+
function getOrderSignBytes(order) {
|
|
1381
|
+
return serializeOrderToBytes(order);
|
|
1382
|
+
}
|
|
1383
|
+
function serializeSignedOrder(signed) {
|
|
1384
|
+
const orderBytes = serializeOrderToBytes(signed.order);
|
|
1385
|
+
const buf = new Uint8Array(242);
|
|
1386
|
+
buf.set(orderBytes, 0);
|
|
1387
|
+
buf.set(signed.signature, 178);
|
|
1388
|
+
return buf;
|
|
1389
|
+
}
|
|
1390
|
+
function deserializeSignedOrder(bytes) {
|
|
1391
|
+
if (bytes.length !== 242) throw new InvalidParamError("SignedOrder must be 242 bytes");
|
|
1392
|
+
const readPubkey = (offset) => new web3_js.PublicKey(bytes.slice(offset, offset + 32));
|
|
1393
|
+
const readU64 = (offset) => new BN4__default.default(bytes.slice(offset, offset + 8), "le");
|
|
1394
|
+
const readI64 = (offset) => new BN4__default.default(bytes.slice(offset, offset + 8), "le");
|
|
1395
|
+
const order = {
|
|
1396
|
+
maker: readPubkey(0),
|
|
1397
|
+
condition: readPubkey(32),
|
|
1398
|
+
tokenId: bytes[64],
|
|
1399
|
+
side: bytes[65],
|
|
1400
|
+
makerAmount: readU64(66),
|
|
1401
|
+
takerAmount: readU64(74),
|
|
1402
|
+
nonce: readU64(82),
|
|
1403
|
+
expiry: readI64(90),
|
|
1404
|
+
createdAt: readI64(98),
|
|
1405
|
+
fee: readU64(106),
|
|
1406
|
+
taker: readPubkey(114),
|
|
1407
|
+
signer: readPubkey(146)
|
|
1408
|
+
};
|
|
1409
|
+
const signature = bytes.slice(178, 242);
|
|
1410
|
+
return { order, signature };
|
|
1411
|
+
}
|
|
1412
|
+
function verifySignedOrder(signed) {
|
|
1413
|
+
const message = serializeOrderToBytes(signed.order);
|
|
1414
|
+
return nacl__namespace.sign.detached.verify(
|
|
1415
|
+
message,
|
|
1416
|
+
signed.signature,
|
|
1417
|
+
signed.order.signer.toBytes()
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
function detectMatchType(a, b) {
|
|
1421
|
+
const _a = "order" in a ? a.order : a;
|
|
1422
|
+
const _b = "order" in b ? b.order : b;
|
|
1423
|
+
return _detectMatchType(_a, _b);
|
|
1424
|
+
}
|
|
1425
|
+
function _detectMatchType(a, b) {
|
|
1426
|
+
const SIDE_BUY = 0;
|
|
1427
|
+
if (a.tokenId === b.tokenId) {
|
|
1428
|
+
const aBuy2 = a.side === SIDE_BUY;
|
|
1429
|
+
const bBuy2 = b.side === SIDE_BUY;
|
|
1430
|
+
if (aBuy2 !== bBuy2) return "COMPLEMENTARY";
|
|
1431
|
+
throw new InvalidParamError(
|
|
1432
|
+
"Orders with same tokenId must be one BUY and one SELL (COMPLEMENTARY)"
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
const aBuy = a.side === SIDE_BUY;
|
|
1436
|
+
const bBuy = b.side === SIDE_BUY;
|
|
1437
|
+
if (aBuy && bBuy) return "MINT";
|
|
1438
|
+
if (!aBuy && !bBuy) return "MERGE";
|
|
1439
|
+
throw new InvalidParamError(
|
|
1440
|
+
"Orders with different tokenIds must both be BUY (MINT) or both SELL (MERGE)"
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1341
1443
|
|
|
1342
1444
|
// src/programs/clob.ts
|
|
1343
1445
|
var ClobClient = class {
|
|
@@ -1674,7 +1776,7 @@ ${logs.join("\n")}`);
|
|
|
1674
1776
|
* [extraAccountMetaList, hookConfig, hookProgram]
|
|
1675
1777
|
* [feeManagement, fee_config, mkt_override, company_ata, oracle_vault] (when fee > 0)
|
|
1676
1778
|
*/
|
|
1677
|
-
async buildMatchComplementaryIxs(takerSigned, makersSigned, collateralMint, feeRecipient, operator, opts) {
|
|
1779
|
+
async buildMatchComplementaryIxs(takerSigned, makersSigned, collateralMint, feeRecipient, operator, opts, useTakerPrice = false) {
|
|
1678
1780
|
const condition = takerSigned.order.condition;
|
|
1679
1781
|
const tokenId = takerSigned.order.tokenId;
|
|
1680
1782
|
const taker = takerSigned.order.maker;
|
|
@@ -1724,7 +1826,7 @@ ${logs.join("\n")}`);
|
|
|
1724
1826
|
];
|
|
1725
1827
|
}
|
|
1726
1828
|
}
|
|
1727
|
-
const matchIx = await this.program.methods.matchComplementary(takerNonce, fillAmount).accounts({
|
|
1829
|
+
const matchIx = await this.program.methods.matchComplementary(takerNonce, fillAmount, useTakerPrice).accounts({
|
|
1728
1830
|
operator,
|
|
1729
1831
|
payer: this.walletPubkey,
|
|
1730
1832
|
clobConfig: this.configPda(),
|
|
@@ -1799,7 +1901,9 @@ ${logs.join("\n")}`);
|
|
|
1799
1901
|
collateralMint,
|
|
1800
1902
|
feeRecipient,
|
|
1801
1903
|
operatorWallet.publicKey,
|
|
1802
|
-
opts
|
|
1904
|
+
opts,
|
|
1905
|
+
true
|
|
1906
|
+
// useTakerPrice: SELL gets filled at BUY's price (maker's price per doc)
|
|
1803
1907
|
);
|
|
1804
1908
|
allIxs.push(...ixs);
|
|
1805
1909
|
}
|
|
@@ -2068,6 +2172,53 @@ ${logs.join("\n")}`);
|
|
|
2068
2172
|
if (allBuy) return this.matchMintOrders(taker, makers, collateralMint, feeRecipient, operatorWallet, alt);
|
|
2069
2173
|
return this.matchMergeOrders(taker, makers, collateralMint, feeRecipient, operatorWallet, alt, opts);
|
|
2070
2174
|
}
|
|
2175
|
+
/**
|
|
2176
|
+
* High-level match: caller passes price + quantity + keypair — SDK builds,
|
|
2177
|
+
* signs, and submits in one call. No manual amount calculation needed.
|
|
2178
|
+
*
|
|
2179
|
+
* Amounts are computed from each order's own limit `price` (percentage, e.g. 51 for 51%).
|
|
2180
|
+
* NEVER pass averageMatchedPrice — that is an engine output, not an order input.
|
|
2181
|
+
*
|
|
2182
|
+
* @param taker { keypair, condition, tokenId, side, price, quantity, nonce?, expiry? }
|
|
2183
|
+
* @param makers Array of same shape
|
|
2184
|
+
* @param decimals Collateral decimals (default 9 for USDS)
|
|
2185
|
+
*/
|
|
2186
|
+
async matchOrdersFromPrice(taker, makers, decimals = 9, opts) {
|
|
2187
|
+
const nacl2 = await import('tweetnacl');
|
|
2188
|
+
const buildSigned = (p) => {
|
|
2189
|
+
const order = buildOrderFromPrice({
|
|
2190
|
+
maker: p.keypair.publicKey,
|
|
2191
|
+
condition: p.condition,
|
|
2192
|
+
tokenId: p.tokenId,
|
|
2193
|
+
side: p.side,
|
|
2194
|
+
price: p.price,
|
|
2195
|
+
quantity: p.quantity,
|
|
2196
|
+
decimals,
|
|
2197
|
+
nonce: p.nonce,
|
|
2198
|
+
expiry: p.expiry,
|
|
2199
|
+
fee: p.fee,
|
|
2200
|
+
taker: p.taker
|
|
2201
|
+
});
|
|
2202
|
+
const msg = serializeOrderToBytes(order);
|
|
2203
|
+
const sig = nacl2.default.sign.detached(msg, p.keypair.secretKey);
|
|
2204
|
+
return { order, signature: sig };
|
|
2205
|
+
};
|
|
2206
|
+
const takerSigned = buildSigned(taker);
|
|
2207
|
+
const sortedMakers = [...makers].sort((a, b) => {
|
|
2208
|
+
const sameToken = a.tokenId === taker.tokenId && b.tokenId === taker.tokenId;
|
|
2209
|
+
const isDirectBuy = taker.side === 0 && sameToken;
|
|
2210
|
+
const isDirectSell = taker.side === 1 && sameToken;
|
|
2211
|
+
const isMint = taker.side === 0 && taker.tokenId === 1;
|
|
2212
|
+
const isMerge = taker.side === 1 && taker.tokenId === 1;
|
|
2213
|
+
if (isDirectBuy) return a.price - b.price;
|
|
2214
|
+
if (isDirectSell) return b.price - a.price;
|
|
2215
|
+
if (isMint) return b.price - a.price;
|
|
2216
|
+
if (isMerge) return a.price - b.price;
|
|
2217
|
+
return 0;
|
|
2218
|
+
});
|
|
2219
|
+
const makersSigned = sortedMakers.map(buildSigned);
|
|
2220
|
+
return this.matchOrders(takerSigned, makersSigned, opts);
|
|
2221
|
+
}
|
|
2071
2222
|
// ─── Queries ─────────────────────────────────────────────────────────────────
|
|
2072
2223
|
async fetchConfig() {
|
|
2073
2224
|
try {
|
|
@@ -8707,6 +8858,10 @@ var clob_exchange_default = {
|
|
|
8707
8858
|
{
|
|
8708
8859
|
name: "fill_amount",
|
|
8709
8860
|
type: "u64"
|
|
8861
|
+
},
|
|
8862
|
+
{
|
|
8863
|
+
name: "use_taker_price",
|
|
8864
|
+
type: "bool"
|
|
8710
8865
|
}
|
|
8711
8866
|
]
|
|
8712
8867
|
},
|
|
@@ -14850,91 +15005,7 @@ var XMarketSDK = class {
|
|
|
14850
15005
|
return this._admin;
|
|
14851
15006
|
}
|
|
14852
15007
|
};
|
|
14853
|
-
|
|
14854
|
-
return {
|
|
14855
|
-
maker: params.maker,
|
|
14856
|
-
condition: params.condition,
|
|
14857
|
-
tokenId: params.tokenId,
|
|
14858
|
-
side: params.side,
|
|
14859
|
-
makerAmount: params.makerAmount,
|
|
14860
|
-
takerAmount: params.takerAmount,
|
|
14861
|
-
nonce: params.nonce ?? new BN5__default.default(Date.now()),
|
|
14862
|
-
expiry: params.expiry ?? new BN5__default.default(0),
|
|
14863
|
-
createdAt: params.createdAt ?? new BN5__default.default(Math.floor(Date.now() / 1e3)),
|
|
14864
|
-
fee: params.fee ?? new BN5__default.default(0),
|
|
14865
|
-
taker: params.taker ?? new web3_js.PublicKey(new Uint8Array(32)),
|
|
14866
|
-
signer: params.maker
|
|
14867
|
-
};
|
|
14868
|
-
}
|
|
14869
|
-
function signOrderWithKeypair(order, keypair) {
|
|
14870
|
-
const message = serializeOrderToBytes(order);
|
|
14871
|
-
const signature = nacl__namespace.sign.detached(message, keypair.secretKey);
|
|
14872
|
-
return { order, signature };
|
|
14873
|
-
}
|
|
14874
|
-
function getOrderSignBytes(order) {
|
|
14875
|
-
return serializeOrderToBytes(order);
|
|
14876
|
-
}
|
|
14877
|
-
function serializeSignedOrder(signed) {
|
|
14878
|
-
const orderBytes = serializeOrderToBytes(signed.order);
|
|
14879
|
-
const buf = new Uint8Array(242);
|
|
14880
|
-
buf.set(orderBytes, 0);
|
|
14881
|
-
buf.set(signed.signature, 178);
|
|
14882
|
-
return buf;
|
|
14883
|
-
}
|
|
14884
|
-
function deserializeSignedOrder(bytes) {
|
|
14885
|
-
if (bytes.length !== 242) throw new InvalidParamError("SignedOrder must be 242 bytes");
|
|
14886
|
-
const readPubkey = (offset) => new web3_js.PublicKey(bytes.slice(offset, offset + 32));
|
|
14887
|
-
const readU64 = (offset) => new BN5__default.default(bytes.slice(offset, offset + 8), "le");
|
|
14888
|
-
const readI64 = (offset) => new BN5__default.default(bytes.slice(offset, offset + 8), "le");
|
|
14889
|
-
const order = {
|
|
14890
|
-
maker: readPubkey(0),
|
|
14891
|
-
condition: readPubkey(32),
|
|
14892
|
-
tokenId: bytes[64],
|
|
14893
|
-
side: bytes[65],
|
|
14894
|
-
makerAmount: readU64(66),
|
|
14895
|
-
takerAmount: readU64(74),
|
|
14896
|
-
nonce: readU64(82),
|
|
14897
|
-
expiry: readI64(90),
|
|
14898
|
-
createdAt: readI64(98),
|
|
14899
|
-
fee: readU64(106),
|
|
14900
|
-
taker: readPubkey(114),
|
|
14901
|
-
signer: readPubkey(146)
|
|
14902
|
-
};
|
|
14903
|
-
const signature = bytes.slice(178, 242);
|
|
14904
|
-
return { order, signature };
|
|
14905
|
-
}
|
|
14906
|
-
function verifySignedOrder(signed) {
|
|
14907
|
-
const message = serializeOrderToBytes(signed.order);
|
|
14908
|
-
return nacl__namespace.sign.detached.verify(
|
|
14909
|
-
message,
|
|
14910
|
-
signed.signature,
|
|
14911
|
-
signed.order.signer.toBytes()
|
|
14912
|
-
);
|
|
14913
|
-
}
|
|
14914
|
-
function detectMatchType(a, b) {
|
|
14915
|
-
const _a = "order" in a ? a.order : a;
|
|
14916
|
-
const _b = "order" in b ? b.order : b;
|
|
14917
|
-
return _detectMatchType(_a, _b);
|
|
14918
|
-
}
|
|
14919
|
-
function _detectMatchType(a, b) {
|
|
14920
|
-
const SIDE_BUY = 0;
|
|
14921
|
-
if (a.tokenId === b.tokenId) {
|
|
14922
|
-
const aBuy2 = a.side === SIDE_BUY;
|
|
14923
|
-
const bBuy2 = b.side === SIDE_BUY;
|
|
14924
|
-
if (aBuy2 !== bBuy2) return "COMPLEMENTARY";
|
|
14925
|
-
throw new InvalidParamError(
|
|
14926
|
-
"Orders with same tokenId must be one BUY and one SELL (COMPLEMENTARY)"
|
|
14927
|
-
);
|
|
14928
|
-
}
|
|
14929
|
-
const aBuy = a.side === SIDE_BUY;
|
|
14930
|
-
const bBuy = b.side === SIDE_BUY;
|
|
14931
|
-
if (aBuy && bBuy) return "MINT";
|
|
14932
|
-
if (!aBuy && !bBuy) return "MERGE";
|
|
14933
|
-
throw new InvalidParamError(
|
|
14934
|
-
"Orders with different tokenIds must both be BUY (MINT) or both SELL (MERGE)"
|
|
14935
|
-
);
|
|
14936
|
-
}
|
|
14937
|
-
var MAX_APPROVE_AMOUNT = new BN5__default.default("18446744073709551615");
|
|
15008
|
+
var MAX_APPROVE_AMOUNT = new BN4__default.default("18446744073709551615");
|
|
14938
15009
|
function buildApproveCollateralTx(collateralMint, signer, payer, delegate, amount = MAX_APPROVE_AMOUNT) {
|
|
14939
15010
|
const ownerAta = splToken.getAssociatedTokenAddressSync(collateralMint, signer, false, splToken.TOKEN_PROGRAM_ID);
|
|
14940
15011
|
const approveIx = splToken.createApproveInstruction(
|
|
@@ -15002,11 +15073,13 @@ exports.buildApproveAllOutcomeTokensTx = buildApproveAllOutcomeTokensTx;
|
|
|
15002
15073
|
exports.buildApproveCollateralTx = buildApproveCollateralTx;
|
|
15003
15074
|
exports.buildBatchedEd25519Instruction = buildBatchedEd25519Instruction;
|
|
15004
15075
|
exports.buildOrder = buildOrder;
|
|
15076
|
+
exports.buildOrderFromPrice = buildOrderFromPrice;
|
|
15005
15077
|
exports.deserializeSignedOrder = deserializeSignedOrder;
|
|
15006
15078
|
exports.detectMatchType = detectMatchType;
|
|
15007
15079
|
exports.generateContentHash = generateContentHash;
|
|
15008
15080
|
exports.generateQuestionId = generateQuestionId;
|
|
15009
15081
|
exports.getOrderSignBytes = getOrderSignBytes;
|
|
15082
|
+
exports.orderAmountsFromPrice = orderAmountsFromPrice;
|
|
15010
15083
|
exports.serializeOrderToBytes = serializeOrderToBytes;
|
|
15011
15084
|
exports.serializeSignedOrder = serializeSignedOrder;
|
|
15012
15085
|
exports.signOrder = signOrder;
|