1use tape_api::prelude::*;
2use solana_program::program_pack::Pack;
3use spl_token::state::Mint;
4use steel::*;
5
6const INITIAL_DIFFICULTY: u32 = 7;
7const INITIAL_REWARD_RATE: u64 = ONE_TAPE;
8
9pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
10 let [
11 signer_info,
12 spool_0_info,
13 spool_1_info,
14 spool_2_info,
15 spool_3_info,
16 spool_4_info,
17 spool_5_info,
18 spool_6_info,
19 spool_7_info,
20 archive_info,
21 epoch_info,
22 metadata_info,
23 mint_info,
24 treasury_info,
25 treasury_tokens_info,
26 system_program_info,
27 token_program_info,
28 associated_token_program_info,
29 metadata_program_info,
30 rent_sysvar_info,
31 ] = accounts else {
32 return Err(ProgramError::NotEnoughAccountKeys);
33 };
34
35 spool_0_info
36 .is_empty()?
37 .is_writable()?
38 .has_seeds(&[SPOOL, &[0]], &tape_api::ID)?;
39 spool_1_info
40 .is_empty()?
41 .is_writable()?
42 .has_seeds(&[SPOOL, &[1]], &tape_api::ID)?;
43 spool_2_info
44 .is_empty()?
45 .is_writable()?
46 .has_seeds(&[SPOOL, &[2]], &tape_api::ID)?;
47 spool_3_info
48 .is_empty()?
49 .is_writable()?
50 .has_seeds(&[SPOOL, &[3]], &tape_api::ID)?;
51 spool_4_info
52 .is_empty()?
53 .is_writable()?
54 .has_seeds(&[SPOOL, &[4]], &tape_api::ID)?;
55 spool_5_info
56 .is_empty()?
57 .is_writable()?
58 .has_seeds(&[SPOOL, &[5]], &tape_api::ID)?;
59 spool_6_info
60 .is_empty()?
61 .is_writable()?
62 .has_seeds(&[SPOOL, &[6]], &tape_api::ID)?;
63 spool_7_info
64 .is_empty()?
65 .is_writable()?
66 .has_seeds(&[SPOOL, &[7]], &tape_api::ID)?;
67
68 archive_info
69 .is_empty()?
70 .is_writable()?
71 .has_seeds(&[ARCHIVE], &tape_api::ID)?;
72
73 epoch_info
74 .is_empty()?
75 .is_writable()?
76 .has_seeds(&[EPOCH], &tape_api::ID)?;
77
78 let (mint_address, mint_bump) = mint_pda();
80 let (treasury_address, treasury_bump) = treasury_pda();
81 let (metadata_address, _metadata_bump) = metadata_pda(mint_address);
82
83 assert_eq!(mint_bump, MINT_BUMP);
84 assert_eq!(treasury_bump, TREASURY_BUMP);
85
86 mint_info
87 .is_empty()?
88 .is_writable()?
89 .has_address(&mint_address)?;
90
91 metadata_info
92 .is_empty()?
93 .is_writable()?
94 .has_address(&metadata_address)?;
95
96 treasury_info
97 .is_empty()?
98 .is_writable()?
99 .has_address(&treasury_address)?;
100
101 treasury_tokens_info
102 .is_empty()?
103 .is_writable()?;
104
105 system_program_info
107 .is_program(&system_program::ID)?;
108 token_program_info
109 .is_program(&spl_token::ID)?;
110 associated_token_program_info
111 .is_program(&spl_associated_token_account::ID)?;
112
113 solana_program::log::msg!("metadata: {}", metadata_program_info.key);
114
115 metadata_program_info
116 .is_program(&mpl_token_metadata::ID)?;
117 rent_sysvar_info
118 .is_sysvar(&sysvar::rent::ID)?;
119
120 let spool_infos = [
121 spool_0_info,
122 spool_1_info,
123 spool_2_info,
124 spool_3_info,
125 spool_4_info,
126 spool_5_info,
127 spool_6_info,
128 spool_7_info,
129 ];
130
131 for i in 0..SPOOL_COUNT {
133 create_program_account::<Spool>(
134 spool_infos[i],
135 system_program_info,
136 signer_info,
137 &tape_api::ID,
138 &[SPOOL, &[i as u8]],
139 )?;
140 let spool = spool_infos[i].as_account_mut::<Spool>(&tape_api::ID)?;
141 spool.id = i as u64;
142 spool.available_rewards = 0;
143 spool.theoretical_rewards = 0;
144 }
145
146 create_program_account::<Epoch>(
148 epoch_info,
149 system_program_info,
150 signer_info,
151 &tape_api::ID,
152 &[EPOCH],
153 )?;
154
155 let epoch = epoch_info.as_account_mut::<Epoch>(&tape_api::ID)?;
156
157 epoch.base_rate = INITIAL_REWARD_RATE;
158 epoch.difficulty = INITIAL_DIFFICULTY as u64;
159 epoch.last_epoch_at = 0;
160
161 create_program_account::<Archive>(
162 archive_info,
163 system_program_info,
164 signer_info,
165 &tape_api::ID,
166 &[ARCHIVE],
167 )?;
168
169 let archive = archive_info.as_account_mut::<Archive>(&tape_api::ID)?;
170
171 archive.tapes_stored = 0;
173
174 create_program_account::<Treasury>(
176 treasury_info,
177 system_program_info,
178 signer_info,
179 &tape_api::ID,
180 &[TREASURY],
181 )?;
182
183 allocate_account_with_bump(
185 mint_info,
186 system_program_info,
187 signer_info,
188 Mint::LEN,
189 &spl_token::ID,
190 &[MINT, MINT_SEED],
191 MINT_BUMP,
192 )?;
193 initialize_mint_signed_with_bump(
194 mint_info,
195 treasury_info,
196 None,
197 token_program_info,
198 rent_sysvar_info,
199 TOKEN_DECIMALS,
200 &[MINT, MINT_SEED],
201 MINT_BUMP,
202 )?;
203
204 mpl_token_metadata::instructions::CreateMetadataAccountV3Cpi {
206 __program: metadata_program_info,
207 metadata: metadata_info,
208 mint: mint_info,
209 mint_authority: treasury_info,
210 payer: signer_info,
211 update_authority: (signer_info, true),
212 system_program: system_program_info,
213 rent: Some(rent_sysvar_info),
214 __args: mpl_token_metadata::instructions::CreateMetadataAccountV3InstructionArgs {
215 data: mpl_token_metadata::types::DataV2 {
216 name: METADATA_NAME.to_string(),
217 symbol: METADATA_SYMBOL.to_string(),
218 uri: METADATA_URI.to_string(),
219 seller_fee_basis_points: 0,
220 creators: None,
221 collection: None,
222 uses: None,
223 },
224 is_mutable: true,
225 collection_details: None,
226 },
227 }
228 .invoke_signed(&[&[TREASURY, &[TREASURY_BUMP]]])?;
229
230 create_associated_token_account(
232 signer_info,
233 treasury_info,
234 treasury_tokens_info,
235 mint_info,
236 system_program_info,
237 token_program_info,
238 associated_token_program_info,
239 )?;
240
241 Ok(())
242}