@solana/program-client-core 8.3.0-canary-20260909094827 → 8.3.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.
- package/dist/index.browser.cjs +20 -3
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.mjs +21 -4
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.native.mjs +21 -4
- package/dist/index.native.mjs.map +1 -1
- package/dist/index.node.cjs +20 -3
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +21 -4
- package/dist/index.node.mjs.map +1 -1
- package/dist/types/instruction-input-resolution.d.ts +171 -10
- package/dist/types/instruction-input-resolution.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/instruction-input-resolution.ts +230 -17
|
@@ -1,6 +1,36 @@
|
|
|
1
|
-
import { type Address, type ProgramDerivedAddress } from '@solana/addresses';
|
|
2
|
-
import { type AccountMeta } from '@solana/instructions';
|
|
1
|
+
import { type Address, type HasAddress, type ProgramDerivedAddress } from '@solana/addresses';
|
|
2
|
+
import { type AccountMeta, type AccountNonSignerMeta, AccountRole } from '@solana/instructions';
|
|
3
3
|
import { type AccountSignerMeta, type TransactionSigner } from '@solana/signers';
|
|
4
|
+
/**
|
|
5
|
+
* Represents the accepted input values for a non-signer instruction account.
|
|
6
|
+
*
|
|
7
|
+
* Namely, one of the following:
|
|
8
|
+
* - An {@link Address} — the most common case.
|
|
9
|
+
* - Any object exposing an `address` property (see {@link HasAddress}) — e.g. a framework's
|
|
10
|
+
* address wrapper class. Note that {@link TransactionSigner | TransactionSigners} satisfy this
|
|
11
|
+
* shape too, in which case they act as plain address carriers for non-signer accounts.
|
|
12
|
+
* - A {@link ProgramDerivedAddress} — i.e. an `[address, bump]` tuple.
|
|
13
|
+
* - An {@link AccountNonSignerMeta} — i.e. `{ address, role }` — to explicitly override the
|
|
14
|
+
* role derived from the program's IDL, e.g. to mark an account as writable or readonly.
|
|
15
|
+
*
|
|
16
|
+
* @typeParam TAddress - Supply a string literal to define an account having a particular address.
|
|
17
|
+
*
|
|
18
|
+
* @see {@link InstructionSignerInput}
|
|
19
|
+
*/
|
|
20
|
+
export type InstructionAccountInput<TAddress extends string = string> = AccountNonSignerMeta<TAddress> | Address<TAddress> | HasAddress<TAddress> | ProgramDerivedAddress<TAddress>;
|
|
21
|
+
/**
|
|
22
|
+
* Represents the accepted input values for a signer instruction account.
|
|
23
|
+
*
|
|
24
|
+
* Namely, one of the following:
|
|
25
|
+
* - A {@link TransactionSigner} — the most common case.
|
|
26
|
+
* - An {@link AccountSignerMeta} — i.e. `{ address, role, signer }` — to explicitly override the
|
|
27
|
+
* role derived from the program's IDL, e.g. to mark a signer account as writable or readonly.
|
|
28
|
+
*
|
|
29
|
+
* @typeParam TAddress - Supply a string literal to define an account having a particular address.
|
|
30
|
+
*
|
|
31
|
+
* @see {@link InstructionAccountInput}
|
|
32
|
+
*/
|
|
33
|
+
export type InstructionSignerInput<TAddress extends string = string> = AccountSignerMeta<TAddress> | TransactionSigner<TAddress>;
|
|
4
34
|
/**
|
|
5
35
|
* Ensures a resolved instruction input is not null or undefined.
|
|
6
36
|
*
|
|
@@ -29,8 +59,9 @@ export declare function getNonNullResolvedInstructionInput<T>(inputName: string,
|
|
|
29
59
|
* Extracts the address from a resolved instruction account.
|
|
30
60
|
*
|
|
31
61
|
* A resolved instruction account can be an {@link Address}, a {@link ProgramDerivedAddress},
|
|
32
|
-
* or a {@link TransactionSigner}
|
|
33
|
-
*
|
|
62
|
+
* or any object exposing an `address` property — such as a {@link TransactionSigner}, an
|
|
63
|
+
* account meta, or a framework's address wrapper class (see {@link HasAddress}). This
|
|
64
|
+
* function extracts the underlying address from any of these types.
|
|
34
65
|
*
|
|
35
66
|
* @typeParam T - The address type, defaults to `string`.
|
|
36
67
|
*
|
|
@@ -70,7 +101,8 @@ export declare function getResolvedInstructionAccountAsProgramDerivedAddress<T e
|
|
|
70
101
|
/**
|
|
71
102
|
* Extracts a {@link TransactionSigner} from a resolved instruction account.
|
|
72
103
|
*
|
|
73
|
-
* This function validates that the resolved account is a transaction signer
|
|
104
|
+
* This function validates that the resolved account is a transaction signer — or an
|
|
105
|
+
* {@link AccountSignerMeta} carrying one — and returns the signer.
|
|
74
106
|
* Use this when you need the resolved account to be a signer.
|
|
75
107
|
*
|
|
76
108
|
* @typeParam T - The address type, defaults to `string`.
|
|
@@ -90,10 +122,16 @@ export declare function getResolvedInstructionAccountAsTransactionSigner<T exten
|
|
|
90
122
|
/**
|
|
91
123
|
* Represents a resolved account input for an instruction.
|
|
92
124
|
*
|
|
93
|
-
* During instruction building, account inputs are resolved to this type which
|
|
94
|
-
*
|
|
95
|
-
* The value can be
|
|
96
|
-
*
|
|
125
|
+
* During instruction building, account inputs are resolved to this type which captures
|
|
126
|
+
* the account value alongside the signer and writable flags declared by the program's IDL.
|
|
127
|
+
* The value can be any {@link InstructionAccountInput}, any {@link InstructionSignerInput},
|
|
128
|
+
* or `null` for optional accounts.
|
|
129
|
+
*
|
|
130
|
+
* The optional `isSigner` flag describes whether the IDL requires the account to sign the
|
|
131
|
+
* transaction — with `'either'` meaning the account may or may not be a signer, in which
|
|
132
|
+
* case providing a {@link TransactionSigner} value is what marks it as one. Omitting the
|
|
133
|
+
* flag — e.g. in program clients generated before its introduction — is equivalent to
|
|
134
|
+
* setting it to `'either'`.
|
|
97
135
|
*
|
|
98
136
|
* @typeParam TAddress - The address type, defaults to `string`.
|
|
99
137
|
* @typeParam TValue - The type of the resolved value.
|
|
@@ -102,14 +140,123 @@ export declare function getResolvedInstructionAccountAsTransactionSigner<T exten
|
|
|
102
140
|
* ```ts
|
|
103
141
|
* const mintAccount: ResolvedInstructionAccount = {
|
|
104
142
|
* value: mintAddress,
|
|
143
|
+
* isSigner: false,
|
|
105
144
|
* isWritable: true,
|
|
106
145
|
* };
|
|
107
146
|
* ```
|
|
108
147
|
*/
|
|
109
|
-
export type ResolvedInstructionAccount<TAddress extends string = string, TValue extends
|
|
148
|
+
export type ResolvedInstructionAccount<TAddress extends string = string, TValue extends InstructionAccountInput<TAddress> | InstructionSignerInput<TAddress> | null = InstructionAccountInput<TAddress> | InstructionSignerInput<TAddress> | null> = {
|
|
149
|
+
isSigner?: boolean | 'either';
|
|
110
150
|
isWritable: boolean;
|
|
111
151
|
value: TValue;
|
|
112
152
|
};
|
|
153
|
+
/**
|
|
154
|
+
* Extracts the address type parameter from an instruction account input.
|
|
155
|
+
*
|
|
156
|
+
* Given any {@link InstructionAccountInput} or {@link InstructionSignerInput} — e.g. an
|
|
157
|
+
* {@link Address}, an address-bearing object (see {@link HasAddress}), a
|
|
158
|
+
* {@link ProgramDerivedAddress} or an account meta — this type helper resolves to the
|
|
159
|
+
* branded address string it carries. This allows generated program clients to recover the
|
|
160
|
+
* address type parameter of an account from the caller's input type alone — e.g. via
|
|
161
|
+
* `InstructionAccountInputAddress<TInput['authority']>` — instead of declaring a dedicated
|
|
162
|
+
* address type parameter on the instruction builder.
|
|
163
|
+
*
|
|
164
|
+
* When given a union of inputs, the helper distributes over it, so a union whose members
|
|
165
|
+
* all share the same address brand resolves to that brand. Inputs carrying no brand
|
|
166
|
+
* resolve to `string`.
|
|
167
|
+
*
|
|
168
|
+
* @typeParam TInput - The type of the input provided by the caller for this account.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* type A = InstructionAccountInputAddress<Address<'1234'>>; // '1234'
|
|
173
|
+
* type B = InstructionAccountInputAddress<TransactionSigner<'1234'>>; // '1234'
|
|
174
|
+
* type C = InstructionAccountInputAddress<ProgramDerivedAddress<'1234'>>; // '1234'
|
|
175
|
+
* type D = InstructionAccountInputAddress<Address>; // string
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @see {@link ResolvedInstructionAccountMeta}
|
|
179
|
+
*/
|
|
180
|
+
export type InstructionAccountInputAddress<TInput> = TInput extends HasAddress<infer TAddress> ? TAddress : TInput extends ProgramDerivedAddress<infer TAddress> ? TAddress : TInput extends Address<infer TAddress> ? TAddress : string;
|
|
181
|
+
/**
|
|
182
|
+
* Computes the account meta type produced by an instruction account, based on the input
|
|
183
|
+
* provided by the caller.
|
|
184
|
+
*
|
|
185
|
+
* This type helper mirrors the runtime logic of {@link getAccountMetaFactory} so that
|
|
186
|
+
* generated program clients can accurately type the accounts of the instructions they
|
|
187
|
+
* return. Namely:
|
|
188
|
+
* - When the input carries an explicit `role` — i.e. it is an {@link AccountNonSignerMeta} or an
|
|
189
|
+
* {@link AccountSignerMeta} — the meta type preserves the input's role type: an inline
|
|
190
|
+
* `role: AccountRole.READONLY` override resolves to `ReadonlyAccount`, while a role only
|
|
191
|
+
* known at runtime widens to {@link AccountMeta}. If the input also carries a `signer`,
|
|
192
|
+
* {@link AccountSignerMeta} is used so the attached signer is reflected in the type.
|
|
193
|
+
* - When the input is a {@link TransactionSigner}, the meta type is `TSignerMeta` — e.g.
|
|
194
|
+
* `ReadonlySignerAccount<TAddress> & AccountSignerMeta<TAddress>` for accounts the IDL
|
|
195
|
+
* declares as signers. For non-signer accounts, `TSignerMeta` should be left to its
|
|
196
|
+
* default of `TAddress` so that signers merely act as address carriers.
|
|
197
|
+
* - Otherwise, the helper resolves to `TAddress` — the branded address string that generated
|
|
198
|
+
* instruction types map to the account meta declared by the program's IDL.
|
|
199
|
+
*
|
|
200
|
+
* Note that the checks are wrapped in tuples (`[TInput] extends [...]`) to prevent unions
|
|
201
|
+
* from distributing. If `TInput` is not narrowed to the caller's specific input type — e.g.
|
|
202
|
+
* when a declared input union is provided instead — the helper deterministically falls back
|
|
203
|
+
* to `TAddress`, matching the account meta declared by the program's IDL.
|
|
204
|
+
*
|
|
205
|
+
* @typeParam TInput - The type of the input provided by the caller for this account.
|
|
206
|
+
* @typeParam TAddress - The address type parameter of the account.
|
|
207
|
+
* @typeParam TSignerMeta - The meta type produced when a {@link TransactionSigner} is
|
|
208
|
+
* provided. Defaults to `TAddress`, which treats signers as plain address carriers.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* The instruction builder below captures the caller's input in a single `TInput` type
|
|
212
|
+
* parameter and recovers each account's address type parameter from it using
|
|
213
|
+
* {@link InstructionAccountInputAddress}.
|
|
214
|
+
* ```ts
|
|
215
|
+
* declare function getTransferInstruction<TInput extends TransferInput>(
|
|
216
|
+
* input: TInput,
|
|
217
|
+
* ): TransferInstruction<
|
|
218
|
+
* ResolvedInstructionAccountMeta<
|
|
219
|
+
* TInput['authority'],
|
|
220
|
+
* InstructionAccountInputAddress<TInput['authority']>,
|
|
221
|
+
* ReadonlySignerAccount<InstructionAccountInputAddress<TInput['authority']>> &
|
|
222
|
+
* AccountSignerMeta<InstructionAccountInputAddress<TInput['authority']>>
|
|
223
|
+
* >
|
|
224
|
+
* >;
|
|
225
|
+
* ```
|
|
226
|
+
*
|
|
227
|
+
* Alternatively, instruction builders may keep a dedicated address type parameter per
|
|
228
|
+
* account. In that case, the parameter below must intersect the concrete input type with
|
|
229
|
+
* the inferred `TInput` type parameter (`TransferInput<TAccountAuthority> & TInput`) —
|
|
230
|
+
* referencing the address type parameters only in `TInput`'s constraint makes their
|
|
231
|
+
* inference fall back to `string`. Defaulting `TInput` to the concrete input type keeps
|
|
232
|
+
* call sites with explicit type arguments working.
|
|
233
|
+
* ```ts
|
|
234
|
+
* declare function getTransferInstruction<
|
|
235
|
+
* TAccountAuthority extends string,
|
|
236
|
+
* TInput extends TransferInput<TAccountAuthority> = TransferInput<TAccountAuthority>,
|
|
237
|
+
* >(
|
|
238
|
+
* input: TransferInput<TAccountAuthority> & TInput,
|
|
239
|
+
* ): TransferInstruction<
|
|
240
|
+
* ResolvedInstructionAccountMeta<
|
|
241
|
+
* TInput['authority'],
|
|
242
|
+
* TAccountAuthority,
|
|
243
|
+
* ReadonlySignerAccount<TAccountAuthority> & AccountSignerMeta<TAccountAuthority>
|
|
244
|
+
* >
|
|
245
|
+
* >;
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @see {@link getAccountMetaFactory}
|
|
249
|
+
* @see {@link InstructionAccountInputAddress}
|
|
250
|
+
*/
|
|
251
|
+
export type ResolvedInstructionAccountMeta<TInput, TAddress extends string, TSignerMeta = TAddress> = [TInput] extends [
|
|
252
|
+
{
|
|
253
|
+
role: infer TRole extends AccountRole;
|
|
254
|
+
}
|
|
255
|
+
] ? ([TInput] extends [{
|
|
256
|
+
signer: TransactionSigner<TAddress>;
|
|
257
|
+
}] ? AccountSignerMeta<TAddress> : AccountMeta<TAddress>) & {
|
|
258
|
+
readonly role: TRole;
|
|
259
|
+
} : [TInput] extends [TransactionSigner<TAddress>] ? TSignerMeta : TAddress;
|
|
113
260
|
/**
|
|
114
261
|
* Creates a factory function that converts resolved instruction accounts to account metas.
|
|
115
262
|
*
|
|
@@ -117,12 +264,26 @@ export type ResolvedInstructionAccount<TAddress extends string = string, TValue
|
|
|
117
264
|
* {@link AccountMeta} or {@link AccountSignerMeta} objects suitable for building instructions.
|
|
118
265
|
* It also determines how to handle optional accounts based on the provided strategy.
|
|
119
266
|
*
|
|
267
|
+
* The role of the resulting account meta is determined as follows, in order of precedence:
|
|
268
|
+
* 1. If the value carries an explicit `role` — i.e. it is an {@link AccountNonSignerMeta} or
|
|
269
|
+
* an {@link AccountSignerMeta} — that role is used as-is, regardless of the flags declared
|
|
270
|
+
* by the program's IDL.
|
|
271
|
+
* 2. Otherwise, if the value is a {@link TransactionSigner} and the account's `isSigner` flag
|
|
272
|
+
* is not `false`, the IDL's writable flag is upgraded to the corresponding signer role and
|
|
273
|
+
* the signer is attached to the meta. When `isSigner` is `false`, the signer merely acts
|
|
274
|
+
* as an address carrier and no upgrade occurs. Omitting the flag is equivalent to `'either'`.
|
|
275
|
+
* 3. Otherwise, the IDL's writable flag decides between the readonly and writable roles.
|
|
276
|
+
*
|
|
120
277
|
* @param programAddress - The program address, used when optional accounts use the `programId` strategy.
|
|
121
278
|
* @param optionalAccountStrategy - How to handle null account values:
|
|
122
279
|
* - `'omitted'`: Optional accounts are excluded from the instruction entirely.
|
|
123
280
|
* - `'programId'`: Optional accounts are replaced with the program address as a read-only account.
|
|
124
281
|
* @returns A factory function that converts a resolved account to an account meta.
|
|
125
282
|
*
|
|
283
|
+
* @throws Throws a {@link SolanaError} when the account's `isSigner` flag is `true` but the
|
|
284
|
+
* provided value is neither a {@link TransactionSigner} nor carries an explicit `role`. Use
|
|
285
|
+
* `createNoopSigner()` from `@solana/signers` if the account's signature is provided by other means.
|
|
286
|
+
*
|
|
126
287
|
* @example
|
|
127
288
|
* ```ts
|
|
128
289
|
* const toAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instruction-input-resolution.d.ts","sourceRoot":"","sources":["../../src/instruction-input-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"instruction-input-resolution.d.ts","sourceRoot":"","sources":["../../src/instruction-input-resolution.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/program-client-core",
|
|
3
|
-
"version": "8.3.0
|
|
3
|
+
"version": "8.3.0",
|
|
4
4
|
"description": "Core utilities for building Solana program clients",
|
|
5
5
|
"homepage": "https://www.solanakit.com/api#solanaprogram-client-core",
|
|
6
6
|
"exports": {
|
|
@@ -56,15 +56,15 @@
|
|
|
56
56
|
"maintained node versions"
|
|
57
57
|
],
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@solana/
|
|
60
|
-
"@solana/
|
|
61
|
-
"@solana/codecs-core": "8.3.0
|
|
62
|
-
"@solana/
|
|
63
|
-
"@solana/
|
|
64
|
-
"@solana/instructions": "8.3.0
|
|
65
|
-
"@solana/plugin-interfaces": "8.3.0
|
|
66
|
-
"@solana/rpc-api": "8.3.0
|
|
67
|
-
"@solana/signers": "8.3.0
|
|
59
|
+
"@solana/addresses": "8.3.0",
|
|
60
|
+
"@solana/accounts": "8.3.0",
|
|
61
|
+
"@solana/codecs-core": "8.3.0",
|
|
62
|
+
"@solana/instruction-plans": "8.3.0",
|
|
63
|
+
"@solana/errors": "8.3.0",
|
|
64
|
+
"@solana/instructions": "8.3.0",
|
|
65
|
+
"@solana/plugin-interfaces": "8.3.0",
|
|
66
|
+
"@solana/rpc-api": "8.3.0",
|
|
67
|
+
"@solana/signers": "8.3.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"typescript": ">=5.4.0"
|
|
@@ -1,12 +1,51 @@
|
|
|
1
|
-
import { type Address, isProgramDerivedAddress, type ProgramDerivedAddress } from '@solana/addresses';
|
|
1
|
+
import { type Address, type HasAddress, isProgramDerivedAddress, type ProgramDerivedAddress } from '@solana/addresses';
|
|
2
2
|
import {
|
|
3
3
|
SOLANA_ERROR__PROGRAM_CLIENTS__RESOLVED_INSTRUCTION_INPUT_MUST_BE_NON_NULL,
|
|
4
|
+
SOLANA_ERROR__PROGRAM_CLIENTS__RESOLVED_INSTRUCTION_INPUT_MUST_BE_SIGNER,
|
|
4
5
|
SOLANA_ERROR__PROGRAM_CLIENTS__UNEXPECTED_RESOLVED_INSTRUCTION_INPUT_TYPE,
|
|
5
6
|
SolanaError,
|
|
6
7
|
} from '@solana/errors';
|
|
7
|
-
import { type AccountMeta, AccountRole, upgradeRoleToSigner } from '@solana/instructions';
|
|
8
|
+
import { type AccountMeta, type AccountNonSignerMeta, AccountRole, upgradeRoleToSigner } from '@solana/instructions';
|
|
8
9
|
import { type AccountSignerMeta, isTransactionSigner, type TransactionSigner } from '@solana/signers';
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Represents the accepted input values for a non-signer instruction account.
|
|
13
|
+
*
|
|
14
|
+
* Namely, one of the following:
|
|
15
|
+
* - An {@link Address} — the most common case.
|
|
16
|
+
* - Any object exposing an `address` property (see {@link HasAddress}) — e.g. a framework's
|
|
17
|
+
* address wrapper class. Note that {@link TransactionSigner | TransactionSigners} satisfy this
|
|
18
|
+
* shape too, in which case they act as plain address carriers for non-signer accounts.
|
|
19
|
+
* - A {@link ProgramDerivedAddress} — i.e. an `[address, bump]` tuple.
|
|
20
|
+
* - An {@link AccountNonSignerMeta} — i.e. `{ address, role }` — to explicitly override the
|
|
21
|
+
* role derived from the program's IDL, e.g. to mark an account as writable or readonly.
|
|
22
|
+
*
|
|
23
|
+
* @typeParam TAddress - Supply a string literal to define an account having a particular address.
|
|
24
|
+
*
|
|
25
|
+
* @see {@link InstructionSignerInput}
|
|
26
|
+
*/
|
|
27
|
+
export type InstructionAccountInput<TAddress extends string = string> =
|
|
28
|
+
| AccountNonSignerMeta<TAddress>
|
|
29
|
+
| Address<TAddress>
|
|
30
|
+
| HasAddress<TAddress>
|
|
31
|
+
| ProgramDerivedAddress<TAddress>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Represents the accepted input values for a signer instruction account.
|
|
35
|
+
*
|
|
36
|
+
* Namely, one of the following:
|
|
37
|
+
* - A {@link TransactionSigner} — the most common case.
|
|
38
|
+
* - An {@link AccountSignerMeta} — i.e. `{ address, role, signer }` — to explicitly override the
|
|
39
|
+
* role derived from the program's IDL, e.g. to mark a signer account as writable or readonly.
|
|
40
|
+
*
|
|
41
|
+
* @typeParam TAddress - Supply a string literal to define an account having a particular address.
|
|
42
|
+
*
|
|
43
|
+
* @see {@link InstructionAccountInput}
|
|
44
|
+
*/
|
|
45
|
+
export type InstructionSignerInput<TAddress extends string = string> =
|
|
46
|
+
| AccountSignerMeta<TAddress>
|
|
47
|
+
| TransactionSigner<TAddress>;
|
|
48
|
+
|
|
10
49
|
/**
|
|
11
50
|
* Ensures a resolved instruction input is not null or undefined.
|
|
12
51
|
*
|
|
@@ -43,8 +82,9 @@ export function getNonNullResolvedInstructionInput<T>(inputName: string, value:
|
|
|
43
82
|
* Extracts the address from a resolved instruction account.
|
|
44
83
|
*
|
|
45
84
|
* A resolved instruction account can be an {@link Address}, a {@link ProgramDerivedAddress},
|
|
46
|
-
* or a {@link TransactionSigner}
|
|
47
|
-
*
|
|
85
|
+
* or any object exposing an `address` property — such as a {@link TransactionSigner}, an
|
|
86
|
+
* account meta, or a framework's address wrapper class (see {@link HasAddress}). This
|
|
87
|
+
* function extracts the underlying address from any of these types.
|
|
48
88
|
*
|
|
49
89
|
* @typeParam T - The address type, defaults to `string`.
|
|
50
90
|
*
|
|
@@ -109,7 +149,8 @@ export function getResolvedInstructionAccountAsProgramDerivedAddress<T extends s
|
|
|
109
149
|
/**
|
|
110
150
|
* Extracts a {@link TransactionSigner} from a resolved instruction account.
|
|
111
151
|
*
|
|
112
|
-
* This function validates that the resolved account is a transaction signer
|
|
152
|
+
* This function validates that the resolved account is a transaction signer — or an
|
|
153
|
+
* {@link AccountSignerMeta} carrying one — and returns the signer.
|
|
113
154
|
* Use this when you need the resolved account to be a signer.
|
|
114
155
|
*
|
|
115
156
|
* @typeParam T - The address type, defaults to `string`.
|
|
@@ -129,22 +170,29 @@ export function getResolvedInstructionAccountAsTransactionSigner<T extends strin
|
|
|
129
170
|
inputName: string,
|
|
130
171
|
value: ResolvedInstructionAccount<T>['value'] | undefined,
|
|
131
172
|
): TransactionSigner<T> {
|
|
132
|
-
|
|
173
|
+
const signer = value && hasExplicitRole(value) && 'signer' in value ? value.signer : value;
|
|
174
|
+
if (!isResolvedInstructionAccountSigner<T>(signer)) {
|
|
133
175
|
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__UNEXPECTED_RESOLVED_INSTRUCTION_INPUT_TYPE, {
|
|
134
176
|
expectedType: 'TransactionSigner',
|
|
135
177
|
inputName,
|
|
136
178
|
});
|
|
137
179
|
}
|
|
138
|
-
return
|
|
180
|
+
return signer;
|
|
139
181
|
}
|
|
140
182
|
|
|
141
183
|
/**
|
|
142
184
|
* Represents a resolved account input for an instruction.
|
|
143
185
|
*
|
|
144
|
-
* During instruction building, account inputs are resolved to this type which
|
|
145
|
-
*
|
|
146
|
-
* The value can be
|
|
147
|
-
*
|
|
186
|
+
* During instruction building, account inputs are resolved to this type which captures
|
|
187
|
+
* the account value alongside the signer and writable flags declared by the program's IDL.
|
|
188
|
+
* The value can be any {@link InstructionAccountInput}, any {@link InstructionSignerInput},
|
|
189
|
+
* or `null` for optional accounts.
|
|
190
|
+
*
|
|
191
|
+
* The optional `isSigner` flag describes whether the IDL requires the account to sign the
|
|
192
|
+
* transaction — with `'either'` meaning the account may or may not be a signer, in which
|
|
193
|
+
* case providing a {@link TransactionSigner} value is what marks it as one. Omitting the
|
|
194
|
+
* flag — e.g. in program clients generated before its introduction — is equivalent to
|
|
195
|
+
* setting it to `'either'`.
|
|
148
196
|
*
|
|
149
197
|
* @typeParam TAddress - The address type, defaults to `string`.
|
|
150
198
|
* @typeParam TValue - The type of the resolved value.
|
|
@@ -153,22 +201,139 @@ export function getResolvedInstructionAccountAsTransactionSigner<T extends strin
|
|
|
153
201
|
* ```ts
|
|
154
202
|
* const mintAccount: ResolvedInstructionAccount = {
|
|
155
203
|
* value: mintAddress,
|
|
204
|
+
* isSigner: false,
|
|
156
205
|
* isWritable: true,
|
|
157
206
|
* };
|
|
158
207
|
* ```
|
|
159
208
|
*/
|
|
160
209
|
export type ResolvedInstructionAccount<
|
|
161
210
|
TAddress extends string = string,
|
|
162
|
-
TValue extends
|
|
163
|
-
|
|
|
164
|
-
|
|
|
165
|
-
| TransactionSigner<TAddress>
|
|
211
|
+
TValue extends InstructionAccountInput<TAddress> | InstructionSignerInput<TAddress> | null =
|
|
212
|
+
| InstructionAccountInput<TAddress>
|
|
213
|
+
| InstructionSignerInput<TAddress>
|
|
166
214
|
| null,
|
|
167
215
|
> = {
|
|
216
|
+
isSigner?: boolean | 'either';
|
|
168
217
|
isWritable: boolean;
|
|
169
218
|
value: TValue;
|
|
170
219
|
};
|
|
171
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Extracts the address type parameter from an instruction account input.
|
|
223
|
+
*
|
|
224
|
+
* Given any {@link InstructionAccountInput} or {@link InstructionSignerInput} — e.g. an
|
|
225
|
+
* {@link Address}, an address-bearing object (see {@link HasAddress}), a
|
|
226
|
+
* {@link ProgramDerivedAddress} or an account meta — this type helper resolves to the
|
|
227
|
+
* branded address string it carries. This allows generated program clients to recover the
|
|
228
|
+
* address type parameter of an account from the caller's input type alone — e.g. via
|
|
229
|
+
* `InstructionAccountInputAddress<TInput['authority']>` — instead of declaring a dedicated
|
|
230
|
+
* address type parameter on the instruction builder.
|
|
231
|
+
*
|
|
232
|
+
* When given a union of inputs, the helper distributes over it, so a union whose members
|
|
233
|
+
* all share the same address brand resolves to that brand. Inputs carrying no brand
|
|
234
|
+
* resolve to `string`.
|
|
235
|
+
*
|
|
236
|
+
* @typeParam TInput - The type of the input provided by the caller for this account.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* type A = InstructionAccountInputAddress<Address<'1234'>>; // '1234'
|
|
241
|
+
* type B = InstructionAccountInputAddress<TransactionSigner<'1234'>>; // '1234'
|
|
242
|
+
* type C = InstructionAccountInputAddress<ProgramDerivedAddress<'1234'>>; // '1234'
|
|
243
|
+
* type D = InstructionAccountInputAddress<Address>; // string
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @see {@link ResolvedInstructionAccountMeta}
|
|
247
|
+
*/
|
|
248
|
+
export type InstructionAccountInputAddress<TInput> =
|
|
249
|
+
TInput extends HasAddress<infer TAddress>
|
|
250
|
+
? TAddress
|
|
251
|
+
: TInput extends ProgramDerivedAddress<infer TAddress>
|
|
252
|
+
? TAddress
|
|
253
|
+
: TInput extends Address<infer TAddress>
|
|
254
|
+
? TAddress
|
|
255
|
+
: string;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Computes the account meta type produced by an instruction account, based on the input
|
|
259
|
+
* provided by the caller.
|
|
260
|
+
*
|
|
261
|
+
* This type helper mirrors the runtime logic of {@link getAccountMetaFactory} so that
|
|
262
|
+
* generated program clients can accurately type the accounts of the instructions they
|
|
263
|
+
* return. Namely:
|
|
264
|
+
* - When the input carries an explicit `role` — i.e. it is an {@link AccountNonSignerMeta} or an
|
|
265
|
+
* {@link AccountSignerMeta} — the meta type preserves the input's role type: an inline
|
|
266
|
+
* `role: AccountRole.READONLY` override resolves to `ReadonlyAccount`, while a role only
|
|
267
|
+
* known at runtime widens to {@link AccountMeta}. If the input also carries a `signer`,
|
|
268
|
+
* {@link AccountSignerMeta} is used so the attached signer is reflected in the type.
|
|
269
|
+
* - When the input is a {@link TransactionSigner}, the meta type is `TSignerMeta` — e.g.
|
|
270
|
+
* `ReadonlySignerAccount<TAddress> & AccountSignerMeta<TAddress>` for accounts the IDL
|
|
271
|
+
* declares as signers. For non-signer accounts, `TSignerMeta` should be left to its
|
|
272
|
+
* default of `TAddress` so that signers merely act as address carriers.
|
|
273
|
+
* - Otherwise, the helper resolves to `TAddress` — the branded address string that generated
|
|
274
|
+
* instruction types map to the account meta declared by the program's IDL.
|
|
275
|
+
*
|
|
276
|
+
* Note that the checks are wrapped in tuples (`[TInput] extends [...]`) to prevent unions
|
|
277
|
+
* from distributing. If `TInput` is not narrowed to the caller's specific input type — e.g.
|
|
278
|
+
* when a declared input union is provided instead — the helper deterministically falls back
|
|
279
|
+
* to `TAddress`, matching the account meta declared by the program's IDL.
|
|
280
|
+
*
|
|
281
|
+
* @typeParam TInput - The type of the input provided by the caller for this account.
|
|
282
|
+
* @typeParam TAddress - The address type parameter of the account.
|
|
283
|
+
* @typeParam TSignerMeta - The meta type produced when a {@link TransactionSigner} is
|
|
284
|
+
* provided. Defaults to `TAddress`, which treats signers as plain address carriers.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* The instruction builder below captures the caller's input in a single `TInput` type
|
|
288
|
+
* parameter and recovers each account's address type parameter from it using
|
|
289
|
+
* {@link InstructionAccountInputAddress}.
|
|
290
|
+
* ```ts
|
|
291
|
+
* declare function getTransferInstruction<TInput extends TransferInput>(
|
|
292
|
+
* input: TInput,
|
|
293
|
+
* ): TransferInstruction<
|
|
294
|
+
* ResolvedInstructionAccountMeta<
|
|
295
|
+
* TInput['authority'],
|
|
296
|
+
* InstructionAccountInputAddress<TInput['authority']>,
|
|
297
|
+
* ReadonlySignerAccount<InstructionAccountInputAddress<TInput['authority']>> &
|
|
298
|
+
* AccountSignerMeta<InstructionAccountInputAddress<TInput['authority']>>
|
|
299
|
+
* >
|
|
300
|
+
* >;
|
|
301
|
+
* ```
|
|
302
|
+
*
|
|
303
|
+
* Alternatively, instruction builders may keep a dedicated address type parameter per
|
|
304
|
+
* account. In that case, the parameter below must intersect the concrete input type with
|
|
305
|
+
* the inferred `TInput` type parameter (`TransferInput<TAccountAuthority> & TInput`) —
|
|
306
|
+
* referencing the address type parameters only in `TInput`'s constraint makes their
|
|
307
|
+
* inference fall back to `string`. Defaulting `TInput` to the concrete input type keeps
|
|
308
|
+
* call sites with explicit type arguments working.
|
|
309
|
+
* ```ts
|
|
310
|
+
* declare function getTransferInstruction<
|
|
311
|
+
* TAccountAuthority extends string,
|
|
312
|
+
* TInput extends TransferInput<TAccountAuthority> = TransferInput<TAccountAuthority>,
|
|
313
|
+
* >(
|
|
314
|
+
* input: TransferInput<TAccountAuthority> & TInput,
|
|
315
|
+
* ): TransferInstruction<
|
|
316
|
+
* ResolvedInstructionAccountMeta<
|
|
317
|
+
* TInput['authority'],
|
|
318
|
+
* TAccountAuthority,
|
|
319
|
+
* ReadonlySignerAccount<TAccountAuthority> & AccountSignerMeta<TAccountAuthority>
|
|
320
|
+
* >
|
|
321
|
+
* >;
|
|
322
|
+
* ```
|
|
323
|
+
*
|
|
324
|
+
* @see {@link getAccountMetaFactory}
|
|
325
|
+
* @see {@link InstructionAccountInputAddress}
|
|
326
|
+
*/
|
|
327
|
+
export type ResolvedInstructionAccountMeta<TInput, TAddress extends string, TSignerMeta = TAddress> = [TInput] extends [
|
|
328
|
+
{ role: infer TRole extends AccountRole },
|
|
329
|
+
]
|
|
330
|
+
? ([TInput] extends [{ signer: TransactionSigner<TAddress> }]
|
|
331
|
+
? AccountSignerMeta<TAddress>
|
|
332
|
+
: AccountMeta<TAddress>) & { readonly role: TRole }
|
|
333
|
+
: [TInput] extends [TransactionSigner<TAddress>]
|
|
334
|
+
? TSignerMeta
|
|
335
|
+
: TAddress;
|
|
336
|
+
|
|
172
337
|
/**
|
|
173
338
|
* Creates a factory function that converts resolved instruction accounts to account metas.
|
|
174
339
|
*
|
|
@@ -176,12 +341,26 @@ export type ResolvedInstructionAccount<
|
|
|
176
341
|
* {@link AccountMeta} or {@link AccountSignerMeta} objects suitable for building instructions.
|
|
177
342
|
* It also determines how to handle optional accounts based on the provided strategy.
|
|
178
343
|
*
|
|
344
|
+
* The role of the resulting account meta is determined as follows, in order of precedence:
|
|
345
|
+
* 1. If the value carries an explicit `role` — i.e. it is an {@link AccountNonSignerMeta} or
|
|
346
|
+
* an {@link AccountSignerMeta} — that role is used as-is, regardless of the flags declared
|
|
347
|
+
* by the program's IDL.
|
|
348
|
+
* 2. Otherwise, if the value is a {@link TransactionSigner} and the account's `isSigner` flag
|
|
349
|
+
* is not `false`, the IDL's writable flag is upgraded to the corresponding signer role and
|
|
350
|
+
* the signer is attached to the meta. When `isSigner` is `false`, the signer merely acts
|
|
351
|
+
* as an address carrier and no upgrade occurs. Omitting the flag is equivalent to `'either'`.
|
|
352
|
+
* 3. Otherwise, the IDL's writable flag decides between the readonly and writable roles.
|
|
353
|
+
*
|
|
179
354
|
* @param programAddress - The program address, used when optional accounts use the `programId` strategy.
|
|
180
355
|
* @param optionalAccountStrategy - How to handle null account values:
|
|
181
356
|
* - `'omitted'`: Optional accounts are excluded from the instruction entirely.
|
|
182
357
|
* - `'programId'`: Optional accounts are replaced with the program address as a read-only account.
|
|
183
358
|
* @returns A factory function that converts a resolved account to an account meta.
|
|
184
359
|
*
|
|
360
|
+
* @throws Throws a {@link SolanaError} when the account's `isSigner` flag is `true` but the
|
|
361
|
+
* provided value is neither a {@link TransactionSigner} nor carries an explicit `role`. Use
|
|
362
|
+
* `createNoopSigner()` from `@solana/signers` if the account's signature is provided by other means.
|
|
363
|
+
*
|
|
185
364
|
* @example
|
|
186
365
|
* ```ts
|
|
187
366
|
* const toAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
@@ -195,8 +374,26 @@ export function getAccountMetaFactory(programAddress: Address, optionalAccountSt
|
|
|
195
374
|
return Object.freeze({ address: programAddress, role: AccountRole.READONLY });
|
|
196
375
|
}
|
|
197
376
|
|
|
377
|
+
// Explicit roles always take precedence over the flags declared by the program's IDL.
|
|
378
|
+
if (hasExplicitRole(account.value)) {
|
|
379
|
+
return Object.freeze({
|
|
380
|
+
address: account.value.address,
|
|
381
|
+
role: account.value.role,
|
|
382
|
+
...('signer' in account.value && account.value.signer ? { signer: account.value.signer } : {}),
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Only mark implicit values as signers when the IDL declares
|
|
387
|
+
// the account as a signer or lets the input decide (`'either'`).
|
|
388
|
+
const idlIsSigner = account.isSigner ?? 'either';
|
|
389
|
+
const isSigner = idlIsSigner !== false && isResolvedInstructionAccountSigner(account.value);
|
|
390
|
+
if (!isSigner && idlIsSigner === true) {
|
|
391
|
+
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__RESOLVED_INSTRUCTION_INPUT_MUST_BE_SIGNER, {
|
|
392
|
+
inputName,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
198
396
|
const writableRole = account.isWritable ? AccountRole.WRITABLE : AccountRole.READONLY;
|
|
199
|
-
const isSigner = isResolvedInstructionAccountSigner(account.value);
|
|
200
397
|
return Object.freeze({
|
|
201
398
|
address: getAddressFromResolvedInstructionAccount(inputName, account.value),
|
|
202
399
|
role: isSigner ? upgradeRoleToSigner(writableRole) : writableRole,
|
|
@@ -205,7 +402,23 @@ export function getAccountMetaFactory(programAddress: Address, optionalAccountSt
|
|
|
205
402
|
};
|
|
206
403
|
}
|
|
207
404
|
|
|
208
|
-
|
|
405
|
+
/**
|
|
406
|
+
* Checks whether a resolved instruction account value carries an explicit account role,
|
|
407
|
+
* i.e. whether it is an {@link AccountNonSignerMeta} or an {@link AccountSignerMeta}.
|
|
408
|
+
*
|
|
409
|
+
* Since {@link AccountRole} is a numeric enum, requiring `role` to be a number prevents
|
|
410
|
+
* unrelated `role` properties on address-bearing objects from being mistaken for a role
|
|
411
|
+
* override.
|
|
412
|
+
*/
|
|
413
|
+
function hasExplicitRole(
|
|
414
|
+
value: NonNullable<ResolvedInstructionAccount['value']>,
|
|
415
|
+
): value is AccountNonSignerMeta | AccountSignerMeta {
|
|
416
|
+
return typeof value === 'object' && 'role' in value && typeof value.role === 'number';
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function isResolvedInstructionAccountSigner<TAddress extends string = string>(
|
|
420
|
+
value: unknown,
|
|
421
|
+
): value is TransactionSigner<TAddress> {
|
|
209
422
|
return (
|
|
210
423
|
!!value &&
|
|
211
424
|
typeof value === 'object' &&
|