@solana-program/compute-budget 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +3 -8
  2. package/dist/src/index.js +8 -15
  3. package/dist/src/index.js.map +1 -1
  4. package/dist/src/index.mjs +9 -16
  5. package/dist/src/index.mjs.map +1 -1
  6. package/dist/types/estimateAndSetComputeLimit.d.ts.map +1 -1
  7. package/dist/types/estimateComputeLimitInternal.d.ts.map +1 -1
  8. package/dist/types/generated/instructions/requestHeapFrame.d.ts +1 -1
  9. package/dist/types/generated/instructions/requestHeapFrame.d.ts.map +1 -1
  10. package/dist/types/generated/instructions/requestUnits.d.ts +1 -1
  11. package/dist/types/generated/instructions/requestUnits.d.ts.map +1 -1
  12. package/dist/types/generated/instructions/setComputeUnitLimit.d.ts +1 -1
  13. package/dist/types/generated/instructions/setComputeUnitLimit.d.ts.map +1 -1
  14. package/dist/types/generated/instructions/setComputeUnitPrice.d.ts +1 -1
  15. package/dist/types/generated/instructions/setComputeUnitPrice.d.ts.map +1 -1
  16. package/dist/types/generated/instructions/setLoadedAccountsDataSizeLimit.d.ts +1 -1
  17. package/dist/types/generated/instructions/setLoadedAccountsDataSizeLimit.d.ts.map +1 -1
  18. package/dist/types/generated/programs/computeBudget.d.ts +1 -1
  19. package/dist/types/generated/programs/computeBudget.d.ts.map +1 -1
  20. package/dist/types/introspect.d.ts.map +1 -1
  21. package/dist/types/setComputeLimit.d.ts.map +1 -1
  22. package/dist/types/setComputePrice.d.ts.map +1 -1
  23. package/package.json +34 -29
  24. package/src/constants.ts +12 -0
  25. package/src/estimateAndSetComputeLimit.ts +58 -0
  26. package/src/estimateComputeLimit.ts +77 -0
  27. package/src/estimateComputeLimitInternal.ts +167 -0
  28. package/src/generated/index.ts +10 -0
  29. package/src/generated/instructions/index.ts +13 -0
  30. package/src/generated/instructions/requestHeapFrame.ts +114 -0
  31. package/src/generated/instructions/requestUnits.ts +115 -0
  32. package/src/generated/instructions/setComputeUnitLimit.ts +110 -0
  33. package/src/generated/instructions/setComputeUnitPrice.ts +110 -0
  34. package/src/generated/instructions/setLoadedAccountsDataSizeLimit.ts +107 -0
  35. package/src/generated/programs/computeBudget.ts +181 -0
  36. package/src/generated/programs/index.ts +9 -0
  37. package/src/index.ts +8 -0
  38. package/src/introspect.ts +75 -0
  39. package/src/setComputeLimit.ts +76 -0
  40. package/src/setComputePrice.ts +78 -0
