clockwork_network/instructions/
entry_create.rs1use {
2 crate::{errors::ClockworkError, state::*},
3 anchor_lang::{prelude::*, solana_program::{instruction::Instruction, system_program}},
4 anchor_spl::{associated_token::get_associated_token_address, token::TokenAccount},
5 clockwork_crank::state::{CrankResponse, Queue, SEED_QUEUE},
6 std::mem::size_of,
7};
8
9#[derive(Accounts)]
10pub struct EntryCreate<'info> {
11 #[account(seeds = [SEED_AUTHORITY], bump)]
12 pub authority: Box<Account<'info, Authority>>,
13
14 #[account(seeds = [SEED_CONFIG], bump)]
15 pub config: Box<Account<'info, Config>>,
16
17 #[account(
18 init,
19 seeds = [
20 SEED_SNAPSHOT_ENTRY,
21 snapshot.key().as_ref(),
22 snapshot.node_count.to_be_bytes().as_ref()
23 ],
24 bump,
25 payer = payer,
26 space = 8 + size_of::<SnapshotEntry>(),
27 )]
28 pub entry: Account<'info, SnapshotEntry>,
29
30 #[account(
31 seeds = [
32 SEED_NODE,
33 node.id.to_be_bytes().as_ref(),
34 ],
35 bump,
36 constraint = node.id == snapshot.node_count @ ClockworkError::InvalidNode
37 )]
38 pub node: Box<Account<'info, Node>>,
39
40 #[account(mut)]
41 pub payer: Signer<'info>,
42
43 #[account(seeds = [SEED_REGISTRY], bump)]
44 pub registry: Box<Account<'info, Registry>>,
45
46 #[account(
47 mut,
48 seeds = [
49 SEED_SNAPSHOT,
50 snapshot.id.to_be_bytes().as_ref()
51 ],
52 bump,
53 constraint = snapshot.status == SnapshotStatus::InProgress @ ClockworkError::SnapshotNotInProgress,
54 constraint = snapshot.node_count < registry.node_count,
55 )]
56 pub snapshot: Account<'info, Snapshot>,
57
58 #[account(
59 signer,
60 seeds = [
61 SEED_QUEUE,
62 authority.key().as_ref(),
63 "snapshot".as_bytes()
64 ],
65 seeds::program = clockwork_crank::ID,
66 bump,
67 has_one = authority
68 )]
69 pub snapshot_queue: Account<'info, Queue>,
70
71 #[account(
72 associated_token::authority = node,
73 associated_token::mint = config.mint,
74 )]
75 pub stake: Account<'info, TokenAccount>,
76
77 #[account(address = system_program::ID)]
78 pub system_program: Program<'info, System>,
79}
80
81pub fn handler(ctx: Context<EntryCreate>) -> Result<CrankResponse> {
82 let authority = &ctx.accounts.authority;
84 let config = &ctx.accounts.config;
85 let entry = &mut ctx.accounts.entry;
86 let node = &ctx.accounts.node;
87 let registry = &ctx.accounts.registry;
88 let stake = &ctx.accounts.stake;
89 let snapshot = &mut ctx.accounts.snapshot;
90 let snapshot_queue = &ctx.accounts.snapshot_queue;
91 let system_program = &ctx.accounts.system_program;
92
93 snapshot.capture(entry, node, stake)?;
95
96 let next_instruction = if snapshot.node_count < registry.node_count {
98 let next_id = node.id.checked_add(1).unwrap();
100 let next_node_pubkey = Node::pubkey(next_id);
101 let next_entry_pubkey = SnapshotEntry::pubkey(snapshot.key(), next_id);
102 let stake_pubkey = get_associated_token_address(&next_node_pubkey, &config.mint);
103 Some(
104 Instruction {
105 program_id: crate::ID,
106 accounts: vec![
107 AccountMeta::new_readonly(authority.key(), false),
108 AccountMeta::new_readonly(config.key(), false),
109 AccountMeta::new(next_entry_pubkey, false),
110 AccountMeta::new_readonly(next_node_pubkey, false),
111 AccountMeta::new(clockwork_crank::payer::ID, true),
112 AccountMeta::new_readonly(registry.key(), false),
113 AccountMeta::new(snapshot.key(), false),
114 AccountMeta::new_readonly(snapshot_queue.key(), true),
115 AccountMeta::new_readonly(stake_pubkey, false),
116 AccountMeta::new_readonly(system_program.key(), false)
117 ],
118 data: clockwork_crank::anchor::sighash("entry_create").into(),
119 }
120 .into()
121 )
122 } else {
123 Some(
125 Instruction {
126 program_id: crate::ID,
127 accounts: vec![
128 AccountMeta::new_readonly(authority.key(), false),
129 AccountMeta::new_readonly(config.key(), false),
130 AccountMeta::new(Snapshot::pubkey(snapshot.id.checked_sub(1).unwrap()), false), AccountMeta::new(snapshot.key(), false), AccountMeta::new(registry.key(), false),
133 AccountMeta::new_readonly(snapshot_queue.key(), true),
134 ],
135 data: clockwork_crank::anchor::sighash("snapshot_rotate").into(),
136 }
137 .into()
138 )
139 };
140
141 Ok(CrankResponse { next_instruction })
142}