1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use anchor_client::{solana_sdk::pubkey::Pubkey, ClientError, Program};
use anyhow::{anyhow, Result};
use mpl_candy_machine::CollectionPDA;
use mpl_token_metadata::{
    pda::{find_master_edition_account, find_metadata_account},
    state::{Key, MasterEditionV2, Metadata, TokenMetadataAccount, MAX_MASTER_EDITION_LEN},
    utils::try_from_slice_checked,
};

use crate::candy_machine::CANDY_MACHINE_ID;

pub type PdaInfo<T> = (Pubkey, T);

pub fn find_metadata_pda(mint: &Pubkey) -> Pubkey {
    let (pda, _bump) = find_metadata_account(mint);

    pda
}

pub fn get_metadata_pda(mint: &Pubkey, program: &Program) -> Result<PdaInfo<Metadata>> {
    let metadata_pubkey = find_metadata_pda(mint);
    let metadata_account = program.rpc().get_account(&metadata_pubkey).map_err(|_| {
        anyhow!(
            "Couldn't find metadata account: {}",
            &metadata_pubkey.to_string()
        )
    })?;
    let metadata = Metadata::safe_deserialize(metadata_account.data.as_slice());
    metadata.map(|m| (metadata_pubkey, m)).map_err(|_| {
        anyhow!(
            "Failed to deserialize metadata account: {}",
            &metadata_pubkey.to_string()
        )
    })
}

pub fn find_master_edition_pda(mint: &Pubkey) -> Pubkey {
    let (pda, _bump) = find_master_edition_account(mint);

    pda
}

pub fn get_master_edition_pda(
    mint: &Pubkey,
    program: &Program,
) -> Result<PdaInfo<MasterEditionV2>> {
    let master_edition_pubkey = find_master_edition_pda(mint);
    let master_edition_account =
        program
            .rpc()
            .get_account(&master_edition_pubkey)
            .map_err(|_| {
                anyhow!(
                    "Couldn't find master edition account: {}",
                    &master_edition_pubkey.to_string()
                )
            })?;
    let master_edition = try_from_slice_checked(
        master_edition_account.data.as_slice(),
        Key::MasterEditionV2,
        MAX_MASTER_EDITION_LEN,
    );
    master_edition
        .map(|m| (master_edition_pubkey, m))
        .map_err(|_| {
            anyhow!(
                "Invalid master edition account: {}",
                &master_edition_pubkey.to_string()
            )
        })
}

pub fn find_candy_machine_creator_pda(candy_machine_id: &Pubkey) -> (Pubkey, u8) {
    // Derive metadata account
    let creator_seeds = &["candy_machine".as_bytes(), candy_machine_id.as_ref()];

    Pubkey::find_program_address(creator_seeds, &CANDY_MACHINE_ID)
}

pub fn find_collection_pda(candy_machine_id: &Pubkey) -> (Pubkey, u8) {
    // Derive collection PDA address
    let collection_seeds = &["collection".as_bytes(), candy_machine_id.as_ref()];

    Pubkey::find_program_address(collection_seeds, &CANDY_MACHINE_ID)
}

pub fn find_freeze_pda(candy_machine_id: &Pubkey) -> (Pubkey, u8) {
    // Derive freeze PDA address
    let freeze_seeds = &["freeze".as_bytes(), candy_machine_id.as_ref()];

    Pubkey::find_program_address(freeze_seeds, &CANDY_MACHINE_ID)
}

pub fn get_collection_pda(
    candy_machine: &Pubkey,
    program: &Program,
) -> Result<PdaInfo<CollectionPDA>> {
    let collection_pda_pubkey = find_collection_pda(candy_machine).0;
    program
        .account(collection_pda_pubkey)
        .map(|c| (collection_pda_pubkey, c))
        .map_err(|e| match e {
            ClientError::AccountNotFound => anyhow!("Candy Machine collection is not set!"),
            _ => anyhow!(
                "Failed to deserialize collection PDA account: {}",
                &collection_pda_pubkey.to_string()
            ),
        })
}