From 6e67af9e6e89a1a0ea63b40c49556049ba9c6f3b Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Tue, 26 Sep 2023 00:00:27 +0500 Subject: [PATCH 1/7] Change min delay time to 30ms for fireblocks GET transaction details call --- fireblocks/src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fireblocks/src/client.rs b/fireblocks/src/client.rs index 7cad220..804f704 100644 --- a/fireblocks/src/client.rs +++ b/fireblocks/src/client.rs @@ -167,7 +167,7 @@ impl Client { .retry( &ExponentialBuilder::default() .with_jitter() - .with_min_delay(Duration::from_millis(250)) + .with_min_delay(Duration::from_millis(30)) .with_max_times(10), ) .await?; From d76986d114cb86d68068b0dc8e4fb8f40d9738a4 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Mon, 16 Oct 2023 16:01:49 +0500 Subject: [PATCH 2/7] Sign batched queued mints transaction --- api/proto.lock | 16 +++--- api/proto.toml | 14 ++--- api/src/events/signer.rs | 2 +- api/src/events/solana.rs | 108 ++++++++++++++++++++++++++++++++++++++- fireblocks/src/client.rs | 11 ++-- 5 files changed, 129 insertions(+), 22 deletions(-) diff --git a/api/proto.lock b/api/proto.lock index d5d8369..6d26538 100644 --- a/api/proto.lock +++ b/api/proto.lock @@ -1,27 +1,27 @@ [[schemas]] subject = "customer" -version = 2 +version = 1 sha512 = "d75800df0d4744c6b0f4d9a9952d3bfd0bb6b24a8babd19104cc11b54a525f85551b3c7375d69aeabbcf629cd826aa0bc6b0c0467add20716c504f5e856ce1c5" [[schemas]] subject = "nfts" -version = 29 -sha512 = "b3b2136bd6c7a136d317da84395661de5fc056e8270510575a3281d78884d99a0d89f444754ed02cb18ad26dcc7cd65300c1df73b9d74d2edc6bcc8d552465d0" +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 = 2 +sha512 = "c990f468d9bb9d44655c70b7de6ed57e512c75c4821768ff3d3d1ee067d5b54537969e9885e354f637c1386a3d11c0e97fabaf9e2d567c436a745e8b6d6af8cd" [[schemas]] subject = "timestamp" @@ -30,5 +30,5 @@ sha512 = "d167e0a143c813073eef8597f0b237e5a8eaf32abbf709724e8071b2dd73ce0438b82f [[schemas]] subject = "treasury" -version = 23 +version = 1 sha512 = "0e4d77999767d5971122e720c1cee7a57c3e47ce69f58a582f1762d8e65e031ea3bd9024cfc21bd7da5db6e38a71657151c58cdfa21d9ff643fb2fc657105cf5" diff --git a/api/proto.toml b/api/proto.toml index e66a353..03d40ae 100644 --- a/api/proto.toml +++ b/api/proto.toml @@ -1,11 +1,11 @@ [registry] -endpoint = "https://schemas.holaplex.tools" +endpoint = "http://localhost:8081" [schemas] -organization = 5 -nfts = 29 -customer = 2 -treasury = 23 -solana_nfts = 11 -polygon_nfts = 6 +organization = 1 +nfts = 1 +customer = 1 +treasury = 1 +solana_nfts = 2 +polygon_nfts = 1 timestamp = 1 \ No newline at end of file diff --git a/api/src/events/signer.rs b/api/src/events/signer.rs index 7037c6d..665ae90 100644 --- a/api/src/events/signer.rs +++ b/api/src/events/signer.rs @@ -70,7 +70,7 @@ pub(crate) async fn sign_message( let transaction = fireblocks .client() .create() - .raw_transaction(asset_id, vault_id, message, note) + .raw_transaction(asset_id, vault_id, vec![message], note) .await .map_err(ProcessorError::Fireblocks)?; diff --git a/api/src/events/solana.rs b/api/src/events/solana.rs index 19ff1f5..bdb4b3e 100644 --- a/api/src/events/solana.rs +++ b/api/src/events/solana.rs @@ -8,12 +8,13 @@ use hub_core::{ use super::{ signer::{find_vault_id_by_wallet_address, sign_message, Sign}, - Processor, Result, + Processor, ProcessorError, Result, }; use crate::proto::{ solana_nft_events::Event as SolanaNftEvent, treasury_events::{Event, SolanaTransactionResult, TransactionStatus}, - SolanaNftEventKey, SolanaNftEvents, SolanaPendingTransaction, TreasuryEventKey, TreasuryEvents, + SolanaMintBatchPayload, SolanaNftEventKey, SolanaNftEvents, SolanaPendingTransaction, + TreasuryEventKey, TreasuryEvents, }; #[derive(Debug, Clone, Copy)] @@ -154,11 +155,114 @@ impl<'a> Solana<'a> { self.send_and_notify(EventKind::RetryMintOpenDrop, key, payload) .await?; }, + Some(SolanaNftEvent::MintOpenDropBatchSigningRequested(payload)) => { + self.sign_mint_batch(key, payload).await?; + }, _ => (), } Ok(()) } + + pub async fn sign_mint_batch( + &self, + key: SolanaNftEventKey, + payload: SolanaMintBatchPayload, + ) -> Result<()> { + let conn = self.0.db.get(); + let fireblocks = &self.0.fireblocks; + let pubkeys = payload.signers_pubkeys.clone(); + + let note = &format!( + "Mint batch signing for collection {:?} by {:?} for project {:?}", + key.id, key.user_id, key.project_id, + ); + + let messages = &payload + .mint_transactions + .clone() + .into_iter() + .map(|m| m.serialized_message) + .collect::>(); + + let tx = |vault: String| async move { + let asset_id = fireblocks.assets().id("SOL"); + + let transaction = fireblocks + .client() + .create() + .raw_transaction(asset_id, vault, messages.clone(), note.to_string()) + .await + .map_err(ProcessorError::Fireblocks)?; + + let details = fireblocks + .client() + .wait_on_transaction_completion(transaction.id) + .await + .map_err(ProcessorError::Fireblocks)?; + + Result::<_>::Ok(details) + }; + + let mut futures = Vec::new(); + + for req_sig in pubkeys.clone() { + let vault_id = find_vault_id_by_wallet_address(conn, req_sig).await?; + futures.push(tx(vault_id)); + } + + let futs_result = future::join_all(futures) + .await + .into_iter() + .map(|r| r.map(|d| d.signed_messages)) + .collect::>>()?; + + let signatures = futs_result[0] + .clone() + .into_iter() + .zip( + payload + .mint_transactions + .iter() + .map(|m| m.signer_signature.clone()), + ) + .zip(futs_result[1].clone().into_iter()) + .map(|((a, b), c)| (a, b, c)) + .collect::>(); + + for (sig1, sig2, sig3) in signatures { + let key = key.clone(); + + let sig1_bytes = <[u8; 64]>::from_hex(sig1.signature.full_sig)?; + let sig1 = bs58::encode(sig1_bytes).into_string(); + + let sig3_bytes = <[u8; 64]>::from_hex(sig3.signature.full_sig)?; + let sig3 = bs58::encode(sig3_bytes).into_string(); + + let mut signed_message_signatures = vec![sig1, sig3]; + + // this will be true if mint is uncompressed + if let Some(sig2) = sig2 { + signed_message_signatures.insert(1, sig2); + } + + let txn = SolanaTransactionResult { + serialized_message: None, + signed_message_signatures, + status: TransactionStatus::Completed.into(), + }; + + let evt = Event::SolanaMintOpenDropSigned(txn); + self.producer() + .send( + Some(&TreasuryEvents { event: Some(evt) }), + Some(&key.into()), + ) + .await?; + } + + Ok(()) + } } #[async_trait] diff --git a/fireblocks/src/client.rs b/fireblocks/src/client.rs index 804f704..9be8fac 100644 --- a/fireblocks/src/client.rs +++ b/fireblocks/src/client.rs @@ -471,7 +471,7 @@ impl CreateRequestBuilder { &self, asset_id: String, vault_id: String, - message: Vec, + messages: Vec>, note: String, ) -> Result { let tx = CreateTransaction { @@ -488,9 +488,12 @@ impl CreateRequestBuilder { amount: "0".to_string(), feelevel: None, extra_parameters: Some(ExtraParameters::RawMessageData(RawMessageData { - messages: vec![UnsignedMessage { - content: hex::encode(&message), - }], + messages: messages + .into_iter() + .map(|m| UnsignedMessage { + content: hex::encode(m), + }) + .collect(), })), note: Some(note), }; From 5fd89b7df97358f56809ef47ec05a30d302f91f2 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Tue, 17 Oct 2023 09:58:22 +0500 Subject: [PATCH 3/7] update schemas --- api/proto.lock | 14 +++++++------- api/proto.toml | 14 +++++++------- api/src/events/solana.rs | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/api/proto.lock b/api/proto.lock index 6d26538..22051c0 100644 --- a/api/proto.lock +++ b/api/proto.lock @@ -1,27 +1,27 @@ [[schemas]] subject = "customer" -version = 1 +version = 2 sha512 = "d75800df0d4744c6b0f4d9a9952d3bfd0bb6b24a8babd19104cc11b54a525f85551b3c7375d69aeabbcf629cd826aa0bc6b0c0467add20716c504f5e856ce1c5" [[schemas]] subject = "nfts" -version = 1 +version = 31 sha512 = "449574f8551ab8c17824af9e08b1658ad1b26ac80340230ddf02e7a1e0979d8a47025913a6598799cf83dd1a9cda87697ee87a13f404ebb52c95ea0084205767" [[schemas]] subject = "organization" -version = 1 +version = 5 sha512 = "9fb28ac73d9712292297394a5fa53a7dae9deba6847353582987ba749859301c23c05fd49d2ce84a1640f8864c5c04d59fa38907700b280000e5c4afc96654bf" [[schemas]] subject = "polygon_nfts" -version = 1 +version = 6 sha512 = "c5ddf43d2958ec690ee2261d0ff9808b67ce810d2fc4b6077f96f561929a920f03509fc8bd7adbda219250eb019f5f7be8a3f51c554f665ea1881f7a973ef2a6" [[schemas]] subject = "solana_nfts" -version = 2 -sha512 = "c990f468d9bb9d44655c70b7de6ed57e512c75c4821768ff3d3d1ee067d5b54537969e9885e354f637c1386a3d11c0e97fabaf9e2d567c436a745e8b6d6af8cd" +version = 12 +sha512 = "4f85496c50a82cb40faa097cf6d0cb23275b3b90cb561d01388f3e5a71282a8b8e1eea617b7d712b0e415d65af483209fac2db1591456fa814a1f41a1c457433" [[schemas]] subject = "timestamp" @@ -30,5 +30,5 @@ sha512 = "d167e0a143c813073eef8597f0b237e5a8eaf32abbf709724e8071b2dd73ce0438b82f [[schemas]] subject = "treasury" -version = 1 +version = 23 sha512 = "0e4d77999767d5971122e720c1cee7a57c3e47ce69f58a582f1762d8e65e031ea3bd9024cfc21bd7da5db6e38a71657151c58cdfa21d9ff643fb2fc657105cf5" diff --git a/api/proto.toml b/api/proto.toml index 03d40ae..5bb1a54 100644 --- a/api/proto.toml +++ b/api/proto.toml @@ -1,11 +1,11 @@ [registry] -endpoint = "http://localhost:8081" +endpoint = "https://schemas.holaplex.tools" [schemas] -organization = 1 -nfts = 1 -customer = 1 -treasury = 1 -solana_nfts = 2 -polygon_nfts = 1 +organization = 5 +nfts = 31 +customer = 2 +treasury = 23 +solana_nfts = 12 +polygon_nfts = 6 timestamp = 1 \ No newline at end of file diff --git a/api/src/events/solana.rs b/api/src/events/solana.rs index bdb4b3e..e8de1ed 100644 --- a/api/src/events/solana.rs +++ b/api/src/events/solana.rs @@ -13,7 +13,7 @@ use super::{ use crate::proto::{ solana_nft_events::Event as SolanaNftEvent, treasury_events::{Event, SolanaTransactionResult, TransactionStatus}, - SolanaMintBatchPayload, SolanaNftEventKey, SolanaNftEvents, SolanaPendingTransaction, + SolanaMintPendingTransactions, SolanaNftEventKey, SolanaNftEvents, SolanaPendingTransaction, TreasuryEventKey, TreasuryEvents, }; @@ -155,7 +155,7 @@ impl<'a> Solana<'a> { self.send_and_notify(EventKind::RetryMintOpenDrop, key, payload) .await?; }, - Some(SolanaNftEvent::MintOpenDropBatchSigningRequested(payload)) => { + Some(SolanaNftEvent::MintOpenDropBatchedSigningRequested(payload)) => { self.sign_mint_batch(key, payload).await?; }, _ => (), @@ -167,7 +167,7 @@ impl<'a> Solana<'a> { pub async fn sign_mint_batch( &self, key: SolanaNftEventKey, - payload: SolanaMintBatchPayload, + payload: SolanaMintPendingTransactions, ) -> Result<()> { let conn = self.0.db.get(); let fireblocks = &self.0.fireblocks; From 8963acae1a86580e455b53cb016a6112ca8d9324 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Tue, 17 Oct 2023 18:05:36 +0500 Subject: [PATCH 4/7] send message content with event --- api/src/events/processor.rs | 5 +++++ api/src/events/solana.rs | 29 ++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/api/src/events/processor.rs b/api/src/events/processor.rs index b0dae68..f4e70c9 100644 --- a/api/src/events/processor.rs +++ b/api/src/events/processor.rs @@ -1,5 +1,6 @@ use fireblocks::Fireblocks; use hub_core::{ + bs58, prelude::*, producer::{Producer, SendError}, thiserror, uuid, @@ -49,6 +50,8 @@ pub enum ProcessorError { MissingSafeTransferFromTxn, #[error("Signed message not found in transaction response")] MissingSignedMessage, + #[error("Invalid number of signer pubkeys")] + InvalidNumberOfSigners, #[error("Invalid ECDSA pubkey recovery scalar")] #[permanent] @@ -68,6 +71,8 @@ pub enum ProcessorError { DbError(#[from] DbErr), #[error("Error sending message")] SendError(#[from] SendError), + #[error("Base58 decode error")] + Bs58DecodeError(#[from] bs58::decode::Error), } pub type Result = std::result::Result; diff --git a/api/src/events/solana.rs b/api/src/events/solana.rs index e8de1ed..a759633 100644 --- a/api/src/events/solana.rs +++ b/api/src/events/solana.rs @@ -173,6 +173,10 @@ impl<'a> Solana<'a> { let fireblocks = &self.0.fireblocks; let pubkeys = payload.signers_pubkeys.clone(); + if pubkeys.len() != 2 { + return Err(ProcessorError::InvalidNumberOfSigners); + } + let note = &format!( "Mint batch signing for collection {:?} by {:?} for project {:?}", key.id, key.user_id, key.project_id, @@ -220,35 +224,34 @@ impl<'a> Solana<'a> { let signatures = futs_result[0] .clone() .into_iter() + .zip(futs_result[1].clone().into_iter()) .zip( payload .mint_transactions .iter() .map(|m| m.signer_signature.clone()), ) - .zip(futs_result[1].clone().into_iter()) - .map(|((a, b), c)| (a, b, c)) .collect::>(); - for (sig1, sig2, sig3) in signatures { + for ((sig1, sig2), sig3) in signatures { let key = key.clone(); + let mut signatures = Vec::new(); + let content = bs58::decode(sig1.content).into_vec()?; let sig1_bytes = <[u8; 64]>::from_hex(sig1.signature.full_sig)?; - let sig1 = bs58::encode(sig1_bytes).into_string(); - - let sig3_bytes = <[u8; 64]>::from_hex(sig3.signature.full_sig)?; - let sig3 = bs58::encode(sig3_bytes).into_string(); + signatures.push(bs58::encode(sig1_bytes).into_string()); - let mut signed_message_signatures = vec![sig1, sig3]; + let sig2_bytes = <[u8; 64]>::from_hex(sig2.signature.full_sig)?; + signatures.push(bs58::encode(sig2_bytes).into_string()); - // this will be true if mint is uncompressed - if let Some(sig2) = sig2 { - signed_message_signatures.insert(1, sig2); + // Uncompressed mint message needs to be signed by mint key pair + if let Some(sig3) = sig3 { + signatures.insert(1, sig3); } let txn = SolanaTransactionResult { - serialized_message: None, - signed_message_signatures, + serialized_message: Some(content), + signed_message_signatures: signatures, status: TransactionStatus::Completed.into(), }; From 641d6af4bb992204fb884e2defa621a21e9b9421 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Wed, 18 Oct 2023 18:49:22 +0500 Subject: [PATCH 5/7] fix decoding of message for batched mint --- api/src/events/processor.rs | 2 -- api/src/events/solana.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/api/src/events/processor.rs b/api/src/events/processor.rs index f4e70c9..9675499 100644 --- a/api/src/events/processor.rs +++ b/api/src/events/processor.rs @@ -71,8 +71,6 @@ pub enum ProcessorError { DbError(#[from] DbErr), #[error("Error sending message")] SendError(#[from] SendError), - #[error("Base58 decode error")] - Bs58DecodeError(#[from] bs58::decode::Error), } pub type Result = std::result::Result; diff --git a/api/src/events/solana.rs b/api/src/events/solana.rs index a759633..4721dc9 100644 --- a/api/src/events/solana.rs +++ b/api/src/events/solana.rs @@ -236,7 +236,7 @@ impl<'a> Solana<'a> { for ((sig1, sig2), sig3) in signatures { let key = key.clone(); let mut signatures = Vec::new(); - let content = bs58::decode(sig1.content).into_vec()?; + let content = hex::decode(sig1.content)?; let sig1_bytes = <[u8; 64]>::from_hex(sig1.signature.full_sig)?; signatures.push(bs58::encode(sig1_bytes).into_string()); From 355adfded9b21a27331a7ec2612e46803bd862f4 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Wed, 18 Oct 2023 19:12:52 +0500 Subject: [PATCH 6/7] Fix: Send mint id as event key.id for mint in batch --- api/src/events/solana.rs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/api/src/events/solana.rs b/api/src/events/solana.rs index 4721dc9..3c18e1d 100644 --- a/api/src/events/solana.rs +++ b/api/src/events/solana.rs @@ -13,8 +13,8 @@ use super::{ use crate::proto::{ solana_nft_events::Event as SolanaNftEvent, treasury_events::{Event, SolanaTransactionResult, TransactionStatus}, - SolanaMintPendingTransactions, SolanaNftEventKey, SolanaNftEvents, SolanaPendingTransaction, - TreasuryEventKey, TreasuryEvents, + SolanaMintPendingTransactions, SolanaMintTransaction, SolanaNftEventKey, SolanaNftEvents, + SolanaPendingTransaction, TreasuryEventKey, TreasuryEvents, }; #[derive(Debug, Clone, Copy)] @@ -225,18 +225,18 @@ impl<'a> Solana<'a> { .clone() .into_iter() .zip(futs_result[1].clone().into_iter()) - .zip( - payload - .mint_transactions - .iter() - .map(|m| m.signer_signature.clone()), - ) + .zip(payload.mint_transactions.into_iter()) .collect::>(); - for ((sig1, sig2), sig3) in signatures { - let key = key.clone(); + for ((sig1, sig2), mint_transaction) in signatures { let mut signatures = Vec::new(); - let content = hex::decode(sig1.content)?; + let key = key.clone(); + + let SolanaMintTransaction { + serialized_message, + mint_id, + signer_signature, + } = mint_transaction; let sig1_bytes = <[u8; 64]>::from_hex(sig1.signature.full_sig)?; signatures.push(bs58::encode(sig1_bytes).into_string()); @@ -245,12 +245,12 @@ impl<'a> Solana<'a> { signatures.push(bs58::encode(sig2_bytes).into_string()); // Uncompressed mint message needs to be signed by mint key pair - if let Some(sig3) = sig3 { - signatures.insert(1, sig3); + if let Some(signer_signature) = signer_signature { + signatures.insert(1, signer_signature); } let txn = SolanaTransactionResult { - serialized_message: Some(content), + serialized_message: Some(serialized_message), signed_message_signatures: signatures, status: TransactionStatus::Completed.into(), }; @@ -259,7 +259,11 @@ impl<'a> Solana<'a> { self.producer() .send( Some(&TreasuryEvents { event: Some(evt) }), - Some(&key.into()), + Some(&TreasuryEventKey { + id: mint_id, + user_id: key.user_id, + project_id: key.project_id, + }), ) .await?; } From a717d119b6c31eadfaa52e6969da9c4348a86121 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Wed, 18 Oct 2023 21:33:35 +0500 Subject: [PATCH 7/7] Fix: out of order signed messages from fireblocks --- api/src/events/processor.rs | 1 - api/src/events/solana.rs | 127 +++++++++++++++++++++++------------- 2 files changed, 81 insertions(+), 47 deletions(-) diff --git a/api/src/events/processor.rs b/api/src/events/processor.rs index 9675499..d2b5905 100644 --- a/api/src/events/processor.rs +++ b/api/src/events/processor.rs @@ -1,6 +1,5 @@ use fireblocks::Fireblocks; use hub_core::{ - bs58, prelude::*, producer::{Producer, SendError}, thiserror, uuid, diff --git a/api/src/events/solana.rs b/api/src/events/solana.rs index 3c18e1d..64e1e69 100644 --- a/api/src/events/solana.rs +++ b/api/src/events/solana.rs @@ -1,4 +1,4 @@ -use std::time::Instant; +use std::{collections::HashMap, time::Instant}; use hex::FromHex; use hub_core::{ @@ -219,53 +219,88 @@ impl<'a> Solana<'a> { .await .into_iter() .map(|r| r.map(|d| d.signed_messages)) - .collect::>>()?; - - let signatures = futs_result[0] - .clone() - .into_iter() - .zip(futs_result[1].clone().into_iter()) - .zip(payload.mint_transactions.into_iter()) - .collect::>(); - - for ((sig1, sig2), mint_transaction) in signatures { - let mut signatures = Vec::new(); - let key = key.clone(); - - let SolanaMintTransaction { - serialized_message, - mint_id, - signer_signature, - } = mint_transaction; - - let sig1_bytes = <[u8; 64]>::from_hex(sig1.signature.full_sig)?; - signatures.push(bs58::encode(sig1_bytes).into_string()); - - let sig2_bytes = <[u8; 64]>::from_hex(sig2.signature.full_sig)?; - signatures.push(bs58::encode(sig2_bytes).into_string()); + .collect::>>(); + + match futs_result { + Ok(results) => { + let mut hashmap = HashMap::new(); + for messages in results { + for msg in messages { + let bytes = <[u8; 64]>::from_hex(msg.signature.full_sig)?; + let signature = bs58::encode(bytes).into_string(); + + hashmap + .entry(msg.content) + .or_insert(Vec::new()) + .push(signature); + } + } + + for tx in payload.mint_transactions { + let key = key.clone(); + + let SolanaMintTransaction { + mint_id, + signer_signature, + serialized_message, + } = tx; + + let hex_message = hex::encode(serialized_message.clone()); + + let mut signatures = hashmap + .get(&hex_message) + .ok_or(ProcessorError::MissingSignedMessage)? + .clone(); + + // Uncompressed mint message needs to be signed by mint key pair + if let Some(signer_signature) = signer_signature { + signatures.insert(1, signer_signature); + } + + let txn = SolanaTransactionResult { + serialized_message: Some(serialized_message), + signed_message_signatures: signatures, + status: TransactionStatus::Completed.into(), + }; + + let evt = Event::SolanaMintOpenDropSigned(txn); + self.producer() + .send( + Some(&TreasuryEvents { event: Some(evt) }), + Some(&TreasuryEventKey { + id: mint_id, + user_id: key.user_id, + project_id: key.project_id, + }), + ) + .await?; + } + }, - // Uncompressed mint message needs to be signed by mint key pair - if let Some(signer_signature) = signer_signature { - signatures.insert(1, signer_signature); - } + Err(e) => { + error!("Error signing mint batch: {:?}", e); - let txn = SolanaTransactionResult { - serialized_message: Some(serialized_message), - signed_message_signatures: signatures, - status: TransactionStatus::Completed.into(), - }; - - let evt = Event::SolanaMintOpenDropSigned(txn); - self.producer() - .send( - Some(&TreasuryEvents { event: Some(evt) }), - Some(&TreasuryEventKey { - id: mint_id, - user_id: key.user_id, - project_id: key.project_id, - }), - ) - .await?; + let txn = SolanaTransactionResult { + serialized_message: None, + signed_message_signatures: vec![], + status: TransactionStatus::Failed.into(), + }; + + for tx in payload.mint_transactions { + let evt = Event::SolanaMintOpenDropSigned(txn.clone()); + let key = key.clone(); + self.producer() + .send( + Some(&TreasuryEvents { event: Some(evt) }), + Some(&TreasuryEventKey { + id: tx.mint_id, + user_id: key.user_id, + project_id: key.project_id, + }), + ) + .await?; + } + }, } Ok(())