Skip to content

Commit

Permalink
Merge pull request #36 from holaplex/abdul/update-mint
Browse files Browse the repository at this point in the history
Update Collection Mint and support retry
  • Loading branch information
imabdulbasit committed Aug 10, 2023
2 parents fa0716b + 29b0825 commit 1e03fe4
Show file tree
Hide file tree
Showing 11 changed files with 349 additions and 20 deletions.
22 changes: 21 additions & 1 deletion consumer/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use holaplex_hub_nfts_solana_core::proto::{
MetaplexMasterEditionTransaction, SolanaPendingTransaction, TransferMetaplexAssetTransaction,
UpdateSolanaMintPayload,
};
use holaplex_hub_nfts_solana_entity::collections;
use holaplex_hub_nfts_solana_entity::{collection_mints, collections, update_revisions};
use hub_core::prelude::*;
use solana_program::pubkey::Pubkey;

Expand Down Expand Up @@ -54,6 +55,13 @@ pub struct UpdateMasterEditionAddresses {
pub update_authority: Pubkey,
}

#[derive(Clone)]
pub struct UpdateCollectionMintAddresses {
pub payer: Pubkey,
pub metadata: Pubkey,
pub update_authority: Pubkey,
}

#[derive(Clone)]
pub struct TransferAssetAddresses {
pub owner: Pubkey,
Expand Down Expand Up @@ -101,6 +109,18 @@ pub trait CollectionBackend {
collection: &collections::Model,
txn: MetaplexMasterEditionTransaction,
) -> Result<TransactionResponse<UpdateMasterEditionAddresses>>;

fn update_mint(
&self,
collection: &collections::Model,
mint: &collection_mints::Model,
txn: UpdateSolanaMintPayload,
) -> Result<TransactionResponse<UpdateCollectionMintAddresses>>;

fn retry_update_mint(
&self,
revision: &update_revisions::Model,
) -> Result<TransactionResponse<UpdateCollectionMintAddresses>>;
}

pub trait MintBackend<T, R> {
Expand Down
119 changes: 115 additions & 4 deletions consumer/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ use holaplex_hub_nfts_solana_core::{
MintMetaplexMetadataTransaction, SolanaCompletedMintTransaction,
SolanaCompletedTransferTransaction, SolanaCompletedUpdateTransaction,
SolanaFailedTransaction, SolanaNftEventKey, SolanaNftEvents, SolanaPendingTransaction,
SolanaTransactionFailureReason, TransferMetaplexAssetTransaction,
SolanaTransactionFailureReason, TransferMetaplexAssetTransaction, UpdateSolanaMintPayload,
},
sea_orm::{DatabaseConnection, DbErr, Set},
sea_orm::{ActiveModelTrait, DatabaseConnection, DbErr, EntityTrait, Set},
Collection, CollectionMint, CompressionLeaf, Services,
};
use holaplex_hub_nfts_solana_entity::{collection_mints, collections, compression_leafs};
use holaplex_hub_nfts_solana_entity::{
collection_mints, collections, compression_leafs, update_revisions,
};
use hub_core::{
chrono::Utc,
prelude::*,
Expand All @@ -29,7 +31,7 @@ use solana_sdk::signature::Signature;
use crate::{
backend::{
CollectionBackend, MasterEditionAddresses, MintBackend, MintEditionAddresses,
MintMetaplexAddresses, TransferBackend,
MintMetaplexAddresses, TransferBackend, UpdateCollectionMintAddresses,
},
solana::{CompressedRef, EditionRef, Solana, SolanaAssetIdError, UncompressedRef},
};
Expand Down Expand Up @@ -109,6 +111,8 @@ pub enum EventKind {
UpdateCollection,
MintToCollection,
RetryMintToCollection,
UpdateCollectionMint,
RetryUpdateCollectionMint,
}

impl EventKind {
Expand All @@ -125,6 +129,8 @@ impl EventKind {
Self::UpdateCollection => "collection update",
Self::MintToCollection => "mint to collection",
Self::RetryMintToCollection => "mint to collection retry",
Self::UpdateCollectionMint => "collection mint update",
Self::RetryUpdateCollectionMint => "collection mint update retry",
}
}

Expand All @@ -145,6 +151,12 @@ impl EventKind {
EventKind::RetryMintToCollection => {
SolanaNftEvent::RetryMintToCollectionSigningRequested(tx)
},
EventKind::UpdateCollectionMint => {
SolanaNftEvent::UpdateCollectionMintSigningRequested(tx)
},
EventKind::RetryUpdateCollectionMint => {
SolanaNftEvent::RetryUpdateMintSigningRequested(tx)
},
}
}

Expand Down Expand Up @@ -286,6 +298,16 @@ impl EventKind {
address: collection_mint.mint,
})
},
Self::UpdateCollectionMint => {
SolanaNftEvent::UpdateCollectionMintSubmitted(SolanaCompletedUpdateTransaction {
signature,
})
},
Self::RetryUpdateCollectionMint => {
SolanaNftEvent::RetryUpdateMintSubmitted(SolanaCompletedUpdateTransaction {
signature,
})
},
})
}

