@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.mjs CHANGED
@@ -2,7 +2,7 @@ import * as anchor5 from '@coral-xyz/anchor';
2
2
  import { PublicKey, SYSVAR_INSTRUCTIONS_PUBKEY, SystemProgram, SYSVAR_RENT_PUBKEY, ComputeBudgetProgram, Transaction, TransactionInstruction, Ed25519Program, AddressLookupTableProgram, TransactionMessage, VersionedTransaction, Connection } from '@solana/web3.js';
3
3
  import { createHash } from 'crypto';
4
4
  import { TOKEN_2022_PROGRAM_ID, getAssociatedTokenAddressSync, ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, createAssociatedTokenAccountIdempotentInstruction, createApproveInstruction } from '@solana/spl-token';
5
- import BN5 from 'bn.js';
5
+ import BN4 from 'bn.js';
6
6
  import * as nacl from 'tweetnacl';
7
7
 
8
8
  // src/sdk.ts
@@ -1312,6 +1312,108 @@ function buildBatchedEd25519Instruction(orders) {
1312
1312
  });
1313
1313
  }
1314
1314
  var IX_SYSVAR = SYSVAR_INSTRUCTIONS_PUBKEY;
1315
+ function buildOrder(params) {
1316
+ return {
1317
+ maker: params.maker,
1318
+ condition: params.condition,
1319
+ tokenId: params.tokenId,
1320
+ side: params.side,
1321
+ makerAmount: params.makerAmount,
1322
+ takerAmount: params.takerAmount,
1323
+ nonce: params.nonce ?? new BN4(Date.now()),
1324
+ expiry: params.expiry ?? new BN4(0),
1325
+ createdAt: params.createdAt ?? new BN4(Math.floor(Date.now() / 1e3)),
1326
+ fee: params.fee ?? new BN4(0),
1327
+ taker: params.taker ?? new PublicKey(new Uint8Array(32)),
1328
+ signer: params.maker
1329
+ };
1330
+ }
1331
+ function orderAmountsFromPrice(side, price, quantity, decimals = 9) {
1332
+ const PRICE_PRECISION = new BN4(1e6);
1333
+ const DENOM = new BN4(100).mul(PRICE_PRECISION);
1334
+ const base = new BN4(10).pow(new BN4(decimals));
1335
+ const priceScaled = new BN4(Math.round(price * 1e6));
1336
+ const quantityBase = new BN4(quantity).mul(base);
1337
+ const collateral = quantityBase.mul(priceScaled).div(DENOM);
1338
+ return side === 0 ? { makerAmount: collateral, takerAmount: quantityBase } : { makerAmount: quantityBase, takerAmount: collateral };
1339
+ }
1340
+ function buildOrderFromPrice(params) {
1341
+ const { makerAmount, takerAmount } = orderAmountsFromPrice(
1342
+ params.side,
1343
+ params.price,
1344
+ params.quantity,
1345
+ params.decimals ?? 9
1346
+ );
1347
+ return buildOrder({ ...params, makerAmount, takerAmount });
1348
+ }
1349
+ function signOrderWithKeypair(order, keypair) {
1350
+ const message = serializeOrderToBytes(order);
1351
+ const signature = nacl.sign.detached(message, keypair.secretKey);
1352
+ return { order, signature };
1353
+ }
1354
+ function getOrderSignBytes(order) {
1355
+ return serializeOrderToBytes(order);
1356
+ }
1357
+ function serializeSignedOrder(signed) {
1358
+ const orderBytes = serializeOrderToBytes(signed.order);
1359
+ const buf = new Uint8Array(242);
1360
+ buf.set(orderBytes, 0);
1361
+ buf.set(signed.signature, 178);
1362
+ return buf;
1363
+ }
1364
+ function deserializeSignedOrder(bytes) {
1365
+ if (bytes.length !== 242) throw new InvalidParamError("SignedOrder must be 242 bytes");
1366
+ const readPubkey = (offset) => new PublicKey(bytes.slice(offset, offset + 32));
1367
+ const readU64 = (offset) => new BN4(bytes.slice(offset, offset + 8), "le");
1368
+ const readI64 = (offset) => new BN4(bytes.slice(offset, offset + 8), "le");
1369
+ const order = {
1370
+ maker: readPubkey(0),
1371
+ condition: readPubkey(32),
1372
+ tokenId: bytes[64],
1373
+ side: bytes[65],
1374
+ makerAmount: readU64(66),
1375
+ takerAmount: readU64(74),
1376
+ nonce: readU64(82),
1377
+ expiry: readI64(90),
1378
+ createdAt: readI64(98),
1379
+ fee: readU64(106),
1380
+ taker: readPubkey(114),
1381
+ signer: readPubkey(146)
1382
+ };
1383
+ const signature = bytes.slice(178, 242);
1384
+ return { order, signature };
1385
+ }
1386
+ function verifySignedOrder(signed) {
1387
+ const message = serializeOrderToBytes(signed.order);
1388
+ return nacl.sign.detached.verify(
1389
+ message,
1390
+ signed.signature,
1391
+ signed.order.signer.toBytes()
1392
+ );
1393
+ }
1394
+ function detectMatchType(a, b) {
1395
+ const _a = "order" in a ? a.order : a;
1396
+ const _b = "order" in b ? b.order : b;
1397
+ return _detectMatchType(_a, _b);
1398
+ }
1399
+ function _detectMatchType(a, b) {
1400
+ const SIDE_BUY = 0;
1401
+ if (a.tokenId === b.tokenId) {
1402
+ const aBuy2 = a.side === SIDE_BUY;
1403
+ const bBuy2 = b.side === SIDE_BUY;
1404
+ if (aBuy2 !== bBuy2) return "COMPLEMENTARY";
1405
+ throw new InvalidParamError(
1406
+ "Orders with same tokenId must be one BUY and one SELL (COMPLEMENTARY)"
1407
+ );
1408
+ }
1409
+ const aBuy = a.side === SIDE_BUY;
1410
+ const bBuy = b.side === SIDE_BUY;
1411
+ if (aBuy && bBuy) return "MINT";
1412
+ if (!aBuy && !bBuy) return "MERGE";
1413
+ throw new InvalidParamError(
1414
+ "Orders with different tokenIds must both be BUY (MINT) or both SELL (MERGE)"
1415
+ );
1416
+ }
1315
1417
 
