Skip to content

Commit

Permalink
mutation for batched random queued mints
Browse files Browse the repository at this point in the history
  • Loading branch information
imabdulbasit committed Oct 16, 2023
1 parent 3e32bdc commit 259c56f
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 16 deletions.
16 changes: 8 additions & 8 deletions api/proto.lock
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
[[schemas]]
subject = "customer"
version = 2
version = 1
sha512 = "d75800df0d4744c6b0f4d9a9952d3bfd0bb6b24a8babd19104cc11b54a525f85551b3c7375d69aeabbcf629cd826aa0bc6b0c0467add20716c504f5e856ce1c5"

[[schemas]]
subject = "nfts"
version = 30
sha512 = "bee70bd6f0f18a8049f93bceb9c4b500b49352f9d19d55d5a411da92cbd786c88bec47f73e1ef6946ceefc7de8e558f704bf8187be9d9f4e49bd102baec29327"
version = 1
sha512 = "449574f8551ab8c17824af9e08b1658ad1b26ac80340230ddf02e7a1e0979d8a47025913a6598799cf83dd1a9cda87697ee87a13f404ebb52c95ea0084205767"

[[schemas]]
subject = "organization"
version = 5
version = 1
sha512 = "9fb28ac73d9712292297394a5fa53a7dae9deba6847353582987ba749859301c23c05fd49d2ce84a1640f8864c5c04d59fa38907700b280000e5c4afc96654bf"

[[schemas]]
subject = "polygon_nfts"
version = 6
version = 1
sha512 = "c5ddf43d2958ec690ee2261d0ff9808b67ce810d2fc4b6077f96f561929a920f03509fc8bd7adbda219250eb019f5f7be8a3f51c554f665ea1881f7a973ef2a6"

[[schemas]]
subject = "solana_nfts"
version = 11
sha512 = "967fefde938a0f6ce05194e4fca15673e681caac54d8aeec114c5d38418632b9696dbaf5362345a15114e5abb49de55d0af8b9edcc0f2c91f9ef1ccc4ff55d68"
version = 1
sha512 = "c1b1f3af0097d52622e7b8628fd6085fa4cced9e91883fff309de370f4ff55f8a58c388e5eee69d1755b113e39c772f113ff6220d8a7dc435b79bc51e121473e"

[[schemas]]
subject = "timestamp"
Expand All @@ -30,5 +30,5 @@ sha512 = "d167e0a143c813073eef8597f0b237e5a8eaf32abbf709724e8071b2dd73ce0438b82f

[[schemas]]
subject = "treasury"
version = 23
version = 1
sha512 = "0e4d77999767d5971122e720c1cee7a57c3e47ce69f58a582f1762d8e65e031ea3bd9024cfc21bd7da5db6e38a71657151c58cdfa21d9ff643fb2fc657105cf5"
14 changes: 7 additions & 7 deletions api/proto.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[registry]
endpoint = "https://schemas.holaplex.tools"
endpoint = "http://localhost:8081"

[schemas]
organization = 5
nfts = 30
customer = 2
treasury = 23
solana_nfts = 11
polygon_nfts = 6
organization = 1
nfts = 1
customer = 1
treasury = 1
solana_nfts = 1
polygon_nfts = 1
timestamp = 1
201 changes: 200 additions & 1 deletion api/src/mutations/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ use crate::{
objects::{CollectionMint, Creator, MetadataJsonInput},
proto::{
self, nft_events::Event as NftEvent, CreationStatus as NftCreationStatus, MetaplexMetadata,
MintCollectionCreation, MintCreation, NftEventKey, NftEvents, RetryUpdateSolanaMintPayload,
MintCollectionCreation, MintCreation, MintOpenDropTransaction, NftEventKey, NftEvents,
RetryUpdateSolanaMintPayload, SolanaMintOpenDropBatchedPayload,
},
Actions, AppContext, OrganizationId, UserID,
};
Expand Down Expand Up @@ -1291,6 +1292,190 @@ impl Mutation {
collection_mint: mint.into(),
})
}

