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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
//! A high-performance, trait-based Solana program framework for building **fast**,
//! **reliable**, and **type-safe** programs.
//!
//! Star Frame provides a modern approach to Solana program development with zero-cost
//! abstractions, comprehensive compile-time validation, and an intuitive API design
//! optimized for Solana's compute unit constraints.
//!
//! ## Key Features
//!
//! - **Type Safety**: Catch errors at compile time with zero-cost abstractions
//! - **Performance**: Optimized for Solana's compute unit constraints
//! - **Developer Experience**: Intuitive APIs with comprehensive validation
//! - **Modularity**: Composable components for accounts, instructions, and program logic
//!
//! # Getting Started
//!
//! Add `star_frame` and `bytemuck` to your `Cargo.toml`:
//!
//! ```shell
//! cargo add star_frame bytemuck
//! ```
//!
//! # Lifecycle of a Star Frame Transaction
//!
//! Here's what happens when you call a into a Star Frame program:
//!
//! ## Program Entrypoint
//!
//! The [`StarFrameProgram`](crate::program::StarFrameProgram) derive macro generates the program entrypoint:
//!
//! ```
//! # fn main() {}
//! use star_frame::prelude::*;
//! # type CounterInstructionSet = ();
//! #[derive(StarFrameProgram)]
//! #[program(
//! instruction_set = CounterInstructionSet,
//! id = "Coux9zxTFKZpRdFpE4F7Fs5RZ6FdaURdckwS61BUTMG",
//! )]
//! pub struct CounterProgram;
//! ```
//!
//! The [`StarFrameProgram::entrypoint`](crate::program::StarFrameProgram::entrypoint)'s default implementation calls in to the
//! [`InstructionSet::dispatch`](crate::instruction::InstructionSet::dispatch) method.
//!
//! ## Instruction Set Dispatch
//!
//! The [`InstructionSet`](crate::instruction::InstructionSet) derive macro defines instruction discriminants for each instruction variant
//! (by default it is compatible with Anchor's sighashes, but you can override it), and generates dispatch logic:
//!
//! ```
//! # fn main() {}
//! use star_frame::prelude::*;
//!
//! #[derive(InstructionSet)]
//! # #[ix_set(skip_idl)]
//! pub enum CounterInstructionSet {
//! Initialize(Initialize),
//! Increment(Increment),
//! }
//!
//! # #[derive(Debug)]
//! # pub struct Initialize;
//! # #[derive(Debug)]
//! # pub struct Increment;
//! # star_frame::impl_blank_ix!(Initialize, Increment);
//! ```
//!
//! The derived [`InstructionSet::dispatch`](crate::instruction::InstructionSet::dispatch) method matches on the instruction discriminant
//! from the instruction data, and calls [`Instruction::process_from_raw`](crate::instruction::Instruction::process_from_raw) for the matched instruction.
//!
//! ## Instruction Processing
//!
//! The [`Instruction`](crate::instruction::Instruction) trait provides the low-level interface for instruction processing,
//! but it's rough and requires manual handling of raw account data and instruction bytes. In most cases, you should
//! implement the [`StarFrameInstruction`](crate::instruction::StarFrameInstruction) and [`InstructionArgs`](crate::instruction::InstructionArgs)
//! traits instead. The `Instruction` trait is implemented generically for all instructions that implement `StarFrameInstruction`.
//!
//! Check the docs on [`StarFrameInstruction`](crate::instruction::StarFrameInstruction) for how that implementation works.
//!
//! ## Instruction Data Parsing
//!
//! Instructions implement [`BorshDeserialize`](borsh::BorshDeserialize) (to parse the instruction data), and [`InstructionArgs`](crate::instruction::InstructionArgs)
//! (to split the data into `AccountSet` lifecycle arguments). See the [`InstructionArgs`](crate::instruction::InstructionArgs) trait for more information.
//!
//! ```
//! use star_frame::prelude::*;
//! # fn main() {}
//! #[derive(BorshSerialize, BorshDeserialize, Debug, InstructionArgs)]
//! # #[instruction_args(skip_idl)]
//! pub struct Initialize {
//! #[ix_args(&run)]
//! pub start_at: Option<u64>,
//! }
//! ```
//!
//! ## Defining Program Accounts
//!
//! Star Frame provides multiple ways to define program accounts for different use cases:
//!
//! ### Basic Account with Standard Derive
//!
//! For statically sized accounts, you can use the [`ProgramAccount`](derive@crate::account_set::ProgramAccount) derive.
//! For the best performance, you can use [`bytemuck`] (with the [`zero_copy`] macro for convenience) with [`Account`](crate::account_set::account::Account):
//!
//! ```
//! # fn main() {}
//! # #[derive(StarFrameProgram)]
//! # #[program(instruction_set = (), id = System::ID, no_entrypoint)]
//! # pub struct MyProgram;
//! #
//! use star_frame::prelude::*;
//!
//! #[zero_copy(pod)]
//! #[derive(Default, Debug, Eq, PartialEq, ProgramAccount)]
//! #[program_account(seeds = CounterSeeds)]
//! pub struct CounterAccount {
//! pub authority: Pubkey,
//! pub count: u64,
//! }
//!
//! // Strongly typed seeds can be defined too!
//! #[derive(Debug, GetSeeds, Clone)]
//! #[get_seeds(seed_const = b"COUNTER")]
//! pub struct CounterSeeds {
//! pub authority: Pubkey,
//! }
//! ```
//!
//! You can also use [`borsh`] with [`BorshAccount`](crate::account_set::borsh_account::BorshAccount) if you don't ~~like~~ need performance.
//!
//! ### Unsized Accounts with the Unsized Type system
//!
//! For accounts with variable-size data like vectors or dynamic strings, use [`unsized_type`](crate::unsize::unsized_type).
//!
//! ```
//! # fn main() {}
//! use star_frame::prelude::*;
//! #
//! # #[derive(StarFrameProgram)]
//! # #[program(instruction_set = (), id = System::ID, no_entrypoint)]
//! # pub struct MyProgram;
//! #
//! #[derive(Debug, GetSeeds, Clone)]
//! # pub struct CounterSeeds;
//!
//! #[unsized_type(program_account, seeds = CounterSeeds)]
//! pub struct CounterAccount {
//! pub authority: Pubkey,
//! #[unsized_start]
//! pub count_tracker: UnsizedMap<Pubkey, PackedValue<u64>>,
//! }
//! ```
//! Check out the [`unsize`] module for more details.
//!
//! ## Account Set Validation
//!
//! Accounts are validated through [`AccountSet`](crate::account_set::AccountSet) traits with compile-time and runtime checks:
//!
//! ```
//! # fn main() {}
//! use star_frame::prelude::*;
//! #[derive(AccountSet)]
//! # #[account_set(skip_default_idl)]
//! pub struct InitializeAccounts {
//! #[validate(funder)]
//! pub authority: Signer<Mut<SystemAccount>>,
//! #[validate(arg = (
//! Create(()),
//! Seeds(CounterSeeds { authority: *self.authority.pubkey() }),
//! ))]
//! pub counter: Init<Seeded<Account<CounterAccount>>>,
//! pub system_program: Program<System>,
//! }
//! #
//! # #[derive(StarFrameProgram)]
//! # #[program(instruction_set = (), id = System::ID, no_entrypoint)]
//! # pub struct MyProgram;
//! #
//! # #[derive(Align1, Pod, Zeroable, Default, Copy, Clone, Debug, Eq, PartialEq, ProgramAccount)]
//! # #[program_account(seeds = CounterSeeds)]
//! # #[repr(C, packed)]
//! # pub struct CounterAccount {
//! # authority: Pubkey,
//! # }
//! #
//! # #[derive(Debug, GetSeeds, Clone)]
//! # #[get_seeds(seed_const = b"COUNTER")]
//! # pub struct CounterSeeds {
//! # pub authority: Pubkey,
//! # }
//!
//! ```
//!
//! ## Instruction Processing
//!
//! Finally, [`StarFrameInstruction::process`](crate::instruction::StarFrameInstruction::process) executes the instruction logic:
//!
//! ```
//! use star_frame::prelude::*;
//! # fn main() {}
//! # #[derive(StarFrameProgram)]
//! # #[program(instruction_set = (), id = System::ID, no_entrypoint)]
//! # pub struct MyProgram;
//! #
//! # #[derive(BorshSerialize, BorshDeserialize, Debug, InstructionArgs)]
//! # #[instruction_args(skip_idl)]
//! # pub struct Initialize {
//! # #[ix_args(&run)]
//! # pub start_at: Option<u64>,
//! # }
//! #
//! # #[derive(Align1, Pod, Zeroable, Default, Copy, Clone, Debug, Eq, PartialEq, ProgramAccount)]
//! # #[repr(C, packed)]
//! # pub struct CounterAccount {
//! # pub authority: Pubkey,
//! # pub count: u64,
//! # }
//! # #[derive(AccountSet, Debug)]
//! # #[account_set(skip_default_idl)]
//! # pub struct InitializeAccounts {
//! # pub counter: Mut<Account<CounterAccount>>,
//! # pub authority: AccountInfo,
//! # }
//! use star_frame::prelude::*;
//!
//! impl StarFrameInstruction for Initialize {
//! type Accounts<'decode, 'arg> = InitializeAccounts;
//! type ReturnType = ();
//!
//! fn process(
//! accounts: &mut Self::Accounts<'_, '_>,
//! start_at: &Option<u64>,
//! _ctx: &mut Context,
//! ) -> Result<()> {
//! **accounts.counter.data_mut()? = CounterAccount {
//! authority: *accounts.authority.pubkey(),
//! count: start_at.unwrap_or(0),
//! };
//! Ok(())
//! }
//! }
//! ```
//!
//! You can directly implement [`StarFrameInstruction`](crate::instruction::StarFrameInstruction) with the process function using the
//! [`star_frame_instruction`](crate::instruction::star_frame_instruction) macro.
//! ```
//! # fn main() {}
//! # #[derive(StarFrameProgram)]
//! # #[program(instruction_set = (), id = System::ID, no_entrypoint)]
//! # pub struct MyProgram;
//! #
//! # #[derive(BorshSerialize, BorshDeserialize, Debug, InstructionArgs)]
//! # #[instruction_args(skip_idl)]
//! # pub struct Initialize {
//! # #[ix_args(&run)]
//! # pub start_at: Option<u64>,
//! # }
//! #
//! # #[derive(Align1, Pod, Zeroable, Default, Copy, Clone, Debug, Eq, PartialEq, ProgramAccount)]
//! # #[repr(C, packed)]
//! # pub struct CounterAccount {
//! # pub authority: Pubkey,
//! # pub count: u64,
//! # }
//! # #[derive(AccountSet, Debug)]
//! # #[account_set(skip_default_idl)]
//! # pub struct InitializeAccounts {
//! # pub counter: Mut<Account<CounterAccount>>,
//! # pub authority: AccountInfo,
//! # }
//! use star_frame::prelude::*;
//!
//! #[star_frame_instruction]
//! fn Initialize(accounts: &mut InitializeAccounts, start_at: &Option<u64>) -> Result<()> {
//! **accounts.counter.data_mut()? = CounterAccount {
//! authority: *accounts.authority.pubkey(),
//! count: start_at.unwrap_or(0),
//! };
//! Ok(())
//! }
//! ```
//!
//! ## Putting it all together
//!
//! You can check out our [example programs](https://github.com/staratlasmeta/star_frame/tree/main/example_programs) for more information,
//! and the [simple counter example](https://github.com/staratlasmeta/star_frame/blob/main/example_programs/simple_counter/src/lib.rs) for how these steps are
//! put together.
//!
//! # Generating IDLs
//!
//! Star Frame can automatically generate Codama IDL files for your programs when the `idl` feature flag is enabled.
//! IDLs are JSON files that describe your program's interface, making it easier for clients to interact with your program.
//! Check out the [Codama](https://github.com/codama-idl/codama) for more information on generating clients and using the IDL.
//!
//! ## Enabling IDL Generation
//!
//! Add the `idl` feature to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! star_frame = { version = "*", features = ["idl"] }
//! ```
//!
//! ## Generating an IDL
//!
//! Programs that derive [`StarFrameProgram`](crate::program::StarFrameProgram) automatically implement
//! [`ProgramToIdl`](crate::idl::ProgramToIdl). You can create a test to generate the IDL:
//!
//! ```ignore
//! #[cfg(feature = "idl")]
//! #[test]
//! fn generate_idl() -> Result<()> {
//! use star_frame::prelude::*;
//! let idl = CounterProgram::program_to_idl()?;
//! let codama_idl: ProgramNode = idl.try_into()?;
//! let idl_json = codama_idl.to_json()?;
//! std::fs::write("idl.json", &idl_json)?;
//! Ok(())
//! }
//! ```
//! And run it with:
//! ```shell
//! cargo test --features idl -- generate_idl
//! ```
//!
//! # Feature Flags
//!
//! Star Frame provides several feature flags to customize functionality:
//! - `idl` - Enables IDL generation for client libraries
//! - `test_helpers` - Provides utilities for testing programs and the unsized type system
//! - `cleanup_rent_warning` - Emits a warning message if the account has more lamports than required by rent on cleanup
//! - `aggressive_inline` - Adds `#[inline(always)]` to more functions. Can be beneficial in some cases, but will likely increase binary size and may even reduce performance.
//! This should only be used when you have thorough benchmarks and are confident in the performance impact.
pub extern crate advancer;
pub extern crate borsh;
pub extern crate bytemuck;
pub extern crate derive_more;
pub extern crate derive_where;
pub extern crate fixed;
pub extern crate itertools;
pub extern crate num_traits;
pub extern crate paste;
pub extern crate pinocchio;
pub extern crate self as star_frame;
pub extern crate serde;
pub extern crate serde_json;
pub extern crate solana_instruction;
pub extern crate solana_pubkey;
pub extern crate star_frame_idl;
pub extern crate static_assertions;
pub extern crate typenum;
/// Internal paths mainly for use in macros. DO NOT USE MANUALLY. NOT PART OF THE PUBLIC API.
pub use Result as IdlResult;
pub use ErrorCode;
pub type Result<T, E = Error> = Result;
/// Equivalent to `Ok::<_, Error>(value)`
pub use Instruction as SolanaInstruction;
pub use ;
use StarFrameDeclaredProgram;
compile_error!;