Skip to content

Commit

Permalink
Merge pull request #264 from cardinal-labs/giannis/migrateToHandlePay…
Browse files Browse the repository at this point in the history
…mentWithRoyalties

Migrate to handle payment with royalties
  • Loading branch information
Giannis Chatziveroglou authored Aug 1, 2022
2 parents 25b1483 + 224b51a commit ffc176e
Show file tree
Hide file tree
Showing 17 changed files with 757 additions and 107 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions programs/cardinal-paid-claim-approver/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ pub enum ErrorCode {
InvalidPaymentManager,
#[msg("Invalid payment mint")]
InvalidPaymentMint,
#[msg("Invalid mint")]
InvalidMint,
}
31 changes: 27 additions & 4 deletions programs/cardinal-paid-claim-approver/src/instructions/pay.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::{errors::ErrorCode, state::*},
anchor_lang::prelude::*,
anchor_spl::token::{self, Token, TokenAccount, Transfer},
anchor_spl::token::{self, Mint, Token, TokenAccount, Transfer},
cardinal_payment_manager::program::CardinalPaymentManager,
cardinal_token_manager::{program::CardinalTokenManager, state::TokenManager, utils::assert_payment_token_account},
};
Expand Down Expand Up @@ -48,17 +48,40 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
let remaining_accs = &mut ctx.remaining_accounts.iter();
assert_payment_token_account(&ctx.accounts.payment_token_account, &ctx.accounts.token_manager, remaining_accs)?;

let token_manager = &mut ctx.accounts.token_manager;
let claim_approver = &mut ctx.accounts.claim_approver;

let payment_mint_info = next_account_info(remaining_accs)?;
let payment_mint = Account::<Mint>::try_from(payment_mint_info)?;
if claim_approver.payment_mint != payment_mint.key() {
return Err(error!(ErrorCode::InvalidPaymentMint));
}

let mint_info = next_account_info(remaining_accs)?;
let mint = Account::<Mint>::try_from(mint_info)?;
if token_manager.mint != mint.key() {
return Err(error!(ErrorCode::InvalidMint));
}
let mint_metadata_info = next_account_info(remaining_accs)?;
let rent = next_account_info(remaining_accs)?;
let system_program = next_account_info(remaining_accs)?;

