@theliem/xmarket-sdk 3.10.0 → 3.12.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
@@ -1889,11 +1889,8 @@ ${logs.join("\n")}`);
1889
1889
  * remaining_accounts per NO maker (5):
1890
1890
  * [order_record, buyer_no_token, buyer_no_collateral, buyer_no_position, no_order_status]
1891
1891
  */
1892
- async matchMintOrders(yesSigned, noMakers, collateralMint, _feeRecipient, operatorWallet, lookupTable) {
1893
- await Promise.all([
1894
- this.registerOrderIfNeeded(yesSigned),
1895
- ...noMakers.map((m) => this.registerOrderIfNeeded(m))
1896
- ]);
1892
+ /** Build the match_mint_orders instruction (no signing, no sending). */
1893
+ async _buildMintIx(yesSigned, noMakers, collateralMint, operator, payer) {
1897
1894
  const condition = yesSigned.order.condition;
1898
1895
  const taker = yesSigned.order.maker;
1899
1896
  const takerNonce = yesSigned.order.nonce;
@@ -1941,9 +1938,9 @@ ${logs.join("\n")}`);
1941
1938
  { pubkey: hookConfig, isSigner: false, isWritable: false },
1942
1939
  { pubkey: hookProgram, isSigner: false, isWritable: false }
1943
1940
  );
