-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from holaplex/ryans/compression
Compressed NFTs
- Loading branch information
Showing
18 changed files
with
1,981 additions
and
1,027 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,3 @@ | ||
[workspace] | ||
members = ["consumer", "core", "entity", "migration", "indexer"] | ||
resolver = "2" | ||
|
||
[workspace.dependencies] | ||
holaplex-hub-nfts-solana-core = { path = "core" } | ||
holaplex-hub-nfts-solana-entity = { path = "entity" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
mod b58 { | ||
use serde::{de::Visitor, Deserializer, Serializer}; | ||
|
||
pub fn serialize<S: Serializer>(bytes: &[u8], ser: S) -> Result<S::Ok, S::Error> { | ||
ser.serialize_str(&bs58::encode(bytes).into_string()) | ||
} | ||
|
||
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Vec<u8>, D::Error> { | ||
struct Vis; | ||
|
||
impl<'a> Visitor<'a> for Vis { | ||
type Value = Vec<u8>; | ||
|
||
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
f.write_str("a base58-encoded string") | ||
} | ||
|
||
fn visit_str<E: serde::de::Error>(self, s: &str) -> Result<Self::Value, E> { | ||
bs58::decode(s).into_vec().map_err(E::custom) | ||
} | ||
} | ||
|
||
de.deserialize_str(Vis) | ||
} | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct Base58(#[serde(with = "b58")] pub Vec<u8>); | ||
|
||
impl From<Vec<u8>> for Base58 { | ||
fn from(v: Vec<u8>) -> Self { | ||
Self(v) | ||
} | ||
} | ||
|
||
impl From<Base58> for Vec<u8> { | ||
fn from(Base58(v): Base58) -> Self { | ||
v | ||
} | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct Asset { | ||
pub interface: String, | ||
pub id: Base58, | ||
pub content: serde_json::Value, | ||
pub authorities: Vec<AssetAuthority>, | ||
pub compression: AssetCompression, | ||
pub grouping: Vec<AssetGrouping>, | ||
pub royalty: AssetRoyalty, | ||
pub creators: Vec<AssetCreator>, | ||
pub ownership: AssetOwnership, | ||
pub supply: Option<u32>, | ||
pub mutable: bool, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetAuthority { | ||
pub address: Base58, | ||
pub scopes: Vec<String>, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetCompression { | ||
pub eligible: bool, | ||
pub compressed: bool, | ||
pub data_hash: Base58, | ||
pub creator_hash: Base58, | ||
pub asset_hash: Base58, | ||
pub tree: Base58, | ||
pub seq: u32, | ||
pub leaf_id: u32, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetGrouping { | ||
pub group_key: String, | ||
pub group_value: Base58, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetRoyalty { | ||
pub royalty_model: String, | ||
pub target: Option<serde_json::Number>, // TODO: what type is this | ||
pub percent: serde_json::Number, // TODO: this is fractional, use BCD to avoid rounding error | ||
pub basis_points: u32, | ||
pub primary_sale_happened: bool, | ||
pub locked: bool, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetCreator { | ||
pub address: Base58, | ||
pub share: u32, | ||
pub verified: bool, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetOwnership { | ||
pub frozen: bool, | ||
pub delegated: bool, | ||
pub delegate: Base58, | ||
pub ownership_model: String, | ||
pub owner: Base58, | ||
} | ||
|
||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub struct AssetProof { | ||
pub root: Base58, | ||
pub proof: Vec<Base58>, | ||
pub node_index: u32, | ||
pub leaf: Base58, | ||
pub tree_id: Base58, | ||
} | ||
|
||
#[jsonrpsee::proc_macros::rpc(client)] | ||
pub trait Rpc { | ||
#[method(name = "getAsset", param_kind = map)] | ||
fn get_asset(&self, id: &str) -> Result<Asset, Error>; | ||
|
||
#[method(name = "getAssetProof", param_kind = map)] | ||
fn get_asset_proof(&self, id: &str) -> Result<AssetProof, Error>; | ||
|
||
// Supposedly Triton offers these but their docs were crashing my browser | ||
// so I don't know what the signatures are. | ||
|
||
// #[method(name = "getAssetsByAuthority")] | ||
// fn get_assets_by_authority(&self); | ||
|
||
// #[method(name = "getAssetsByOwner")] | ||
// fn get_assets_by_owner(&self); | ||
|
||
// #[method(name = "getAssetsByGroup")] | ||
// fn get_assets_by_group(&self); | ||
|
||
// #[method(name = "getAssetsByCreator")] | ||
// fn get_assets_by_creator(&self); | ||
|
||
// #[method(name = "searchAssets")] | ||
// fn search_assets(&self); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
use holaplex_hub_nfts_solana_core::proto::{ | ||
MetaplexMasterEditionTransaction, SolanaPendingTransaction, TransferMetaplexAssetTransaction, | ||
}; | ||
use holaplex_hub_nfts_solana_entity::{collection_mints, collections}; | ||
use hub_core::prelude::*; | ||
use solana_program::pubkey::Pubkey; | ||
|
||
#[derive(Clone)] | ||
pub struct MasterEditionAddresses { | ||
pub metadata: Pubkey, | ||
pub associated_token_account: Pubkey, | ||
pub owner: Pubkey, | ||
pub master_edition: Pubkey, | ||
pub mint: Pubkey, | ||
pub update_authority: Pubkey, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct MintEditionAddresses { | ||
pub edition: Pubkey, | ||
pub mint: Pubkey, | ||
pub metadata: Pubkey, | ||
pub owner: Pubkey, | ||
pub associated_token_account: Pubkey, | ||
pub recipient: Pubkey, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct MintMetaplexAddresses { | ||
pub mint: Pubkey, | ||
pub metadata: Pubkey, | ||
pub owner: Pubkey, | ||
pub associated_token_account: Pubkey, | ||
pub recipient: Pubkey, | ||
pub update_authority: Pubkey, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct MintCompressedMintV1Addresses { | ||
pub owner: Pubkey, | ||
pub recipient: Pubkey, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct UpdateMasterEditionAddresses { | ||
pub metadata: Pubkey, | ||
pub update_authority: Pubkey, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct TransferAssetAddresses { | ||
pub owner: Pubkey, | ||
pub recipient: Pubkey, | ||
pub recipient_associated_token_account: Pubkey, | ||
pub owner_associated_token_account: Pubkey, | ||
} | ||
|
||
/// Represents a response from a transaction on the blockchain. This struct | ||
/// provides the serialized message and the signatures of the signed message. | ||
pub struct TransactionResponse<A> { | ||
/// The serialized version of the message from the transaction. | ||
pub serialized_message: Vec<u8>, | ||
|
||
/// The signatures of the signed message or the public keys of wallets that should sign the transaction. Order matters. | ||
pub signatures_or_signers_public_keys: Vec<String>, | ||
|
||
/// Addresses that are related to the transaction. | ||
pub addresses: A, | ||
} | ||
|
||
impl<A> From<TransactionResponse<A>> for SolanaPendingTransaction { | ||
fn from( | ||
TransactionResponse { | ||
serialized_message, | ||
signatures_or_signers_public_keys, | ||
.. | ||
}: TransactionResponse<A>, | ||
) -> Self { | ||
Self { | ||
serialized_message, | ||
signatures_or_signers_public_keys, | ||
} | ||
} | ||
} | ||
|
||
pub trait CollectionBackend { | ||
fn create( | ||
&self, | ||
txn: MetaplexMasterEditionTransaction, | ||
) -> Result<TransactionResponse<MasterEditionAddresses>>; | ||
|
||
fn update( | ||
&self, | ||
collection: &collections::Model, | ||
txn: MetaplexMasterEditionTransaction, | ||
) -> Result<TransactionResponse<UpdateMasterEditionAddresses>>; | ||
} | ||
|
||
pub trait MintBackend<T, R> { | ||
fn mint(&self, collection: &collections::Model, txn: T) -> Result<TransactionResponse<R>>; | ||
} | ||
|
||
#[async_trait] | ||
pub trait TransferBackend { | ||
async fn transfer( | ||
&self, | ||
collection_mint: &collection_mints::Model, | ||
txn: TransferMetaplexAssetTransaction, | ||
) -> Result<TransactionResponse<TransferAssetAddresses>>; | ||
} |
Oops, something went wrong.