-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add create donation v2 with multi currency support
- Loading branch information
1 parent
c035269
commit bcda92c
Showing
6 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
programs/donaproto/src/instructions/create_donation_v2.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
use anchor_lang::prelude::*; | ||
use anchor_spl::token::{Mint, TokenAccount}; | ||
use raydium_amm_v3::states::PoolState; | ||
|
||
use crate::{ | ||
errors::DonationError, | ||
states::{AuthorizedClmmPool, CreatorData, DonationData, DonationProtocolData, MAX_IPFS_HASH_LEN}, | ||
utils::calculate_amount, AUTHORIZED_CLMM_POOL_PREFIX, CREATOR_PREFIX, HOLDING_PREFIX, | ||
}; | ||
|
||
#[derive(Accounts)] | ||
pub struct CreateDonationV2<'info> { | ||
#[account(init, payer = creator_wallet_address, space = DonationData::LEN)] | ||
pub donation_data: Account<'info, DonationData>, | ||
#[account( | ||
constraint = donation_protocol.donation_mint == default_donation_mint.key(), | ||
)] | ||
pub donation_protocol: Account<'info, DonationProtocolData>, | ||
|
||
#[account( | ||
constraint = holding_wallet.owner == *holding_wallet_owner.key, | ||
constraint = holding_wallet.mint == donation_mint.key(), | ||
)] | ||
pub holding_wallet: Account<'info, TokenAccount>, | ||
#[account( | ||
seeds = [ | ||
HOLDING_PREFIX.as_bytes(), | ||
donation_data.to_account_info().key.as_ref(), | ||
], | ||
bump, | ||
)] | ||
/// CHECK: pda account ["holding", donation_data] | ||
holding_wallet_owner: AccountInfo<'info>, | ||
|
||
#[account( | ||
constraint = recipient.mint == donation_mint.key(), | ||
)] | ||
pub recipient: Account<'info, TokenAccount>, | ||
|
||
#[account(mut, | ||
constraint = creator_data.donation_protocol.key() == donation_protocol.key(), | ||
seeds = [ | ||
CREATOR_PREFIX.as_bytes(), | ||
donation_protocol.to_account_info().key.as_ref(), | ||
creator_wallet_address.key().as_ref(), | ||
], | ||
bump, | ||
)] | ||
pub creator_data: Account<'info, CreatorData>, | ||
pub donation_mint: Account<'info, Mint>, | ||
pub default_donation_mint: Account<'info, Mint>, | ||
#[account( | ||
seeds = [ | ||
AUTHORIZED_CLMM_POOL_PREFIX.as_bytes(), | ||
donation_protocol.key().as_ref(), | ||
pool_state.key().as_ref(), | ||
], | ||
bump, | ||
constraint = authorized_clmm_pool.donation_protocol == donation_protocol.key(), | ||
constraint = authorized_clmm_pool.pool_state == pool_state.key(), | ||
)] | ||
pub authorized_clmm_pool: Account<'info, AuthorizedClmmPool>, | ||
#[account( | ||
constraint = (pool_state.load()?.token_mint_0 == donation_protocol.donation_mint && pool_state.load()?.token_mint_1 == donation_mint.key()) | ||
|| (pool_state.load()?.token_mint_1 == donation_protocol.donation_mint && pool_state.load()?.token_mint_0 == donation_mint.key()), | ||
)] | ||
pub pool_state: AccountLoader<'info, PoolState>, | ||
#[account(mut)] | ||
pub creator_wallet_address: Signer<'info>, | ||
pub system_program: Program<'info, System>, | ||
pub rent: Sysvar<'info, Rent> | ||
} | ||
|
||
pub fn create_donation_v2( | ||
ctx: Context<CreateDonationV2>, | ||
amount: u64, | ||
ipfs_hash: String, | ||
ending_timestamp: u64, | ||
holding_bump: u8, | ||
) -> Result<()> { | ||
let now_timestamp = Clock::get().expect("Time error").unix_timestamp as u64; | ||
if ending_timestamp <= now_timestamp { | ||
return Err(DonationError::InvalidEndingTimestamp.into()); | ||
} | ||
if ipfs_hash.len() > MAX_IPFS_HASH_LEN { | ||
return Err(DonationError::IpfsHashTooLong.into()); | ||
} | ||
if amount < ctx.accounts.donation_protocol.min_amount_to_collect { | ||
return Err(DonationError::DonationAmountTooLow.into()); | ||
} | ||
|
||
let donation_data = &mut ctx.accounts.donation_data; | ||
donation_data.amount_collecting = amount; | ||
donation_data.ending_timestamp = ending_timestamp; | ||
donation_data.is_closed = false; | ||
donation_data.recipient = ctx.accounts.recipient.key(); | ||
donation_data.creator_data = ctx.accounts.creator_data.key(); | ||
donation_data.donation_protocol = ctx.accounts.donation_protocol.key(); | ||
donation_data.holding_wallet = ctx.accounts.holding_wallet.key(); | ||
donation_data.donation_mint = ctx.accounts.donation_mint.key(); | ||
donation_data.holding_bump = holding_bump; | ||
donation_data.ipfs_hash = ipfs_hash; | ||
|
||
let default_donation_mint = &ctx.accounts.default_donation_mint; | ||
let donation_mint = &ctx.accounts.donation_mint; | ||
let is_default_token_mint_0 = ctx.accounts.pool_state.load()?.token_mint_0 == ctx.accounts.donation_protocol.donation_mint; | ||
|
||
let amount = calculate_amount( | ||
default_donation_mint.decimals, | ||
donation_mint.decimals, | ||
amount, | ||
ctx.accounts.pool_state.load()?.sqrt_price_x64, | ||
is_default_token_mint_0, | ||
); | ||
|
||
let creator_data = &mut ctx.accounts.creator_data; | ||
creator_data.total_amount_collecting = creator_data.total_amount_collecting.checked_add(amount).unwrap(); | ||
creator_data.donations_created_count = creator_data.donations_created_count.checked_add(1).unwrap(); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/// A library for handling Q64.64 fixed point numbers | ||
/// copied from `raydium-clmm` program library | ||
// TODO: write tests for this module | ||
|
||
pub const Q64: u128 = (u64::MAX as u128) + 1; // 2^64 | ||
pub const RESOLUTION: u8 = 64; | ||
|
||
pub fn multipler(decimals: u8) -> f64 { | ||
(10_i32).checked_pow(decimals.try_into().unwrap()).unwrap() as f64 | ||
} | ||
|
||
pub fn from_x64_price(price: u128) -> f64 { | ||
price as f64 / Q64 as f64 | ||
} | ||
|
||
pub fn sqrt_price_x64_to_price(price: u128, decimals_0: u8, decimals_1: u8) -> f64 { | ||
from_x64_price(price).powi(2) * multipler(decimals_0) / multipler(decimals_1) | ||
} | ||
|
||
pub fn identify_mint_decimals( | ||
default_donation_mint_decimals: u8, | ||
donation_mint_decimals: u8, | ||
is_default_token_mint_0: bool, | ||
) -> (u8, u8) { | ||
if is_default_token_mint_0 { | ||
return (default_donation_mint_decimals, donation_mint_decimals); | ||
} | ||
|
||
(donation_mint_decimals, default_donation_mint_decimals) | ||
} | ||
|
||
pub fn amount_from_price( | ||
amount: u64, | ||
price: f64, | ||
is_default_token_mint_0: bool, | ||
) -> u64 { | ||
if is_default_token_mint_0 { | ||
return (amount as f64 / price).round() as u64; | ||
} | ||
|
||
(amount as f64 * price).round() as u64 | ||
} | ||
|
||
pub fn calculate_amount( | ||
default_donation_mint_decimals: u8, | ||
donation_mint_decimals: u8, | ||
amount: u64, | ||
sqrt_price_x64: u128, | ||
is_default_token_mint_0: bool, | ||
) -> u64 { | ||
let (decimals_0, decimals_1) = identify_mint_decimals( | ||
default_donation_mint_decimals, | ||
donation_mint_decimals, | ||
is_default_token_mint_0, | ||
); | ||
let price = sqrt_price_x64_to_price(sqrt_price_x64, decimals_0, decimals_1); | ||
|
||
amount_from_price(amount, price, is_default_token_mint_0) | ||
} |