Skip to content

Commit

Permalink
Scaffolded new backends and asset API client.
Browse files Browse the repository at this point in the history
  • Loading branch information
ray-kast committed Jul 7, 2023
1 parent 893759c commit a100069
Show file tree
Hide file tree
Showing 10 changed files with 876 additions and 635 deletions.
405 changes: 248 additions & 157 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions Cargo.toml
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" }
4 changes: 3 additions & 1 deletion consumer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ mpl-bubblegum = "0.8.0"
mpl-token-metadata = "1.8.3"
holaplex-hub-nfts-solana-core = { path = "../core" }
holaplex-hub-nfts-solana-entity = { path = "../entity" }
jsonrpsee = { version = "0.18.2", features = ["macros", "http-client"] }
bs58 = "0.5.0"

[dependencies.hub-core]
package = "holaplex-hub-core"
version = "0.2.0"
git = "https://github.com/holaplex/hub-core"
branch = "stable"
features = ["kafka"]
features = ["kafka"]
141 changes: 141 additions & 0 deletions consumer/src/asset_api.rs
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);
}
28 changes: 23 additions & 5 deletions consumer/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,45 @@ pub struct TransactionResponse<A> {
pub addresses: A,
}

pub trait Backend {
// TODO: include this in collections::Model
pub enum CollectionType {
Legacy,
Verified,
}

// Legacy, Verified
#[async_trait]
pub trait CollectionBackend {
fn create(
&self,
txn: MetaplexMasterEditionTransaction,
) -> Result<TransactionResponse<MasterEditionAddresses>>;
}

// Uncompressed, Compressed
#[async_trait]
pub trait MintBackend {
fn mint(
&self,
collection_ty: CollectionType,
collection: &collections::Model,
txn: MintMetaplexEditionTransaction,
) -> Result<TransactionResponse<MintEditionAddresses>>;

fn update(
// TODO: probably better to replace all errors here with an Error enum
fn try_update(
&self,
collection_ty: CollectionType,
collection: &collections::Model,
txn: MetaplexMasterEditionTransaction,
) -> Result<TransactionResponse<UpdateMasterEditionAddresses>>;
) -> Result<Option<TransactionResponse<UpdateMasterEditionAddresses>>>;

fn transfer(
// Right now only this one needs to be async to support hitting the asset
// API for transfer data
async fn transfer(
&self,
mint: &collection_mints::Model,
collection_ty: CollectionType,
collection_mint: &collection_mints::Model,
txn: TransferMetaplexAssetTransaction,
) -> Result<TransactionResponse<TransferAssetAddresses>>;
}
Loading

0 comments on commit a100069

Please sign in to comment.