@@ -10,6 +10,8 @@ import {
1010 combineCodec ,
1111 getStructDecoder ,
1212 getStructEncoder ,
13+ getU16Decoder ,
14+ getU16Encoder ,
1315 getU8Decoder ,
1416 getU8Encoder ,
1517 transformEncoder ,
@@ -18,11 +20,17 @@ import {
1820 type Decoder ,
1921 type Encoder ,
2022 type IAccountMeta ,
23+ type IAccountSignerMeta ,
2124 type IInstruction ,
2225 type IInstructionWithAccounts ,
2326 type IInstructionWithData ,
27+ type ReadonlyAccount ,
28+ type ReadonlySignerAccount ,
29+ type TransactionSigner ,
30+ type WritableAccount ,
2431} from '@solana/web3.js' ;
2532import { PROGRAM_METADATA_PROGRAM_ADDRESS } from '../programs' ;
33+ import { getAccountMetaFactory , type ResolvedAccount } from '../shared' ;
2634
2735export const EXTEND_DISCRIMINATOR = 8 ;
2836
@@ -32,24 +40,58 @@ export function getExtendDiscriminatorBytes() {
3240
3341export type ExtendInstruction <
3442 TProgram extends string = typeof PROGRAM_METADATA_PROGRAM_ADDRESS ,
43+ TAccountAccount extends string | IAccountMeta < string > = string ,
44+ TAccountAuthority extends string | IAccountMeta < string > = string ,
45+ TAccountProgram extends string | IAccountMeta < string > = string ,
46+ TAccountProgramData extends string | IAccountMeta < string > = string ,
3547 TRemainingAccounts extends readonly IAccountMeta < string > [ ] = [ ] ,
3648> = IInstruction < TProgram > &
3749 IInstructionWithData < Uint8Array > &
38- IInstructionWithAccounts < TRemainingAccounts > ;
50+ IInstructionWithAccounts <
51+ [
52+ TAccountAccount extends string
53+ ? WritableAccount < TAccountAccount >
54+ : TAccountAccount ,
55+ TAccountAuthority extends string
56+ ? ReadonlySignerAccount < TAccountAuthority > &
57+ IAccountSignerMeta < TAccountAuthority >
58+ : TAccountAuthority ,
59+ TAccountProgram extends string
60+ ? ReadonlyAccount < TAccountProgram >
61+ : TAccountProgram ,
62+ TAccountProgramData extends string
63+ ? ReadonlyAccount < TAccountProgramData >
64+ : TAccountProgramData ,
65+ ...TRemainingAccounts ,
66+ ]
67+ > ;
3968
40- export type ExtendInstructionData = { discriminator : number } ;
69+ export type ExtendInstructionData = {
70+ discriminator : number ;
71+ /** Length (in bytes) to add to the account size. */
72+ length : number ;
73+ } ;
4174
42- export type ExtendInstructionDataArgs = { } ;
75+ export type ExtendInstructionDataArgs = {
76+ /** Length (in bytes) to add to the account size. */
77+ length : number ;
78+ } ;
4379
4480export function getExtendInstructionDataEncoder ( ) : Encoder < ExtendInstructionDataArgs > {
4581 return transformEncoder (
46- getStructEncoder ( [ [ 'discriminator' , getU8Encoder ( ) ] ] ) ,
82+ getStructEncoder ( [
83+ [ 'discriminator' , getU8Encoder ( ) ] ,
84+ [ 'length' , getU16Encoder ( ) ] ,
85+ ] ) ,
4786 ( value ) => ( { ...value , discriminator : EXTEND_DISCRIMINATOR } )
4887 ) ;
4988}
5089
5190export function getExtendInstructionDataDecoder ( ) : Decoder < ExtendInstructionData > {
52- return getStructDecoder ( [ [ 'discriminator' , getU8Decoder ( ) ] ] ) ;
91+ return getStructDecoder ( [
92+ [ 'discriminator' , getU8Decoder ( ) ] ,
93+ [ 'length' , getU16Decoder ( ) ] ,
94+ ] ) ;
5395}
5496
5597export function getExtendInstructionDataCodec ( ) : Codec <
@@ -62,37 +104,136 @@ export function getExtendInstructionDataCodec(): Codec<
62104 ) ;
63105}
64106
65- export type ExtendInput = { } ;
107+ export type ExtendInput <
108+ TAccountAccount extends string = string ,
109+ TAccountAuthority extends string = string ,
110+ TAccountProgram extends string = string ,
111+ TAccountProgramData extends string = string ,
112+ > = {
113+ /** Buffer or metadata account. */
114+ account : Address < TAccountAccount > ;
115+ /** Authority account. */
116+ authority : TransactionSigner < TAccountAuthority > ;
117+ /** Program account. */
118+ program ?: Address < TAccountProgram > ;
119+ /** Program data account. */
120+ programData ?: Address < TAccountProgramData > ;
121+ length : ExtendInstructionDataArgs [ 'length' ] ;
122+ } ;
66123
67124export function getExtendInstruction <
125+ TAccountAccount extends string ,
126+ TAccountAuthority extends string ,
127+ TAccountProgram extends string ,
128+ TAccountProgramData extends string ,
68129 TProgramAddress extends Address = typeof PROGRAM_METADATA_PROGRAM_ADDRESS ,
69- > ( config ?: {
70- programAddress ?: TProgramAddress ;
71- } ) : ExtendInstruction < TProgramAddress > {
130+ > (
131+ input : ExtendInput <
132+ TAccountAccount ,
133+ TAccountAuthority ,
134+ TAccountProgram ,
135+ TAccountProgramData
136+ > ,
137+ config ?: { programAddress ?: TProgramAddress }
138+ ) : ExtendInstruction <
139+ TProgramAddress ,
140+ TAccountAccount ,
141+ TAccountAuthority ,
142+ TAccountProgram ,
143+ TAccountProgramData
144+ > {
72145 // Program address.
73146 const programAddress =
74147 config ?. programAddress ?? PROGRAM_METADATA_PROGRAM_ADDRESS ;
75148
149+ // Original accounts.
150+ const originalAccounts = {
151+ account : { value : input . account ?? null , isWritable : true } ,
152+ authority : { value : input . authority ?? null , isWritable : false } ,
153+ program : { value : input . program ?? null , isWritable : false } ,
154+ programData : { value : input . programData ?? null , isWritable : false } ,
155+ } ;
156+ const accounts = originalAccounts as Record <
157+ keyof typeof originalAccounts ,
158+ ResolvedAccount
159+ > ;
160+
161+ // Original args.
162+ const args = { ...input } ;
163+
164+ const getAccountMeta = getAccountMetaFactory ( programAddress , 'programId' ) ;
76165 const instruction = {
166+ accounts : [
167+ getAccountMeta ( accounts . account ) ,
168+ getAccountMeta ( accounts . authority ) ,
169+ getAccountMeta ( accounts . program ) ,
170+ getAccountMeta ( accounts . programData ) ,
171+ ] ,
77172 programAddress,
78- data : getExtendInstructionDataEncoder ( ) . encode ( { } ) ,
79- } as ExtendInstruction < TProgramAddress > ;
173+ data : getExtendInstructionDataEncoder ( ) . encode (
174+ args as ExtendInstructionDataArgs
175+ ) ,
176+ } as ExtendInstruction <
177+ TProgramAddress ,
178+ TAccountAccount ,
179+ TAccountAuthority ,
180+ TAccountProgram ,
181+ TAccountProgramData
182+ > ;
80183
81184 return instruction ;
82185}
83186
84187export type ParsedExtendInstruction <
85188 TProgram extends string = typeof PROGRAM_METADATA_PROGRAM_ADDRESS ,
189+ TAccountMetas extends readonly IAccountMeta [ ] = readonly IAccountMeta [ ] ,
86190> = {
87191 programAddress : Address < TProgram > ;
192+ accounts : {
193+ /** Buffer or metadata account. */
194+ account : TAccountMetas [ 0 ] ;
195+ /** Authority account. */
196+ authority : TAccountMetas [ 1 ] ;
197+ /** Program account. */
198+ program ?: TAccountMetas [ 2 ] | undefined ;
199+ /** Program data account. */
200+ programData ?: TAccountMetas [ 3 ] | undefined ;
201+ } ;
88202 data : ExtendInstructionData ;
89203} ;
90204
91- export function parseExtendInstruction < TProgram extends string > (
92- instruction : IInstruction < TProgram > & IInstructionWithData < Uint8Array >
93- ) : ParsedExtendInstruction < TProgram > {
205+ export function parseExtendInstruction <
206+ TProgram extends string ,
207+ TAccountMetas extends readonly IAccountMeta [ ] ,
208+ > (
209+ instruction : IInstruction < TProgram > &
210+ IInstructionWithAccounts < TAccountMetas > &
211+ IInstructionWithData < Uint8Array >
212+ ) : ParsedExtendInstruction < TProgram , TAccountMetas > {
213+ if ( instruction . accounts . length < 4 ) {
214+ // TODO: Coded error.
215+ throw new Error ( 'Not enough accounts' ) ;
216+ }
217+ let accountIndex = 0 ;
218+ const getNextAccount = ( ) => {
219+ const accountMeta = instruction . accounts ! [ accountIndex ] ! ;
220+ accountIndex += 1 ;
221+ return accountMeta ;
222+ } ;
223+ const getNextOptionalAccount = ( ) => {
224+ const accountMeta = getNextAccount ( ) ;
225+ return accountMeta . address === PROGRAM_METADATA_PROGRAM_ADDRESS
226+ ? undefined
227+ : accountMeta ;
228+ } ;
94229 return {
95230 programAddress : instruction . programAddress ,
231+ accounts : {
232+ account : getNextAccount ( ) ,
233+ authority : getNextAccount ( ) ,
234+ program : getNextOptionalAccount ( ) ,
235+ programData : getNextOptionalAccount ( ) ,
236+ } ,
96237 data : getExtendInstructionDataDecoder ( ) . decode ( instruction . data ) ,
97238 } ;
98239}
0 commit comments