Created
September 30, 2023 17:57
-
-
Save ronanyeah/070c4bafce4a717992a7db78b517c05a to your computer and use it in GitHub Desktop.
Send a Solana compressed NFT using a Rust client
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
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