sablier_network_program/jobs/distribute_fees/
process_entry.rs1use anchor_lang::{prelude::*, solana_program::instruction::Instruction, InstructionData};
2use sablier_utils::thread::ThreadResponse;
3
4use crate::{constants::*, state::*};
5
6#[derive(Accounts)]
7pub struct DistributeFeesProcessEntry<'info> {
8 #[account(address = Config::pubkey())]
9 pub config: AccountLoader<'info, Config>,
10
11 #[account(
12 mut,
13 seeds = [
14 SEED_DELEGATION,
15 delegation.worker.as_ref(),
16 delegation.id.to_be_bytes().as_ref(),
17 ],
18 bump,
19 constraint = delegation.id == snapshot_entry.id,
20 has_one = worker,
21 )]
22 pub delegation: Account<'info, Delegation>,
23
24 #[account(
25 mut,
26 seeds = [
27 SEED_FEE,
28 fee.worker.as_ref(),
29 ],
30 bump,
31 has_one = worker,
32 )]
33 pub fee: Account<'info, Fee>,
34
35 #[account(address = Registry::pubkey())]
36 pub registry: Account<'info, Registry>,
37
38 #[account(
39 address = snapshot.pubkey(),
40 constraint = snapshot.id == registry.current_epoch
41 )]
42 pub snapshot: Account<'info, Snapshot>,
43
44 #[account(
45 address = snapshot_entry.pubkey(),
46 has_one = snapshot_frame,
47 )]
48 pub snapshot_entry: Account<'info, SnapshotEntry>,
49
50 #[account(
51 address = snapshot_frame.pubkey(),
52 has_one = snapshot,
53 has_one = worker,
54 )]
55 pub snapshot_frame: Account<'info, SnapshotFrame>,
56
57 #[account(address = config.load()?.epoch_thread)]
58 pub thread: Signer<'info>,
59
60 #[account(address = worker.pubkey())]
61 pub worker: Account<'info, Worker>,
62}
63
64pub fn handler(ctx: Context<DistributeFeesProcessEntry>) -> Result<ThreadResponse> {
65 let config = &ctx.accounts.config;
67 let delegation = &mut ctx.accounts.delegation;
68 let fee = &mut ctx.accounts.fee;
69 let registry = &ctx.accounts.registry;
70 let snapshot = &ctx.accounts.snapshot;
71 let snapshot_entry = &ctx.accounts.snapshot_entry;
72 let snapshot_frame = &ctx.accounts.snapshot_frame;
73 let thread = &ctx.accounts.thread;
74 let worker = &ctx.accounts.worker;
75
76 let distribution_balance = if snapshot_frame.stake_amount > 0 {
78 fee.distributable_balance * snapshot_entry.stake_amount / snapshot_frame.stake_amount
79 } else {
80 0
81 };
82
83 fee.sub_lamports(distribution_balance)?;
85 delegation.add_lamports(distribution_balance)?;
86
87 delegation.yield_balance += distribution_balance;
89
90 let dynamic_instruction = if (snapshot_entry.id + 1) < snapshot_frame.total_entries {
92 let next_delegation_pubkey = Delegation::pubkey(worker.key(), delegation.id + 1);
94 let next_snapshot_entry_pubkey =
95 SnapshotEntry::pubkey(snapshot_frame.key(), snapshot_entry.id + 1);
96 Some(
97 Instruction {
98 program_id: crate::ID,
99 accounts: crate::accounts::DistributeFeesProcessEntry {
100 config: config.key(),
101 delegation: next_delegation_pubkey,
102 fee: fee.key(),
103 registry: registry.key(),
104 snapshot: snapshot.key(),
105 snapshot_entry: next_snapshot_entry_pubkey,
106 snapshot_frame: snapshot_frame.key(),
107 thread: thread.key(),
108 worker: worker.key(),
109 }
110 .to_account_metas(Some(true)),
111 data: crate::instruction::DistributeFeesProcessEntry {}.data(),
112 }
113 .into(),
114 )
115 } else if (snapshot_frame.id + 1) < snapshot.total_frames {
116 let next_worker_pubkey = Worker::pubkey(worker.id + 1);
118 let next_snapshot_frame_pubkey =
119 SnapshotFrame::pubkey(snapshot.key(), snapshot_frame.id + 1);
120 Some(
121 Instruction {
122 program_id: crate::ID,
123 accounts: crate::accounts::DistributeFeesProcessFrame {
124 config: config.key(),
125 fee: Fee::pubkey(next_worker_pubkey),
126 registry: registry.key(),
127 snapshot: snapshot.key(),
128 snapshot_frame: next_snapshot_frame_pubkey,
129 thread: thread.key(),
130 worker: next_worker_pubkey,
131 }
132 .to_account_metas(Some(true)),
133 data: crate::instruction::DistributeFeesProcessFrame {}.data(),
134 }
135 .into(),
136 )
137 } else {
138 None
139 };
140
141 Ok(ThreadResponse {
142 dynamic_instruction,
143 close_to: None,
144 trigger: None,
145 })
146}