sugar_cli/update/
process.rs

1use std::str::FromStr;
2
3use anchor_client::solana_sdk::pubkey::Pubkey;
4use anyhow::Result;
5use console::style;
6use mpl_candy_machine_core::{
7    accounts as nft_accounts, instruction as nft_instruction, CandyMachineData,
8};
9
10use crate::{
11    cache::load_cache,
12    candy_machine::{get_candy_machine_state, CANDY_MACHINE_ID},
13    common::*,
14    config::{data::ConfigData, parser::get_config_data},
15    utils::{assert_correct_authority, spinner_with_style},
16};
17
18pub struct UpdateArgs {
19    pub keypair: Option<String>,
20    pub rpc_url: Option<String>,
21    pub cache: String,
22    pub new_authority: Option<String>,
23    pub config: String,
24    pub candy_machine: Option<String>,
25}
26
27pub fn process_update(args: UpdateArgs) -> Result<()> {
28    let sugar_config = sugar_setup(args.keypair, args.rpc_url)?;
29    let client = setup_client(&sugar_config)?;
30    let config_data = get_config_data(&args.config)?;
31
32    // the candy machine id specified takes precedence over the one from the cache
33    let candy_machine_id = match args.candy_machine {
34        Some(candy_machine_id) => candy_machine_id,
35        None => {
36            let cache = load_cache(&args.cache, false)?;
37            cache.program.candy_machine
38        }
39    };
40
41    let candy_pubkey = match Pubkey::from_str(&candy_machine_id) {
42        Ok(candy_pubkey) => candy_pubkey,
43        Err(_) => {
44            let error = anyhow!("Failed to parse candy machine id: {}", candy_machine_id);
45            error!("{:?}", error);
46            return Err(error);
47        }
48    };
49
50    println!(
51        "{} {}Loading candy machine",
52        style("[1/2]").bold().dim(),
53        LOOKING_GLASS_EMOJI
54    );
55    println!("{} {}", style("Candy machine ID:").bold(), candy_machine_id);
56
57    let pb = spinner_with_style();
58    pb.set_message("Connecting...");
59
60    let candy_machine_state = get_candy_machine_state(&sugar_config, &candy_pubkey)?;
61    let candy_machine_data = create_candy_machine_data(&config_data, &candy_machine_state.data)?;
62
63    pb.finish_with_message("Done");
64
65    assert_correct_authority(
66        &sugar_config.keypair.pubkey(),
67        &candy_machine_state.authority,
68    )?;
69
70    println!(
71        "\n{} {}Updating configuration",
72        style("[2/2]").bold().dim(),
73        COMPUTER_EMOJI
74    );
75
76    let program = client.program(CANDY_MACHINE_ID);
77    let builder = program
78        .request()
79        .accounts(nft_accounts::Update {
80            candy_machine: candy_pubkey,
81            authority: program.payer(),
82        })
83        .args(nft_instruction::Update {
84            data: candy_machine_data,
85        });
86
87    let pb = spinner_with_style();
88    pb.set_message("Sending update transaction...");
89
90    let update_signature = builder.send()?;
91
92    pb.finish_with_message(format!(
93        "{} {}",
94        style("Update signature:").bold(),
95        update_signature
96    ));
97
98    if let Some(new_authority) = args.new_authority {
99        let pb = spinner_with_style();
100        pb.set_message("Sending update authority transaction...");
101
102        let new_authority_pubkey = Pubkey::from_str(&new_authority)?;
103        let builder = program
104            .request()
105            .accounts(nft_accounts::SetAuthority {
106                candy_machine: candy_pubkey,
107                authority: program.payer(),
108            })
109            .args(nft_instruction::SetAuthority {
110                new_authority: new_authority_pubkey,
111            });
112
113        let authority_signature = builder.send()?;
114        pb.finish_with_message(format!(
115            "{} {}",
116            style("Authority signature:").bold(),
117            authority_signature
118        ));
119    }
120
121    Ok(())
122}
123
124fn create_candy_machine_data(
125    config: &ConfigData,
126    candy_machine: &CandyMachineData,
127) -> Result<CandyMachineData> {
128    let hidden_settings = config.hidden_settings.as_ref().map(|s| s.to_candy_format());
129
130    let creators = config
131        .creators
132        .clone()
133        .into_iter()
134        .map(|c| c.to_candy_format())
135        .collect::<Result<Vec<mpl_candy_machine_core::Creator>>>()?;
136
137    let data = CandyMachineData {
138        symbol: config.symbol.clone(),
139        seller_fee_basis_points: config.seller_fee_basis_points,
140        max_supply: 0,
141        is_mutable: config.is_mutable,
142        creators,
143        hidden_settings,
144        config_line_settings: candy_machine.config_line_settings.clone(),
145        items_available: config.number,
146    };
147    Ok(data)
148}