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

Commit 049777c

Browse files
authored
token-cli: Add initialize-member command (#6163)
* token-cli: Add initialize-member command * Rename update-authority -> group-update-authority
1 parent 65b81cc commit 049777c

File tree

3 files changed

+155
-1
lines changed

3 files changed

+155
-1
lines changed

token/cli/src/clap_app.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub enum CommandName {
109109
UpdateMetadata,
110110
InitializeGroup,
111111
UpdateGroupMaxSize,
112+
InitializeMember,
112113
UpdateConfidentialTransferSettings,
113114
ConfigureConfidentialTransferAccount,
114115
EnableConfidentialCredits,
@@ -1041,6 +1042,53 @@ pub fn app<'a, 'b>(
10411042
),
10421043
)
10431044
)
1045+
.subcommand(
1046+
SubCommand::with_name(CommandName::InitializeMember.into())
1047+
.about("Initialize group member extension on a token mint")
1048+
.arg(
1049+
Arg::with_name("token")
1050+
.validator(is_valid_pubkey)
1051+
.value_name("TOKEN_MINT_ADDRESS")
1052+
.takes_value(true)
1053+
.required(true)
1054+
.index(1)
1055+
.help("The token address of the member account."),
1056+
)
1057+
.arg(
1058+
Arg::with_name("group_token")
1059+
.validator(is_valid_pubkey)
1060+
.value_name("TOKEN_MINT_ADDRESS")
1061+
.takes_value(true)
1062+
.required(true)
1063+
.index(2)
1064+
.help("The token address of the group account that the token will join."),
1065+
)
1066+
.arg(
1067+
Arg::with_name("mint_authority")
1068+
.long("mint-authority")
1069+
.alias("owner")
1070+
.value_name("KEYPAIR")
1071+
.validator(is_valid_signer)
1072+
.takes_value(true)
1073+
.help(
1074+
"Specify the mint authority keypair. \
1075+
This may be a keypair file or the ASK keyword. \
1076+
Defaults to the client keypair."
1077+
),
1078+
)
1079+
.arg(
1080+
Arg::with_name("group_update_authority")
1081+
.long("group-update-authority")
1082+
.value_name("KEYPAIR")
1083+
.validator(is_valid_signer)
1084+
.takes_value(true)
1085+
.help(
1086+
"Specify the update authority keypair. \
1087+
This may be a keypair file or the ASK keyword. \
1088+
Defaults to the client keypair address."
1089+
),
1090+
)
1091+
)
10441092
.subcommand(
10451093
SubCommand::with_name(CommandName::CreateAccount.into())
10461094
.about("Create a new token account")

token/cli/src/command.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,37 @@ async fn command_update_group_max_size(
653653
})
654654
}
655655

