@@ -386,6 +386,7 @@ async fn command_create_token(
386
386
authority : Pubkey ,
387
387
enable_freeze : bool ,
388
388
enable_close : bool ,
389
+ enable_non_transferable : bool ,
389
390
memo : Option < String > ,
390
391
rate_bps : Option < i16 > ,
391
392
bulk_signers : Vec < Arc < dyn Signer > > ,
@@ -417,6 +418,10 @@ async fn command_create_token(
417
418
} )
418
419
}
419
420
421
+ if enable_non_transferable {
422
+ extensions. push ( ExtensionInitializationParams :: NonTransferable ) ;
423
+ }
424
+
420
425
if let Some ( text) = memo {
421
426
token. with_memo ( text, vec ! [ config. default_signer( ) ?. pubkey( ) ] ) ;
422
427
}
@@ -2160,6 +2165,15 @@ fn app<'a, 'b>(
2160
2165
Rate authority defaults to the mint authority."
2161
2166
) ,
2162
2167
)
2168
+ . arg (
2169
+ Arg :: with_name ( "enable_non_transferable" )
2170
+ . long ( "enable-non-transferable" )
2171
+ . alias ( "enable-nontransferable" )
2172
+ . takes_value ( false )
2173
+ . help (
2174
+ "Permanently force tokens to be non-transferable. Thay may still be burned."
2175
+ ) ,
2176
+ )
2163
2177
. nonce_args ( true )
2164
2178
. arg ( memo_arg ( ) )
2165
2179
)
@@ -3114,6 +3128,7 @@ async fn process_command<'a>(
3114
3128
mint_authority,
3115
3129
arg_matches. is_present ( "enable_freeze" ) ,
3116
3130
arg_matches. is_present ( "enable_close" ) ,
3131
+ arg_matches. is_present ( "enable_non_transferable" ) ,
3117
3132
memo,
3118
3133
rate_bps,
3119
3134
bulk_signers,
@@ -3707,6 +3722,7 @@ mod tests {
3707
3722
transaction:: Transaction ,
3708
3723
} ,
3709
3724
solana_test_validator:: { ProgramInfo , TestValidator , TestValidatorGenesis } ,
3725
+ spl_token_2022:: extension:: non_transferable:: NonTransferable ,
3710
3726
spl_token_client:: client:: {
3711
3727
ProgramClient , ProgramRpcClient , ProgramRpcClientSendTransaction ,
3712
3728
} ,
@@ -3828,6 +3844,7 @@ mod tests {
3828
3844
payer. pubkey ( ) ,
3829
3845
false ,
3830
3846
false ,
3847
+ false ,
3831
3848
None ,
3832
3849
None ,
3833
3850
bulk_signers,
@@ -3854,6 +3871,7 @@ mod tests {
3854
3871
payer. pubkey ( ) ,
3855
3872
false ,
3856
3873
false ,
3874
+ false ,
3857
3875
None ,
3858
3876
Some ( rate_bps) ,
3859
3877
bulk_signers,
@@ -5100,6 +5118,7 @@ mod tests {
5100
5118
payer. pubkey ( ) ,
5101
5119
false ,
5102
5120
true ,
5121
+ false ,
5103
5122
None ,
5104
5123
None ,
5105
5124
bulk_signers,
@@ -5383,4 +5402,57 @@ mod tests {
5383
5402
. await ;
5384
5403
result. unwrap_err ( ) ;
5385
5404
}
5405
+
5406
+ #[ tokio:: test]
5407
+ #[ serial]
5408
+ async fn non_transferable ( ) {
5409
+ let ( test_validator, payer) = new_validator_for_test ( ) . await ;
5410
+ let config =
5411
+ test_config_with_default_signer ( & test_validator, & payer, & spl_token_2022:: id ( ) ) ;
5412
+
5413
+ let token_keypair = Keypair :: new ( ) ;
5414
+ let token_pubkey = token_keypair. pubkey ( ) ;
5415
+ let bulk_signers: Vec < Arc < dyn Signer > > =
5416
+ vec ! [ Arc :: new( clone_keypair( & payer) ) , Arc :: new( token_keypair) ] ;
5417
+
5418
+ command_create_token (
5419
+ & config,
5420
+ TEST_DECIMALS ,
5421
+ token_pubkey,
5422
+ payer. pubkey ( ) ,
5423
+ false ,
5424
+ false ,
5425
+ true ,
5426
+ None ,
5427
+ None ,
5428
+ bulk_signers,
5429
+ )
5430
+ . await
5431
+ . unwrap ( ) ;
5432
+
5433
+ let account = config. rpc_client . get_account ( & token_pubkey) . await . unwrap ( ) ;
5434
+ let test_mint = StateWithExtensionsOwned :: < Mint > :: unpack ( account. data ) . unwrap ( ) ;
5435
+ assert ! ( test_mint. get_extension:: <NonTransferable >( ) . is_ok( ) ) ;
5436
+
5437
+ let associated_account = create_associated_account ( & config, & payer, token_pubkey) . await ;
5438
+ let aux_account = create_auxiliary_account ( & config, & payer, token_pubkey) . await ;
5439
+ mint_tokens ( & config, & payer, token_pubkey, 100.0 , associated_account) . await ;
5440
+
5441
+ // transfer not allowed
5442
+ process_test_command (
5443
+ & config,
5444
+ & payer,
5445
+ & [
5446
+ "spl-token" ,
5447
+ CommandName :: Transfer . into ( ) ,
5448
+ "--from" ,
5449
+ & associated_account. to_string ( ) ,
5450
+ & token_pubkey. to_string ( ) ,
5451
+ "1" ,
5452
+ & aux_account. to_string ( ) ,
5453
+ ] ,
5454
+ )
5455
+ . await
5456
+ . unwrap_err ( ) ;
5457
+ }
5386
5458
}
0 commit comments