@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 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 BN5 = require('bn.js');
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 BN5__default = /*#__PURE__*/_interopDefault(BN5);
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
- function buildOrder(params) {
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;