Skip to content

Instantly share code, notes, and snippets.

@mralbertchen
Created November 16, 2022 19:01
Show Gist options
  • Save mralbertchen/dfb8c27134f0cf5124b287f73af5e49f to your computer and use it in GitHub Desktop.
Save mralbertchen/dfb8c27134f0cf5124b287f73af5e49f to your computer and use it in GitHub Desktop.
Fit ixs into txs
getTransactionBaseSize(signers = 1) {
return (
3 + // compact array length encoding for signatures (compact-u16, 1-3 bytes)
64 * signers + // number of signatures
3 + // message header
32 // blockhash
);
}
getInstructionByteSize(
ix: TransactionInstruction,
newAccounts = ix.keys.length + 1
) {
return (
1 + // program id index
3 + // compact array length encoding for keys (compact-u16, 1-3 bytes)
ix.keys.length + // key index length
ix.data.length + // data length
newAccounts * 32 // key size + deduct existing accounts in transaction
);
}
getAddedSize(
ixAddresses: string[],
currentAccounts: string[],
ix: TransactionInstruction
) {
const newAccounts = difference(ixAddresses, currentAccounts);
// console.log(`instruction has ${newAccounts.length} new accounts`);
const addedSize = this.getInstructionByteSize(ix, newAccounts.length);
// console.log(`instruction adds ${addedSize} bytes to tx`);
return { addedSize, newAccounts };
}
fitInstructionsIntoTransactions(ixs: TransactionInstruction[], signers = 1) {
const baseTxSize = this.getTransactionBaseSize(signers);
const txs = [];
const sizes = [];
let currentTx = new anchor.web3.Transaction();
let currentSize = baseTxSize;
let currentAccounts: string[] = [];
txs.push(currentTx);
for (const ix of ixs) {
const ixAddresses = [
...ix.keys.map((meta) => meta.pubkey),
ix.programId,
].map((key) => key.toString());
let { addedSize, newAccounts } = this.getAddedSize(
ixAddresses,
currentAccounts,
ix
);
if (currentSize + addedSize < this.MAX_TX_SIZE) {
currentTx.add(ix);
currentSize += addedSize;
} else {
// console.log(`Does not fit, creating new tx`);
sizes.push(currentSize);
currentTx = new anchor.web3.Transaction();
currentTx.add(ix);
// recalculate added size
currentAccounts = [];
({ addedSize, newAccounts } = this.getAddedSize(
ixAddresses,
currentAccounts,
ix
));
currentSize = baseTxSize + addedSize;
txs.push(currentTx);
}
// console.log(`currentSize: ${currentSize}`);
currentAccounts.push(...newAccounts);
}
sizes.push(currentSize);
// console.log(
// `Transaction count:`,
// txs.length,
// `Instruction breakdown:`,
// txs.map((tx) => tx.instructions.length),
// `Sizes:`,
// sizes
// );
return txs;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment