📬Versioned Transactions
Fit more instructions into a single transaction with Solana's new features
Github repository: https://github.com/zetamarkets/sdk/tree/main/examples/versioned-txes
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";
const NETWORK_URL = process.env["network_url"]!;
const SERVER_URL = process.env["server_url"];
const STARTING_BALANCE = 10_000;
const ASSETS = [constants.Asset.SOL, constants.Asset.ARB, constants.Asset.APT];
const USER_KEY = Keypair.generate();
const WALLET = new Wallet(USER_KEY);
const CONNECTION: Connection = new Connection(NETWORK_URL, "confirmed");
const MAX_SINGLE_MARKET_PLACE_ORDER_IXS = 6;
const MAX_ALL_PERP_MARKET_PLACE_ORDER_IXS = 6;
async function main() {
// Airdropping SOL.
await CONNECTION.requestAirdrop(WALLET.publicKey, 1_000_000_000);
await fetch(`${SERVER_URL}/faucet/USDC`, {
method: "post",
body: JSON.stringify({
key: WALLET.publicKey.toString(),
amount: 10_000,
}),
headers: { "Content-Type": "application/json" },
});
const loadExchangeConfig = types.defaultLoadExchangeConfig(
Network.DEVNET,
CONNECTION,
utils.defaultCommitment(),
0, // ThrottleMs - increase if you are running into rate limit issues on startup.
true
);
await Exchange.load(loadExchangeConfig);
const client = await CrossClient.load(
CONNECTION,
WALLET,
undefined,
undefined,
undefined,
undefined,
true
);
console.log("client loaded:", client.publicKey.toBase58());
await client.deposit(utils.convertDecimalToNativeInteger(STARTING_BALANCE));
await utils.sleep(500);
console.log(
`User margin acc balance: ${
Exchange.riskCalculator.getCrossMarginAccountState(client.account!)
.balance
}`
);
await Promise.all(
ASSETS.map(async (asset) => {
return client.initializeOpenOrdersAccount(asset);
})
);
await Promise.all(
ASSETS.map(async (asset) => {
let singleMarketTx = new Transaction();
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
)
);
}
await utils.processTransaction(
client.provider,
singleMarketTx,
undefined,
undefined,
undefined,
utils.getZetaLutArr()
);
})
);
await utils.sleep(2000);
ASSETS.forEach((asset) => {
console.log(
`client has ${client.getOrders(asset).length} orders on ${asset}`
);
});
await client.cancelAllMarketOrders();
let multiMarketTx = new Transaction();
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
)
);
}
await utils.processTransaction(
client.provider,
multiMarketTx,
undefined,
undefined,
undefined,
utils.getZetaLutArr()
);
await utils.sleep(2000);
ASSETS.forEach((asset) => {
console.log(
`client has ${client.getOrders(asset).length} orders on ${asset}`
);
});
await Exchange.close();
await client.close();
}
main().catch(console.error.bind(console));
Last updated