@theliem/xmarket-sdk 3.3.0 → 3.4.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
@@ -12,6 +12,7 @@ interface ProgramIds {
12
12
  feeManagement?: PublicKey;
13
13
  presale?: PublicKey;
14
14
  marketOracle?: PublicKey;
15
+ adminContract?: PublicKey;
15
16
  }
16
17
  interface CollateralConfig {
17
18
  mint: PublicKey;
@@ -431,6 +432,8 @@ declare class MarketClient {
431
432
  removeAdmin(owner?: PublicKey): Promise<Transaction>;
432
433
  addToWhitelist(address: PublicKey, authority?: PublicKey, payer?: PublicKey): Promise<Transaction>;
433
434
  removeFromWhitelist(address: PublicKey, authority?: PublicKey, payer?: PublicKey): Promise<Transaction>;
435
+ growConfig(owner?: PublicKey, payer?: PublicKey): Promise<Transaction>;
436
+ restoreConfig(snapshot: Buffer, owner?: PublicKey, payer?: PublicKey): Promise<Transaction>;
434
437
  fetchConfig(): Promise<QuestionMarketConfig | null>;
435
438
  fetchQuestion(questionPda: PublicKey): Promise<Question | null>;
436
439
  questionPda(questionId: Uint8Array): PublicKey;
@@ -488,7 +491,16 @@ declare class MarketClient {
488
491
  * Whitelist-only: distribute presale vault → 10% agents + 10% company + 80% botmm.
489
492
  * Closes presale_vault ATA and presale PDA after distribution; lamports returned to payer.
490
493
  */
491
- collectPresaleRevenue(presalePda: PublicKey, currencyMint: PublicKey, referralAddress: PublicKey, companyAddress: PublicKey, botmmAddress: PublicKey, caller?: PublicKey, payer?: PublicKey): Promise<Transaction>;
494
+ collectPresaleRevenue(params: {
495
+ presalePda: PublicKey;
496
+ currencyMint: PublicKey;
497
+ conditionId: Uint8Array;
498
+ referralAddress: PublicKey;
499
+ companyAddress: PublicKey;
500
+ adminOwner: PublicKey;
501
+ caller?: PublicKey;
502
+ payer?: PublicKey;
503
+ }): Promise<Transaction>;
492
504
  /**
493
505
  * Whitelist-only: snapshot MST supply so holders can claim trading fees.
494
506
  * Call after oracle resolves the question.
@@ -546,103 +558,101 @@ declare class ClobClient {
546
558
  get walletPubkey(): PublicKey;
547
559
  /**
548
560
  * Get or create an ALT for a condition.
549
- * First call: creates + extends ALT on-chain, waits for activation (~2s).
550
- * Subsequent calls for same condition: returns cached ALT instantly.
551
- * BE devs never interact with this — called automatically by matchOrders.
561
+ * Includes order_record PDAs for taker + all makers so match tx stays under 1232 bytes.
552
562
  */
553
- ensureAlt(condition: PublicKey, collateralMint: PublicKey, buyerPubkey: PublicKey, buyerNonce: anchor.BN, makers: SignedOrder[]): Promise<AddressLookupTableAccount>;
563
+ ensureAlt(condition: PublicKey, collateralMint: PublicKey, takerSigned: SignedOrder, makers: SignedOrder[]): Promise<AddressLookupTableAccount>;
564
+ private _sendLegacyTxSig;
554
565
  private _sendLegacyTx;
555
566
  /**
556
- * Send a match transaction as versioned (v0).
557
- * Pass a pre-built AddressLookupTableAccount to compress account keys and
558
- * stay under the 1232-byte limit — required for match_complementary which
559
- * has ~25 accounts + 2 Ed25519 precompile instructions (~1697 bytes raw).
560
- *
561
- * If `whitelistedWallet` is provided and differs from `this.provider.wallet`,
562
- * both wallets sign the transaction (whitelisted operator + payer).
567
+ * Send a match transaction as versioned (v0) with optional ALT.
568
+ * Both operator wallet and payer (this.provider.wallet) sign.
563
569
  */
564
570
  sendMatchTx(instructions: TransactionInstruction[], lookupTable?: AddressLookupTableAccount, whitelistedWallet?: anchor.Wallet): Promise<string>;
565
571
  configPda(): PublicKey;
566
- /** One-time setup. Caller becomes admin. */
572
+ /**
573
+ * Register a signed order on-chain.
574
+ * Sends Ed25519 precompile ix + register_order ix in one legacy tx.
575
+ * Called at match time (engine-triggered), not at order placement.
576
+ */
577
+ registerOrder(signed: SignedOrder): Promise<string>;
578
+ /** Register only if the PDA doesn't exist yet (idempotent). */
579
+ private registerOrderIfNeeded;
580
+ /** Cancel an order — closes its OrderRecord PDA and returns rent to maker. */
581
+ cancelOrder(nonce: anchor.BN): Promise<TxResult>;
567
582
  initialize(operators: PublicKey[], feeRecipient: PublicKey, feeRateBps: number): Promise<TxResult>;
568
- /** Admin adds an operator to the whitelist. */
569
583
  addOperator(operator: PublicKey): Promise<TxResult>;
570
- /** Admin removes an operator from the whitelist. */
571
584
  removeOperator(operator: PublicKey): Promise<TxResult>;
572
- /** Admin pause/unpause the CLOB. */
573
585
  setPaused(paused: boolean): Promise<TxResult>;
574
- /**
575
- * Emergency reset of CLOB config (upgrade authority only).
576
- */
577
586
  forceResetClob(programData: PublicKey, newAdmin: PublicKey, newOperators: PublicKey[], newFeeRecipient: PublicKey, newFeeRateBps: number): Promise<TxResult>;
578
587
  /**
579
- * COMPLEMENTARY match: 1 buyer (taker) + N sellers (makers), same tokenId.
580
- *
581
- * Transaction structure:
582
- * ix[0] Ed25519(taker/buyer)
583
- * ix[1+i] Ed25519(maker_i/seller_i)
584
- * ix[N+1] match_complementary(buyNonce, makerNonces[])
585
- *
586
- * remaining_accounts: [hook×3] [seller×5 × N]
587
- */
588
- /** Build Ed25519 + matchComplementary instructions without sending.
588
+ * Build match_complementary instruction (no Ed25519 OrderRecord PDAs used).
589
589
  *
590
- * If `buySigned.order.fee > 0` and `feeClient` + `feeConfigOwner` are wired in,
591
- * automatically appends 5 fee_management remaining_accounts so the program CPIs
592
- * to distribute_fee internally. No manual `feeDistribute` param needed.
590
+ * remaining_accounts layout:
591
+ * [seller, order_record, seller_token, seller_collateral, seller_position, sell_status] × N
592
+ * [extraAccountMetaList, hookConfig, hookProgram]
593
+ * [feeManagement, fee_config, mkt_override, company_ata, oracle_vault] (when fee > 0)
593
594
  */
594
- buildMatchComplementaryIxs(buySigned: SignedOrder, makersSigned: SignedOrder[], collateralMint: PublicKey, feeRecipient: PublicKey, operator: PublicKey, opts?: {
595
+ buildMatchComplementaryIxs(takerSigned: SignedOrder, makersSigned: SignedOrder[], collateralMint: PublicKey, feeRecipient: PublicKey, operator: PublicKey, opts?: {
595
596
  marketOracleVault?: PublicKey;
597
+ fillAmount?: anchor.BN;
596
598
  }): Promise<TransactionInstruction[]>;
599
+ /**
600
+ * COMPLEMENTARY: 1 taker (BUY) + N makers (SELL), same tokenId.
601
+ * Phase 1: register taker + all makers in parallel.
602
+ * Phase 2: 1 atomic match tx.
603
+ */
597
604
  private matchComplementary;
598
605
  /**
599
- * MINT match: 1 YES buyer (taker) + N NO buyers (makers).
600
- *
601
- * Transaction structure:
602
- * ix[0] Ed25519(taker/YES buyer)
603
- * ix[1+i] Ed25519(maker_i/NO buyer)
604
- * ix[N+1] match_mint_orders(yesNonce, makerNonces[])
606
+ * MINT: 1 YES buyer (taker) + N NO buyers (makers).
607
+ * Phase 1: register taker + all NO makers in parallel.
608
+ * Phase 2: 1 atomic match tx.
605
609
  *
606
- * remaining_accounts: [maker×5 × N] (no hook accounts — mint_to doesn't fire hook)
610
+ * remaining_accounts per NO maker (5):
611
+ * [order_record, buyer_no_token, buyer_no_collateral, buyer_no_position, no_order_status]
607
612
  */
608
613
  private matchMintOrders;
609
614
  /**
610
- * MERGE match: 1 YES seller (taker) + N NO sellers (makers).
615
+ * MERGE: 1 YES seller (taker) + N NO sellers (makers).
616
+ * Phase 1: register taker + all NO makers in parallel.
617
+ * Phase 2: 1 atomic match tx.
611
618
  *
612
- * Transaction structure:
613
- * ix[0] Ed25519(taker/YES seller)
614
- * ix[1+i] Ed25519(maker_i/NO seller)
615
- * ix[N+1] match_merge_orders(yesNonce, makerNonces[])
616
- *
617
- * remaining_accounts: [maker×5 × N] (no hook accounts — burn doesn't fire hook)
619
+ * remaining_accounts per NO maker (5):
620
+ * [order_record, seller_no_token, seller_no_collateral, seller_no_position, no_order_status]
621
+ * After all makers, optional 5 fee accounts.
618
622
  */
619
623
  private matchMergeOrders;
620
624
  /**
621
- * Auto-detect match type and execute 1-taker + N-makers in a single transaction.
625
+ * Auto-detect match type and execute 2-phase:
626
+ * Phase 1 — register all orders (taker + makers) on-chain in parallel.
627
+ * Phase 2 — 1 atomic match transaction.
622
628
  *
623
- * Detection (pure, no RPC) based on taker.order vs makers[0].order:
624
- * taker.tokenId === makers[0].tokenId: taker BUY + all makers SELL → COMPLEMENTARY
625
- * taker.tokenId !== makers[0].tokenId + taker BUY + all makers BUYMINT
626
- * taker.tokenId !== makers[0].tokenId + taker SELL + all makers SELL MERGE
627
- * Otherwisethrows InvalidParamError
629
+ * Detection (pure, no RPC):
630
+ * taker.tokenId === makers[0].tokenId:
631
+ * taker BUY + all makers SELLCOMPLEMENTARY
632
+ * taker.tokenId !== makers[0].tokenId + all BUY MINT
633
+ * taker.tokenId !== makers[0].tokenId + all SELL MERGE
628
634
  *
629
- * All makers must have the same tokenId and side as makers[0].
630
- */
631
- /**
632
- * Auto-detect match type and execute in a single transaction.
633
- * ALT is managed automatically (created on first call per condition, cached thereafter).
634
- * feeRecipient and collateralMint are derived from on-chain config.
635
- * Fee distribution (distribute_fee CPI) fires automatically when order.fee > 0.
636
- *
637
- * @param opts.marketOracleVault Required for presale markets (is_admin=false).
638
- * Pass the ATA of the market_oracle PDA so 50% of fee goes there.
639
- * For admin markets (is_admin=true) omit — payer is used as placeholder (no transfer).
635
+ * @param opts.marketOracleVault Oracle vault ATA for presale markets.
636
+ * Omit for admin markets (payer used as placeholder).
640
637
  */
641
638
  matchOrders(taker: SignedOrder, makers: SignedOrder[], opts?: {
642
639
  marketOracleVault?: PublicKey;
643
640
  }): Promise<TxResult>;
644
641
  fetchConfig(): Promise<ClobConfig | null>;
645
642
  fetchOrderStatus(maker: PublicKey, nonce: anchor.BN): Promise<OrderStatus | null>;
643
+ fetchOrderRecord(maker: PublicKey, nonce: anchor.BN): Promise<{
644
+ maker: PublicKey;
645
+ condition: PublicKey;
646
+ tokenId: number;
647
+ side: number;
648
+ makerAmount: anchor.BN;
649
+ takerAmount: anchor.BN;
650
+ nonce: anchor.BN;
651
+ expiry: anchor.BN;
652
+ fee: anchor.BN;
653
+ taker: PublicKey;
654
+ signer: PublicKey;
655
+ } | null>;
646
656
  }
647
657
 
648
658
  interface PresaleInfo {
@@ -732,6 +742,50 @@ declare class MarketOracleClient {
732
742
  fetchUserClaimRecord(marketOraclePda: PublicKey, user: PublicKey): Promise<UserClaimRecord | null>;
733
743
  }
734
744
 
745
+ interface AdminConfigInfo {
746
+ version: number;
747
+ owner: PublicKey;
748
+ collateralMint: PublicKey;
749
+ authorizedCaller: PublicKey;
750
+ adminWhitelist: PublicKey[];
751
+ whitelist: PublicKey[];
752
+ bump: number;
753
+ }
754
+ interface ClaimRecordInfo {
755
+ conditionId: number[];
756
+ amount: anchor.BN;
757
+ bump: number;
758
+ }
759
+ declare class AdminClient {
760
+ private readonly program;
761
+ private readonly provider;
762
+ private readonly programIds;
763
+ constructor(program: anchor.Program, provider: anchor.AnchorProvider, programIds: ProgramIds);
764
+ get walletPubkey(): PublicKey;
765
+ get configPda(): PublicKey;
766
+ configPdaFor(owner: PublicKey): PublicKey;
767
+ adminVault(owner: PublicKey, collateralMint: PublicKey): PublicKey;
768
+ fetchConfig(owner?: anchor.web3.PublicKey): Promise<AdminConfigInfo | null>;
769
+ fetchClaimRecord(conditionId: Uint8Array): Promise<ClaimRecordInfo | null>;
770
+ initialize(authorizedCaller: PublicKey, collateralMint: PublicKey, owner?: PublicKey): Promise<Transaction>;
771
+ addAdmin(address: PublicKey, owner?: PublicKey): Promise<Transaction>;
772
+ removeAdmin(address: PublicKey, owner?: PublicKey): Promise<Transaction>;
773
+ addToWhitelist(address: PublicKey, owner: PublicKey, admin?: PublicKey, payer?: PublicKey): Promise<Transaction>;
774
+ removeFromWhitelist(address: PublicKey, owner: PublicKey, admin?: PublicKey, payer?: PublicKey): Promise<Transaction>;
775
+ /**
776
+ * Normally called via CPI from question_market (authorized_caller signs).
777
+ * For testing: initialize with authorizedCaller = wallet, call directly.
778
+ */
779
+ setPresaleAmount(conditionId: Uint8Array, amount: anchor.BN, owner?: PublicKey, caller?: PublicKey, payer?: PublicKey): Promise<Transaction>;
780
+ claim(conditionId: Uint8Array, collateralMint: PublicKey, owner: PublicKey, claimer?: PublicKey, payer?: PublicKey): Promise<Transaction>;
781
+ updateConfig(authorizedCaller: PublicKey, owner?: PublicKey): Promise<Transaction>;
782
+ /**
783
+ * BOTMM sends USDC from their wallet to the market_oracle vault for a condition.
784
+ * Whitelist-only. No amount validation — caller responsible.
785
+ */
786
+ distributeMarket(conditionId: Uint8Array, amount: anchor.BN, collateralMint: PublicKey, marketOracleVault: PublicKey, owner: PublicKey, claimer?: PublicKey, payer?: PublicKey): Promise<Transaction>;
787
+ }
788
+
735
789
  declare class XMarketSDK {
736
790
  readonly provider: anchor.AnchorProvider;
737
791
  readonly networkConfig: NetworkConfig;
@@ -745,6 +799,7 @@ declare class XMarketSDK {
745
799
  private _fee?;
746
800
  private _presale?;
747
801
  private _marketOracle?;
802
+ private _admin?;
748
803
  constructor(config: NetworkConfig, wallet: anchor.Wallet, marketOwner?: PublicKey);
749
804
  private _withAddress;
750
805
  get oracle(): OracleClient;
@@ -755,6 +810,7 @@ declare class XMarketSDK {
755
810
  get fee(): FeeManagementClient;
756
811
  get presale(): PresaleClient;
757
812
  get marketOracle(): MarketOracleClient;
813
+ get admin(): AdminClient;
758
814
  }
759
815
 
760
816
  declare const SEEDS: {
@@ -783,6 +839,8 @@ declare const SEEDS: {
783
839
  readonly userBuy: Buffer<ArrayBuffer>;
784
840
  readonly marketOracle: Buffer<ArrayBuffer>;
785
841
  readonly userClaim: Buffer<ArrayBuffer>;
842
+ readonly adminConfig: Buffer<ArrayBuffer>;
843
+ readonly claimRecord: Buffer<ArrayBuffer>;
786
844
  };
787
845
  declare class PDA {
788
846
  static questionMarketConfig(owner: PublicKey, programIds: Pick<ProgramIds, "questionMarket">): [PublicKey, number];
@@ -802,6 +860,7 @@ declare class PDA {
802
860
  static extraAccountMetaList(mint: PublicKey, programIds: Pick<ProgramIds, "hook">): [PublicKey, number];
803
861
  static clobConfig(programIds: Pick<ProgramIds, "clobExchange">): [PublicKey, number];
804
862
  static orderStatus(maker: PublicKey, nonce: BN, programIds: Pick<ProgramIds, "clobExchange">): [PublicKey, number];
863
+ static orderRecord(maker: PublicKey, nonce: BN, programIds: Pick<ProgramIds, "clobExchange">): [PublicKey, number];
805
864
  static feeConfig(owner: PublicKey, programIds: Pick<ProgramIds, "feeManagement">): [PublicKey, number];
806
865
  static questionFee(conditionPda: PublicKey, programIds: Pick<ProgramIds, "feeManagement">): [PublicKey, number];
807
866
  static marketFeeOverride(conditionPda: PublicKey, programIds: Pick<ProgramIds, "feeManagement">): [PublicKey, number];
@@ -811,6 +870,8 @@ declare class PDA {
811
870
  static userBuyRecord(presalePda: PublicKey, user: PublicKey, programIds: Pick<ProgramIds, "presale">): [PublicKey, number];
812
871
  static marketOraclePda(questionPda: PublicKey, programIds: Pick<ProgramIds, "marketOracle">): [PublicKey, number];
813
872
  static userClaimRecord(marketOraclePda: PublicKey, user: PublicKey, programIds: Pick<ProgramIds, "marketOracle">): [PublicKey, number];
873
+ static adminConfig(owner: PublicKey, programIds: Pick<ProgramIds, "adminContract">): [PublicKey, number];
874
+ static claimRecord(conditionId: Uint8Array, programIds: Pick<ProgramIds, "adminContract">): [PublicKey, number];
814
875
  }
815
876
  /** Unique 32-byte question ID: SHA-256(content + timestamp). Different each call. */
816
877
  declare function generateQuestionId(content: string, salt?: number): Uint8Array;
@@ -944,4 +1005,4 @@ declare function buildApproveCollateralTx(collateralMint: PublicKey, signer: Pub
944
1005
  */
945
1006
  declare function buildApproveAllOutcomeTokensTx(condition: PublicKey, signer: PublicKey, payer: PublicKey, delegate: PublicKey, programIds: ProgramIds, amount?: BN): Transaction;
946
1007
 
947
- export { AccountNotFoundError, 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 };
1008
+ 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 };
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ interface ProgramIds {
12
12
  feeManagement?: PublicKey;
13
13
  presale?: PublicKey;
14
14
  marketOracle?: PublicKey;
15
+ adminContract?: PublicKey;
15
16
  }
16
17
  interface CollateralConfig {
17
18
  mint: PublicKey;
@@ -431,6 +432,8 @@ declare class MarketClient {
431
432
  removeAdmin(owner?: PublicKey): Promise<Transaction>;
432
433
  addToWhitelist(address: PublicKey, authority?: PublicKey, payer?: PublicKey): Promise<Transaction>;
433
434
  removeFromWhitelist(address: PublicKey, authority?: PublicKey, payer?: PublicKey): Promise<Transaction>;
435
+ growConfig(owner?: PublicKey, payer?: PublicKey): Promise<Transaction>;
436
+ restoreConfig(snapshot: Buffer, owner?: PublicKey, payer?: PublicKey): Promise<Transaction>;
434
437
  fetchConfig(): Promise<QuestionMarketConfig | null>;
435
438
  fetchQuestion(questionPda: PublicKey): Promise<Question | null>;
436
439
  questionPda(questionId: Uint8Array): PublicKey;
@@ -488,7 +491,16 @@ declare class MarketClient {
488
491
  * Whitelist-only: distribute presale vault → 10% agents + 10% company + 80% botmm.
489
492
  * Closes presale_vault ATA and presale PDA after distribution; lamports returned to payer.
490
493
  */
491
- collectPresaleRevenue(presalePda: PublicKey, currencyMint: PublicKey, referralAddress: PublicKey, companyAddress: PublicKey, botmmAddress: PublicKey, caller?: PublicKey, payer?: PublicKey): Promise<Transaction>;
494
+ collectPresaleRevenue(params: {
495
+ presalePda: PublicKey;
496
+ currencyMint: PublicKey;
497
+ conditionId: Uint8Array;
498
+ referralAddress: PublicKey;
499
+ companyAddress: PublicKey;
500
+ adminOwner: PublicKey;
501
+ caller?: PublicKey;
502
+ payer?: PublicKey;
503
+ }): Promise<Transaction>;
492
504
  /**
493
505
  * Whitelist-only: snapshot MST supply so holders can claim trading fees.
494
506
  * Call after oracle resolves the question.
@@ -546,103 +558,101 @@ declare class ClobClient {
546
558
  get walletPubkey(): PublicKey;
547
559
  /**
548
560
  * Get or create an ALT for a condition.
549
- * First call: creates + extends ALT on-chain, waits for activation (~2s).
550
- * Subsequent calls for same condition: returns cached ALT instantly.
551
- * BE devs never interact with this — called automatically by matchOrders.
561
+ * Includes order_record PDAs for taker + all makers so match tx stays under 1232 bytes.
552
562
  */
553
- ensureAlt(condition: PublicKey, collateralMint: PublicKey, buyerPubkey: PublicKey, buyerNonce: anchor.BN, makers: SignedOrder[]): Promise<AddressLookupTableAccount>;
563
+ ensureAlt(condition: PublicKey, collateralMint: PublicKey, takerSigned: SignedOrder, makers: SignedOrder[]): Promise<AddressLookupTableAccount>;
564
+ private _sendLegacyTxSig;
554
565
  private _sendLegacyTx;
555
566
  /**
556
- * Send a match transaction as versioned (v0).
557
- * Pass a pre-built AddressLookupTableAccount to compress account keys and
558
- * stay under the 1232-byte limit — required for match_complementary which
559
- * has ~25 accounts + 2 Ed25519 precompile instructions (~1697 bytes raw).
560
- *
561
- * If `whitelistedWallet` is provided and differs from `this.provider.wallet`,
562
- * both wallets sign the transaction (whitelisted operator + payer).
567
+ * Send a match transaction as versioned (v0) with optional ALT.
568
+ * Both operator wallet and payer (this.provider.wallet) sign.
563
569
  */
564
570
  sendMatchTx(instructions: TransactionInstruction[], lookupTable?: AddressLookupTableAccount, whitelistedWallet?: anchor.Wallet): Promise<string>;
565
571
  configPda(): PublicKey;
566
- /** One-time setup. Caller becomes admin. */
572
+ /**
573
+ * Register a signed order on-chain.
574
+ * Sends Ed25519 precompile ix + register_order ix in one legacy tx.
575
+ * Called at match time (engine-triggered), not at order placement.
576
+ */
577
+ registerOrder(signed: SignedOrder): Promise<string>;
578
+ /** Register only if the PDA doesn't exist yet (idempotent). */
579
+ private registerOrderIfNeeded;
580
+ /** Cancel an order — closes its OrderRecord PDA and returns rent to maker. */
581
+ cancelOrder(nonce: anchor.BN): Promise<TxResult>;
567
582
  initialize(operators: PublicKey[], feeRecipient: PublicKey, feeRateBps: number): Promise<TxResult>;
568
- /** Admin adds an operator to the whitelist. */
569
583
  addOperator(operator: PublicKey): Promise<TxResult>;
570
- /** Admin removes an operator from the whitelist. */
571
584
  removeOperator(operator: PublicKey): Promise<TxResult>;
572
- /** Admin pause/unpause the CLOB. */
573
585
  setPaused(paused: boolean): Promise<TxResult>;
574
- /**
575
- * Emergency reset of CLOB config (upgrade authority only).
576
- */
577
586
  forceResetClob(programData: PublicKey, newAdmin: PublicKey, newOperators: PublicKey[], newFeeRecipient: PublicKey, newFeeRateBps: number): Promise<TxResult>;
578
587
  /**
579
- * COMPLEMENTARY match: 1 buyer (taker) + N sellers (makers), same tokenId.
580
- *
581
- * Transaction structure:
582
- * ix[0] Ed25519(taker/buyer)
583
- * ix[1+i] Ed25519(maker_i/seller_i)
584
- * ix[N+1] match_complementary(buyNonce, makerNonces[])
585
- *
586
- * remaining_accounts: [hook×3] [seller×5 × N]
587
- */
588
- /** Build Ed25519 + matchComplementary instructions without sending.
588
+ * Build match_complementary instruction (no Ed25519 OrderRecord PDAs used).
589
589
  *
590
- * If `buySigned.order.fee > 0` and `feeClient` + `feeConfigOwner` are wired in,
591
- * automatically appends 5 fee_management remaining_accounts so the program CPIs
592
- * to distribute_fee internally. No manual `feeDistribute` param needed.
590
+ * remaining_accounts layout:
591
+ * [seller, order_record, seller_token, seller_collateral, seller_position, sell_status] × N
592
+ * [extraAccountMetaList, hookConfig, hookProgram]
593
+ * [feeManagement, fee_config, mkt_override, company_ata, oracle_vault] (when fee > 0)
593
594
  */
594
- buildMatchComplementaryIxs(buySigned: SignedOrder, makersSigned: SignedOrder[], collateralMint: PublicKey, feeRecipient: PublicKey, operator: PublicKey, opts?: {
595
+ buildMatchComplementaryIxs(takerSigned: SignedOrder, makersSigned: SignedOrder[], collateralMint: PublicKey, feeRecipient: PublicKey, operator: PublicKey, opts?: {
595
596
  marketOracleVault?: PublicKey;
597
+ fillAmount?: anchor.BN;
596
598
  }): Promise<TransactionInstruction[]>;
599
+ /**
600
+ * COMPLEMENTARY: 1 taker (BUY) + N makers (SELL), same tokenId.
601
+ * Phase 1: register taker + all makers in parallel.
602
+ * Phase 2: 1 atomic match tx.
603
+ */
597
604
  private matchComplementary;
598
605
  /**
599
- * MINT match: 1 YES buyer (taker) + N NO buyers (makers).
600
- *
601
- * Transaction structure:
602
- * ix[0] Ed25519(taker/YES buyer)
603
- * ix[1+i] Ed25519(maker_i/NO buyer)
604
- * ix[N+1] match_mint_orders(yesNonce, makerNonces[])
606
+ * MINT: 1 YES buyer (taker) + N NO buyers (makers).
607
+ * Phase 1: register taker + all NO makers in parallel.
608
+ * Phase 2: 1 atomic match tx.
605
609
  *
606
- * remaining_accounts: [maker×5 × N] (no hook accounts — mint_to doesn't fire hook)
610
+ * remaining_accounts per NO maker (5):
611
+ * [order_record, buyer_no_token, buyer_no_collateral, buyer_no_position, no_order_status]
607
612
  */
608
613
  private matchMintOrders;
609
614
  /**
610
- * MERGE match: 1 YES seller (taker) + N NO sellers (makers).
615
+ * MERGE: 1 YES seller (taker) + N NO sellers (makers).
616
+ * Phase 1: register taker + all NO makers in parallel.
617
+ * Phase 2: 1 atomic match tx.
611
618
  *
612
- * Transaction structure:
613
- * ix[0] Ed25519(taker/YES seller)
614
- * ix[1+i] Ed25519(maker_i/NO seller)
615
- * ix[N+1] match_merge_orders(yesNonce, makerNonces[])
616
- *
617
- * remaining_accounts: [maker×5 × N] (no hook accounts — burn doesn't fire hook)
619
+ * remaining_accounts per NO maker (5):
620
+ * [order_record, seller_no_token, seller_no_collateral, seller_no_position, no_order_status]
621
+ * After all makers, optional 5 fee accounts.
618
622
  */
619
623
  private matchMergeOrders;
620
624
  /**
621
- * Auto-detect match type and execute 1-taker + N-makers in a single transaction.
625
+ * Auto-detect match type and execute 2-phase:
626
+ * Phase 1 — register all orders (taker + makers) on-chain in parallel.
627
+ * Phase 2 — 1 atomic match transaction.
622
628
  *
623
- * Detection (pure, no RPC) based on taker.order vs makers[0].order:
624
- * taker.tokenId === makers[0].tokenId: taker BUY + all makers SELL → COMPLEMENTARY
625
- * taker.tokenId !== makers[0].tokenId + taker BUY + all makers BUYMINT
626
- * taker.tokenId !== makers[0].tokenId + taker SELL + all makers SELL MERGE
627
- * Otherwisethrows InvalidParamError
629
+ * Detection (pure, no RPC):
630
+ * taker.tokenId === makers[0].tokenId:
631
+ * taker BUY + all makers SELLCOMPLEMENTARY
632
+ * taker.tokenId !== makers[0].tokenId + all BUY MINT
633
+ * taker.tokenId !== makers[0].tokenId + all SELL MERGE
628
634
  *
629
- * All makers must have the same tokenId and side as makers[0].
630
- */
631
- /**
632
- * Auto-detect match type and execute in a single transaction.
633
- * ALT is managed automatically (created on first call per condition, cached thereafter).
634
- * feeRecipient and collateralMint are derived from on-chain config.
635
- * Fee distribution (distribute_fee CPI) fires automatically when order.fee > 0.
636
- *
637
- * @param opts.marketOracleVault Required for presale markets (is_admin=false).
638
- * Pass the ATA of the market_oracle PDA so 50% of fee goes there.
639
- * For admin markets (is_admin=true) omit — payer is used as placeholder (no transfer).
635
+ * @param opts.marketOracleVault Oracle vault ATA for presale markets.
636
+ * Omit for admin markets (payer used as placeholder).
640
637
  */
641
638
  matchOrders(taker: SignedOrder, makers: SignedOrder[], opts?: {
642
639
  marketOracleVault?: PublicKey;
643
640
  }): Promise<TxResult>;
644
641
  fetchConfig(): Promise<ClobConfig | null>;
645
642
  fetchOrderStatus(maker: PublicKey, nonce: anchor.BN): Promise<OrderStatus | null>;
643
+ fetchOrderRecord(maker: PublicKey, nonce: anchor.BN): Promise<{
644
+ maker: PublicKey;
645
+ condition: PublicKey;
646
+ tokenId: number;
647
+ side: number;
648
+ makerAmount: anchor.BN;
649
+ takerAmount: anchor.BN;
650
+ nonce: anchor.BN;
651
+ expiry: anchor.BN;
652
+ fee: anchor.BN;
653
+ taker: PublicKey;
654
+ signer: PublicKey;
655
+ } | null>;
646
656
  }
647
657
 
648
658
  interface PresaleInfo {
@@ -732,6 +742,50 @@ declare class MarketOracleClient {
732
742
  fetchUserClaimRecord(marketOraclePda: PublicKey, user: PublicKey): Promise<UserClaimRecord | null>;
733
743
  }
734
744
 
745
+ interface AdminConfigInfo {
746
+ version: number;
747
+ owner: PublicKey;
748
+ collateralMint: PublicKey;
749
+ authorizedCaller: PublicKey;
750
+ adminWhitelist: PublicKey[];
751
+ whitelist: PublicKey[];
752
+ bump: number;
753
+ }
754
+ interface ClaimRecordInfo {
755
+ conditionId: number[];
756
+ amount: anchor.BN;
757
+ bump: number;
758
+ }
759
+ declare class AdminClient {
760
+ private readonly program;
761
+ private readonly provider;
762
+ private readonly programIds;
763
+ constructor(program: anchor.Program, provider: anchor.AnchorProvider, programIds: ProgramIds);
764
+ get walletPubkey(): PublicKey;
765
+ get configPda(): PublicKey;
766
+ configPdaFor(owner: PublicKey): PublicKey;
767
+ adminVault(owner: PublicKey, collateralMint: PublicKey): PublicKey;
768
+ fetchConfig(owner?: anchor.web3.PublicKey): Promise<AdminConfigInfo | null>;
769
+ fetchClaimRecord(conditionId: Uint8Array): Promise<ClaimRecordInfo | null>;
770
+ initialize(authorizedCaller: PublicKey, collateralMint: PublicKey, owner?: PublicKey): Promise<Transaction>;
771
+ addAdmin(address: PublicKey, owner?: PublicKey): Promise<Transaction>;
772
+ removeAdmin(address: PublicKey, owner?: PublicKey): Promise<Transaction>;
773
+ addToWhitelist(address: PublicKey, owner: PublicKey, admin?: PublicKey, payer?: PublicKey): Promise<Transaction>;
774
+ removeFromWhitelist(address: PublicKey, owner: PublicKey, admin?: PublicKey, payer?: PublicKey): Promise<Transaction>;
775
+ /**
776
+ * Normally called via CPI from question_market (authorized_caller signs).
777
+ * For testing: initialize with authorizedCaller = wallet, call directly.
778
+ */
779
+ setPresaleAmount(conditionId: Uint8Array, amount: anchor.BN, owner?: PublicKey, caller?: PublicKey, payer?: PublicKey): Promise<Transaction>;
780
+ claim(conditionId: Uint8Array, collateralMint: PublicKey, owner: PublicKey, claimer?: PublicKey, payer?: PublicKey): Promise<Transaction>;
781
+ updateConfig(authorizedCaller: PublicKey, owner?: PublicKey): Promise<Transaction>;
782
+ /**
783
+ * BOTMM sends USDC from their wallet to the market_oracle vault for a condition.
784
+ * Whitelist-only. No amount validation — caller responsible.
785
+ */
786
+ distributeMarket(conditionId: Uint8Array, amount: anchor.BN, collateralMint: PublicKey, marketOracleVault: PublicKey, owner: PublicKey, claimer?: PublicKey, payer?: PublicKey): Promise<Transaction>;
787
+ }
788
+
735
789
  declare class XMarketSDK {
736
790
  readonly provider: anchor.AnchorProvider;
737
791
  readonly networkConfig: NetworkConfig;
@@ -745,6 +799,7 @@ declare class XMarketSDK {
745
799
  private _fee?;
746
800
  private _presale?;
747
801
  private _marketOracle?;
802
+ private _admin?;
748
803
  constructor(config: NetworkConfig, wallet: anchor.Wallet, marketOwner?: PublicKey);
749
804
  private _withAddress;
750
805
  get oracle(): OracleClient;
@@ -755,6 +810,7 @@ declare class XMarketSDK {
755
810
  get fee(): FeeManagementClient;
756
811
  get presale(): PresaleClient;
757
812
  get marketOracle(): MarketOracleClient;
813
+ get admin(): AdminClient;
758
814
  }
759
815
 
760
816
  declare const SEEDS: {
@@ -783,6 +839,8 @@ declare const SEEDS: {
783
839
  readonly userBuy: Buffer<ArrayBuffer>;
784
840
  readonly marketOracle: Buffer<ArrayBuffer>;
785
841
  readonly userClaim: Buffer<ArrayBuffer>;
842
+ readonly adminConfig: Buffer<ArrayBuffer>;
843
+ readonly claimRecord: Buffer<ArrayBuffer>;
786
844
  };
787
845
  declare class PDA {
788
846
  static questionMarketConfig(owner: PublicKey, programIds: Pick<ProgramIds, "questionMarket">): [PublicKey, number];
@@ -802,6 +860,7 @@ declare class PDA {
802
860
  static extraAccountMetaList(mint: PublicKey, programIds: Pick<ProgramIds, "hook">): [PublicKey, number];
803
861
  static clobConfig(programIds: Pick<ProgramIds, "clobExchange">): [PublicKey, number];
804
862
  static orderStatus(maker: PublicKey, nonce: BN, programIds: Pick<ProgramIds, "clobExchange">): [PublicKey, number];
863
+ static orderRecord(maker: PublicKey, nonce: BN, programIds: Pick<ProgramIds, "clobExchange">): [PublicKey, number];
805
864
  static feeConfig(owner: PublicKey, programIds: Pick<ProgramIds, "feeManagement">): [PublicKey, number];
806
865
  static questionFee(conditionPda: PublicKey, programIds: Pick<ProgramIds, "feeManagement">): [PublicKey, number];
807
866
  static marketFeeOverride(conditionPda: PublicKey, programIds: Pick<ProgramIds, "feeManagement">): [PublicKey, number];
@@ -811,6 +870,8 @@ declare class PDA {
811
870
  static userBuyRecord(presalePda: PublicKey, user: PublicKey, programIds: Pick<ProgramIds, "presale">): [PublicKey, number];
812
871
  static marketOraclePda(questionPda: PublicKey, programIds: Pick<ProgramIds, "marketOracle">): [PublicKey, number];
813
872
  static userClaimRecord(marketOraclePda: PublicKey, user: PublicKey, programIds: Pick<ProgramIds, "marketOracle">): [PublicKey, number];
873
+ static adminConfig(owner: PublicKey, programIds: Pick<ProgramIds, "adminContract">): [PublicKey, number];
874
+ static claimRecord(conditionId: Uint8Array, programIds: Pick<ProgramIds, "adminContract">): [PublicKey, number];
814
875
  }
815
876
  /** Unique 32-byte question ID: SHA-256(content + timestamp). Different each call. */
816
877
  declare function generateQuestionId(content: string, salt?: number): Uint8Array;
@@ -944,4 +1005,4 @@ declare function buildApproveCollateralTx(collateralMint: PublicKey, signer: Pub
944
1005
  */
945
1006
  declare function buildApproveAllOutcomeTokensTx(condition: PublicKey, signer: PublicKey, payer: PublicKey, delegate: PublicKey, programIds: ProgramIds, amount?: BN): Transaction;
946
1007
 
947
- export { AccountNotFoundError, 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 };
1008
+ 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 };