close idl account

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-07-26 10:16:17 +02:00
parent 1153380487
commit d102903441
4 changed files with 94 additions and 2 deletions

View File

@ -314,6 +314,9 @@ pub enum IdlCommand {
#[clap(short, long)]
filepath: String,
},
Close {
program_id: Pubkey,
},
/// Writes an IDL into a buffer account. This can be used with SetBuffer
/// to perform an upgrade.
WriteBuffer {
@ -1522,6 +1525,7 @@ fn idl(cfg_override: &ConfigOverride, subcmd: IdlCommand) -> Result<()> {
program_id,
filepath,
} => idl_init(cfg_override, program_id, filepath),
IdlCommand::Close { program_id } => idl_close(cfg_override, program_id),
IdlCommand::WriteBuffer {
program_id,
filepath,
@ -1564,6 +1568,17 @@ fn idl_init(cfg_override: &ConfigOverride, program_id: Pubkey, idl_filepath: Str
})
}
fn idl_close(cfg_override: &ConfigOverride, program_id: Pubkey) -> Result<()> {
with_workspace(cfg_override, |cfg| {
let idl_address = IdlAccount::address(&program_id);
idl_close_account(&cfg, &program_id, idl_address)?;
println!("Idl account closed: {:?}", idl_address);
Ok(())
})
}
fn idl_write_buffer(
cfg_override: &ConfigOverride,
program_id: Pubkey,
@ -1737,6 +1752,44 @@ fn idl_erase_authority(cfg_override: &ConfigOverride, program_id: Pubkey) -> Res
Ok(())
}
fn idl_close_account(cfg: &Config, program_id: &Pubkey, idl_address: Pubkey) -> Result<()> {
let keypair = solana_sdk::signature::read_keypair_file(&cfg.provider.wallet.to_string())
.map_err(|_| anyhow!("Unable to read keypair file"))?;
let url = cluster_url(cfg, &cfg.test_validator);
let client = RpcClient::new(url);
// Instruction accounts.
let accounts = vec![
AccountMeta::new(idl_address, false),
AccountMeta::new_readonly(keypair.pubkey(), true),
AccountMeta::new(keypair.pubkey(), true),
];
// Instruction.
let ix = Instruction {
program_id: *program_id,
accounts,
data: { serialize_idl_ix(anchor_lang::idl::IdlInstruction::Close {})? },
};
// Send transaction.
let latest_hash = client.get_latest_blockhash()?;
let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&keypair.pubkey()),
&[&keypair],
latest_hash,
);
client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
CommitmentConfig::confirmed(),
RpcSendTransactionConfig {
skip_preflight: true,
..RpcSendTransactionConfig::default()
},
)?;
Ok(())
}
// Write the idl to the account buffer, chopping up the IDL into pieces
// and sending multiple transactions in the event the IDL doesn't fit into
// a single transaction.
@ -2517,7 +2570,12 @@ fn create_idl_account(
// Run `Create instruction.
{
let data = serialize_idl_ix(anchor_lang::idl::IdlInstruction::Create {
data_len: (idl_data.len() as u64) * 2, // Double for future growth.
// Double for future growth.
data_len: if (idl_data.len() as u64) * 2 > 10240 {
10196 // note: 44 bytes get added somewhere along the line
} else {
(idl_data.len() as u64) * 2
},
})?;
let program_signer = Pubkey::find_program_address(&[], program_id).0;
let accounts = vec![

View File

@ -45,6 +45,7 @@ pub enum IdlInstruction {
SetBuffer,
// Sets a new authority on the IdlAccount.
SetAuthority { new_authority: Pubkey },
Close,
}
// Accounts for the Create instruction.
@ -85,6 +86,18 @@ pub struct IdlSetBuffer<'info> {
pub authority: Signer<'info>,
}
// Accounts for closing the canonical Idl buffer.
#[derive(Accounts)]
pub struct IdlCloseAccount<'info> {
#[account(mut, has_one = authority, close = sol_destination)]
#[allow(deprecated)]
pub account: ProgramAccount<'info, IdlAccount>,
#[account(constraint = authority.key != &ERASED_AUTHORITY)]
pub authority: Signer<'info>,
#[account(mut)]
pub sol_destination: AccountInfo<'info>,
}
// The account holding a program's IDL. This is stored on chain so that clients
// can fetch it and generate a client with nothing but a program's ID.
//

View File

@ -32,6 +32,14 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
__idl_create_account(program_id, &mut accounts, data_len)?;
accounts.exit(program_id)?;
},
anchor_lang::idl::IdlInstruction::Close => {
let mut bumps = std::collections::BTreeMap::new();
let mut reallocs = std::collections::BTreeSet::new();
let mut accounts =
anchor_lang::idl::IdlCloseAccount::try_accounts(program_id, &mut accounts, &[], &mut bumps, &mut reallocs)?;
__idl_close_account(program_id, &mut accounts)?;
accounts.exit(program_id)?;
},
anchor_lang::idl::IdlInstruction::CreateBuffer => {
let mut bumps = std::collections::BTreeMap::new();
let mut reallocs = std::collections::BTreeSet::new();
@ -140,6 +148,17 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
Ok(())
}
#[inline(never)]
pub fn __idl_close_account(
program_id: &Pubkey,
accounts: &mut anchor_lang::idl::IdlCloseAccount,
) -> anchor_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
anchor_lang::prelude::msg!("Instruction: IdlCloseAccount");
Ok(())
}
#[inline(never)]
pub fn __idl_create_buffer(
program_id: &Pubkey,

View File

@ -264,7 +264,9 @@ fn parse_ty(f: &syn::Field) -> ParseResult<Ty> {
"UncheckedAccount" => Ty::UncheckedAccount,
"Loader" => Ty::Loader(parse_program_account_zero_copy(&path)?),
"AccountLoader" => Ty::AccountLoader(parse_program_account_loader(&path)?),
"AccountLoaderDynamic" => Ty::AccountLoaderDynamic(parse_program_mango_account_loader(&path)?),
"AccountLoaderDynamic" => {
Ty::AccountLoaderDynamic(parse_program_mango_account_loader(&path)?)
}
"Account" => Ty::Account(parse_account_ty(&path)?),
"Program" => Ty::Program(parse_program_ty(&path)?),
"Signer" => Ty::Signer,