async fn mint_random_queued_to_drop_batched(
&self,
ctx: &Context<'_>,
input: MintRandomQueuedBatchedInput,
) -> Result<MintRandomQueuedBatchedPayload> {
let AppContext {
db,
user_id,
organization_id,
balance,
..
} = ctx.data::<AppContext>()?;
let credits = ctx.data::<CreditsClient<Actions>>()?;
let conn = db.get();
let nfts_producer = ctx.data::<Producer<NftEvents>>()?;

let UserID(id) = user_id;
let OrganizationId(org) = organization_id;

let user_id = id.ok_or(Error::new("X-USER-ID header not found"))?;
let org_id = org.ok_or(Error::new("X-ORGANIZATION-ID header not found"))?;
let balance = balance
.0
.ok_or(Error::new("X-CREDIT-BALANCE header not found"))?;

let batch_size = input.recipients.len();

if batch_size == 0 {
return Err(Error::new("No recipients provided"));
}

if batch_size > 250 {
return Err(Error::new("Batch size cannot be greater than 250"));
}

let drop = drops::Entity::find_by_id(input.drop)
.one(conn)
.await?
.ok_or(Error::new("drop not found"))?;

let mints = CollectionMints::find()
.filter(collection_mints::Column::CollectionId.eq(drop.collection_id))
.filter(collection_mints::Column::CreationStatus.eq(CreationStatus::Queued))
.order_by(SimpleExpr::FunctionCall(Func::random()), Order::Asc)
.limit(Some(batch_size.try_into()?))
.all(conn)
.await?;

if mints.len() != batch_size {
return Err(Error::new("Not enough mints found for the drop"));
}

let collection = collections::Entity::find_by_id(drop.collection_id)
.one(conn)
.await?
.ok_or(Error::new("collection not found"))?;

let project_id = collection.project_id;
let blockchain = collection.blockchain;

if blockchain != BlockchainEnum::Solana {
return Err(Error::new("Only Solana is supported at this time"));
}

let owner_address = fetch_owner(conn, project_id, blockchain).await?;

let action = if input.compressed {
Actions::MintCompressed
} else {
Actions::Mint
};

let event_key = NftEventKey {
id: collection.id.to_string(),
user_id: user_id.to_string(),
project_id: project_id.to_string(),
};

let mut transactions = Vec::new();

for (mint, recipient) in mints.clone().into_iter().zip(input.recipients.into_iter()) {
let metadata_json = metadata_jsons::Entity::find_by_id(mint.id)
.one(conn)
.await?
.ok_or(Error::new("metadata json not found"))?;

let metadata_uri = metadata_json
.uri
.ok_or(Error::new("No metadata json uri found"))?;

let creators = mint_creators::Entity::find_by_collection_mint_id(mint.id)
.all(conn)
.await?;

let TransactionId(deduction_id) = credits
.submit_pending_deduction(
org_id,
user_id,
action,
collection.blockchain.into(),
balance,
)
.await?;

let tx = conn.begin().await?;

let mut collection_am = collections::ActiveModel::from(collection.clone());
collection_am.total_mints = Set(collection.total_mints.add(1));
collection_am.update(&tx).await?;

let mut mint_am: collection_mints::ActiveModel = mint.into();

mint_am.creation_status = Set(CreationStatus::Pending);
mint_am.credits_deduction_id = Set(Some(deduction_id));
mint_am.compressed = Set(Some(input.compressed));
mint_am.owner = Set(Some(recipient.clone()));
mint_am.seller_fee_basis_points = Set(collection.seller_fee_basis_points);

let mint = mint_am.update(&tx).await?;

let mint_history_am = mint_histories::ActiveModel {
mint_id: Set(mint.id),
wallet: Set(recipient.clone()),
collection_id: Set(collection.id),
tx_signature: Set(None),
status: Set(CreationStatus::Pending),
created_at: Set(Utc::now().into()),
..Default::default()
};

mint_history_am.insert(&tx).await?;

tx.commit().await?;

nfts_producer
.send(
Some(&NftEvents {
event: Some(NftEvent::DropMinted(MintCreation {
drop_id: drop.id.to_string(),
status: NftCreationStatus::InProgress as i32,
})),
}),
Some(&NftEventKey {
id: mint.id.to_string(),
project_id: drop.project_id.to_string(),
user_id: user_id.to_string(),
}),
)
.await?;

transactions.push(MintOpenDropTransaction {
recipient_address: recipient,
metadata: Some(MetaplexMetadata {
owner_address: owner_address.clone(),
name: metadata_json.name,
symbol: metadata_json.symbol,
metadata_uri,
seller_fee_basis_points: mint.seller_fee_basis_points.into(),
creators: creators.into_iter().map(Into::into).collect(),
}),
mint_id: mint.id.to_string(),
});
}

nfts_producer
.send(
Some(&NftEvents {
event: Some(NftEvent::SolanaMintOpenDropBatched(
SolanaMintOpenDropBatchedPayload {
collection_id: collection.id.to_string(),
compressed: input.compressed,
mint_open_drop_transactions: transactions,
},
)),
}),
Some(&event_key),
)
.await?;

Ok(MintRandomQueuedBatchedPayload {
collection_mints: mints.into_iter().map(Into::into).collect(),
})
}
}

fn validate_compress(blockchain: BlockchainEnum, compressed: bool) -> Result<(), Error> {
Expand Down Expand Up @@ -1475,3 +1660,17 @@ pub struct MintRandomQueuedInput {
recipient: String,
compressed: bool,
}

/// Represents input data for `mint_random_queued_batched` mutation
#[derive(Debug, Clone, InputObject)]
pub struct MintRandomQueuedBatchedInput {
drop: Uuid,
recipients: Vec<String>,
compressed: bool,
}

/// Represents payload data for `mint_random_queued_batched` mutation
#[derive(Debug, Clone, SimpleObject)]
pub struct MintRandomQueuedBatchedPayload {
collection_mints: Vec<CollectionMint>,
}

0 comments on commit 259c56f

Please sign in to comment.