@solana/instruction-plans 6.3.1 → 6.3.2-canary-20260313112147
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.
- package/package.json +9 -8
- package/src/append-instruction-plan.ts +90 -0
- package/src/index.ts +60 -0
- package/src/instruction-plan-input.ts +258 -0
- package/src/instruction-plan.ts +1066 -0
- package/src/transaction-plan-errors.ts +261 -0
- package/src/transaction-plan-executor.ts +307 -0
- package/src/transaction-plan-result.ts +1583 -0
- package/src/transaction-plan.ts +721 -0
- package/src/transaction-planner.ts +421 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/instruction-plans",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.2-canary-20260313112147",
|
|
4
4
|
"description": "Construct, plan and execute transactions from multiple instructions.",
|
|
5
5
|
"homepage": "https://www.solanakit.com/api#solanainstruction-plans",
|
|
6
6
|
"exports": {
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"types": "./dist/types/index.d.ts",
|
|
34
34
|
"type": "commonjs",
|
|
35
35
|
"files": [
|
|
36
|
-
"./dist/"
|
|
36
|
+
"./dist/",
|
|
37
|
+
"./src/"
|
|
37
38
|
],
|
|
38
39
|
"sideEffects": false,
|
|
39
40
|
"keywords": [
|
|
@@ -55,12 +56,12 @@
|
|
|
55
56
|
"maintained node versions"
|
|
56
57
|
],
|
|
57
58
|
"dependencies": {
|
|
58
|
-
"@solana/errors": "6.3.
|
|
59
|
-
"@solana/
|
|
60
|
-
"@solana/
|
|
61
|
-
"@solana/promises": "6.3.
|
|
62
|
-
"@solana/transaction-messages": "6.3.
|
|
63
|
-
"@solana/transactions": "6.3.
|
|
59
|
+
"@solana/errors": "6.3.2-canary-20260313112147",
|
|
60
|
+
"@solana/instructions": "6.3.2-canary-20260313112147",
|
|
61
|
+
"@solana/keys": "6.3.2-canary-20260313112147",
|
|
62
|
+
"@solana/promises": "6.3.2-canary-20260313112147",
|
|
63
|
+
"@solana/transaction-messages": "6.3.2-canary-20260313112147",
|
|
64
|
+
"@solana/transactions": "6.3.2-canary-20260313112147"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"typescript": "^5.0.0"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SOLANA_ERROR__INVARIANT_VIOLATION__INVALID_INSTRUCTION_PLAN_KIND, SolanaError } from '@solana/errors';
|
|
2
|
+
import { type Instruction } from '@solana/instructions';
|
|
3
|
+
import {
|
|
4
|
+
appendTransactionMessageInstruction,
|
|
5
|
+
appendTransactionMessageInstructions,
|
|
6
|
+
TransactionMessage,
|
|
7
|
+
TransactionMessageWithFeePayer,
|
|
8
|
+
} from '@solana/transaction-messages';
|
|
9
|
+
|
|
10
|
+
import { flattenInstructionPlan, InstructionPlan } from './instruction-plan';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A helper type to append instructions to a transaction message
|
|
14
|
+
* without losing type information about the current instructions.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
type AppendTransactionMessageInstructions<TTransactionMessage extends TransactionMessage> = ReturnType<
|
|
18
|
+
typeof appendTransactionMessageInstructions<TTransactionMessage, Instruction[]>
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Appends all instructions from an instruction plan to a transaction message.
|
|
23
|
+
*
|
|
24
|
+
* This function flattens the instruction plan into its leaf plans and sequentially
|
|
25
|
+
* appends each instruction to the provided transaction message. It handles both
|
|
26
|
+
* single instructions and message packer plans.
|
|
27
|
+
*
|
|
28
|
+
* Note that any {@link MessagePackerInstructionPlan} is assumed to only append
|
|
29
|
+
* instructions. If it modifies other properties of the transaction message, the
|
|
30
|
+
* type of the returned transaction message may not accurately reflect those changes.
|
|
31
|
+
*
|
|
32
|
+
* @typeParam TTransactionMessage - The type of transaction message being modified.
|
|
33
|
+
*
|
|
34
|
+
* @param transactionMessage - The transaction message to append instructions to.
|
|
35
|
+
* @param instructionPlan - The instruction plan containing the instructions to append.
|
|
36
|
+
* @returns The transaction message with all instructions from the plan appended.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* Appending a simple instruction plan to a transaction message.
|
|
40
|
+
* ```ts
|
|
41
|
+
* import { appendTransactionMessageInstructionPlan } from '@solana/instruction-plans';
|
|
42
|
+
* import { createTransactionMessage, setTransactionMessageFeePayer } from '@solana/transaction-messages';
|
|
43
|
+
*
|
|
44
|
+
* const message = setTransactionMessageFeePayer(feePayer, createTransactionMessage({ version: 0 }));
|
|
45
|
+
* const plan = singleInstructionPlan(myInstruction);
|
|
46
|
+
*
|
|
47
|
+
* const messageWithInstructions = appendTransactionMessageInstructionPlan(message, plan);
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* Appending a sequential instruction plan.
|
|
52
|
+
* ```ts
|
|
53
|
+
* const plan = sequentialInstructionPlan([instructionA, instructionB, instructionC]);
|
|
54
|
+
* const messageWithInstructions = appendTransactionMessageInstructionPlan(message, plan);
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @see {@link InstructionPlan}
|
|
58
|
+
* @see {@link flattenInstructionPlan}
|
|
59
|
+
*/
|
|
60
|
+
export function appendTransactionMessageInstructionPlan<
|
|
61
|
+
TTransactionMessage extends TransactionMessage & TransactionMessageWithFeePayer,
|
|
62
|
+
>(
|
|
63
|
+
instructionPlan: InstructionPlan,
|
|
64
|
+
transactionMessage: TTransactionMessage,
|
|
65
|
+
): AppendTransactionMessageInstructions<TTransactionMessage> {
|
|
66
|
+
type Out = AppendTransactionMessageInstructions<TTransactionMessage>;
|
|
67
|
+
|
|
68
|
+
const leafInstructionPlans = flattenInstructionPlan(instructionPlan);
|
|
69
|
+
|
|
70
|
+
return leafInstructionPlans.reduce(
|
|
71
|
+
(messageSoFar, plan) => {
|
|
72
|
+
const kind = plan.kind;
|
|
73
|
+
if (kind === 'single') {
|
|
74
|
+
return appendTransactionMessageInstruction(plan.instruction, messageSoFar) as unknown as Out;
|
|
75
|
+
}
|
|
76
|
+
if (kind === 'messagePacker') {
|
|
77
|
+
const messagerPacker = plan.getMessagePacker();
|
|
78
|
+
let nextMessage: Out = messageSoFar;
|
|
79
|
+
while (!messagerPacker.done()) {
|
|
80
|
+
nextMessage = messagerPacker.packMessageToCapacity(nextMessage) as Out;
|
|
81
|
+
}
|
|
82
|
+
return nextMessage;
|
|
83
|
+
}
|
|
84
|
+
throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__INVALID_INSTRUCTION_PLAN_KIND, {
|
|
85
|
+
kind,
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
transactionMessage as unknown as Out,
|
|
89
|
+
);
|
|
90
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instruction plans describe operations that go beyond a
|
|
3
|
+
* single instruction and may even span multiple transactions.
|
|
4
|
+
*
|
|
5
|
+
* They define a set of instructions that must be executed following a specific order.
|
|
6
|
+
* For instance, imagine we wanted to create an instruction plan for a simple escrow
|
|
7
|
+
* transfer between Alice and Bob. First, both would need to deposit their assets
|
|
8
|
+
* into a vault. This could happen in any order. Then and only then, the vault can be
|
|
9
|
+
* activated to switch the assets. Alice and Bob can now both withdraw each other’s assets
|
|
10
|
+
* (again, in any order). Here’s how we could describe an instruction plan for such an operation.
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const instructionPlan = sequentialInstructionPlan([
|
|
14
|
+
* parallelInstructionPlan([
|
|
15
|
+
* depositFromAlice,
|
|
16
|
+
* depositFromBob,
|
|
17
|
+
* ]),
|
|
18
|
+
* activateVault,
|
|
19
|
+
* parallelInstructionPlan([
|
|
20
|
+
* withdrawToAlice,
|
|
21
|
+
* withdrawToBob,
|
|
22
|
+
* ]),
|
|
23
|
+
* ]);
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* As you can see, instruction plans don’t concern themselves with:
|
|
27
|
+
* - Adding structural instructions — e.g. compute budget limits and prices.
|
|
28
|
+
* - Building transaction messages from these instructions.
|
|
29
|
+
* That is planning how many can fit into a single instruction, adding a fee payer, a lifetime, etc.
|
|
30
|
+
* - Compiling, signing and sending transactions to the network.
|
|
31
|
+
*
|
|
32
|
+
* Instead, they solely focus on describing operations and delegate
|
|
33
|
+
* all that to two components introduced in this package:
|
|
34
|
+
* - **Transaction planner**: builds transaction messages from an
|
|
35
|
+
* instruction plan and returns an appropriate transaction plan.
|
|
36
|
+
* - **Transaction plan executor**: compiles, signs and sends
|
|
37
|
+
* transaction plans and returns a detailed result of this operation.
|
|
38
|
+
*
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Plan instructions into transactions.
|
|
41
|
+
* const transactionPlan = await transactionPlanner(instructionPlan);
|
|
42
|
+
*
|
|
43
|
+
* // Execute transactions.
|
|
44
|
+
* const transactionPlanResult = await transactionPlanExecutor(transactionPlan);
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* This separation of concerns not only improves the developer experience but also
|
|
48
|
+
* allows program maintainers to offer helper functions that go beyond a single instruction,
|
|
49
|
+
* while leaving their consumers to decide how they want these operations to materialise.
|
|
50
|
+
*
|
|
51
|
+
* @packageDocumentation
|
|
52
|
+
*/
|
|
53
|
+
export * from './append-instruction-plan';
|
|
54
|
+
export * from './instruction-plan';
|
|
55
|
+
export * from './instruction-plan-input';
|
|
56
|
+
export * from './transaction-plan';
|
|
57
|
+
export * from './transaction-plan-errors';
|
|
58
|
+
export * from './transaction-plan-executor';
|
|
59
|
+
export * from './transaction-plan-result';
|
|
60
|
+
export * from './transaction-planner';
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import type { Instruction } from '@solana/instructions';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type InstructionPlan,
|
|
5
|
+
isInstructionPlan,
|
|
6
|
+
sequentialInstructionPlan,
|
|
7
|
+
singleInstructionPlan,
|
|
8
|
+
} from './instruction-plan';
|
|
9
|
+
import {
|
|
10
|
+
isTransactionPlan,
|
|
11
|
+
sequentialTransactionPlan,
|
|
12
|
+
SingleTransactionPlan,
|
|
13
|
+
singleTransactionPlan,
|
|
14
|
+
TransactionPlan,
|
|
15
|
+
} from './transaction-plan';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A flexible input type that can be used to create an {@link InstructionPlan}.
|
|
19
|
+
*
|
|
20
|
+
* This type accepts:
|
|
21
|
+
* - A single {@link Instruction}.
|
|
22
|
+
* - An existing {@link InstructionPlan}.
|
|
23
|
+
* - An array of instructions and/or instruction plans.
|
|
24
|
+
*
|
|
25
|
+
* Use the {@link parseInstructionPlanInput} function to convert this input
|
|
26
|
+
* into a proper {@link InstructionPlan}.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* Using a single instruction.
|
|
30
|
+
* ```ts
|
|
31
|
+
* const input: InstructionPlanInput = myInstruction;
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* Use as argument type in a function that will parse it into an InstructionPlan.
|
|
36
|
+
* ```ts
|
|
37
|
+
* function myFunction(input: InstructionPlanInput) {
|
|
38
|
+
* const plan = parseInstructionPlanInput(input);
|
|
39
|
+
* // Use the plan...
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @see {@link parseInstructionPlanInput}
|
|
44
|
+
* @see {@link InstructionPlan}
|
|
45
|
+
*/
|
|
46
|
+
export type InstructionPlanInput = Instruction | InstructionPlan | readonly (Instruction | InstructionPlan)[];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Parses an {@link InstructionPlanInput} and returns an {@link InstructionPlan}.
|
|
50
|
+
*
|
|
51
|
+
* This function handles the following input types:
|
|
52
|
+
* - A single {@link Instruction} is wrapped in a {@link SingleInstructionPlan}.
|
|
53
|
+
* - An existing {@link InstructionPlan} is returned as-is.
|
|
54
|
+
* - An array with a single element is unwrapped and parsed recursively.
|
|
55
|
+
* - An array with multiple elements is wrapped in a divisible {@link SequentialInstructionPlan}.
|
|
56
|
+
*
|
|
57
|
+
* @param input - The input to parse into an instruction plan.
|
|
58
|
+
* @return The parsed instruction plan.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* Parsing a single instruction.
|
|
62
|
+
* ```ts
|
|
63
|
+
* const plan = parseInstructionPlanInput(myInstruction);
|
|
64
|
+
* // Equivalent to: singleInstructionPlan(myInstruction)
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* Parsing an array of instructions.
|
|
69
|
+
* ```ts
|
|
70
|
+
* const plan = parseInstructionPlanInput([instructionA, instructionB]);
|
|
71
|
+
* // Equivalent to: sequentialInstructionPlan([instructionA, instructionB])
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* Parsing a mixed array with nested plans.
|
|
76
|
+
* ```ts
|
|
77
|
+
* const plan = parseInstructionPlanInput([
|
|
78
|
+
* instructionA,
|
|
79
|
+
* parallelInstructionPlan([instructionB, instructionC]),
|
|
80
|
+
* ]);
|
|
81
|
+
* // Returns a sequential plan containing:
|
|
82
|
+
* // - A single instruction plan for instructionA.
|
|
83
|
+
* // - The parallel plan for instructionB and instructionC.
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* Single-element arrays are unwrapped.
|
|
88
|
+
* ```ts
|
|
89
|
+
* const plan = parseInstructionPlanInput([myInstruction]);
|
|
90
|
+
* // Equivalent to: singleInstructionPlan(myInstruction)
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @see {@link InstructionPlanInput}
|
|
94
|
+
* @see {@link InstructionPlan}
|
|
95
|
+
*/
|
|
96
|
+
export function parseInstructionPlanInput(input: InstructionPlanInput): InstructionPlan {
|
|
97
|
+
if (Array.isArray(input) && input.length === 1) {
|
|
98
|
+
return parseInstructionPlanInput(input[0]);
|
|
99
|
+
}
|
|
100
|
+
if (Array.isArray(input)) {
|
|
101
|
+
return sequentialInstructionPlan(input.map(parseInstructionPlanInput));
|
|
102
|
+
}
|
|
103
|
+
return isInstructionPlan(input) ? input : singleInstructionPlan(input as Instruction);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A flexible input type that can be used to create a {@link TransactionPlan}.
|
|
108
|
+
*
|
|
109
|
+
* This type accepts:
|
|
110
|
+
* - A single {@link TransactionMessage} with a fee payer.
|
|
111
|
+
* - An existing {@link TransactionPlan}.
|
|
112
|
+
* - An array of transaction messages and/or transaction plans.
|
|
113
|
+
*
|
|
114
|
+
* Use the {@link parseTransactionPlanInput} function to convert this input
|
|
115
|
+
* into a proper {@link TransactionPlan}.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* Using a single transaction message.
|
|
119
|
+
* ```ts
|
|
120
|
+
* const input: TransactionPlanInput = myTransactionMessage;
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* Use as argument type in a function that will parse it into a TransactionPlan.
|
|
125
|
+
* ```ts
|
|
126
|
+
* function myFunction(input: TransactionPlanInput) {
|
|
127
|
+
* const plan = parseTransactionPlanInput(input);
|
|
128
|
+
* // Use the plan...
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @see {@link parseTransactionPlanInput}
|
|
133
|
+
* @see {@link TransactionPlan}
|
|
134
|
+
*/
|
|
135
|
+
export type TransactionPlanInput =
|
|
136
|
+
| SingleTransactionPlan['message']
|
|
137
|
+
| TransactionPlan
|
|
138
|
+
| readonly (SingleTransactionPlan['message'] | TransactionPlan)[];
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Parses a {@link TransactionPlanInput} and returns a {@link TransactionPlan}.
|
|
142
|
+
*
|
|
143
|
+
* This function handles the following input types:
|
|
144
|
+
* - A single {@link TransactionMessage} is wrapped in a {@link SingleTransactionPlan}.
|
|
145
|
+
* - An existing {@link TransactionPlan} is returned as-is.
|
|
146
|
+
* - An array with a single element is unwrapped and parsed recursively.
|
|
147
|
+
* - An array with multiple elements is wrapped in a divisible {@link SequentialTransactionPlan}.
|
|
148
|
+
*
|
|
149
|
+
* @param input - The input to parse into a transaction plan.
|
|
150
|
+
* @return The parsed transaction plan.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* Parsing a single transaction message.
|
|
154
|
+
* ```ts
|
|
155
|
+
* const plan = parseTransactionPlanInput(myTransactionMessage);
|
|
156
|
+
* // Equivalent to: singleTransactionPlan(myTransactionMessage)
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* Parsing an array of transaction messages.
|
|
161
|
+
* ```ts
|
|
162
|
+
* const plan = parseTransactionPlanInput([messageA, messageB]);
|
|
163
|
+
* // Equivalent to: sequentialTransactionPlan([messageA, messageB])
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* Parsing a mixed array with nested plans.
|
|
168
|
+
* ```ts
|
|
169
|
+
* const plan = parseTransactionPlanInput([
|
|
170
|
+
* messageA,
|
|
171
|
+
* parallelTransactionPlan([messageB, messageC]),
|
|
172
|
+
* ]);
|
|
173
|
+
* // Returns a sequential plan containing:
|
|
174
|
+
* // - A single transaction plan for messageA.
|
|
175
|
+
* // - The parallel plan for messageB and messageC.
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* Single-element arrays are unwrapped.
|
|
180
|
+
* ```ts
|
|
181
|
+
* const plan = parseTransactionPlanInput([myTransactionMessage]);
|
|
182
|
+
* // Equivalent to: singleTransactionPlan(myTransactionMessage)
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* @see {@link TransactionPlanInput}
|
|
186
|
+
* @see {@link TransactionPlan}
|
|
187
|
+
*/
|
|
188
|
+
export function parseTransactionPlanInput(input: TransactionPlanInput): TransactionPlan {
|
|
189
|
+
if (Array.isArray(input) && input.length === 1) {
|
|
190
|
+
return parseTransactionPlanInput(input[0]);
|
|
191
|
+
}
|
|
192
|
+
if (Array.isArray(input)) {
|
|
193
|
+
return sequentialTransactionPlan(input.map(item => parseTransactionPlanInput(item)));
|
|
194
|
+
}
|
|
195
|
+
return isTransactionPlan(input) ? input : singleTransactionPlan(input as SingleTransactionPlan['message']);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Parses an {@link InstructionPlanInput} or {@link TransactionPlanInput} and
|
|
200
|
+
* returns the appropriate plan type.
|
|
201
|
+
*
|
|
202
|
+
* This function automatically detects whether the input represents instructions
|
|
203
|
+
* or transactions and delegates to the appropriate parser:
|
|
204
|
+
* - If the input is a transaction message or transaction plan, it delegates
|
|
205
|
+
* to {@link parseTransactionPlanInput}.
|
|
206
|
+
* - Otherwise, it delegates to {@link parseInstructionPlanInput}.
|
|
207
|
+
*
|
|
208
|
+
* @param input - The input to parse, which can be either an instruction-based
|
|
209
|
+
* or transaction-based input.
|
|
210
|
+
* @returns The parsed plan, either an {@link InstructionPlan} or a {@link TransactionPlan}.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* Parsing an instruction input.
|
|
214
|
+
* ```ts
|
|
215
|
+
* const plan = parseInstructionOrTransactionPlanInput(myInstruction);
|
|
216
|
+
* // Returns an InstructionPlan
|
|
217
|
+
* ```
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* Parsing a transaction message input.
|
|
221
|
+
* ```ts
|
|
222
|
+
* const plan = parseInstructionOrTransactionPlanInput(myTransactionMessage);
|
|
223
|
+
* // Returns a TransactionPlan
|
|
224
|
+
* ```
|
|
225
|
+
*
|
|
226
|
+
* @see {@link parseInstructionPlanInput}
|
|
227
|
+
* @see {@link parseTransactionPlanInput}
|
|
228
|
+
* @see {@link InstructionPlanInput}
|
|
229
|
+
* @see {@link TransactionPlanInput}
|
|
230
|
+
*/
|
|
231
|
+
export function parseInstructionOrTransactionPlanInput(
|
|
232
|
+
input: InstructionPlanInput | TransactionPlanInput,
|
|
233
|
+
): InstructionPlan | TransactionPlan {
|
|
234
|
+
if (Array.isArray(input) && input.length === 0) {
|
|
235
|
+
return parseTransactionPlanInput(input);
|
|
236
|
+
}
|
|
237
|
+
if (Array.isArray(input) && isTransactionPlanInput(input[0])) {
|
|
238
|
+
return parseTransactionPlanInput(input as TransactionPlanInput);
|
|
239
|
+
}
|
|
240
|
+
if (isTransactionPlanInput(input)) {
|
|
241
|
+
return parseTransactionPlanInput(input as TransactionPlanInput);
|
|
242
|
+
}
|
|
243
|
+
return parseInstructionPlanInput(input as InstructionPlanInput);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function isTransactionPlanInput(value: unknown): value is SingleTransactionPlan['message'] | TransactionPlan {
|
|
247
|
+
return isTransactionPlan(value) || isTransactionMessage(value);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function isTransactionMessage(value: unknown): value is SingleTransactionPlan['message'] {
|
|
251
|
+
return (
|
|
252
|
+
typeof value === 'object' &&
|
|
253
|
+
value !== null &&
|
|
254
|
+
'instructions' in value &&
|
|
255
|
+
Array.isArray(value.instructions) &&
|
|
256
|
+
'version' in value
|
|
257
|
+
);
|
|
258
|
+
}
|