Skip to content

Commit

Permalink
[token-dispenser] Allow multiple transactions (#11)
Browse files Browse the repository at this point in the history
* Allow multiple transactions

* Passes tests

* Renames

* Remove cart
  • Loading branch information
guibescos authored Jun 15, 2023
1 parent 9c0cdb5 commit d5aa059
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 10 deletions.
2 changes: 1 addition & 1 deletion token-dispenser/programs/token-dispenser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ cpi = ["no-entrypoint"]
default = []

[dependencies]
anchor-lang = "0.27.0"
anchor-lang = { version = "0.27.0", features = ["init-if-needed"] }

pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain.git"}

Expand Down
78 changes: 69 additions & 9 deletions token-dispenser/programs/token-dispenser/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(clippy::result_large_err)]

use {
anchor_lang::{
prelude::*,
Expand Down Expand Up @@ -36,6 +37,7 @@ declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

const CONFIG_SEED: &[u8] = b"config";
const RECEIPT_SEED: &[u8] = b"receipt";
const CART_SEED: &[u8] = b"cart";
#[program]
pub mod token_dispenser {
use super::*;
Expand All @@ -58,11 +60,7 @@ pub mod token_dispenser {
*/
pub fn claim(ctx: Context<Claim>, claim_certificates: Vec<ClaimCertificate>) -> Result<()> {
let config = &ctx.accounts.config;

let mut total_amount: u64 = 0;

// Check that the claimant is not claiming tokens for more than one ecosystem
verify_one_identity_per_ecosystem(&claim_certificates)?;
let cart = &mut ctx.accounts.cart;

// TO DO : Actually check the proof of identity and the proof of inclusion
for (index, claim_certificate) in claim_certificates.iter().enumerate() {
Expand All @@ -85,13 +83,18 @@ pub mod token_dispenser {
ctx.accounts.claimant.key,
ctx.remaining_accounts,
)?;
total_amount = total_amount

cart.amount = cart
.amount
.checked_add(claim_certificate.amount)
.ok_or(ErrorCode::ArithmeticOverflow)?;
}

// TO DO : Check that the claimant has not already claimed the tokens (We will initialize a
// claim account for each leaf that has been claimed)
// Check that the claimant is not claiming tokens more than once per ecosystem
if cart.set.contains(&claim_certificate.proof_of_identity) {
return Err(ErrorCode::MoreThanOneIdentityPerEcosystem.into());
}
cart.set.insert(&claim_certificate.proof_of_identity);
}

// TO DO : Send tokens to claimant (we will also initialize a vesting account for them)
Ok(())
Expand All @@ -116,11 +119,15 @@ pub struct Initialize<'info> {
#[derive(Accounts)]
#[instruction(claim_certificates : Vec<ClaimCertificate>)]
pub struct Claim<'info> {
#[account(mut)]
pub claimant: Signer<'info>,
pub dispenser_guard: Signer<'info>, /* Check that the dispenser guard has signed and matches
* the config - Done */
#[account(seeds = [CONFIG_SEED], bump, has_one = dispenser_guard)]
pub config: Account<'info, Config>,
#[account(init_if_needed, space = Cart::LEN, payer = claimant, seeds = [CART_SEED, claimant.key.as_ref()], bump)]
pub cart: Account<'info, Cart>,
pub system_program: Program<'info, System>,
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -167,6 +174,21 @@ pub enum ProofOfIdentity {
Cosmwasm,
}

impl ProofOfIdentity {
pub fn to_discriminant(&self) -> usize {
match self {
ProofOfIdentity::Discord => 0,
ProofOfIdentity::Solana(_) => 1,
ProofOfIdentity::Evm => 2,
ProofOfIdentity::Sui => 3,
ProofOfIdentity::Aptos => 4,
ProofOfIdentity::Cosmwasm => 5,
}
}

pub const NUMBER_OF_VARIANTS: usize = 6;
}

pub fn get_claim(claim_certificate: &ClaimCertificate) -> ClaimInfo {
ClaimInfo {
identity: get_identity(&claim_certificate.proof_of_identity),
Expand Down Expand Up @@ -228,6 +250,38 @@ impl Config {

#[account]
pub struct Receipt {}

#[account]
pub struct Cart {
pub amount: u64,
pub set: ClaimedEcosystems,
}

impl Cart {
pub const LEN: usize = 8 + 8 + 6;
}
#[derive(AnchorDeserialize, AnchorSerialize, Clone)]
pub struct ClaimedEcosystems {
set: [bool; ProofOfIdentity::NUMBER_OF_VARIANTS],
}

impl ClaimedEcosystems {
pub fn new() -> Self {
ClaimedEcosystems {
set: [false; ProofOfIdentity::NUMBER_OF_VARIANTS],
}
}

pub fn insert(&mut self, item: &ProofOfIdentity) -> () {
let index = item.to_discriminant();
self.set[index] = true;
}
pub fn contains(&self, item: &ProofOfIdentity) -> bool {
self.set[item.to_discriminant()]
}
}


////////////////////////////////////////////////////////////////////////////////
// Error.
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -315,6 +369,10 @@ pub fn get_receipt_pda(leaf: &[u8]) -> (Pubkey, u8) {
)
}

pub fn get_cart_pda(claimant: &Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[CART_SEED, claimant.as_ref()], &crate::id())
}

impl crate::accounts::Initialize {
pub fn populate(payer: Pubkey) -> Self {
crate::accounts::Initialize {
Expand All @@ -331,6 +389,8 @@ impl crate::accounts::Claim {
claimant,
dispenser_guard,
config: get_config_pda().0,
cart: get_cart_pda(&claimant).0,
system_program: system_program::System::id(),
}
}
}

0 comments on commit d5aa059

Please sign in to comment.