656+
async fn command_initialize_member(
657+
config: &Config<'_>,
658+
member_token_pubkey: Pubkey,
659+
mint_authority: Pubkey,
660+
group_token_pubkey: Pubkey,
661+
group_update_authority: Pubkey,
662+
bulk_signers: Vec<Arc<dyn Signer>>,
663+
) -> CommandResult {
664+
let token = token_client_from_config(config, &member_token_pubkey, None)?;
665+
666+
let res = token
667+
.token_group_initialize_member_with_rent_transfer(
668+
&config.fee_payer()?.pubkey(),
669+
&mint_authority,
670+
&group_token_pubkey,
671+
&group_update_authority,
672+
&bulk_signers,
673+
)
674+
.await?;
675+
676+
let tx_return = finish_tx(config, &res, false).await?;
677+
Ok(match tx_return {
678+
TransactionReturnData::CliSignature(signature) => {
679+
config.output_format.formatted_string(&signature)
680+
}
681+
TransactionReturnData::CliSignOnlyData(sign_only_data) => {
682+
config.output_format.formatted_string(&sign_only_data)
683+
}
684+
})
685+
}
686+
656687
async fn command_set_transfer_fee(
657688
config: &Config<'_>,
658689
token_pubkey: Pubkey,
@@ -3551,6 +3582,34 @@ pub async fn process_command<'a>(
35513582
)
35523583
.await
35533584
}
3585+
(CommandName::InitializeMember, arg_matches) => {
3586+
let member_token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)
3587+
.unwrap()
3588+
.unwrap();
3589+
let group_token_pubkey =
3590+
pubkey_of_signer(arg_matches, "group_token", &mut wallet_manager)
3591+
.unwrap()
3592+
.unwrap();
3593+
let (mint_authority_signer, mint_authority) =
3594+
config.signer_or_default(arg_matches, "mint_authority", &mut wallet_manager);
3595+
let (group_update_authority_signer, group_update_authority) = config.signer_or_default(
3596+
arg_matches,
3597+
"group_update_authority",
3598+
&mut wallet_manager,
3599+
);
3600+
let mut bulk_signers = vec![mint_authority_signer];
3601+
push_signer_with_dedup(group_update_authority_signer, &mut bulk_signers);
3602+
3603+
command_initialize_member(
3604+
config,
3605+
member_token_pubkey,
3606+
mint_authority,
3607+
group_token_pubkey,
3608+
group_update_authority,
3609+
bulk_signers,
3610+
)
3611+
.await
3612+
}
35543613
(CommandName::CreateAccount, arg_matches) => {
35553614
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)
35563615
.unwrap()

token/cli/tests/command.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use {
4646
},
4747
token::Token,
4848
},
49-
spl_token_group_interface::state::TokenGroup,
49+
spl_token_group_interface::state::{TokenGroup, TokenGroupMember},
5050
spl_token_metadata_interface::state::TokenMetadata,
5151
std::{ffi::OsString, path::PathBuf, str::FromStr, sync::Arc},
5252
tempfile::NamedTempFile,
@@ -3865,4 +3865,51 @@ async fn group(test_validator: &TestValidator, payer: &Keypair) {
38653865

38663866
let updated_extension = updated_mint_state.get_extension::<TokenGroup>().unwrap();
38673867
assert_eq!(updated_extension.max_size, new_max_size.into());
3868+
3869+
// Create member token
3870+
let result = process_test_command(
3871+
&config,
3872+
payer,
3873+
&[
3874+
"spl-token",
3875+
CommandName::CreateToken.into(),
3876+
"--program-id",
3877+
&program_id.to_string(),
3878+
"--enable-member",
3879+
],
3880+
)
3881+
.await
3882+
.unwrap();
3883+
3884+
let value: serde_json::Value = serde_json::from_str(&result).unwrap();
3885+
let member_mint =
3886+
Pubkey::from_str(value["commandOutput"]["address"].as_str().unwrap()).unwrap();
3887+
3888+
// Initialize it as a member of the group
3889+
process_test_command(
3890+
&config,
3891+
payer,
3892+
&[
3893+
"spl-token",
3894+
CommandName::InitializeMember.into(),
3895+
&member_mint.to_string(),
3896+
&mint.to_string(),
3897+
],
3898+
)
3899+
.await
3900+
.unwrap();
3901+
3902+
let account = config.rpc_client.get_account(&mint).await.unwrap();
3903+
let group_mint_state = StateWithExtensionsOwned::<Mint>::unpack(account.data).unwrap();
3904+
let extension = group_mint_state.get_extension::<TokenGroup>().unwrap();
3905+
assert_eq!(u32::from(extension.size), 1);
3906+
3907+
let account = config.rpc_client.get_account(&member_mint).await.unwrap();
3908+
let member_mint_state = StateWithExtensionsOwned::<Mint>::unpack(account.data).unwrap();
3909+
let extension = member_mint_state
3910+
.get_extension::<TokenGroupMember>()
3911+
.unwrap();
3912+
assert_eq!(extension.group, mint);
3913+
assert_eq!(extension.mint, member_mint);
3914+
assert_eq!(u32::from(extension.member_number), 1);
38683915
}

0 commit comments

Comments
 (0)