1944
- const matchIx = await this.program.methods.matchMintOrders(takerNonce, fillAmount, true).accounts({
1945
- operator: operatorWallet.publicKey,
1946
- payer: this.walletPubkey,
1941
+ return this.program.methods.matchMintOrders(takerNonce, fillAmount, true).accounts({
1942
+ operator,
1943
+ payer,
1947
1944
  clobConfig,
1948
1945
  condition,
1949
1946
  taker,
@@ -1970,6 +1967,19 @@ ${logs.join("\n")}`);
1970
1967
  associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
1971
1968
  systemProgram: SystemProgram.programId
1972
1969
  }).remainingAccounts(remainingAccounts).instruction();
1970
+ }
1971
+ async matchMintOrders(yesSigned, noMakers, collateralMint, _feeRecipient, operatorWallet, lookupTable) {
1972
+ await Promise.all([
1973
+ this.registerOrderIfNeeded(yesSigned),
1974
+ ...noMakers.map((m) => this.registerOrderIfNeeded(m))
1975
+ ]);
1976
+ const condition = yesSigned.order.condition;
1977
+ const clobConfig = this.configPda();
1978
+ const [yesMint] = PDA.yesMint(condition, this.programIds);
1979
+ const [noMint] = PDA.noMint(condition, this.programIds);
1980
+ const clobYesAta = getAssociatedTokenAddressSync(yesMint, clobConfig, true, TOKEN_2022_PROGRAM_ID);
1981
+ const clobNoAta = getAssociatedTokenAddressSync(noMint, clobConfig, true, TOKEN_2022_PROGRAM_ID);
1982
+ const matchIx = await this._buildMintIx(yesSigned, noMakers, collateralMint, operatorWallet.publicKey, this.walletPubkey);
1973
1983
  await this._ensureClobOutcomeAtas(yesMint, noMint, clobConfig, clobYesAta, clobNoAta);
1974
1984
  const sig = await this.sendMatchTx([matchIx], lookupTable, operatorWallet);
1975
1985
  return { signature: sig };
@@ -1983,11 +1993,8 @@ ${logs.join("\n")}`);
1983
1993
  * [order_record, seller_no_token, seller_no_collateral, seller_no_position, no_order_status]
1984
1994
  * After all makers, optional 5 fee accounts.
1985
1995
  */
1986
- async matchMergeOrders(yesSigned, noMakers, collateralMint, feeRecipient, operatorWallet, lookupTable, opts) {
1987
- await Promise.all([
1988
- this.registerOrderIfNeeded(yesSigned),
1989
- ...noMakers.map((m) => this.registerOrderIfNeeded(m))
1990
- ]);
1996
+ /** Build the match_merge_orders instruction (no signing, no sending). */
1997
+ async _buildMergeIx(yesSigned, noMakers, collateralMint, operator, payer, opts) {
1991
1998
  const condition = yesSigned.order.condition;
1992
1999
  const sellerYes = yesSigned.order.maker;
1993
2000
  const takerNonce = yesSigned.order.nonce;
@@ -2040,7 +2047,7 @@ ${logs.join("\n")}`);
2040
2047
  const feeOverridePda = PDA.marketFeeOverride(condition, this.programIds)[0];
2041
2048
  const feeOverrideExists = await this.provider.connection.getAccountInfo(feeOverridePda);
2042
2049
  if (feeOverrideExists) {
2043
- const oracleVault = opts?.marketOracleVault ?? this.walletPubkey;
2050
+ const oracleVault = opts?.marketOracleVault ?? payer;
2044
2051
  remainingAccounts.push(
2045
2052
  { pubkey: this.programIds.feeManagement, isSigner: false, isWritable: false },
2046
2053
  { pubkey: PDA.feeConfig(this.feeConfigOwner, this.programIds)[0], isSigner: false, isWritable: false },
@@ -2051,9 +2058,9 @@ ${logs.join("\n")}`);
2051
2058
  }
2052
2059
  }
2053
2060
  }
2054
- const matchIx = await this.program.methods.matchMergeOrders(takerNonce, fillAmount, true).accounts({
2055
- operator: operatorWallet.publicKey,
2056
- payer: this.walletPubkey,
2061
+ return this.program.methods.matchMergeOrders(takerNonce, fillAmount, true).accounts({
2062
+ operator,
2063
+ payer,
2057
2064
  clobConfig,
2058
2065
  condition,
2059
2066
  taker: sellerYes,
@@ -2079,6 +2086,19 @@ ${logs.join("\n")}`);
2079
2086
  associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
2080
2087
  systemProgram: SystemProgram.programId
2081
2088
  }).remainingAccounts(remainingAccounts).instruction();
2089
+ }
2090
+ async matchMergeOrders(yesSigned, noMakers, collateralMint, _feeRecipient, operatorWallet, lookupTable, opts) {
2091
+ await Promise.all([
2092
+ this.registerOrderIfNeeded(yesSigned),
2093
+ ...noMakers.map((m) => this.registerOrderIfNeeded(m))
2094
+ ]);
2095
+ const condition = yesSigned.order.condition;
2096
+ const clobConfig = this.configPda();
2097
+ const [yesMint] = PDA.yesMint(condition, this.programIds);
2098
+ const [noMint] = PDA.noMint(condition, this.programIds);
2099
+ const clobYesAta = getAssociatedTokenAddressSync(yesMint, clobConfig, true, TOKEN_2022_PROGRAM_ID);
2100
+ const clobNoAta = getAssociatedTokenAddressSync(noMint, clobConfig, true, TOKEN_2022_PROGRAM_ID);
2101
+ const matchIx = await this._buildMergeIx(yesSigned, noMakers, collateralMint, operatorWallet.publicKey, this.walletPubkey, opts);
2082
2102
  await this._ensureClobOutcomeAtas(yesMint, noMint, clobConfig, clobYesAta, clobNoAta);
2083
2103
  const sig = await this.sendMatchTx([matchIx], lookupTable, operatorWallet);
2084
2104
  return { signature: sig };
@@ -2103,7 +2123,7 @@ ${logs.join("\n")}`);
2103
2123
  const cfg = await this.fetchConfig();
2104
2124
  if (!cfg) throw new InvalidParamError("CLOB config not found on-chain");
2105
2125
  const feeRecipient = cfg.feeRecipient;
2106
- const operatorWallet = this.provider.wallet;
2126
+ const operatorWallet = opts?.operatorWallet ?? this.provider.wallet;
2107
2127
  const alt = await this.ensureAlt(
2108
2128
  taker.order.condition,
2109
2129
  collateralMint,
@@ -2191,6 +2211,119 @@ ${logs.join("\n")}`);
2191
2211
  const makersSigned = sortedMakers.map(buildSigned);
2192
2212
  return this.matchOrders(takerSigned, makersSigned, opts);
2193
2213
  }
2214
+ /**
2215
+ * Build an unsigned VersionedTransaction for a set of match instructions.
2216
+ * Callers sign and send externally — mirrors createQuestionAdmin pattern.
2217
+ */
2218
+ async _buildUnsignedVtx(instructions, lookupTable, payer) {
2219
+ const { connection } = this.provider;
2220
+ const { blockhash } = await connection.getLatestBlockhash();
2221
+ const cuLimit = ComputeBudgetProgram.setComputeUnitLimit({ units: 14e5 });
2222
+ const heapFrame = ComputeBudgetProgram.requestHeapFrame({ bytes: 262144 });
2223
+ const message = new TransactionMessage({
2224
+ payerKey: payer,
2225
+ recentBlockhash: blockhash,
2226
+ instructions: [cuLimit, heapFrame, ...instructions]
2227
+ }).compileToV0Message(lookupTable ? [lookupTable] : []);
2228
+ return new VersionedTransaction(message);
2229
+ }
2230
+ /**
2231
+ * Build unsigned VersionedTransaction(s) for matching orders.
2232
+ *
2233
+ * Mirrors createQuestionAdmin pattern — SDK registers orders internally but
2234
+ * returns the match tx unsigned. BE signs with both keypairs and sends:
2235
+ *
2236
+ * const [vtx] = await sdk.clob.buildMatchOrdersTx(taker, makers, operatorPk, payerPk);
2237
+ * vtx.sign([feePayerKeypair, operatorKeypair]);
2238
+ * await connection.sendRawTransaction(vtx.serialize());
2239
+ *
2240
+ * All match types pack into a single VersionedTransaction — same as createQuestionAdmin pattern.
2241
+ * NO-taker MINT/MERGE decomposes into N instructions but all packed in 1 tx.
2242
+ *
2243
+ * @param operator - Whitelisted CLOB operator pubkey (must sign)
2244
+ * @param payer - Fee payer pubkey (must sign, pays tx fee + rent)
2245
+ */
2246
+ async buildMatchOrdersTx(taker, makers, operator, payer, opts) {
2247
+ if (makers.length === 0) throw new InvalidParamError("At least 1 maker required");
2248
+ const collateralMint = this.networkConfig.defaultCollateral.mint;
2249
+ const cfg = await this.fetchConfig();
2250
+ if (!cfg) throw new InvalidParamError("CLOB config not found on-chain");
2251
+ const feeRecipient = cfg.feeRecipient;
2252
+ const alt = await this.ensureAlt(taker.order.condition, collateralMint, taker, makers);
2253
+ const t = taker.order;
2254
+ const m0 = makers[0].order;
2255
+ const SIDE_BUY = 0;
2256
+ const SIDE_SELL = 1;
2257
+ if (t.tokenId === m0.tokenId) {
2258
+ let buySignedOrder, sellCandidates;
2259
+ if (t.side === SIDE_BUY && makers.every((m) => m.order.side === SIDE_SELL)) {
2260
+ buySignedOrder = taker;
2261
+ sellCandidates = makers;
2262
+ } else if (t.side === SIDE_SELL && makers.every((m) => m.order.side === SIDE_BUY)) {
2263
+ await Promise.all([
2264
+ this.registerOrderIfNeeded(taker),
2265
+ ...makers.map((m) => this.registerOrderIfNeeded(m))
2266
+ ]);
2267
+ const ixs3 = await this.buildMatchComplementaryIxs(
2268
+ taker,
2269
+ makers,
2270
+ collateralMint,
2271
+ feeRecipient,
2272
+ operator,
2273
+ opts,
2274
+ false
2275
+ );
2276
+ return this._buildUnsignedVtx(ixs3, alt, payer);
2277
+ } else {
2278
+ throw new InvalidParamError("COMPLEMENTARY requires one BUY and one or more SELLs on same tokenId");
2279
+ }
2280
+ await Promise.all([
2281
+ this.registerOrderIfNeeded(buySignedOrder),
2282
+ ...sellCandidates.map((m) => this.registerOrderIfNeeded(m))
2283
+ ]);
2284
+ const ixs2 = await this.buildMatchComplementaryIxs(
2285
+ buySignedOrder,
2286
+ sellCandidates,
2287
+ collateralMint,
2288
+ feeRecipient,
2289
+ operator,
2290
+ opts
2291
+ );
2292
+ return this._buildUnsignedVtx(ixs2, alt, payer);
2293
+ }
2294
+ const allBuy = t.side === SIDE_BUY && makers.every((m) => m.order.side === SIDE_BUY);
2295
+ const allSell = t.side === SIDE_SELL && makers.every((m) => m.order.side === SIDE_SELL);
2296
+ if (!allBuy && !allSell) throw new InvalidParamError("MINT/MERGE: all orders must be same side");
2297
+ const takerIsYes = t.tokenId === 1 && makers.every((m) => m.order.tokenId === 0);
2298
+ const takerIsNo = t.tokenId === 0 && makers.every((m) => m.order.tokenId === 1);
2299
+ if (!takerIsYes && !takerIsNo) throw new InvalidParamError("MINT/MERGE: orders must be complementary YES+NO pair");
2300
+ const condition = t.condition;
2301
+ const clobConfig = this.configPda();
2302
+ const [yesMint] = PDA.yesMint(condition, this.programIds);
2303
+ const [noMint] = PDA.noMint(condition, this.programIds);
2304
+ const clobYesAta = getAssociatedTokenAddressSync(yesMint, clobConfig, true, TOKEN_2022_PROGRAM_ID);
2305
+ const clobNoAta = getAssociatedTokenAddressSync(noMint, clobConfig, true, TOKEN_2022_PROGRAM_ID);
2306
+ if (takerIsYes) {
2307
+ await Promise.all([
2308
+ this.registerOrderIfNeeded(taker),
2309
+ ...makers.map((m) => this.registerOrderIfNeeded(m))
2310
+ ]);
2311
+ await this._ensureClobOutcomeAtas(yesMint, noMint, clobConfig, clobYesAta, clobNoAta);
2312
+ const ix = allBuy ? await this._buildMintIx(taker, makers, collateralMint, operator, payer) : await this._buildMergeIx(taker, makers, collateralMint, operator, payer, opts);
2313
+ return this._buildUnsignedVtx([ix], alt, payer);
2314
+ }
2315
+ await Promise.all([
2316
+ this.registerOrderIfNeeded(taker),
2317
+ ...makers.map((m) => this.registerOrderIfNeeded(m))
2318
+ ]);
2319
+ await this._ensureClobOutcomeAtas(yesMint, noMint, clobConfig, clobYesAta, clobNoAta);
2320
+ const ixs = [];
2321
+ for (const yesMaker of makers) {
2322
+ const ix = allBuy ? await this._buildMintIx(yesMaker, [taker], collateralMint, operator, payer) : await this._buildMergeIx(yesMaker, [taker], collateralMint, operator, payer, opts);
2323
+ ixs.push(ix);
2324
+ }
2325
+ return this._buildUnsignedVtx(ixs, alt, payer);
2326
+ }
2194
2327
  // ─── Queries ─────────────────────────────────────────────────────────────────
2195
2328
  async fetchConfig() {
2196
2329
  try {