Skip to content

Commit

Permalink
Add Gauntlet support for custom unit price and limit (#425)
Browse files Browse the repository at this point in the history
* add support for custom unit price and limit

* fix signers
  • Loading branch information
RodrigoAD committed Nov 9, 2022
1 parent 9eb6060 commit 0fa7d3a
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 18 deletions.
19 changes: 9 additions & 10 deletions gauntlet/packages/gauntlet-serum-multisig/src/commands/multisig.ts
Expand Up @@ -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)
Expand All @@ -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()
Expand Down
24 changes: 19 additions & 5 deletions gauntlet/packages/gauntlet-solana/src/commands/internal/solana.ts
Expand Up @@ -81,12 +81,23 @@ export default abstract class SolanaCommand extends WriteCommand<TransactionResp
signAndSendRawTx = async (
rawTxs: TransactionInstruction[],
extraSigners?: Keypair[],
overrides: {
units?: number
price?: number
} = {},
): Promise<TransactionSignature> => {
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)
}
Expand All @@ -113,8 +124,11 @@ export default abstract class SolanaCommand extends WriteCommand<TransactionResp

simulateTx = async (signer: PublicKey, txInstructions: TransactionInstruction[], feePayer?: PublicKey) => {
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)
Expand Down
18 changes: 15 additions & 3 deletions 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)
}

0 comments on commit 0fa7d3a

Please sign in to comment.