Expand All @@ -302,6 +324,8 @@ impl EventKind {
Self::UpdateCollection => SolanaNftEvent::UpdateCollectionFailed(tx),
Self::MintToCollection => SolanaNftEvent::MintToCollectionFailed(tx),
Self::RetryMintToCollection => SolanaNftEvent::RetryMintToCollectionFailed(tx),
Self::UpdateCollectionMint => SolanaNftEvent::UpdateCollectionMintFailed(tx),
Self::RetryUpdateCollectionMint => SolanaNftEvent::RetryUpdateMintFailed(tx),
}
}
}
Expand Down Expand Up @@ -435,6 +459,29 @@ impl Processor {
)
.await
},
Some(NftEvent::SolanaUpdatedCollectionMint(payload)) => {
self.process_nft(
EventKind::UpdateCollectionMint,
&key,
self.update_collection_mint(
&UncompressedRef(self.solana()),
&key,
payload,
),
)
.await
},
Some(NftEvent::SolanaRetryUpdatedCollectionMint(_)) => {
self.process_nft(
EventKind::RetryUpdateCollectionMint,
&key,
self.retry_update_collection_mint(
&UncompressedRef(self.solana()),
&key,
),
)
.await
},
_ => Ok(()),
}
},
Expand Down Expand Up @@ -483,6 +530,14 @@ impl Processor {
self.process_treasury(EventKind::RetryCreateCollection, key, res)
.await
},
Some(TreasuryEvent::SolanaUpdateCollectionMintSigned(res)) => {
self.process_treasury(EventKind::UpdateCollectionMint, key, res)
.await
},
Some(TreasuryEvent::SolanaRetryUpdateCollectionMintSigned(res)) => {
self.process_treasury(EventKind::RetryUpdateCollectionMint, key, res)
.await
},
_ => Ok(()),
}
},
Expand Down Expand Up @@ -735,6 +790,62 @@ impl Processor {
Ok(tx.into())
}

async fn update_collection_mint<B: CollectionBackend>(
&self,
backend: &B,
key: &SolanaNftEventKey,
payload: UpdateSolanaMintPayload,
) -> ProcessResult<SolanaPendingTransaction> {
let collection_id = Uuid::parse_str(&payload.collection_id)?;
let collection = Collection::find_by_id(self.db.get(), collection_id)
.await?
.ok_or(ProcessorErrorKind::RecordNotFound)?;
let mint = CollectionMint::find_by_id(self.db.get(), key.id.parse()?)
.await?
.ok_or(ProcessorErrorKind::RecordNotFound)?;

let tx = backend
.update_mint(&collection, &mint, payload)
.map_err(ProcessorErrorKind::Solana)?;

let UpdateCollectionMintAddresses {
payer,
metadata,
update_authority,
} = tx.addresses.clone();
let msg_bytes = tx.serialized_message.clone();

let revision = update_revisions::ActiveModel {
id: Set(key.id.parse()?),
mint_id: Set(mint.id),
serialized_message: Set(msg_bytes),
payer: Set(payer.to_string()),
metadata: Set(metadata.to_string()),
update_authority: Set(update_authority.to_string()),
};

revision.insert(self.db.get()).await?;

Ok(tx.into())
}

async fn retry_update_collection_mint<B: CollectionBackend>(
&self,
backend: &B,
key: &SolanaNftEventKey,
) -> ProcessResult<SolanaPendingTransaction> {
let revision = update_revisions::Entity::find_by_id(Uuid::from_str(&key.id)?)
.one(self.db.get())
.await?
.ok_or(ProcessorErrorKind::RecordNotFound)?;

let tx = backend
.retry_update_mint(&revision)
.map_err(ProcessorErrorKind::Solana)?;

Ok(tx.into())
}

async fn transfer_asset(
&self,
_key: &SolanaNftEventKey,
Expand Down
121 changes: 118 additions & 3 deletions consumer/src/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ use anchor_lang::{prelude::AccountMeta, AnchorDeserialize, InstructionData};
use holaplex_hub_nfts_solana_core::proto::{
treasury_events::SolanaTransactionResult, MasterEdition, MetaplexMasterEditionTransaction,
MetaplexMetadata, MintMetaplexEditionTransaction, MintMetaplexMetadataTransaction,
TransferMetaplexAssetTransaction,
TransferMetaplexAssetTransaction, UpdateSolanaMintPayload,
};
use holaplex_hub_nfts_solana_entity::{
collection_mints, collections, compression_leafs, update_revisions,
};
use holaplex_hub_nfts_solana_entity::{collection_mints, collections, compression_leafs};
use hub_core::{anyhow::Result, clap, prelude::*, thiserror, uuid::Uuid};
use mpl_bubblegum::state::metaplex_adapter::{
Collection, Creator as BubblegumCreator, TokenProgramVersion,
Expand Down Expand Up @@ -41,7 +43,8 @@ use crate::{
backend::{
CollectionBackend, MasterEditionAddresses, MintBackend, MintCompressedMintV1Addresses,
MintEditionAddresses, MintMetaplexAddresses, TransactionResponse, TransferAssetAddresses,
TransferBackend, TransferCompressedMintV1Addresses, UpdateMasterEditionAddresses,
TransferBackend, TransferCompressedMintV1Addresses, UpdateCollectionMintAddresses,
UpdateMasterEditionAddresses,
},
};

Expand Down Expand Up @@ -468,6 +471,118 @@ impl<'a> CollectionBackend for UncompressedRef<'a> {
},
})
}

