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

Commit 1d8d883

Browse files
authored
token-cli: Fix updating metadata with offline signer (#5496)
1 parent 4e81567 commit 1d8d883

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

token/cli/src/main.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ pub const DELEGATE_ADDRESS_ARG: ArgConstant<'static> = ArgConstant {
110110
help: "Address of delegate currently assigned to token account. Required by --sign-only",
111111
};
112112

113+
pub const TRANSFER_LAMPORTS_ARG: ArgConstant<'static> = ArgConstant {
114+
name: "transfer_lamports",
115+
long: "transfer-lamports",
116+
help: "Additional lamports to transfer to make account rent-exempt after reallocation. Required by --sign-only",
117+
};
118+
113119
pub const MULTISIG_SIGNER_ARG: ArgConstant<'static> = ArgConstant {
114120
name: "multisig_signer",
115121
long: "multisig-signer",
@@ -323,6 +329,15 @@ pub fn delegate_address_arg<'a, 'b>() -> Arg<'a, 'b> {
323329
.help(DELEGATE_ADDRESS_ARG.help)
324330
}
325331

332+
pub fn transfer_lamports_arg<'a, 'b>() -> Arg<'a, 'b> {
333+
Arg::with_name(TRANSFER_LAMPORTS_ARG.name)
334+
.long(TRANSFER_LAMPORTS_ARG.long)
335+
.takes_value(true)
336+
.value_name("LAMPORTS")
337+
.validator(is_amount)
338+
.help(TRANSFER_LAMPORTS_ARG.help)
339+
}
340+
326341
pub fn multisig_signer_arg<'a, 'b>() -> Arg<'a, 'b> {
327342
Arg::with_name(MULTISIG_SIGNER_ARG.name)
328343
.long(MULTISIG_SIGNER_ARG.long)
@@ -815,6 +830,7 @@ async fn command_update_metadata(
815830
authority: Pubkey,
816831
field: Field,
817832
value: Option<String>,
833+
transfer_lamports: Option<u64>,
818834
bulk_signers: Vec<Arc<dyn Signer>>,
819835
) -> CommandResult {
820836
let token = token_client_from_config(config, &token_pubkey, None)?;
@@ -826,6 +842,7 @@ async fn command_update_metadata(
826842
&authority,
827843
field,
828844
value,
845+
transfer_lamports,
829846
&bulk_signers,
830847
)
831848
.await?
@@ -2898,6 +2915,16 @@ impl offline::ArgsConfig for SignOnlyNeedsDelegateAddress {
28982915
}
28992916
}
29002917

2918+
struct SignOnlyNeedsTransferLamports {}
2919+
impl offline::ArgsConfig for SignOnlyNeedsTransferLamports {
2920+
fn sign_only_arg<'a, 'b>(&self, arg: Arg<'a, 'b>) -> Arg<'a, 'b> {
2921+
arg.requires_all(&[TRANSFER_LAMPORTS_ARG.name])
2922+
}
2923+
fn signer_arg<'a, 'b>(&self, arg: Arg<'a, 'b>) -> Arg<'a, 'b> {
2924+
arg.requires_all(&[TRANSFER_LAMPORTS_ARG.name])
2925+
}
2926+
}
2927+
29012928
fn minimum_signers_help_string() -> String {
29022929
format!(
29032930
"The minimum number of signers required to allow the operation. [{} <= M <= N]",
@@ -3295,7 +3322,8 @@ fn app<'a, 'b>(
32953322
.help("Specify the metadata update authority keypair. Defaults to the client keypair.")
32963323
)
32973324
.nonce_args(true)
3298-
.offline_args(),
3325+
.arg(transfer_lamports_arg())
3326+
.offline_args_config(&SignOnlyNeedsTransferLamports{}),
32993327
)
33003328
.subcommand(
33013329
SubCommand::with_name(CommandName::CreateAccount.into())
@@ -4622,10 +4650,19 @@ async fn process_command<'a>(
46224650
_ => Field::Key(field.to_string()),
46234651
};
46244652
let value = arg_matches.value_of("value").map(|v| v.to_string());
4653+
let transfer_lamports = value_of::<u64>(arg_matches, TRANSFER_LAMPORTS_ARG.name);
46254654
let bulk_signers = vec![authority_signer];
46264655

4627-
command_update_metadata(config, token_pubkey, authority, field, value, bulk_signers)
4628-
.await
4656+
command_update_metadata(
4657+
config,
4658+
token_pubkey,
4659+
authority,
4660+
field,
4661+
value,
4662+
transfer_lamports,
4663+
bulk_signers,
4664+
)
4665+
.await
46294666
}
46304667
(CommandName::CreateAccount, arg_matches) => {
46314668
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)

token/client/src/token.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3743,11 +3743,15 @@ where
37433743
update_authority: &Pubkey,
37443744
field: Field,
37453745
value: String,
3746+
transfer_lamports: Option<u64>,
37463747
signing_keypairs: &S,
37473748
) -> TokenResult<T::Output> {
3748-
let additional_lamports = self
3749-
.get_additional_rent_for_updated_metadata(field.clone(), value.clone())
3750-
.await?;
3749+
let additional_lamports = if let Some(transfer_lamports) = transfer_lamports {
3750+
transfer_lamports
3751+
} else {
3752+
self.get_additional_rent_for_updated_metadata(field.clone(), value.clone())
3753+
.await?
3754+
};
37513755
let mut instructions = vec![];
37523756
if additional_lamports > 0 {
37533757
instructions.push(system_instruction::transfer(

token/program-2022-test/tests/token_metadata_remove_key.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ async fn success_remove() {
105105
&update_authority.pubkey(),
106106
field,
107107
value,
108+
None,
108109
&[&update_authority],
109110
)
110111
.await

token/program-2022-test/tests/token_metadata_update_field.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ async fn success_update(field: Field, value: String) {
122122
&update_authority.pubkey(),
123123
field,
124124
value,
125+
None,
125126
&[&update_authority],
126127
)
127128
.await

0 commit comments

Comments
 (0)