hydra/processors/distribute/
token_member.rs1use crate::error::HydraError;
2
3use crate::state::{Fanout, FanoutMembershipVoucher, MembershipModel};
4
5use crate::utils::logic::distribution::{distribute_mint, distribute_native};
6
7use crate::utils::validation::*;
8
9use anchor_lang::prelude::*;
10use anchor_spl::token::{Mint, Token, TokenAccount};
11
12#[derive(Accounts)]
13#[instruction(distribute_for_mint: bool)]
14pub struct DistributeTokenMember<'info> {
15 pub payer: Signer<'info>,
16 #[account(mut)]
17 pub member: UncheckedAccount<'info>,
19 #[
20 account(
21 mut,
22 constraint = membership_mint_token_account.delegate.is_none(),
23 constraint = membership_mint_token_account.close_authority.is_none(),
24 constraint = membership_mint_token_account.mint == membership_mint.key(),
25 constraint = membership_mint_token_account.owner == member.key()
26 )]
27 pub membership_mint_token_account: Account<'info, TokenAccount>,
28 #[account(
29 mut,
30 seeds = [b"fanout-membership", fanout.key().as_ref(), member.key().as_ref()],
31 constraint = membership_voucher.membership_key == member.key(),
32 bump = membership_voucher.bump_seed,
33 )]
34 pub membership_voucher: Box<Account<'info, FanoutMembershipVoucher>>,
35 #[account(
36 mut,
37 seeds = [b"fanout-config", fanout.name.as_bytes()],
38 bump = fanout.bump_seed,
39 )]
40 pub fanout: Box<Account<'info, Fanout>>,
41 #[account(mut)]
42 pub holding_account: UncheckedAccount<'info>,
44 #[account(mut)]
45 pub fanout_for_mint: UncheckedAccount<'info>,
47 #[account(mut)]
48 pub fanout_for_mint_membership_voucher: UncheckedAccount<'info>,
50 pub fanout_mint: Account<'info, Mint>,
51 #[account(mut)]
52 pub fanout_mint_member_token_account: UncheckedAccount<'info>,
54 pub system_program: Program<'info, System>,
55 pub rent: Sysvar<'info, Rent>,
56 pub token_program: Program<'info, Token>,
57 #[account(
58 mut,
59 constraint = fanout.membership_mint.is_some() && membership_mint.key() == fanout.membership_mint.unwrap(),
60 )]
61 pub membership_mint: Account<'info, Mint>,
62 #[account(
63 mut,
64 constraint = member_stake_account.owner == membership_voucher.key(),
65 constraint = member_stake_account.mint == membership_mint.key(),
66 constraint = member_stake_account.amount > 0
67 )]
68 pub member_stake_account: Account<'info, TokenAccount>,
69}
70
71pub fn distribute_for_token(
72 ctx: Context<DistributeTokenMember>,
73 distribute_for_mint: bool,
74) -> Result<()> {
75 let fanout = &mut ctx.accounts.fanout;
76 let fanout_info = fanout.to_account_info();
77 let membership_voucher = &mut ctx.accounts.membership_voucher;
78 let membership_voucher_info = membership_voucher.to_account_info();
79 let member = &mut ctx.accounts.member;
80 let membership_mint = &ctx.accounts.membership_mint;
81 fanout.total_shares = membership_mint.supply;
82 assert_ata(
83 &ctx.accounts.member_stake_account.to_account_info(),
84 &membership_voucher.key(),
85 &membership_mint.key(),
86 Some(HydraError::InvalidStakeAta.into()),
87 )?;
88 assert_owned_by(&fanout_info, &crate::ID)?;
89 assert_owned_by(&membership_voucher_info, &crate::ID)?;
90 assert_owned_by(&member.to_account_info(), &System::id())?;
91 assert_membership_model(fanout, MembershipModel::Token)?;
92 assert_shares_distributed(fanout)?;
93
94 if distribute_for_mint {
95 distribute_mint(
96 ctx.accounts.fanout_mint.to_owned(),
97 &mut ctx.accounts.fanout_for_mint,
98 &mut ctx.accounts.fanout_for_mint_membership_voucher,
99 &mut ctx.accounts.fanout_mint_member_token_account,
100 &mut ctx.accounts.holding_account,
101 fanout,
102 &mut ctx.accounts.membership_voucher,
103 ctx.accounts.rent.to_owned(),
104 ctx.accounts.system_program.to_owned(),
105 ctx.accounts.token_program.to_owned(),
106 ctx.accounts.payer.to_account_info(),
107 ctx.accounts.member.to_owned(),
108 &ctx.accounts.member.key(),
109 )?;
110 } else {
111 distribute_native(
112 &mut ctx.accounts.holding_account,
113 &mut ctx.accounts.fanout,
114 &mut ctx.accounts.membership_voucher,
115 ctx.accounts.member.to_owned(),
116 ctx.accounts.rent.to_owned(),
117 )?;
118 }
119 Ok(())
120}