if ctx.accounts.payment_manager.owner.key() == ctx.accounts.cardinal_payment_manager.key() {
let cpi_accounts = cardinal_payment_manager::cpi::accounts::HandlePaymentCtx {
let cpi_accounts = cardinal_payment_manager::cpi::accounts::HandlePaymentWithRoyaltiesCtx {
payment_manager: ctx.accounts.payment_manager.to_account_info(),
payer_token_account: ctx.accounts.payer_token_account.to_account_info(),
fee_collector_token_account: ctx.accounts.fee_collector_token_account.to_account_info(),
payment_token_account: ctx.accounts.payment_token_account.to_account_info(),
payment_mint: payment_mint.to_account_info(),
mint: mint.to_account_info(),
mint_metadata: mint_metadata_info.to_account_info(),
payer: ctx.accounts.payer.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: rent.to_account_info(),
system_program: system_program.to_account_info(),
};
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_payment_manager.to_account_info(), cpi_accounts);
cardinal_payment_manager::cpi::manage_payment(cpi_ctx, ctx.accounts.claim_approver.payment_amount)?;
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_payment_manager.to_account_info(), cpi_accounts).with_remaining_accounts(remaining_accs.cloned().collect::<Vec<AccountInfo<'info>>>());
cardinal_payment_manager::cpi::handle_payment_with_royalties(cpi_ctx, claim_approver.payment_amount)?;
} else {
let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,62 +53,78 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
let total_fees = maker_fee.checked_add(taker_fee).expect("Add error");
let split_fees = total_fees.checked_mul(ROYALTY_FEE_SHARE).unwrap().checked_div(100).expect("Div error");

let mint_metadata = Metadata::from_account_info(&ctx.accounts.mint_metadata.to_account_info())?;
if mint_metadata.mint != ctx.accounts.mint.key() {
return Err(error!(ErrorCode::InvalidMintMetadata));
}
if ctx.accounts.mint_metadata.data_is_empty() {
let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
to: ctx.accounts.fee_collector_token_account.to_account_info(),
authority: ctx.accounts.payer.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_context, total_fees)?;
} else {
let mint_metadata = Metadata::from_account_info(&ctx.accounts.mint_metadata.to_account_info())?;
if mint_metadata.mint != ctx.accounts.mint.key() {
return Err(error!(ErrorCode::InvalidMintMetadata));
}

let creators = mint_metadata.data.creators;
if let Some(creators) = creators {
let remaining_accs = &mut ctx.remaining_accounts.iter();
for creator in creators {
let creator_address_info = next_account_info(remaining_accs)?;
if creator_address_info.key() != creator.address {
return Err(error!(ErrorCode::InvalidCreatorAddress));
}
let creator_token_account_info = next_account_info(remaining_accs)?;
let creator_token_account = Account::<TokenAccount>::try_from(creator_token_account_info);
if creator_token_account.is_err() {
// create associated token account for creator
let cpi_accounts = associated_token::Create {
payer: ctx.accounts.payer.to_account_info(),
associated_token: creator_token_account_info.to_account_info(),
authority: creator_address_info.to_account_info(),
mint: ctx.accounts.payment_mint.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
associated_token::create(cpi_context)?;
} else {
let creator_token_account_unwrapped = creator_token_account?;
if creator_token_account_unwrapped.owner != creator.address && creator_token_account_unwrapped.mint != ctx.accounts.payment_mint.key() {
return Err(error!(ErrorCode::InvalidTokenAccount));
let mut fees_paid_out: u64 = 0;
let creators = mint_metadata.data.creators;
if let Some(creators) = creators {
let remaining_accs = &mut ctx.remaining_accounts.iter();
for creator in creators {
if creator.share != 0 {
let creator_address_info = next_account_info(remaining_accs)?;
if creator_address_info.key() != creator.address {
return Err(error!(ErrorCode::InvalidCreatorAddress));
}
let creator_token_account_info = next_account_info(remaining_accs)?;
let creator_token_account = Account::<TokenAccount>::try_from(creator_token_account_info);
if creator_token_account.is_err() {
// create associated token account for creator
let cpi_accounts = associated_token::Create {
payer: ctx.accounts.payer.to_account_info(),
associated_token: creator_token_account_info.to_account_info(),
authority: creator_address_info.to_account_info(),
mint: ctx.accounts.payment_mint.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
associated_token::create(cpi_context)?;
} else {
let creator_token_account_unwrapped = creator_token_account?;
if creator_token_account_unwrapped.owner != creator.address && creator_token_account_unwrapped.mint != ctx.accounts.payment_mint.key() {
return Err(error!(ErrorCode::InvalidTokenAccount));
}
}
let share = u64::try_from(creator.share).expect("Could not cast u8 to u64");
let creator_funds = split_fees.checked_mul(share).unwrap().checked_div(100).expect("Div error");

if creator_funds > 0 {
fees_paid_out = fees_paid_out.checked_add(creator_funds).expect("Add error");
let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
to: creator_token_account_info.to_account_info(),
authority: ctx.accounts.payer.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_context, creator_funds)?;
}
}
}
let share = u64::try_from(creator.share).expect("Could not cast u8 to u64");
let creator_funds = split_fees.checked_mul(share).unwrap().checked_div(100).expect("Div error");

let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
to: creator_token_account_info.to_account_info(),
authority: ctx.accounts.payer.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_context, creator_funds)?;
}

let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
to: ctx.accounts.fee_collector_token_account.to_account_info(),
authority: ctx.accounts.payer.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_context, split_fees)?;
token::transfer(cpi_context, total_fees.checked_sub(fees_paid_out).expect("Add error"))?;
}
}

Expand Down
2 changes: 2 additions & 0 deletions programs/cardinal-time-invalidator/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ pub enum ErrorCode {
InvalidPaymentManagerProgram,
#[msg("Invalid payment manager")]
InvalidPaymentManager,
#[msg("Invalid mint")]
InvalidMint,
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::{errors::ErrorCode, state::*},
anchor_lang::prelude::*,
anchor_spl::token::{self, Token, TokenAccount, Transfer},
anchor_spl::token::{self, Mint, Token, TokenAccount, Transfer},
cardinal_payment_manager::program::CardinalPaymentManager,
cardinal_token_manager::{
state::{TokenManager, TokenManagerState},
Expand Down Expand Up @@ -44,6 +44,7 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
let remaining_accs = &mut ctx.remaining_accounts.iter();
assert_payment_token_account(&ctx.accounts.payment_token_account, &ctx.accounts.token_manager, remaining_accs)?;

let token_manager = &mut ctx.accounts.token_manager;
let time_invalidator = &mut ctx.accounts.time_invalidator;
if time_invalidator.extension_payment_amount == None || time_invalidator.extension_duration_seconds == None || time_invalidator.extension_payment_mint == None {
return Err(error!(ErrorCode::InvalidTimeInvalidator));
Expand All @@ -70,9 +71,7 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
return Err(error!(ErrorCode::InvalidExtensionAmount));
}

let mut expiration = ctx
.accounts
.token_manager
let mut expiration = token_manager
.state_changed_at
.checked_add(time_invalidator.duration_seconds.expect("No duration set"))
.expect("Add error");
Expand All @@ -85,17 +84,38 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
return Err(error!(ErrorCode::InvalidExtendExpiration));
}

let payment_mint_info = next_account_info(remaining_accs)?;
let payment_mint = Account::<Mint>::try_from(payment_mint_info)?;
if time_invalidator.extension_payment_mint.unwrap() != payment_mint.key() {
return Err(error!(ErrorCode::InvalidPaymentMint));
}

let mint_info = next_account_info(remaining_accs)?;
let mint = Account::<Mint>::try_from(mint_info)?;
if token_manager.mint != mint.key() {
return Err(error!(ErrorCode::InvalidMint));
}
let mint_metadata_info = next_account_info(remaining_accs)?;

let rent = next_account_info(remaining_accs)?;
let system_proram = next_account_info(remaining_accs)?;

if ctx.accounts.payment_manager.owner.key() == ctx.accounts.cardinal_payment_manager.key() {
let cpi_accounts = cardinal_payment_manager::cpi::accounts::HandlePaymentCtx {
let cpi_accounts = cardinal_payment_manager::cpi::accounts::HandlePaymentWithRoyaltiesCtx {
payment_manager: ctx.accounts.payment_manager.to_account_info(),
payer_token_account: ctx.accounts.payer_token_account.to_account_info(),
fee_collector_token_account: ctx.accounts.fee_collector_token_account.to_account_info(),
payment_token_account: ctx.accounts.payment_token_account.to_account_info(),
payment_mint: payment_mint.to_account_info(),
mint: mint.to_account_info(),
mint_metadata: mint_metadata_info.to_account_info(),
payer: ctx.accounts.payer.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: rent.to_account_info(),
system_program: system_proram.to_account_info(),
};
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_payment_manager.to_account_info(), cpi_accounts);
cardinal_payment_manager::cpi::manage_payment(cpi_ctx, price_to_pay)?;
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_payment_manager.to_account_info(), cpi_accounts).with_remaining_accounts(remaining_accs.cloned().collect::<Vec<AccountInfo<'info>>>());
cardinal_payment_manager::cpi::handle_payment_with_royalties(cpi_ctx, price_to_pay)?;
} else {
let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
Expand Down
1 change: 1 addition & 0 deletions programs/cardinal-use-invalidator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ spl-token = { version = "3.2.0", features = ["no-entrypoint"] }
solana-program = "1.9.28"
cardinal-token-manager = { version = "^1.4.10", path = "../cardinal-token-manager", features = ["cpi"] }
cardinal-payment-manager = { version = "^1.4.10", path = "../cardinal-payment-manager", features = ["cpi"] }
mpl-token-metadata = { version = "1.2.5", features = ["no-entrypoint"] }
arrayref = "0.3.6"

[dev-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions programs/cardinal-use-invalidator/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ pub enum ErrorCode {
InvalidPaymentManager,
#[msg("Invalid payment mint")]
InvalidPaymentMint,
#[msg("Invalid mint")]
InvalidMint,
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::{errors::ErrorCode, state::*},
anchor_lang::prelude::*,
anchor_spl::token::{self, Token, TokenAccount, Transfer},
anchor_spl::token::{self, Mint, Token, TokenAccount, Transfer},
cardinal_payment_manager::program::CardinalPaymentManager,
cardinal_token_manager::{
state::{TokenManager, TokenManagerState},
Expand Down Expand Up @@ -43,6 +43,7 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
let remaining_accs = &mut ctx.remaining_accounts.iter();
assert_payment_token_account(&ctx.accounts.payment_token_account, &ctx.accounts.token_manager, remaining_accs)?;

let token_manager = &mut ctx.accounts.token_manager;
let use_invalidator = &mut ctx.accounts.use_invalidator;
if use_invalidator.extension_payment_amount == None || use_invalidator.extension_usages == None || use_invalidator.extension_payment_mint == None || use_invalidator.total_usages == None {
return Err(error!(ErrorCode::InvalidUseInvalidator));
Expand All @@ -59,17 +60,38 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
return Err(error!(ErrorCode::MaxUsagesReached));
}

let payment_mint_info = next_account_info(remaining_accs)?;
let payment_mint = Account::<Mint>::try_from(payment_mint_info)?;
if use_invalidator.extension_payment_mint.unwrap() != payment_mint.key() {
return Err(error!(ErrorCode::InvalidPaymentMint));
}

let mint_info = next_account_info(remaining_accs)?;
let mint = Account::<Mint>::try_from(mint_info)?;
if token_manager.mint != mint.key() {
return Err(error!(ErrorCode::InvalidMint));
}
let mint_metadata_info = next_account_info(remaining_accs)?;

let rent = next_account_info(remaining_accs)?;
let system_proram = next_account_info(remaining_accs)?;

if ctx.accounts.payment_manager.owner.key() == ctx.accounts.cardinal_payment_manager.key() {
let cpi_accounts = cardinal_payment_manager::cpi::accounts::HandlePaymentCtx {
let cpi_accounts = cardinal_payment_manager::cpi::accounts::HandlePaymentWithRoyaltiesCtx {
payment_manager: ctx.accounts.payment_manager.to_account_info(),
payer_token_account: ctx.accounts.payer_token_account.to_account_info(),
fee_collector_token_account: ctx.accounts.fee_collector_token_account.to_account_info(),
payment_token_account: ctx.accounts.payment_token_account.to_account_info(),
payment_mint: payment_mint.to_account_info(),
mint: mint.to_account_info(),
mint_metadata: mint_metadata_info.to_account_info(),
payer: ctx.accounts.payer.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: rent.to_account_info(),
system_program: system_proram.to_account_info(),
};
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_payment_manager.to_account_info(), cpi_accounts);
cardinal_payment_manager::cpi::manage_payment(cpi_ctx, price_to_pay)?;
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_payment_manager.to_account_info(), cpi_accounts).with_remaining_accounts(remaining_accs.cloned().collect::<Vec<AccountInfo<'info>>>());
cardinal_payment_manager::cpi::handle_payment_with_royalties(cpi_ctx, price_to_pay)?;
} else {
let cpi_accounts = Transfer {
from: ctx.accounts.payer_token_account.to_account_info(),
Expand Down
Loading

0 comments on commit ffc176e

Please sign in to comment.