@@ -10,9 +10,15 @@ import {
10
10
} from '@solana/web3.js' ;
11
11
import * as BufferLayout from '@solana/buffer-layout' ;
12
12
import { TOKEN_PROGRAM_ID } from '@solana/spl-token' ;
13
- import { STAKE_POOL_PROGRAM_ID } from './constants' ;
14
13
import { InstructionType , encodeData , decodeData } from './utils' ;
15
14
import BN from 'bn.js' ;
15
+ import {
16
+ METADATA_MAX_NAME_LENGTH ,
17
+ METADATA_MAX_SYMBOL_LENGTH ,
18
+ METADATA_MAX_URI_LENGTH ,
19
+ METADATA_PROGRAM_ID ,
20
+ STAKE_POOL_PROGRAM_ID ,
21
+ } from './constants' ;
16
22
17
23
/**
18
24
* An enumeration of valid StakePoolInstructionType's
@@ -31,6 +37,8 @@ export type StakePoolInstructionType =
31
37
| 'DecreaseAdditionalValidatorStake'
32
38
| 'Redelegate' ;
33
39
40
+ // 'UpdateTokenMetadata' and 'CreateTokenMetadata' have dynamic layouts
41
+
34
42
const MOVE_STAKE_LAYOUT = BufferLayout . struct < any > ( [
35
43
BufferLayout . u8 ( 'instruction' ) ,
36
44
BufferLayout . ns64 ( 'lamports' ) ,
@@ -43,6 +51,38 @@ const UPDATE_VALIDATOR_LIST_BALANCE_LAYOUT = BufferLayout.struct<any>([
43
51
BufferLayout . u8 ( 'noMerge' ) ,
44
52
] ) ;
45
53
54
+ export function tokenMetadataLayout (
55
+ instruction : number ,
56
+ nameLength : number ,
57
+ symbolLength : number ,
58
+ uriLength : number ,
59
+ ) {
60
+ if ( nameLength > METADATA_MAX_NAME_LENGTH ) {
61
+ throw 'maximum token name length is 32 characters' ;
62
+ }
63
+
64
+ if ( symbolLength > METADATA_MAX_SYMBOL_LENGTH ) {
65
+ throw 'maximum token symbol length is 10 characters' ;
66
+ }
67
+
68
+ if ( uriLength > METADATA_MAX_URI_LENGTH ) {
69
+ throw 'maximum token uri length is 200 characters' ;
70
+ }
71
+
72
+ return {
73
+ index : instruction ,
74
+ layout : BufferLayout . struct < any > ( [
75
+ BufferLayout . u8 ( 'instruction' ) ,
76
+ BufferLayout . u32 ( 'nameLen' ) ,
77
+ BufferLayout . blob ( nameLength , 'name' ) ,
78
+ BufferLayout . u32 ( 'symbolLen' ) ,
79
+ BufferLayout . blob ( symbolLength , 'symbol' ) ,
80
+ BufferLayout . u32 ( 'uriLen' ) ,
81
+ BufferLayout . blob ( uriLength , 'uri' ) ,
82
+ ] ) ,
83
+ } ;
84
+ }
85
+
46
86
/**
47
87
* An enumeration of valid stake InstructionType's
48
88
* @internal
@@ -303,6 +343,28 @@ export type RedelegateParams = {
303
343
destinationTransientStakeSeed : number | BN ;
304
344
} ;
305
345
346
+ export type CreateTokenMetadataParams = {
347
+ stakePool : PublicKey ;
348
+ manager : PublicKey ;
349
+ tokenMetadata : PublicKey ;
350
+ withdrawAuthority : PublicKey ;
351
+ poolMint : PublicKey ;
352
+ payer : PublicKey ;
353
+ name : string ;
354
+ symbol : string ;
355
+ uri : string ;
356
+ } ;
357
+
358
+ export type UpdateTokenMetadataParams = {
359
+ stakePool : PublicKey ;
360
+ manager : PublicKey ;
361
+ tokenMetadata : PublicKey ;
362
+ withdrawAuthority : PublicKey ;
363
+ name : string ;
364
+ symbol : string ;
365
+ uri : string ;
366
+ } ;
367
+
306
368
/**
307
369
* Stake Pool Instruction class
308
370
*/
@@ -823,6 +885,84 @@ export class StakePoolInstruction {
823
885
} ) ;
824
886
}
825
887
888
+ /**
889
+ * Creates an instruction to create metadata
890
+ * using the mpl token metadata program for the pool token
891
+ */
892
+ static createTokenMetadata ( params : CreateTokenMetadataParams ) : TransactionInstruction {
893
+ const {
894
+ stakePool,
895
+ withdrawAuthority,
896
+ tokenMetadata,
897
+ manager,
898
+ payer,
899
+ poolMint,
900
+ name,
901
+ symbol,
902
+ uri,
903
+ } = params ;
904
+
905
+ const keys = [
906
+ { pubkey : stakePool , isSigner : false , isWritable : false } ,
907
+ { pubkey : manager , isSigner : true , isWritable : false } ,
908
+ { pubkey : withdrawAuthority , isSigner : false , isWritable : false } ,
909
+ { pubkey : poolMint , isSigner : false , isWritable : false } ,
910
+ { pubkey : payer , isSigner : true , isWritable : true } ,
911
+ { pubkey : tokenMetadata , isSigner : false , isWritable : true } ,
912
+ { pubkey : METADATA_PROGRAM_ID , isSigner : false , isWritable : false } ,
913
+ { pubkey : SystemProgram . programId , isSigner : false , isWritable : false } ,
914
+ { pubkey : SYSVAR_RENT_PUBKEY , isSigner : false , isWritable : false } ,
915
+ ] ;
916
+
917
+ const type = tokenMetadataLayout ( 17 , name . length , symbol . length , uri . length ) ;
918
+ const data = encodeData ( type , {
919
+ nameLen : name . length ,
920
+ name : Buffer . from ( name ) ,
921
+ symbolLen : symbol . length ,
922
+ symbol : Buffer . from ( symbol ) ,
923
+ uriLen : uri . length ,
924
+ uri : Buffer . from ( uri ) ,
925
+ } ) ;
926
+
927
+ return new TransactionInstruction ( {
928
+ programId : STAKE_POOL_PROGRAM_ID ,
929
+ keys,
930
+ data,
931
+ } ) ;
932
+ }
933
+
934
+ /**
935
+ * Creates an instruction to update metadata
936
+ * in the mpl token metadata program account for the pool token
937
+ */
938
+ static updateTokenMetadata ( params : UpdateTokenMetadataParams ) : TransactionInstruction {
939
+ const { stakePool, withdrawAuthority, tokenMetadata, manager, name, symbol, uri } = params ;
940
+
941
+ const keys = [
942
+ { pubkey : stakePool , isSigner : false , isWritable : false } ,
943
+ { pubkey : manager , isSigner : true , isWritable : false } ,
944
+ { pubkey : withdrawAuthority , isSigner : false , isWritable : false } ,
945
+ { pubkey : tokenMetadata , isSigner : false , isWritable : true } ,
946
+ { pubkey : METADATA_PROGRAM_ID , isSigner : false , isWritable : false } ,
947
+ ] ;
948
+
949
+ const type = tokenMetadataLayout ( 18 , name . length , symbol . length , uri . length ) ;
950
+ const data = encodeData ( type , {
951
+ nameLen : name . length ,
952
+ name : Buffer . from ( name ) ,
953
+ symbolLen : symbol . length ,
954
+ symbol : Buffer . from ( symbol ) ,
955
+ uriLen : uri . length ,
956
+ uri : Buffer . from ( uri ) ,
957
+ } ) ;
958
+
959
+ return new TransactionInstruction ( {
960
+ programId : STAKE_POOL_PROGRAM_ID ,
961
+ keys,
962
+ data,
963
+ } ) ;
964
+ }
965
+
826
966
/**
827
967
* Decode a deposit stake pool instruction and retrieve the instruction params.
828
968
*/
0 commit comments