import { SendTxRequest } from "@project-serum/anchor/dist/provider"; import { PublicKey } from "@solana/web3.js"; const MAX_TX_SIZE = 1232; // How much space we want to leave for being safe const BUFFER_ROOM = 130; export const breakUpInstrDataArrays = ( items: T[], createTxFn: (items: T[]) => SendTxRequest ): SendTxRequest[] => { let lastIncluded = 0; let finalSet: T[][] = []; let currentSet: T[] = []; // This has to be base 58 string, with 32 bytes const blockhash = PublicKey.default.toBase58(); while (lastIncluded !== items.length) { currentSet.push(items[lastIncluded]); try { const ret = createTxFn(currentSet); // Set to a dummy 32 byte hash so that we can serialize and get size of the tx ret.tx.recentBlockhash = blockhash; // Again, place a dummy ret.tx.feePayer = PublicKey.default; const serialLen = ret.tx.serializeMessage().length; ret.tx.recentBlockhash = undefined; ret.tx.feePayer = undefined; if (serialLen > MAX_TX_SIZE - BUFFER_ROOM) { throw "encoding overruns buffer"; } lastIncluded += 1; } catch (error) { if ( (error.toString() as string) .toLowerCase() .includes("encoding overruns buffer") ) { // Remove the element which caused the failure currentSet.pop(); finalSet.push([...currentSet]); currentSet = []; } else { throw error; } } } if (currentSet.length !== 0) finalSet.push([...currentSet]); return finalSet.map((set) => { return createTxFn(set); }); }; /** * have dummy as a "nonce", otherwise the tx simulator can give that a transaction was already * processed because there may be requests which look the same (imagine 100 actions all with the same output shape * and you do 5 add actions) * * NOTE: this is not cryptographically secure, but is only meant to help differentiate between txs for the frontend */ export const getRandomNotCryptoSecureNonce = (min: number, max: number) => { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; };