Advanced Solana features help you get more out of your code. This example uses Address Lookup Tables (ALTs), a feature of Solana's new Versioned Transactions, to stack multiple placeOrder instructions into a single transaction. Sandwiching instructions is quite limited without ALTs as you'll quickly run into resource and account limits.
Code
require("dotenv").config();import { Wallet, CrossClient, Exchange, Network, utils, types, assets, constants,} from"@zetamarkets/sdk";import { PublicKey, Connection, Keypair, Transaction } from"@solana/web3.js";import fetch from"node-fetch";constNETWORK_URL=process.env["network_url"]!;constSERVER_URL=process.env["server_url"];constSTARTING_BALANCE=10_000;constASSETS= [constants.Asset.SOL,constants.Asset.ARB,constants.Asset.APT];constUSER_KEY=Keypair.generate();constWALLET=newWallet(USER_KEY);constCONNECTION:Connection=newConnection(NETWORK_URL,"confirmed");constMAX_SINGLE_MARKET_PLACE_ORDER_IXS=6;constMAX_ALL_PERP_MARKET_PLACE_ORDER_IXS=6;asyncfunctionmain() {// Airdropping SOL.awaitCONNECTION.requestAirdrop(WALLET.publicKey,1_000_000_000);awaitfetch(`${SERVER_URL}/faucet/USDC`, { method:"post", body:JSON.stringify({ key:WALLET.publicKey.toString(), amount:10_000, }), headers: { "Content-Type":"application/json" }, });constloadExchangeConfig=types.defaultLoadExchangeConfig(Network.DEVNET,CONNECTION,utils.defaultCommitment(),0,// ThrottleMs - increase if you are running into rate limit issues on startup.true );awaitExchange.load(loadExchangeConfig);constclient=awaitCrossClient.load(CONNECTION,WALLET,undefined,undefined,undefined,undefined,true );console.log("client loaded:",client.publicKey.toBase58());awaitclient.deposit(utils.convertDecimalToNativeInteger(STARTING_BALANCE));awaitutils.sleep(500);console.log(`User margin acc balance: ${Exchange.riskCalculator.getCrossMarginAccountState(client.account!) .balance}` );awaitPromise.all(ASSETS.map(async (asset) => {returnclient.initializeOpenOrdersAccount(asset); }) );awaitPromise.all(ASSETS.map(async (asset) => {let singleMarketTx =newTransaction();for (let i =0; i <MAX_SINGLE_MARKET_PLACE_ORDER_IXS; i++) {singleMarketTx.add(client.createPlacePerpOrderInstruction( asset,utils.convertDecimalToNativeInteger((i +1) /100),utils.convertDecimalToNativeLotSize(1),types.Side.BID ) ); }awaitutils.processTransaction(client.provider, singleMarketTx,undefined,undefined,undefined,utils.getZetaLutArr() ); }) );awaitutils.sleep(2000);ASSETS.forEach((asset) => {console.log(`client has ${client.getOrders(asset).length} orders on ${asset}` ); });awaitclient.cancelAllMarketOrders();let multiMarketTx =newTransaction();for (let i =0; i <MAX_ALL_PERP_MARKET_PLACE_ORDER_IXS; i++) {multiMarketTx.add(client.createPlacePerpOrderInstruction(ASSETS[0],utils.convertDecimalToNativeInteger((i +1) /100),utils.convertDecimalToNativeLotSize(0.01),types.Side.BID ) ); }awaitutils.processTransaction(client.provider, multiMarketTx,undefined,undefined,undefined,utils.getZetaLutArr() );awaitutils.sleep(2000);ASSETS.forEach((asset) => {console.log(`client has ${client.getOrders(asset).length} orders on ${asset}` ); });awaitExchange.close();awaitclient.close();}main().catch(console.error.bind(console));