@@ -0,0 +1,110 @@
1
+ /**
2
+ * This code was AUTOGENERATED using the Codama library.
3
+ * Please DO NOT EDIT THIS FILE, instead use visitors
4
+ * to add features, then rerun Codama to update it.
5
+ *
6
+ * @see https://github.com/codama-idl/codama
7
+ */
8
+
9
+ import {
10
+ combineCodec,
11
+ getStructDecoder,
12
+ getStructEncoder,
13
+ getU64Decoder,
14
+ getU64Encoder,
15
+ getU8Decoder,
16
+ getU8Encoder,
17
+ transformEncoder,
18
+ type AccountMeta,
19
+ type Address,
20
+ type FixedSizeCodec,
21
+ type FixedSizeDecoder,
22
+ type FixedSizeEncoder,
23
+ type Instruction,
24
+ type InstructionWithAccounts,
25
+ type InstructionWithData,
26
+ type ReadonlyUint8Array,
27
+ } from '@solana/kit';
28
+ import { COMPUTE_BUDGET_PROGRAM_ADDRESS } from '../programs';
29
+
30
+ export const SET_COMPUTE_UNIT_PRICE_DISCRIMINATOR = 3;
31
+
32
+ export function getSetComputeUnitPriceDiscriminatorBytes(): ReadonlyUint8Array {
33
+ return getU8Encoder().encode(SET_COMPUTE_UNIT_PRICE_DISCRIMINATOR);
34
+ }
35
+
36
+ export type SetComputeUnitPriceInstruction<
37
+ TProgram extends string = typeof COMPUTE_BUDGET_PROGRAM_ADDRESS,
38
+ TRemainingAccounts extends readonly AccountMeta<string>[] = [],
39
+ > = Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<TRemainingAccounts>;
40
+
41
+ export type SetComputeUnitPriceInstructionData = {
42
+ discriminator: number;
43
+ /** Transaction compute unit price used for prioritization fees. */
44
+ microLamports: bigint;
45
+ };
46
+
47
+ export type SetComputeUnitPriceInstructionDataArgs = {
48
+ /** Transaction compute unit price used for prioritization fees. */
49
+ microLamports: number | bigint;
50
+ };
51
+
52
+ export function getSetComputeUnitPriceInstructionDataEncoder(): FixedSizeEncoder<SetComputeUnitPriceInstructionDataArgs> {
53
+ return transformEncoder(
54
+ getStructEncoder([
55
+ ['discriminator', getU8Encoder()],
56
+ ['microLamports', getU64Encoder()],
57
+ ]),
58
+ value => ({ ...value, discriminator: SET_COMPUTE_UNIT_PRICE_DISCRIMINATOR }),
59
+ );
60
+ }
61
+
62
+ export function getSetComputeUnitPriceInstructionDataDecoder(): FixedSizeDecoder<SetComputeUnitPriceInstructionData> {
63
+ return getStructDecoder([
64
+ ['discriminator', getU8Decoder()],
65
+ ['microLamports', getU64Decoder()],
66
+ ]);
67
+ }
68
+
69
+ export function getSetComputeUnitPriceInstructionDataCodec(): FixedSizeCodec<
70
+ SetComputeUnitPriceInstructionDataArgs,
71
+ SetComputeUnitPriceInstructionData
72
+ > {
73
+ return combineCodec(getSetComputeUnitPriceInstructionDataEncoder(), getSetComputeUnitPriceInstructionDataDecoder());
74
+ }
75
+
76
+ export type SetComputeUnitPriceInput = {
77
+ microLamports: SetComputeUnitPriceInstructionDataArgs['microLamports'];
78
+ };
79
+
80
+ export function getSetComputeUnitPriceInstruction<
81
+ TProgramAddress extends Address = typeof COMPUTE_BUDGET_PROGRAM_ADDRESS,
82
+ >(
83
+ input: SetComputeUnitPriceInput,
84
+ config?: { programAddress?: TProgramAddress },
85
+ ): SetComputeUnitPriceInstruction<TProgramAddress> {
86
+ // Program address.
87
+ const programAddress = config?.programAddress ?? COMPUTE_BUDGET_PROGRAM_ADDRESS;
88
+
89
+ // Original args.
90
+ const args = { ...input };
91
+
92
+ return Object.freeze({
93
+ data: getSetComputeUnitPriceInstructionDataEncoder().encode(args as SetComputeUnitPriceInstructionDataArgs),
94
+ programAddress,
95
+ } as SetComputeUnitPriceInstruction<TProgramAddress>);
96
+ }
97
+
98
+ export type ParsedSetComputeUnitPriceInstruction<TProgram extends string = typeof COMPUTE_BUDGET_PROGRAM_ADDRESS> = {
99
+ programAddress: Address<TProgram>;
100
+ data: SetComputeUnitPriceInstructionData;
101
+ };
102
+
103
+ export function parseSetComputeUnitPriceInstruction<TProgram extends string>(
104
+ instruction: Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array>,
105
+ ): ParsedSetComputeUnitPriceInstruction<TProgram> {
106
+ return {
107
+ programAddress: instruction.programAddress,
108
+ data: getSetComputeUnitPriceInstructionDataDecoder().decode(instruction.data),
109
+ };
110
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * This code was AUTOGENERATED using the Codama library.
3
+ * Please DO NOT EDIT THIS FILE, instead use visitors
4
+ * to add features, then rerun Codama to update it.
5
+ *
6
+ * @see https://github.com/codama-idl/codama
7
+ */
8
+
9
+ import {
10
+ combineCodec,
11
+ getStructDecoder,
12
+ getStructEncoder,
13
+ getU32Decoder,
14
+ getU32Encoder,
15
+ getU8Decoder,
16
+ getU8Encoder,
17
+ transformEncoder,
18
+ type AccountMeta,
19
+ type Address,
20
+ type FixedSizeCodec,
21
+ type FixedSizeDecoder,
22
+ type FixedSizeEncoder,
23
+ type Instruction,
24
+ type InstructionWithAccounts,
25
+ type InstructionWithData,
26
+ type ReadonlyUint8Array,
27
+ } from '@solana/kit';
28
+ import { COMPUTE_BUDGET_PROGRAM_ADDRESS } from '../programs';
29
+
30
+ export const SET_LOADED_ACCOUNTS_DATA_SIZE_LIMIT_DISCRIMINATOR = 4;
31
+
32
+ export function getSetLoadedAccountsDataSizeLimitDiscriminatorBytes(): ReadonlyUint8Array {
33
+ return getU8Encoder().encode(SET_LOADED_ACCOUNTS_DATA_SIZE_LIMIT_DISCRIMINATOR);
34
+ }
35
+
36
+ export type SetLoadedAccountsDataSizeLimitInstruction<
37
+ TProgram extends string = typeof COMPUTE_BUDGET_PROGRAM_ADDRESS,
38
+ TRemainingAccounts extends readonly AccountMeta<string>[] = [],
39
+ > = Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<TRemainingAccounts>;
40
+
41
+ export type SetLoadedAccountsDataSizeLimitInstructionData = { discriminator: number; accountDataSizeLimit: number };
42
+
43
+ export type SetLoadedAccountsDataSizeLimitInstructionDataArgs = { accountDataSizeLimit: number };
44
+
45
+ export function getSetLoadedAccountsDataSizeLimitInstructionDataEncoder(): FixedSizeEncoder<SetLoadedAccountsDataSizeLimitInstructionDataArgs> {
46
+ return transformEncoder(
47
+ getStructEncoder([
48
+ ['discriminator', getU8Encoder()],
49
+ ['accountDataSizeLimit', getU32Encoder()],
50
+ ]),
51
+ value => ({ ...value, discriminator: SET_LOADED_ACCOUNTS_DATA_SIZE_LIMIT_DISCRIMINATOR }),
52
+ );
53
+ }
54
+
55
+ export function getSetLoadedAccountsDataSizeLimitInstructionDataDecoder(): FixedSizeDecoder<SetLoadedAccountsDataSizeLimitInstructionData> {
56
+ return getStructDecoder([
57
+ ['discriminator', getU8Decoder()],
58
+ ['accountDataSizeLimit', getU32Decoder()],
59
+ ]);
60
+ }
61
+
62
+ export function getSetLoadedAccountsDataSizeLimitInstructionDataCodec(): FixedSizeCodec<
63
+ SetLoadedAccountsDataSizeLimitInstructionDataArgs,
64
+ SetLoadedAccountsDataSizeLimitInstructionData
65
+ > {
66
+ return combineCodec(
67
+ getSetLoadedAccountsDataSizeLimitInstructionDataEncoder(),
68
+ getSetLoadedAccountsDataSizeLimitInstructionDataDecoder(),
69
+ );
70
+ }
71
+
72
+ export type SetLoadedAccountsDataSizeLimitInput = {
73
+ accountDataSizeLimit: SetLoadedAccountsDataSizeLimitInstructionDataArgs['accountDataSizeLimit'];
74
+ };
75
+
76
+ export function getSetLoadedAccountsDataSizeLimitInstruction<
77
+ TProgramAddress extends Address = typeof COMPUTE_BUDGET_PROGRAM_ADDRESS,
78
+ >(
79
+ input: SetLoadedAccountsDataSizeLimitInput,
80
+ config?: { programAddress?: TProgramAddress },
81
+ ): SetLoadedAccountsDataSizeLimitInstruction<TProgramAddress> {
82
+ // Program address.
83
+ const programAddress = config?.programAddress ?? COMPUTE_BUDGET_PROGRAM_ADDRESS;
84
+
85
+ // Original args.
86
+ const args = { ...input };
87
+
88
+ return Object.freeze({
89
+ data: getSetLoadedAccountsDataSizeLimitInstructionDataEncoder().encode(
90
+ args as SetLoadedAccountsDataSizeLimitInstructionDataArgs,
91
+ ),
92
+ programAddress,
93
+ } as SetLoadedAccountsDataSizeLimitInstruction<TProgramAddress>);
94
+ }
95
+
96
+ export type ParsedSetLoadedAccountsDataSizeLimitInstruction<
97
+ TProgram extends string = typeof COMPUTE_BUDGET_PROGRAM_ADDRESS,
98
+ > = { programAddress: Address<TProgram>; data: SetLoadedAccountsDataSizeLimitInstructionData };
99
+
100
+ export function parseSetLoadedAccountsDataSizeLimitInstruction<TProgram extends string>(
101
+ instruction: Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array>,
102
+ ): ParsedSetLoadedAccountsDataSizeLimitInstruction<TProgram> {
103
+ return {
104
+ programAddress: instruction.programAddress,
105
+ data: getSetLoadedAccountsDataSizeLimitInstructionDataDecoder().decode(instruction.data),
106
+ };
107
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * This code was AUTOGENERATED using the Codama library.
3
+ * Please DO NOT EDIT THIS FILE, instead use visitors
4
+ * to add features, then rerun Codama to update it.
5
+ *
6
+ * @see https://github.com/codama-idl/codama
7
+ */
8
+
9
+ import {
10
+ containsBytes,
11
+ extendClient,
12
+ getU8Encoder,
13
+ SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_INSTRUCTION,
14
+ SOLANA_ERROR__PROGRAM_CLIENTS__UNRECOGNIZED_INSTRUCTION_TYPE,
15
+ SolanaError,
16
+ type Address,
17
+ type ClientWithTransactionPlanning,
18
+ type ClientWithTransactionSending,
19
+ type Instruction,
20
+ type InstructionWithData,
21
+ type ReadonlyUint8Array,
22
+ } from '@solana/kit';
23
+ import { addSelfPlanAndSendFunctions, type SelfPlanAndSendFunctions } from '@solana/kit/program-client-core';
24
+ import {
25
+ getRequestHeapFrameInstruction,
26
+ getRequestUnitsInstruction,
27
+ getSetComputeUnitLimitInstruction,
28
+ getSetComputeUnitPriceInstruction,
29
+ getSetLoadedAccountsDataSizeLimitInstruction,
30
+ parseRequestHeapFrameInstruction,
31
+ parseRequestUnitsInstruction,
32
+ parseSetComputeUnitLimitInstruction,
33
+ parseSetComputeUnitPriceInstruction,
34
+ parseSetLoadedAccountsDataSizeLimitInstruction,
35
+ type ParsedRequestHeapFrameInstruction,
36
+ type ParsedRequestUnitsInstruction,
37
+ type ParsedSetComputeUnitLimitInstruction,
38
+ type ParsedSetComputeUnitPriceInstruction,
39
+ type ParsedSetLoadedAccountsDataSizeLimitInstruction,
40
+ type RequestHeapFrameInput,
41
+ type RequestUnitsInput,
42
+ type SetComputeUnitLimitInput,
43
+ type SetComputeUnitPriceInput,
44
+ type SetLoadedAccountsDataSizeLimitInput,
45
+ } from '../instructions';
46
+
47
+ export const COMPUTE_BUDGET_PROGRAM_ADDRESS =
48
+ 'ComputeBudget111111111111111111111111111111' as Address<'ComputeBudget111111111111111111111111111111'>;
49
+
50
+ export enum ComputeBudgetInstruction {
51
+ RequestUnits,
52
+ RequestHeapFrame,
53
+ SetComputeUnitLimit,
54
+ SetComputeUnitPrice,
55
+ SetLoadedAccountsDataSizeLimit,
56
+ }
57
+
58
+ export function identifyComputeBudgetInstruction(
59
+ instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array,
60
+ ): ComputeBudgetInstruction {
61
+ const data = 'data' in instruction ? instruction.data : instruction;
62
+ if (containsBytes(data, getU8Encoder().encode(0), 0)) {
63
+ return ComputeBudgetInstruction.RequestUnits;
64
+ }
65
+ if (containsBytes(data, getU8Encoder().encode(1), 0)) {
66
+ return ComputeBudgetInstruction.RequestHeapFrame;
67
+ }
68
+ if (containsBytes(data, getU8Encoder().encode(2), 0)) {
69
+ return ComputeBudgetInstruction.SetComputeUnitLimit;
70
+ }
71
+ if (containsBytes(data, getU8Encoder().encode(3), 0)) {
72
+ return ComputeBudgetInstruction.SetComputeUnitPrice;
73
+ }
74
+ if (containsBytes(data, getU8Encoder().encode(4), 0)) {
75
+ return ComputeBudgetInstruction.SetLoadedAccountsDataSizeLimit;
76
+ }
77
+ throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_INSTRUCTION, {
78
+ instructionData: data,
79
+ programName: 'computeBudget',
80
+ });
81
+ }
82
+
83
+ export type ParsedComputeBudgetInstruction<TProgram extends string = 'ComputeBudget111111111111111111111111111111'> =
84
+ | ({ instructionType: ComputeBudgetInstruction.RequestUnits } & ParsedRequestUnitsInstruction<TProgram>)
85
+ | ({ instructionType: ComputeBudgetInstruction.RequestHeapFrame } & ParsedRequestHeapFrameInstruction<TProgram>)
86
+ | ({
87
+ instructionType: ComputeBudgetInstruction.SetComputeUnitLimit;
88
+ } & ParsedSetComputeUnitLimitInstruction<TProgram>)
89
+ | ({
90
+ instructionType: ComputeBudgetInstruction.SetComputeUnitPrice;
91
+ } & ParsedSetComputeUnitPriceInstruction<TProgram>)
92
+ | ({
93
+ instructionType: ComputeBudgetInstruction.SetLoadedAccountsDataSizeLimit;
94
+ } & ParsedSetLoadedAccountsDataSizeLimitInstruction<TProgram>);
95
+
96
+ export function parseComputeBudgetInstruction<TProgram extends string>(
97
+ instruction: Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array>,
98
+ ): ParsedComputeBudgetInstruction<TProgram> {
99
+ const instructionType = identifyComputeBudgetInstruction(instruction);
100
+ switch (instructionType) {
101
+ case ComputeBudgetInstruction.RequestUnits: {
102
+ return {
103
+ instructionType: ComputeBudgetInstruction.RequestUnits,
104
+ ...parseRequestUnitsInstruction(instruction),
105
+ };
106
+ }
107
+ case ComputeBudgetInstruction.RequestHeapFrame: {
108
+ return {
109
+ instructionType: ComputeBudgetInstruction.RequestHeapFrame,
110
+ ...parseRequestHeapFrameInstruction(instruction),
111
+ };
112
+ }
113
+ case ComputeBudgetInstruction.SetComputeUnitLimit: {
114
+ return {
115
+ instructionType: ComputeBudgetInstruction.SetComputeUnitLimit,
116
+ ...parseSetComputeUnitLimitInstruction(instruction),
117
+ };
118
+ }
119
+ case ComputeBudgetInstruction.SetComputeUnitPrice: {
120
+ return {
121
+ instructionType: ComputeBudgetInstruction.SetComputeUnitPrice,
122
+ ...parseSetComputeUnitPriceInstruction(instruction),
123
+ };
124
+ }
125
+ case ComputeBudgetInstruction.SetLoadedAccountsDataSizeLimit: {
126
+ return {
127
+ instructionType: ComputeBudgetInstruction.SetLoadedAccountsDataSizeLimit,
128
+ ...parseSetLoadedAccountsDataSizeLimitInstruction(instruction),
129
+ };
130
+ }
131
+ default:
132
+ throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__UNRECOGNIZED_INSTRUCTION_TYPE, {
133
+ instructionType: instructionType as string,
134
+ programName: 'computeBudget',
135
+ });
136
+ }
137
+ }
138
+
139
+ export type ComputeBudgetPlugin = { instructions: ComputeBudgetPluginInstructions };
140
+
141
+ export type ComputeBudgetPluginInstructions = {
142
+ requestUnits: (
143
+ input: RequestUnitsInput,
144
+ ) => ReturnType<typeof getRequestUnitsInstruction> & SelfPlanAndSendFunctions;
145
+ requestHeapFrame: (
146
+ input: RequestHeapFrameInput,
147
+ ) => ReturnType<typeof getRequestHeapFrameInstruction> & SelfPlanAndSendFunctions;
148
+ setComputeUnitLimit: (
149
+ input: SetComputeUnitLimitInput,
150
+ ) => ReturnType<typeof getSetComputeUnitLimitInstruction> & SelfPlanAndSendFunctions;
151
+ setComputeUnitPrice: (
152
+ input: SetComputeUnitPriceInput,
153
+ ) => ReturnType<typeof getSetComputeUnitPriceInstruction> & SelfPlanAndSendFunctions;
154
+ setLoadedAccountsDataSizeLimit: (
155
+ input: SetLoadedAccountsDataSizeLimitInput,
156
+ ) => ReturnType<typeof getSetLoadedAccountsDataSizeLimitInstruction> & SelfPlanAndSendFunctions;
157
+ };
158
+
159
+ export type ComputeBudgetPluginRequirements = ClientWithTransactionPlanning & ClientWithTransactionSending;
160
+
161
+ export function computeBudgetProgram() {
162
+ return <T extends ComputeBudgetPluginRequirements>(
163
+ client: T,
164
+ ): Omit<T, 'computeBudget'> & { computeBudget: ComputeBudgetPlugin } => {
165
+ return extendClient(client, {
166
+ computeBudget: <ComputeBudgetPlugin>{
167
+ instructions: {
168
+ requestUnits: input => addSelfPlanAndSendFunctions(client, getRequestUnitsInstruction(input)),
169
+ requestHeapFrame: input =>
170
+ addSelfPlanAndSendFunctions(client, getRequestHeapFrameInstruction(input)),
171
+ setComputeUnitLimit: input =>
172
+ addSelfPlanAndSendFunctions(client, getSetComputeUnitLimitInstruction(input)),
173
+ setComputeUnitPrice: input =>
174
+ addSelfPlanAndSendFunctions(client, getSetComputeUnitPriceInstruction(input)),
175
+ setLoadedAccountsDataSizeLimit: input =>
176
+ addSelfPlanAndSendFunctions(client, getSetLoadedAccountsDataSizeLimitInstruction(input)),
177
+ },
178
+ },
179
+ });
180
+ };
181
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * This code was AUTOGENERATED using the Codama library.
3
+ * Please DO NOT EDIT THIS FILE, instead use visitors
4
+ * to add features, then rerun Codama to update it.
5
+ *
6
+ * @see https://github.com/codama-idl/codama
7
+ */
8
+
9
+ export * from './computeBudget';
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './generated';
2
+
3
+ export * from './constants';
4
+ export * from './estimateAndSetComputeLimit';
5
+ export * from './estimateComputeLimit';
6
+ export * from './introspect';
7
+ export * from './setComputeLimit';
8
+ export * from './setComputePrice';
@@ -0,0 +1,75 @@
1
+ import {
2
+ TransactionMessage,
3
+ getU32Decoder,
4
+ getU64Decoder,
5
+ Instruction,
6
+ MicroLamports,
7
+ ReadonlyUint8Array,
8
+ } from '@solana/kit';
9
+
10
+ import {
11
+ COMPUTE_BUDGET_PROGRAM_ADDRESS,
12
+ ComputeBudgetInstruction,
13
+ identifyComputeBudgetInstruction,
14
+ SetComputeUnitLimitInstruction,
15
+ SetComputeUnitPriceInstruction,
16
+ } from './generated';
17
+
18
+ /**
19
+ * Finds the index of the first `SetComputeUnitLimit` instruction in a transaction message
20
+ * and its set limit, if any.
21
+ */
22
+ export function findSetComputeUnitLimitInstructionIndexAndUnits(
23
+ transactionMessage: TransactionMessage,
24
+ ): { index: number; units: number } | null {
25
+ const index = transactionMessage.instructions.findIndex(isSetComputeUnitLimitInstruction);
26
+ if (index < 0) {
27
+ return null;
28
+ }
29
+
30
+ const units = getU32Decoder().decode(transactionMessage.instructions[index].data as ReadonlyUint8Array, 1);
31
+
32
+ return { index, units };
33
+ }
34
+
35
+ /**
36
+ * Checks if the given instruction is a `SetComputeUnitLimit` instruction.
37
+ */
38
+ function isSetComputeUnitLimitInstruction(instruction: Instruction): instruction is SetComputeUnitLimitInstruction {
39
+ return (
40
+ instruction.programAddress === COMPUTE_BUDGET_PROGRAM_ADDRESS &&
41
+ identifyComputeBudgetInstruction(instruction.data as Uint8Array) ===
42
+ ComputeBudgetInstruction.SetComputeUnitLimit
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Finds the index of the first `SetComputeUnitPrice` instruction in a transaction message
48
+ * and its set micro-lamports, if any.
49
+ */
50
+ export function findSetComputeUnitPriceInstructionIndexAndMicroLamports(
51
+ transactionMessage: TransactionMessage,
52
+ ): { index: number; microLamports: MicroLamports } | null {
53
+ const index = transactionMessage.instructions.findIndex(isSetComputeUnitPriceInstruction);
54
+ if (index < 0) {
55
+ return null;
56
+ }
57
+
58
+ const microLamports = getU64Decoder().decode(
59
+ transactionMessage.instructions[index].data as ReadonlyUint8Array,
60
+ 1,
61
+ ) as MicroLamports;
62
+
63
+ return { index, microLamports };
64
+ }
65
+
66
+ /**
67
+ * Checks if the given instruction is a `SetComputeUnitPrice` instruction.
68
+ */
69
+ function isSetComputeUnitPriceInstruction(instruction: Instruction): instruction is SetComputeUnitPriceInstruction {
70
+ return (
71
+ instruction.programAddress === COMPUTE_BUDGET_PROGRAM_ADDRESS &&
72
+ identifyComputeBudgetInstruction(instruction.data as Uint8Array) ===
73
+ ComputeBudgetInstruction.SetComputeUnitPrice
74
+ );
75
+ }
@@ -0,0 +1,76 @@
1
+ import { appendTransactionMessageInstruction, TransactionMessage } from '@solana/kit';
2
+
3
+ import { PROVISORY_COMPUTE_UNIT_LIMIT } from './constants';
4
+ import { getSetComputeUnitLimitInstruction } from './generated';
5
+ import { findSetComputeUnitLimitInstructionIndexAndUnits } from './introspect';
6
+
7
+ /**
8
+ * Appends a `SetComputeUnitLimit` instruction with a provisory
9
+ * compute unit limit to a given transaction message
10
+ * if and only if it does not already have one.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const transactionMessage = pipe(
15
+ * createTransactionMessage({ version: 0 }),
16
+ * fillProvisorySetComputeUnitLimitInstruction,
17
+ * // ...
18
+ * );
19
+ * ```
20
+ */
21
+ export function fillProvisorySetComputeUnitLimitInstruction<TTransactionMessage extends TransactionMessage>(
22
+ transactionMessage: TTransactionMessage,
23
+ ) {
24
+ return updateOrAppendSetComputeUnitLimitInstruction(
25
+ previousUnits => (previousUnits === null ? PROVISORY_COMPUTE_UNIT_LIMIT : previousUnits),
26
+ transactionMessage,
27
+ );
28
+ }
29
+
30
+ /**
31
+ * Updates the first `SetComputeUnitLimit` instruction in a transaction message
32
+ * with the given units, or appends a new instruction if none exists.
33
+ * A function of the current value can be provided instead of a static value.
34
+ *
35
+ * @param units - The new compute unit limit, or a function that takes the previous
36
+ * compute unit limit and returns the new limit.
37
+ * @param transactionMessage - The transaction message to update.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const updatedTransactionMessage = updateOrAppendSetComputeUnitLimitInstruction(
42
+ * // E.g. Keep the current limit if it is set, otherwise set it to the maximum.
43
+ * (currentUnits) => currentUnits === null ? MAX_COMPUTE_UNIT_LIMIT : currentUnits,
44
+ * transactionMessage,
45
+ * );
46
+ * ```
47
+ */
48
+ export function updateOrAppendSetComputeUnitLimitInstruction<TTransactionMessage extends TransactionMessage>(
49
+ units: number | ((previousUnits: number | null) => number),
50
+ transactionMessage: TTransactionMessage,
51
+ ): TTransactionMessage {
52
+ const getUnits = (previousUnits: number | null): number =>
53
+ typeof units === 'function' ? units(previousUnits) : units;
54
+ const instructionDetails = findSetComputeUnitLimitInstructionIndexAndUnits(transactionMessage);
55
+
56
+ if (!instructionDetails) {
57
+ return appendTransactionMessageInstruction(
58
+ getSetComputeUnitLimitInstruction({ units: getUnits(null) }),
59
+ transactionMessage,
60
+ ) as TTransactionMessage;
61
+ }
62
+
63
+ const { index, units: previousUnits } = instructionDetails;
64
+ const newUnits = getUnits(previousUnits);
65
+ if (newUnits === previousUnits) {
66
+ return transactionMessage;
67
+ }
68
+
69
+ const newInstruction = getSetComputeUnitLimitInstruction({ units: newUnits });
70
+ const newInstructions = [...transactionMessage.instructions];
71
+ newInstructions.splice(index, 1, newInstruction);
72
+ return Object.freeze({
73
+ ...transactionMessage,
74
+ instructions: newInstructions,
75
+ }) as TTransactionMessage;
76
+ }
@@ -0,0 +1,78 @@
1
+ import { appendTransactionMessageInstruction, TransactionMessage, MicroLamports } from '@solana/kit';
2
+
3
+ import { getSetComputeUnitPriceInstruction } from './generated';
4
+ import { findSetComputeUnitPriceInstructionIndexAndMicroLamports } from './introspect';
5
+
6
+ /**
7
+ * Sets the compute unit price of a transaction message in micro-Lamports.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const transactionMessage = pipe(
12
+ * createTransactionMessage({ version: 0 }),
13
+ * (m) => setTransactionMessageComputeUnitPrice(10_000, m),
14
+ * // ...
15
+ * );
16
+ * ```
17
+ */
18
+ export function setTransactionMessageComputeUnitPrice<TTransactionMessage extends TransactionMessage>(
19
+ microLamports: number | bigint,
20
+ transactionMessage: TTransactionMessage,
21
+ ) {
22
+ return appendTransactionMessageInstruction(
23
+ getSetComputeUnitPriceInstruction({ microLamports }),
24
+ transactionMessage,
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Updates the first `SetComputeUnitPrice` instruction in a transaction message
30
+ * with the given micro-Lamports, or appends a new instruction if none exists.
31
+ * A function of the current value can be provided instead of a static value.
32
+ *
33
+ * @param microLamports - The new compute unit price, or a function that
34
+ * takes the previous price and returns the new one.
35
+ * @param transactionMessage - The transaction message to update.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const updatedTransactionMessage = updateOrAppendSetComputeUnitPriceInstruction(
40
+ * // E.g. double the current price or set it to 10_000 if it isn't set.
41
+ * (currentPrice) => currentPrice === null ? 10_000 : currentPrice * 2,
42
+ * transactionMessage,
43
+ * );
44
+ * ```
45
+ */
46
+ export function updateOrAppendSetComputeUnitPriceInstruction<TTransactionMessage extends TransactionMessage>(
47
+ microLamports: MicroLamports | ((previousMicroLamports: MicroLamports | null) => MicroLamports),
48
+ transactionMessage: TTransactionMessage,
49
+ ): TTransactionMessage {
50
+ const getMicroLamports = (previousMicroLamports: MicroLamports | null): MicroLamports =>
51
+ typeof microLamports === 'function' ? microLamports(previousMicroLamports) : microLamports;
52
+ const instructionDetails = findSetComputeUnitPriceInstructionIndexAndMicroLamports(transactionMessage);
53
+
54
+ if (!instructionDetails) {
55
+ return appendTransactionMessageInstruction(
56
+ getSetComputeUnitPriceInstruction({
57
+ microLamports: getMicroLamports(null),
58
+ }),
59
+ transactionMessage,
60
+ ) as TTransactionMessage;
61
+ }
62
+
63
+ const { index, microLamports: previousMicroLamports } = instructionDetails;
64
+ const newMicroLamports = getMicroLamports(previousMicroLamports);
65
+ if (newMicroLamports === previousMicroLamports) {
66
+ return transactionMessage;
67
+ }
68
+
69
+ const newInstruction = getSetComputeUnitPriceInstruction({
70
+ microLamports: newMicroLamports,
71
+ });
72
+ const newInstructions = [...transactionMessage.instructions];
73
+ newInstructions.splice(index, 1, newInstruction);
74
+ return Object.freeze({
75
+ ...transactionMessage,
76
+ instructions: newInstructions,
77
+ }) as TTransactionMessage;
78
+ }