diff --git a/gauntlet/packages/gauntlet-serum-multisig/src/commands/multisig.ts b/gauntlet/packages/gauntlet-serum-multisig/src/commands/multisig.ts index a7023cd16..ee6c8b190 100644 --- a/gauntlet/packages/gauntlet-serum-multisig/src/commands/multisig.ts +++ b/gauntlet/packages/gauntlet-serum-multisig/src/commands/multisig.ts @@ -74,7 +74,10 @@ export const wrapCommand = (command) => { if (this.flags.execute) { await prompt('Continue?') logger.loading(`Executing action...`) - const txhash = await this.sendTxWithIDL(this.signAndSendRawTx, this.program.idl)(rawTxs) + const txhash = await this.sendTxWithIDL(this.signAndSendRawTx, this.program.idl)(rawTxs, null, { + price: Number(this.flags.computePrice), + units: Number(this.flags.computeUnits), + }) logger.success(`TX succeded at ${txhash}`) const msigState = await this.fetchMultisigState(this.multisigAddress) @@ -90,23 +93,19 @@ export const wrapCommand = (command) => { } } - const latestSlot = await this.provider.connection.getSlot() - const recentBlock = await this.provider.connection.getBlock(latestSlot) - if (!recentBlock) { + const { blockhash, lastValidBlockHeight } = await this.provider.connection.getLatestBlockhash() + if (!lastValidBlockHeight) { throw new Error('Block not found. Could not generate message data') } const tx = utils.makeTx(rawTxs, { - recentBlockhash: recentBlock.blockhash, + blockhash, + lastValidBlockHeight, feePayer: signer, }) const msgData = tx.serializeMessage().toString('base64') logger.line() - logger.success( - `Message generated with blockhash ID: ${recentBlock.blockhash.toString()} (${new Date( - recentBlock.blockTime! * 1000, - ).toLocaleString()}). MESSAGE DATA:`, - ) + logger.success(`Message generated with blockhash ID: ${blockhash.toString()}). MESSAGE DATA:`) logger.log() logger.log(msgData) logger.log() diff --git a/gauntlet/packages/gauntlet-solana/src/commands/internal/solana.ts b/gauntlet/packages/gauntlet-solana/src/commands/internal/solana.ts index 2837fcaf1..8521f7e04 100644 --- a/gauntlet/packages/gauntlet-solana/src/commands/internal/solana.ts +++ b/gauntlet/packages/gauntlet-solana/src/commands/internal/solana.ts @@ -81,12 +81,23 @@ export default abstract class SolanaCommand extends WriteCommand => { - const recentBlockhash = (await this.provider.connection.getRecentBlockhash()).blockhash - const tx = makeTx(rawTxs, { - recentBlockhash, - feePayer: this.wallet.publicKey, - }) + const { blockhash, lastValidBlockHeight } = await this.provider.connection.getLatestBlockhash() + if (overrides.units) logger.info(`Sending transaction with custom unit limit: ${overrides.units}`) + if (overrides.price) logger.info(`Sending transaction with custom unit price: ${overrides.price}`) + const tx = makeTx( + rawTxs, + { + blockhash, + lastValidBlockHeight, + feePayer: this.wallet.publicKey, + }, + overrides, + ) if (extraSigners) { tx.sign(...extraSigners) } @@ -113,8 +124,11 @@ export default abstract class SolanaCommand extends WriteCommand { try { + const { blockhash, lastValidBlockHeight } = await this.provider.connection.getLatestBlockhash() const tx = makeTx(txInstructions, { feePayer: feePayer || signer, + blockhash, + lastValidBlockHeight, }) // simulating through connection allows to skip signing tx (useful when using Ledger device) const { value: simulationResponse } = await this.provider.connection.simulateTransaction(tx) diff --git a/gauntlet/packages/gauntlet-solana/src/lib/utils.ts b/gauntlet/packages/gauntlet-solana/src/lib/utils.ts index 7a0a97417..411c918fe 100644 --- a/gauntlet/packages/gauntlet-solana/src/lib/utils.ts +++ b/gauntlet/packages/gauntlet-solana/src/lib/utils.ts @@ -1,5 +1,17 @@ -import { Transaction, TransactionInstruction, TransactionCtorFields } from '@solana/web3.js' +import { Transaction, TransactionInstruction, TransactionBlockhashCtor, ComputeBudgetProgram } from '@solana/web3.js' -export const makeTx = (rawTx: TransactionInstruction[], opts?: TransactionCtorFields): Transaction => { - return rawTx.reduce((tx, instruction) => tx.add(instruction), new Transaction(opts)) +export const makeTx = ( + rawTx: TransactionInstruction[], + opts?: TransactionBlockhashCtor, + overrides: { price?: number; units?: number } = {}, +): Transaction => { + if (overrides.price && overrides.units) + throw new Error('Cannot set limit for units and price in the same transaction') + + let computeIx: TransactionInstruction + if (overrides.price) computeIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: overrides.price }) + if (overrides.units) computeIx = ComputeBudgetProgram.setComputeUnitLimit({ units: overrides.units }) + const initialTx = computeIx ? new Transaction(opts).add(computeIx) : new Transaction(opts) + + return rawTx.reduce((tx, instruction) => tx.add(instruction), initialTx) }