This repository was archived by the owner on Feb 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 545
Expand file tree
/
Copy pathexecuteTransaction.ts
More file actions
105 lines (98 loc) · 3.21 KB
/
executeTransaction.ts
File metadata and controls
105 lines (98 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import {
ComputeBudgetProgram,
Keypair,
Transaction,
TransactionInstruction,
} from '@solana/web3.js'
import {
sendSignedAndAdjacentTransactions,
sendTransaction,
signTransactions,
} from '@utils/send'
import Wallet from '@project-serum/sol-wallet-adapter'
import {
RpcContext,
Proposal,
ProposalTransaction,
withExecuteTransaction,
ProgramAccount,
} from '@solana/spl-governance'
import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery'
/**
* Executes a proposal transaction
* @param rpcContext RPC contextual information
* @param proposal Metadata about the proposal
* @param instruction Instruction that will be executed by the proposal
* @param adjacentTransaction Optional transaction that is sent in the same slot as the proposal instruction.
* @param preExecutionTransactions Optional transactions that are executed before the proposal instruction
*/
export const executeTransaction = async (
{ connection, wallet, programId }: RpcContext,
proposal: ProgramAccount<Proposal>,
instruction: ProgramAccount<ProposalTransaction>,
adjacentTransaction?: Transaction,
preExecutionTransactions?: Transaction[]
) => {
const signers: Keypair[] = []
const instructions: TransactionInstruction[] = []
// Explicitly request the version before making RPC calls to work around race conditions in resolving
// the version for RealmInfo
const programVersion = await fetchProgramVersion(connection, programId)
await withExecuteTransaction(
instructions,
programId,
programVersion,
proposal.account.governance,
proposal.pubkey,
instruction.pubkey,
[...instruction.account.getAllInstructions()]
)
// Create proposal transaction
const proposalTransaction = new Transaction().add(
ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
...instructions
)
// Sign and send all pre-execution transactions
if (preExecutionTransactions && !preExecutionTransactions?.length) {
await Promise.all(
preExecutionTransactions.map((transaction) =>
sendTransaction({
transaction,
wallet,
connection,
sendingMessage: 'Sending pre-execution transaction',
successMessage: 'Sent pre-execution transaction',
})
)
)
}
// Some proposals require additional adjacent transactions due to tx size limits
if (adjacentTransaction) {
const [signedProposalTx, signedAdjacentTx] = await signTransactions({
transactionsAndSigners: [
{ transaction: proposalTransaction },
{ transaction: adjacentTransaction },
],
wallet: (wallet as unknown) as Wallet,
connection,
})
// Send proposal transaction with prepended adjacent transaction
await sendSignedAndAdjacentTransactions({
signedTransaction: signedProposalTx,
adjacentTransaction: signedAdjacentTx,
connection,
sendingMessage: 'Executing instruction',
successMessage: 'Execution finalized',
})
} else {
// Send the proposal transaction
await sendTransaction({
transaction: proposalTransaction,
wallet,
connection,
signers,
sendingMessage: 'Executing instruction',
successMessage: 'Execution finalized',
})
}
}