Skip to content

Instantly share code, notes, and snippets.

@ronanyeah
Created September 30, 2023 17:57
Show Gist options
  • Save ronanyeah/070c4bafce4a717992a7db78b517c05a to your computer and use it in GitHub Desktop.
Save ronanyeah/070c4bafce4a717992a7db78b517c05a to your computer and use it in GitHub Desktop.
Send a Solana compressed NFT using a Rust client
use mpl_bubblegum::accounts::TreeConfig;
use solana_sdk::{bs58, instruction::AccountMeta, instruction::Instruction, pubkey::Pubkey};
#[derive(serde::Deserialize)]
struct HeliusResponse<T> {
result: T,
}
#[derive(serde::Deserialize)]
struct HeliusCompression {
tree: String,
leaf_id: u64,
data_hash: String,
creator_hash: String,
}
#[derive(serde::Deserialize)]
struct HeliusAsset {
compression: HeliusCompression,
}
#[derive(serde::Deserialize)]
struct HeliusProof {
root: String,
proof: Vec<String>,
}
const HELIUS_API_KEY: &'static str = "foo";
pub async fn send_cnft(
client: &reqwest::Client,
mint_id: &Pubkey,
sender: &Pubkey,
receiver: &Pubkey,
) -> Result<Instruction, Box<dyn std::error::Error>> {
let helius_endpoint = format!("https://rpc.helius.xyz/?api-key={}", HELIUS_API_KEY);
let helius_asset: HeliusResponse<HeliusAsset> = client
.post(&helius_endpoint)
.json(&serde_json::json!({
"id": 0,
"jsonrpc": "2.0",
"method": "getAsset",
"params": {
"id": mint_id.to_string()
},
}))
.send()
.await?
.json()
.await?;
let compression = helius_asset.result.compression;
let helius_proof: HeliusResponse<HeliusProof> = client
.post(&helius_endpoint)
.json(&serde_json::json!({
"id": 0,
"jsonrpc": "2.0",
"method": "getAssetProof",
"params": {
"id": mint_id.to_string()
},
}))
.send()
.await?
.json()
.await?;
let proof_path: Vec<Pubkey> = helius_proof
.result
.proof
.into_iter()
.map(|x| x.parse().unwrap())
.collect();
let proof_accounts: Vec<AccountMeta> = proof_path
.into_iter()
.map(|pk| AccountMeta {
pubkey: pk,
is_signer: false,
is_writable: false,
})
.collect();
let tree = compression.tree.parse()?;
let (tree_config, _) = TreeConfig::find_pda(&tree);
let ix = mpl_bubblegum::instructions::TransferBuilder::new()
.merkle_tree(tree)
.tree_config(tree_config)
.nonce(compression.leaf_id)
.index(compression.leaf_id.try_into()?)
.root(bs58::decode(helius_proof.result.root).into_vec()?[..].try_into()?)
.data_hash(bs58::decode(compression.data_hash).into_vec()?[..].try_into()?)
.creator_hash(bs58::decode(compression.creator_hash).into_vec()?[..].try_into()?)
.leaf_owner(*sender, true)
.leaf_delegate(*sender, true)
.new_leaf_owner(*receiver)
.add_remaining_accounts(&proof_accounts)
.instruction();
Ok(ix)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment