Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 919d563

Browse files
authored
[token-CLI] Add command_initialize_group to Token Cli (#6135)
* added extra metas resolution to create_recipient_associated_account_and_transfer() * add command_initialize_group to token CLI * added clap validator for max_size argument * added test for initializeing a token-group * added checks for authority and max_size for group test
1 parent ff8b418 commit 919d563

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed

token/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ spl-token-2022 = { version = "1.0", path = "../program-2022", features = [
3636
] }
3737
spl-token-client = { version = "0.8", path = "../client" }
3838
spl-token-metadata-interface = { version = "0.2", path = "../../token-metadata/interface" }
39+
spl-token-group-interface = { version = "0.1", path = "../../token-group/interface" }
3940
spl-associated-token-account = { version = "2.0", path = "../../associated-token-account/program", features = [
4041
"no-entrypoint",
4142
] }

token/cli/src/clap_app.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub enum CommandName {
107107
SetTransferHook,
108108
InitializeMetadata,
109109
UpdateMetadata,
110+
InitializeGroup,
110111
UpdateConfidentialTransferSettings,
111112
ConfigureConfidentialTransferAccount,
112113
EnableConfidentialCredits,
@@ -960,6 +961,52 @@ pub fn app<'a, 'b>(
960961
.arg(transfer_lamports_arg())
961962
.offline_args_config(&SignOnlyNeedsTransferLamports{}),
962963
)
964+
.subcommand(
965+
SubCommand::with_name(CommandName::InitializeGroup.into())
966+
.about("Initialize group extension on a token mint")
967+
.arg(
968+
Arg::with_name("token")
969+
.validator(is_valid_pubkey)
970+
.value_name("TOKEN_MINT_ADDRESS")
971+
.takes_value(true)
972+
.required(true)
973+
.index(1)
974+
.help("The token address of the group account."),
975+
)
976+
.arg(
977+
Arg::with_name("max_size")
978+
.validator(is_amount)
979+
.value_name("MAX_SIZE")
980+
.takes_value(true)
981+
.required(true)
982+
.index(2)
983+
.help("The number of members in the group."),
984+
)
985+
.arg(
986+
Arg::with_name("mint_authority")
987+
.long("mint-authority")
988+
.alias("owner")
989+
.value_name("KEYPAIR")
990+
.validator(is_valid_signer)
991+
.takes_value(true)
992+
.help(
993+
"Specify the mint authority keypair. \
994+
This may be a keypair file or the ASK keyword. \
995+
Defaults to the client keypair."
996+
),
997+
)
998+
.arg(
999+
Arg::with_name("update_authority")
1000+
.long("update-authority")
1001+
.value_name("ADDRESS")
1002+
.validator(is_valid_pubkey)
1003+
.takes_value(true)
1004+
.help(
1005+
"Specify the update authority address. \
1006+
Defaults to the client keypair address."
1007+
),
1008+
)
1009+
)
9631010
.subcommand(
9641011
SubCommand::with_name(CommandName::CreateAccount.into())
9651012
.about("Create a new token account")

token/cli/src/command.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,37 @@ async fn command_update_metadata(
596596
})
597597
}
598598

599+
#[allow(clippy::too_many_arguments)]
600+
async fn command_initialize_group(
601+
config: &Config<'_>,
602+
token_pubkey: Pubkey,
603+
mint_authority: Pubkey,
604+
update_authority: Pubkey,
605+
max_size: u32,
606+
bulk_signers: Vec<Arc<dyn Signer>>,
607+
) -> CommandResult {
608+
let token = token_client_from_config(config, &token_pubkey, None)?;
609+
610+
let res = token
611+
.token_group_initialize_with_rent_transfer(
612+
&config.fee_payer()?.pubkey(),
613+
&mint_authority,
614+
&update_authority,
615+
max_size,
616+
&bulk_signers,
617+
)
618+
.await?;
619+
620+
let tx_return = finish_tx(config, &res, false).await?;
621+
Ok(match tx_return {
622+
TransactionReturnData::CliSignature(signature) => {
623+
config.output_format.formatted_string(&signature)
624+
}
625+
TransactionReturnData::CliSignOnlyData(sign_only_data) => {
626+
config.output_format.formatted_string(&sign_only_data)
627+
}
628+
})
629+
}
599630
async fn command_set_transfer_fee(
600631
config: &Config<'_>,
601632
token_pubkey: Pubkey,
@@ -3455,6 +3486,27 @@ pub async fn process_command<'a>(
34553486
)
34563487
.await
34573488
}
3489+
(CommandName::InitializeGroup, arg_matches) => {
3490+
let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)
3491+
.unwrap()
3492+
.unwrap();
3493+
let max_size = value_t_or_exit!(arg_matches, "max_size", u32);
3494+
let (mint_authority_signer, mint_authority) =
3495+
config.signer_or_default(arg_matches, "mint_authority", &mut wallet_manager);
3496+
let update_authority =
3497+
config.pubkey_or_default(arg_matches, "update_authority", &mut wallet_manager)?;
3498+
let bulk_signers = vec![mint_authority_signer];
3499+
3500+
command_initialize_group(
3501+
config,
3502+
token_pubkey,
3503+
mint_authority,
3504+
update_authority,
3505+
max_size,
3506+
bulk_signers,
3507+
)
3508+
.await
3509+
}
34583510
(CommandName::CreateAccount, arg_matches) => {
34593511
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)
34603512
.unwrap()