1316
1418
  // src/programs/clob.ts
1317
1419
  var ClobClient = class {
@@ -1648,7 +1750,7 @@ ${logs.join("\n")}`);
1648
1750
  * [extraAccountMetaList, hookConfig, hookProgram]
1649
1751
  * [feeManagement, fee_config, mkt_override, company_ata, oracle_vault] (when fee > 0)
1650
1752
  */
1651
- async buildMatchComplementaryIxs(takerSigned, makersSigned, collateralMint, feeRecipient, operator, opts) {
1753
+ async buildMatchComplementaryIxs(takerSigned, makersSigned, collateralMint, feeRecipient, operator, opts, useTakerPrice = false) {
1652
1754
  const condition = takerSigned.order.condition;
1653
1755
  const tokenId = takerSigned.order.tokenId;
1654
1756
  const taker = takerSigned.order.maker;
@@ -1698,7 +1800,7 @@ ${logs.join("\n")}`);
1698
1800
  ];
1699
1801
  }
1700
1802
  }
1701
- const matchIx = await this.program.methods.matchComplementary(takerNonce, fillAmount).accounts({
1803
+ const matchIx = await this.program.methods.matchComplementary(takerNonce, fillAmount, useTakerPrice).accounts({
1702
1804
  operator,
1703
1805
  payer: this.walletPubkey,
1704
1806
  clobConfig: this.configPda(),
@@ -1773,7 +1875,9 @@ ${logs.join("\n")}`);
1773
1875
  collateralMint,
1774
1876
  feeRecipient,
1775
1877
  operatorWallet.publicKey,
1776
- opts
1878
+ opts,
1879
+ true
1880
+ // useTakerPrice: SELL gets filled at BUY's price (maker's price per doc)
1777
1881
  );
1778
1882
  allIxs.push(...ixs);
1779
1883
  }
@@ -2042,6 +2146,53 @@ ${logs.join("\n")}`);
2042
2146
  if (allBuy) return this.matchMintOrders(taker, makers, collateralMint, feeRecipient, operatorWallet, alt);
2043
2147
  return this.matchMergeOrders(taker, makers, collateralMint, feeRecipient, operatorWallet, alt, opts);
2044
2148
  }
2149
+ /**
2150
+ * High-level match: caller passes price + quantity + keypair — SDK builds,
2151
+ * signs, and submits in one call. No manual amount calculation needed.
2152
+ *
2153
+ * Amounts are computed from each order's own limit `price` (percentage, e.g. 51 for 51%).
2154
+ * NEVER pass averageMatchedPrice — that is an engine output, not an order input.
2155
+ *
2156
+ * @param taker { keypair, condition, tokenId, side, price, quantity, nonce?, expiry? }
2157
+ * @param makers Array of same shape
2158
+ * @param decimals Collateral decimals (default 9 for USDS)
2159
+ */
2160
+ async matchOrdersFromPrice(taker, makers, decimals = 9, opts) {
2161
+ const nacl2 = await import('tweetnacl');
2162
+ const buildSigned = (p) => {
2163
+ const order = buildOrderFromPrice({
2164
+ maker: p.keypair.publicKey,
2165
+ condition: p.condition,
2166
+ tokenId: p.tokenId,
2167
+ side: p.side,
2168
+ price: p.price,
2169
+ quantity: p.quantity,
2170
+ decimals,
2171
+ nonce: p.nonce,
2172
+ expiry: p.expiry,
2173
+ fee: p.fee,
2174
+ taker: p.taker
2175
+ });
2176
+ const msg = serializeOrderToBytes(order);
2177
+ const sig = nacl2.default.sign.detached(msg, p.keypair.secretKey);
2178
+ return { order, signature: sig };
2179
+ };
2180
+ const takerSigned = buildSigned(taker);
2181
+ const sortedMakers = [...makers].sort((a, b) => {
2182
+ const sameToken = a.tokenId === taker.tokenId && b.tokenId === taker.tokenId;
2183
+ const isDirectBuy = taker.side === 0 && sameToken;
2184
+ const isDirectSell = taker.side === 1 && sameToken;
2185
+ const isMint = taker.side === 0 && taker.tokenId === 1;
2186
+ const isMerge = taker.side === 1 && taker.tokenId === 1;
2187
+ if (isDirectBuy) return a.price - b.price;
2188
+ if (isDirectSell) return b.price - a.price;
2189
+ if (isMint) return b.price - a.price;
2190
+ if (isMerge) return a.price - b.price;
2191
+ return 0;
2192
+ });
2193
+ const makersSigned = sortedMakers.map(buildSigned);
2194
+ return this.matchOrders(takerSigned, makersSigned, opts);
2195
+ }
2045
2196
  // ─── Queries ─────────────────────────────────────────────────────────────────
2046
2197
  async fetchConfig() {
2047
2198
  try {
@@ -8681,6 +8832,10 @@ var clob_exchange_default = {
8681
8832
  {
8682
8833
  name: "fill_amount",
8683
8834
  type: "u64"
8835
+ },
8836
+ {
8837
+ name: "use_taker_price",
8838
+ type: "bool"
8684
8839
  }
8685
8840
  ]
8686
8841
  },
@@ -14824,91 +14979,7 @@ var XMarketSDK = class {
14824
14979
  return this._admin;
14825
14980
  }
14826
14981
  };
14827
- function buildOrder(params) {
14828
- return {
14829
- maker: params.maker,
14830
- condition: params.condition,
14831
- tokenId: params.tokenId,
14832
- side: params.side,
14833
- makerAmount: params.makerAmount,
14834
- takerAmount: params.takerAmount,
14835
- nonce: params.nonce ?? new BN5(Date.now()),
14836
- expiry: params.expiry ?? new BN5(0),
14837
- createdAt: params.createdAt ?? new BN5(Math.floor(Date.now() / 1e3)),
14838
- fee: params.fee ?? new BN5(0),
14839
- taker: params.taker ?? new PublicKey(new Uint8Array(32)),
14840
- signer: params.maker
14841
- };
14842
- }
14843
- function signOrderWithKeypair(order, keypair) {
14844
- const message = serializeOrderToBytes(order);
14845
- const signature = nacl.sign.detached(message, keypair.secretKey);
14846
- return { order, signature };
14847
- }
14848
- function getOrderSignBytes(order) {
14849
- return serializeOrderToBytes(order);
14850
- }
14851
- function serializeSignedOrder(signed) {
14852
- const orderBytes = serializeOrderToBytes(signed.order);
14853
- const buf = new Uint8Array(242);
14854
- buf.set(orderBytes, 0);
14855
- buf.set(signed.signature, 178);
14856
- return buf;
14857
- }
14858
- function deserializeSignedOrder(bytes) {
14859
- if (bytes.length !== 242) throw new InvalidParamError("SignedOrder must be 242 bytes");
14860
- const readPubkey = (offset) => new PublicKey(bytes.slice(offset, offset + 32));
14861
- const readU64 = (offset) => new BN5(bytes.slice(offset, offset + 8), "le");
14862
- const readI64 = (offset) => new BN5(bytes.slice(offset, offset + 8), "le");
14863
- const order = {
14864
- maker: readPubkey(0),
14865
- condition: readPubkey(32),
14866
- tokenId: bytes[64],
14867
- side: bytes[65],
14868
- makerAmount: readU64(66),
14869
- takerAmount: readU64(74),
14870
- nonce: readU64(82),
14871
- expiry: readI64(90),
14872
- createdAt: readI64(98),
14873
- fee: readU64(106),
14874
- taker: readPubkey(114),
14875
- signer: readPubkey(146)
14876
- };
14877
- const signature = bytes.slice(178, 242);
14878
- return { order, signature };
14879
- }
14880
- function verifySignedOrder(signed) {
14881
- const message = serializeOrderToBytes(signed.order);
14882
- return nacl.sign.detached.verify(
14883
- message,
14884
- signed.signature,
14885
- signed.order.signer.toBytes()
14886
- );
14887
- }
14888
- function detectMatchType(a, b) {
14889
- const _a = "order" in a ? a.order : a;
14890
- const _b = "order" in b ? b.order : b;
14891
- return _detectMatchType(_a, _b);
14892
- }
14893
- function _detectMatchType(a, b) {
14894
- const SIDE_BUY = 0;
14895
- if (a.tokenId === b.tokenId) {
14896
- const aBuy2 = a.side === SIDE_BUY;
14897
- const bBuy2 = b.side === SIDE_BUY;
14898
- if (aBuy2 !== bBuy2) return "COMPLEMENTARY";
14899
- throw new InvalidParamError(
14900
- "Orders with same tokenId must be one BUY and one SELL (COMPLEMENTARY)"
14901
- );
14902
- }
14903
- const aBuy = a.side === SIDE_BUY;
14904
- const bBuy = b.side === SIDE_BUY;
14905
- if (aBuy && bBuy) return "MINT";
14906
- if (!aBuy && !bBuy) return "MERGE";
14907
- throw new InvalidParamError(
14908
- "Orders with different tokenIds must both be BUY (MINT) or both SELL (MERGE)"
14909
- );
14910
- }
14911
- var MAX_APPROVE_AMOUNT = new BN5("18446744073709551615");
14982
+ var MAX_APPROVE_AMOUNT = new BN4("18446744073709551615");
14912
14983
  function buildApproveCollateralTx(collateralMint, signer, payer, delegate, amount = MAX_APPROVE_AMOUNT) {
14913
14984
  const ownerAta = getAssociatedTokenAddressSync(collateralMint, signer, false, TOKEN_PROGRAM_ID);
14914
14985
  const approveIx = createApproveInstruction(
@@ -14952,6 +15023,6 @@ function buildApproveAllOutcomeTokensTx(condition, signer, payer, delegate, prog
14952
15023
  return tx;
14953
15024
  }
14954
15025
 
14955
- export { AccountNotFoundError, AdminClient, ClobClient, CtfClient, FEE_DENOMINATOR, FeeManagementClient, HookClient, IX_SYSVAR, InvalidParamError, MAX_APPROVE_AMOUNT, MarketClient, MarketOracleClient, OracleClient, PDA, PresaleClient, QuestionStatus, SEEDS, UnauthorizedError, XMarketError, XMarketSDK, buildApproveAllOutcomeTokensTx, buildApproveCollateralTx, buildBatchedEd25519Instruction, buildOrder, deserializeSignedOrder, detectMatchType, generateContentHash, generateQuestionId, getOrderSignBytes, serializeOrderToBytes, serializeSignedOrder, signOrder, signOrderWithKeypair, verifySignedOrder };
15026
+ export { AccountNotFoundError, AdminClient, ClobClient, CtfClient, FEE_DENOMINATOR, FeeManagementClient, HookClient, IX_SYSVAR, InvalidParamError, MAX_APPROVE_AMOUNT, MarketClient, MarketOracleClient, OracleClient, PDA, PresaleClient, QuestionStatus, SEEDS, UnauthorizedError, XMarketError, XMarketSDK, buildApproveAllOutcomeTokensTx, buildApproveCollateralTx, buildBatchedEd25519Instruction, buildOrder, buildOrderFromPrice, deserializeSignedOrder, detectMatchType, generateContentHash, generateQuestionId, getOrderSignBytes, orderAmountsFromPrice, serializeOrderToBytes, serializeSignedOrder, signOrder, signOrderWithKeypair, verifySignedOrder };
14956
15027
  //# sourceMappingURL=index.mjs.map
14957
15028
  //# sourceMappingURL=index.mjs.map