shadow_nft_common/
program_ids.rs

1//! The purpose of this module is to remove a circular depenedency between the minter and standard
2//! program crates. The minter program executes a cpi into the standard program, and the standard
3//! program verifies that a minter program derived address is a signer.
4pub use anchor_lang::prelude::Pubkey;
5
6/// AzCnwh6WUTNmwn1GAF7VP3bnP6VxHCcgP3iWzgmwAxUu
7pub const MINTER_PROGRAM: Pubkey = from_str("AzCnwh6WUTNmwn1GAF7VP3bnP6VxHCcgP3iWzgmwAxUu");
8
9/// 9fQse1hBRfzWweeUod6WEsR4jZf7hVucetEheCaWooY5
10pub const STANDARD_PROGRAM: Pubkey = from_str("9fQse1hBRfzWweeUod6WEsR4jZf7hVucetEheCaWooY5");
11
12pub const fn try_from_str(input: &str) -> Result<Pubkey, &'static str> {
13    match decode_pubkey(input.as_bytes()) {
14        Ok(bytes) => Ok(Pubkey::new_from_array(bytes)),
15        Err(e) => Err(e),
16    }
17}
18
19pub const fn from_str(input: &str) -> Pubkey {
20    match try_from_str(input) {
21        Ok(pubkey) => pubkey,
22        Err(_) => panic!("Invalid base58 Pubkey (Solana & Bitcoin Alphabet)"),
23    }
24}
25
26/// This is const-ified from base58 crate
27const fn new(base: &[u8; 58]) -> ([u8; 58], [u8; 128]) {
28    let mut encode = [0x00; 58];
29    let mut decode = [0xFF; 128];
30
31    let mut i = 0;
32    while i < encode.len() {
33        encode[i] = base[i];
34        decode[base[i] as usize] = i as u8;
35        i += 1;
36    }
37
38    (encode, decode)
39}
40
41/// This is const-ified from base58 crate
42///
43/// TODO: still need to handle oob w/o panic but like cmon just provide a valid pubkey str
44const fn decode_pubkey(input: &[u8]) -> Result<[u8; 32], &'static str> {
45    let mut output = [0; 32];
46
47    const SOLANA_ALPHABET: [u8; 58] =
48        *b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
49    const ENCODE_DECODE: ([u8; 58], [u8; 128]) = new(&SOLANA_ALPHABET);
50    const ENCODE: [u8; 58] = ENCODE_DECODE.0;
51    const DECODE: [u8; 128] = ENCODE_DECODE.1;
52    const ZERO: u8 = ENCODE[0];
53
54    let mut index = 0;
55
56    let len = input.len();
57    let mut i = 0;
58    while i < len {
59        let c = &input[i];
60
61        if *c > 127 {
62            return Err("Input contains non-ASCII");
63        }
64
65        let mut val = DECODE[*c as usize] as usize;
66        if val == 0xFF {
67            return Err("Input contains invalid char");
68        }
69
70        let mut inner_idx = 0;
71        while inner_idx < index {
72            val += (output[inner_idx] as usize) * 58;
73            output[inner_idx] = (val & 0xFF) as u8;
74            val >>= 8;
75            inner_idx += 1;
76        }
77
78        while val > 0 {
79            output[index] = (val & 0xFF) as u8;
80            index += 1;
81            val >>= 8;
82        }
83
84        i += 1;
85    }
86
87    let mut idx = 0;
88    let mut c = input[idx];
89    while c == ZERO {
90        c = input[idx];
91        idx += 1;
92
93        output[index] = 0;
94        index += 1;
95    }
96
97    let mut rev_output = [0; 32];
98    let mut idx = 0;
99    while idx < 32 {
100        rev_output[idx] = output[31 - idx];
101        idx += 1;
102    }
103    Ok(rev_output)
104}
105
106#[test]
107fn test_two_cases() {
108    let input = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS";
109    let expected = Pubkey::new_from_array([
110        218, 7, 92, 178, 255, 94, 198, 129, 118, 19, 222, 83, 11, 105, 42, 135, 53, 71, 119, 105,
111        218, 71, 67, 12, 189, 129, 84, 51, 92, 74, 131, 39,
112    ]);
113    assert_eq!(from_str(input), expected);
114
115    let input = "fBhaujR6iaQkiaDZPsQb5LXLK7y5cRsTaddBV3UWNTq";
116    let expected = Pubkey::new_from_array([
117        9, 200, 43, 65, 225, 51, 167, 33, 30, 3, 37, 197, 7, 16, 205, 73, 131, 203, 140, 102, 102,
118        250, 52, 161, 17, 175, 31, 193, 190, 161, 212, 128,
119    ]);
120    assert_eq!(from_str(input), expected);
121}