token/cli/tests/command.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use {
4646
},
4747
token::Token,
4848
},
49+
spl_token_group_interface::state::TokenGroup,
4950
spl_token_metadata_interface::state::TokenMetadata,
5051
std::{ffi::OsString, path::PathBuf, str::FromStr, sync::Arc},
5152
tempfile::NamedTempFile,
@@ -131,6 +132,7 @@ async fn main() {
131132
async_trial!(group_member_pointer, test_validator, payer),
132133
async_trial!(transfer_hook, test_validator, payer),
133134
async_trial!(metadata, test_validator, payer),
135+
async_trial!(group, test_validator, payer),
134136
async_trial!(confidential_transfer_with_fee, test_validator, payer),
135137
// GC messes with every other test, so have it on its own test validator
136138
async_trial!(gc, gc_test_validator, gc_payer),
@@ -3788,3 +3790,56 @@ async fn metadata(test_validator: &TestValidator, payer: &Keypair) {
37883790
Some(mint).try_into().unwrap()
37893791
);
37903792
}
3793+
3794+
async fn group(test_validator: &TestValidator, payer: &Keypair) {
3795+
let program_id = spl_token_2022::id();
3796+
let config = test_config_with_default_signer(test_validator, payer, &program_id);
3797+
let max_size = 10;
3798+
3799+
// Create token
3800+
let result = process_test_command(
3801+
&config,
3802+
payer,
3803+
&[
3804+
"spl-token",
3805+
CommandName::CreateToken.into(),
3806+
"--program-id",
3807+
&program_id.to_string(),
3808+
"--enable-group",
3809+
],
3810+
)
3811+
.await;
3812+
3813+
let value: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();
3814+
let mint = Pubkey::from_str(value["commandOutput"]["address"].as_str().unwrap()).unwrap();
3815+
3816+
// Initialize the group
3817+
process_test_command(
3818+
&config,
3819+
payer,
3820+
&[
3821+
"spl-token",
3822+
CommandName::InitializeGroup.into(),
3823+
&mint.to_string(),
3824+
&max_size.to_string(),
3825+
],
3826+
)
3827+
.await
3828+
.unwrap();
3829+
3830+
let account = config.rpc_client.get_account(&mint).await.unwrap();
3831+
let mint_state = StateWithExtensionsOwned::<Mint>::unpack(account.data).unwrap();
3832+
3833+
let extension = mint_state.get_extension::<TokenGroup>().unwrap();
3834+
assert_eq!(
3835+
extension.update_authority,
3836+
Some(payer.pubkey()).try_into().unwrap()
3837+
);
3838+
assert_eq!(extension.max_size, max_size.into());
3839+
3840+
let extension_pointer = mint_state.get_extension::<GroupPointer>().unwrap();
3841+
assert_eq!(
3842+
extension_pointer.group_address,
3843+
Some(mint).try_into().unwrap()
3844+
);
3845+
}

0 commit comments

Comments
 (0)