import * as anchor from "@coral-xyz/anchor"; import { SystemProgram, Transaction } from "@solana/web3.js"; import { expect } from "chai"; import fetch from "node-fetch"; import { getTestContext } from "../setup"; describe("Initialize Market (API)", () => { it("Initialize Secondary Market via API", async () => { const ctx = getTestContext(); const { connection, program, axumBaseUrl, marketPda, registryPda, globalAdmin } = ctx; const lotSize = 1; // Minimum trade size: 1 EUA const tickSize = 1000000; // Price increments: 1 USDC (6 decimals) // Step 1: Create API request payload const request = { market: marketPda.toBase58(), registry: registryPda.toBase58(), global_admin: globalAdmin.publicKey.toBase58(), system_program: SystemProgram.programId.toBase58(), lot_size: lotSize, tick_size: tickSize, }; console.log("Calling API to create initialize market transaction..."); // Step 2: Call Axum API to get unsigned transaction const createTxResponse = await fetch( `${axumBaseUrl}/api/secondary-market/initialize-market`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(request), } ); if (!createTxResponse.ok) { const error = await createTxResponse.text(); throw new Error(`Failed to create transaction: ${error}`); } const { transaction_base64, message } = await createTxResponse.json(); console.log(`API Response: ${message}`); // Step 3: Deserialize and sign transaction const txBuffer = Buffer.from(transaction_base64, "base64"); const transaction = Transaction.from(txBuffer); // Sign with globalAdmin (the only required signer - it's the payer and authority) transaction.sign(globalAdmin); console.log("Transaction signed locally"); // Step 4: Submit signed transaction to backend const signedTxBase64 = transaction.serialize().toString("base64"); const submitTxResponse = await fetch(`${axumBaseUrl}/api/submit-tx`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ transaction_base64: signedTxBase64 }), }); if (!submitTxResponse.ok) { const error = await submitTxResponse.text(); throw new Error(`Failed to submit transaction: ${error}`); } const { signature } = await submitTxResponse.json(); console.log(`✓ Transaction signature: ${signature}`); // Step 5: Verify on-chain state const market = await program.account.marketConfig.fetch(marketPda); expect(market.admin.equals(globalAdmin.publicKey)).to.be.true; expect(market.registry.equals(registryPda)).to.be.true; expect(market.lotSize.toNumber()).to.equal(lotSize); expect(market.tickSize.toNumber()).to.equal(tickSize); expect(market.paused).to.be.false; // REMOVED: expect(market.nextOrderId.toNumber()).to.equal(1); expect(market.totalVolume.toNumber()).to.equal(0); expect(market.totalTrades.toNumber()).to.equal(0); console.log("✓ Market account state verified"); console.log(` - Admin: ${market.admin.toBase58()}`); console.log(` - Registry: ${market.registry.toBase58()}`); console.log(` - Lot Size: ${market.lotSize.toNumber()}`); console.log(` - Tick Size: ${market.tickSize.toNumber()}`); console.log(` - Paused: ${market.paused}`); // REMOVED: console.log(` - Next Order ID: ${market.nextOrderId.toNumber()}`); // Step 6: Verify events/logs const txDetails = await connection.getTransaction(signature, { commitment: "confirmed", maxSupportedTransactionVersion: 0, }); if (txDetails?.meta?.logMessages) { const logs = txDetails.meta.logMessages; // Check for market initialized message const hasMarketInitLog = logs.some((log) => log.includes("Market initialized") && log.includes(`lot_size: ${lotSize}`) && log.includes(`tick_size: ${tickSize}`) ); expect(hasMarketInitLog).to.be.true; console.log("✓ Market initialized log message found"); // Check for MarketInitialized event (Anchor emits events as logs) const hasEventLog = logs.some((log) => log.includes("MarketInitialized")); if (hasEventLog) { console.log("✓ MarketInitialized event emitted"); } } console.log("✓ Secondary market initialized successfully via API"); }); });