fn update_mint(
&self,
collection: &collections::Model,
collection_mint: &collection_mints::Model,
payload: UpdateSolanaMintPayload,
) -> Result<TransactionResponse<UpdateCollectionMintAddresses>> {
let metadata = payload
.metadata
.ok_or(SolanaErrorNotFoundMessage::Metadata)?;
let payer: Pubkey = self.0.treasury_wallet_address;
let rpc = &self.0.rpc_client;

let MetaplexMetadata {
name,
symbol,
seller_fee_basis_points,
metadata_uri,
creators,
owner_address,
} = metadata;
let update_authority: Pubkey = owner_address.parse()?;
let mint_pubkey: Pubkey = collection_mint.mint.parse()?;

let (metadata, _) = Pubkey::find_program_address(
&[
b"metadata",
mpl_token_metadata::ID.as_ref(),
mint_pubkey.as_ref(),
],
&mpl_token_metadata::ID,
);

let blockhash = rpc.get_latest_blockhash()?;

let update_ins: Instruction = mpl_token_metadata::instruction::update_metadata_accounts_v2(
mpl_token_metadata::ID,
metadata,
update_authority,
None,
Some(DataV2 {
name,
symbol,
uri: metadata_uri,
seller_fee_basis_points: seller_fee_basis_points.try_into()?,
creators: Some(
creators
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<Creator>, _>>()?,
),
collection: Some(mpl_token_metadata::state::Collection {
verified: true,
key: collection.mint.parse()?,
}),
uses: None,
}),
None,
Some(true),
);

let message = solana_program::message::Message::new_with_blockhash(
&[update_ins],
Some(&payer),
&blockhash,
);

let serialized_message = message.serialize();

Ok(TransactionResponse {
serialized_message,
signatures_or_signers_public_keys: vec![
payer.to_string(),
update_authority.to_string(),
],
addresses: UpdateCollectionMintAddresses {
payer,
metadata,
update_authority,
},
})
}

fn retry_update_mint(
&self,
revision: &update_revisions::Model,
) -> Result<TransactionResponse<UpdateCollectionMintAddresses>> {
let rpc = &self.0.rpc_client;

let update_authority: Pubkey = revision.update_authority.parse()?;
let metadata = revision.metadata.parse()?;
let payer = Pubkey::from_str(&revision.payer)?;

let mut message: solana_program::message::Message =
bincode::deserialize(&revision.serialized_message)?;

let blockhash = rpc.get_latest_blockhash()?;
message.recent_blockhash = blockhash;

Ok(TransactionResponse {
serialized_message: message.serialize(),
signatures_or_signers_public_keys: vec![
payer.to_string(),
update_authority.to_string(),
],
addresses: UpdateCollectionMintAddresses {
payer,
metadata,
update_authority,
},
})
}
}

impl<'a> MintBackend<MintMetaplexEditionTransaction, MintEditionAddresses> for EditionRef<'a> {
Expand Down
12 changes: 6 additions & 6 deletions core/proto.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[[schemas]]
subject = "nfts"
version = 22
sha512 = "c9920f6a5792b067396c88e40b9bd2adfcb55b582734aff924a67a9d5841a5e2839fc734c1bbff66f402f9a9d8852ca5fef1339aaaa3d5b05aa7868ddfa375c1"
version = 25
sha512 = "90dadff6bc75b59bb79d9ed2a65d582923f9ce66b5915c020306571bb446d68ff6648543386838510a60081d7cbb14f43fa2ae22c4c8ecd85874bee4323dd26a"

[[schemas]]
subject = "solana_nfts"
version = 7
sha512 = "73570b9e58f91a06901ba6455986ce1a0d3675e33860d2447160d711a8cebcfb78cfc714fb08644ad83495dc8612b0b123203561af6d93d29ffb0256725047ba"
version = 9
sha512 = "312a84e8ae8b9222c7ec2b307d036dae0bd8dac4363e813c2fcffd5d7fba8741bd802953b1ec0a96baf57a7ce852debb724fcccf3b0bd8a27a9e4cc60344a56f"

[[schemas]]
subject = "treasury"
version = 19
sha512 = "af9c5b6f8f6aef713a686b9253ef87a2332e8a69b4e0adbeab3a587ef2b74c09b510e3b017bf75bc2d1e083846073dcfd39cd104d95a4a76406a3a7fa0dbe2fb"
version = 21
sha512 = "734cff313b8b4854b9a4c03cfd6f95f07b1fd86f8678393ab466443d9da4d6e7c9fc400bdbcc718d83e6c7711857941d4b6dc0ea5d1d926f05a7859a65a15509"
Loading

0 comments on commit 1e03fe4

Please sign in to comment.