token metadata
This commit is contained in:
parent
bfb4a03b88
commit
85e0215869
49
Cargo.lock
generated
49
Cargo.lock
generated
@ -2104,6 +2104,7 @@ dependencies = [
|
||||
"hyper 1.4.1",
|
||||
"hyper-rustls 0.27.3",
|
||||
"hyper-util",
|
||||
"mpl-token-metadata",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"public-ip",
|
||||
@ -2879,6 +2880,19 @@ version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
|
||||
|
||||
[[package]]
|
||||
name = "mpl-token-metadata"
|
||||
version = "5.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989e6a3000e761d3b2d685662a3a9ee99826f9369fb033bd1bc7011b1cf02ed9"
|
||||
dependencies = [
|
||||
"borsh 0.10.4",
|
||||
"num-derive 0.3.3",
|
||||
"num-traits",
|
||||
"solana-program",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.10.0"
|
||||
@ -2968,6 +2982,17 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.4.2"
|
||||
@ -4471,7 +4496,7 @@ dependencies = [
|
||||
"log",
|
||||
"memoffset",
|
||||
"num-bigint 0.4.6",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
"rand 0.8.5",
|
||||
@ -4500,7 +4525,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"libc",
|
||||
"log",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"percentage",
|
||||
"rand 0.8.5",
|
||||
@ -4586,7 +4611,7 @@ dependencies = [
|
||||
"console",
|
||||
"dialoguer",
|
||||
"log",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
"qstring",
|
||||
@ -4906,7 +4931,7 @@ checksum = "cfd8e539a9963c2914ff8426dfe92351a902892aea465cd507e36d638ca0b7d6"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"log",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
@ -4933,7 +4958,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"lazy_static",
|
||||
"merlin",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
@ -4963,7 +4988,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"lazy_static",
|
||||
"merlin",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
@ -5017,7 +5042,7 @@ checksum = "68034596cf4804880d265f834af1ff2f821ad5293e41fa0f8f59086c181fc38e"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"borsh 1.5.1",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"solana-program",
|
||||
"spl-token",
|
||||
@ -5032,7 +5057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "714b53f7312c2802c62f14bc8a07916c2c872761e3d6be97e99fd432be7799ca"
|
||||
dependencies = [
|
||||
"borsh 1.5.1",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"solana-program",
|
||||
"spl-associated-token-account-client",
|
||||
@ -5128,7 +5153,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7b28bed65356558133751cc32b48a7a5ddfc59ac4e941314630bbed1ac10532"
|
||||
dependencies = [
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"solana-program",
|
||||
"spl-program-error-derive",
|
||||
@ -5183,7 +5208,7 @@ checksum = "70a0f06ac7f23dc0984931b1fe309468f14ea58e32660439c1cef19456f5d0e3"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"bytemuck",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"num_enum",
|
||||
"solana-program",
|
||||
@ -5198,7 +5223,7 @@ checksum = "d9c10f3483e48679619c76598d4e4aebb955bc49b0a5cc63323afbf44135c9bf"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"bytemuck",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"num_enum",
|
||||
"solana-program",
|
||||
@ -5222,7 +5247,7 @@ checksum = "c0b788a8c34a917b68b4ed2cdec255d03cc09ccba21545dac39c08a97fce640f"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"bytemuck",
|
||||
"num-derive",
|
||||
"num-derive 0.4.2",
|
||||
"num-traits",
|
||||
"num_enum",
|
||||
"solana-program",
|
||||
|
@ -22,6 +22,7 @@ solana-program = "2.0"
|
||||
solana-sdk = "2.0"
|
||||
spl-associated-token-account = "5.0"
|
||||
spl-token = "6.0"
|
||||
mpl-token-metadata = "5.0"
|
||||
tokio = { version = "1.40", features = ["macros", "rt-multi-thread", "fs"] } # this can be "full"
|
||||
tokio-stream = { version = "0.1", features = ["sync"] }
|
||||
# sgx poc dependencies
|
||||
|
131
src/solana.rs
131
src/solana.rs
@ -1,5 +1,10 @@
|
||||
#![allow(dead_code)]
|
||||
use crate::{grpc::challenge::Keys, persistence::KeysFile};
|
||||
use mpl_token_metadata::{
|
||||
instructions::{CreateMetadataAccountV3, CreateMetadataAccountV3InstructionArgs},
|
||||
types::DataV2,
|
||||
ID as mpl_token_metadata_id,
|
||||
};
|
||||
use solana_client::nonblocking::rpc_client::RpcClient;
|
||||
use solana_program::program_pack::Pack;
|
||||
use solana_sdk::{
|
||||
@ -127,40 +132,48 @@ impl TryFrom<KeysFile> for SolClient {
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_enough_sol(client: &RpcClient, pubkey: &Pubkey) {
|
||||
println!("Waiting for at least 0.01 SOL in address {pubkey}");
|
||||
loop {
|
||||
async fn create_token(client: &RpcClient, payer_keypair: &Keypair) -> Pubkey {
|
||||
// #1 top up the payer
|
||||
println!("Waiting for at least 0.01 SOL in address {}", payer_keypair.pubkey());
|
||||
while !has_enough_lamports(client, &payer_keypair.pubkey(), 10_000_000).await {
|
||||
sleep(Duration::from_secs(30)).await;
|
||||
}
|
||||
|
||||
// #2 create token mint
|
||||
println!("Creating Token Mint");
|
||||
let mut mint_pubkey = None;
|
||||
while mint_pubkey.is_none() {
|
||||
sleep(Duration::from_secs(30)).await;
|
||||
mint_pubkey = create_mint(client, payer_keypair).await;
|
||||
}
|
||||
let mint_pubkey = mint_pubkey.unwrap();
|
||||
println!("Token Mint created: {mint_pubkey}");
|
||||
|
||||
// #3 create token meta
|
||||
println!("Creating Token Metadata");
|
||||
while !create_meta(client, payer_keypair, &mint_pubkey).await {
|
||||
sleep(Duration::from_secs(30)).await;
|
||||
}
|
||||
println!("Token Metadata created");
|
||||
|
||||
mint_pubkey
|
||||
}
|
||||
|
||||
async fn has_enough_lamports(client: &RpcClient, pubkey: &Pubkey, threshold: u64) -> bool {
|
||||
match client.get_balance(pubkey).await {
|
||||
Ok(balance) => {
|
||||
println!("Got {balance} lamports.");
|
||||
if balance > 10_000_000 {
|
||||
return;
|
||||
}
|
||||
println!("{pubkey} needs {threshold} and has {balance}");
|
||||
balance >= threshold
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Could not get balance: {e:?}");
|
||||
}
|
||||
}
|
||||
sleep(Duration::from_secs(30)).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey {
|
||||
loop {
|
||||
wait_for_enough_sol(client, &keypair.pubkey()).await;
|
||||
match create_token_int(client, keypair).await {
|
||||
None => sleep(Duration::from_secs(30)).await,
|
||||
Some(pubkey) => {
|
||||
println!("Mint created: {pubkey}");
|
||||
return pubkey;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubkey> {
|
||||
async fn create_mint(client: &RpcClient, payer_keypair: &Keypair) -> Option<Pubkey> {
|
||||
let mint_keypair = Keypair::new();
|
||||
let payer = Keypair::from_base58_string(&keypair.to_base58_string());
|
||||
let mint_rent = client
|
||||
.get_minimum_balance_for_rent_exemption(Mint::LEN)
|
||||
.await
|
||||
@ -168,7 +181,7 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
||||
.ok()?;
|
||||
|
||||
let create_mint_account_ix = system_instruction::create_account(
|
||||
&payer.pubkey(),
|
||||
&payer_keypair.pubkey(),
|
||||
&mint_keypair.pubkey(),
|
||||
mint_rent,
|
||||
Mint::LEN as u64,
|
||||
@ -176,7 +189,7 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
||||
);
|
||||
|
||||
let init_mint_ix =
|
||||
initialize_mint(&spl_token::id(), &mint_keypair.pubkey(), &payer.pubkey(), None, 9)
|
||||
initialize_mint(&spl_token::id(), &mint_keypair.pubkey(), &payer_keypair.pubkey(), None, 9)
|
||||
.map_err(|e| println!("Can't initialize mint: {e}"))
|
||||
.ok()?;
|
||||
|
||||
@ -185,10 +198,11 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
||||
.await
|
||||
.map_err(|e| println!("Can't get latest blockhash: {e}"))
|
||||
.ok()?;
|
||||
|
||||
let tx = Transaction::new_signed_with_payer(
|
||||
&[create_mint_account_ix, init_mint_ix],
|
||||
Some(&payer.pubkey()),
|
||||
&[&payer, &mint_keypair],
|
||||
Some(&payer_keypair.pubkey()),
|
||||
&[&payer_keypair, &mint_keypair],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
@ -202,3 +216,64 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
async fn create_meta(client: &RpcClient, payer_keypair: &Keypair, mint_pubkey: &Pubkey) -> bool {
|
||||
create_meta_int(client, payer_keypair, mint_pubkey).await.is_some()
|
||||
}
|
||||
|
||||
async fn create_meta_int(
|
||||
client: &RpcClient,
|
||||
payer_keypair: &Keypair,
|
||||
mint_pubkey: &Pubkey,
|
||||
) -> Option<()> {
|
||||
let metadata_seeds = &[b"metadata", mpl_token_metadata_id.as_ref(), mint_pubkey.as_ref()];
|
||||
let (metadata_pda, _bump) =
|
||||
Pubkey::find_program_address(metadata_seeds, &mpl_token_metadata_id);
|
||||
|
||||
let data_v2 = DataV2 {
|
||||
name: "DeTEE Hacker Challenge Token".to_string(),
|
||||
symbol: "DTHC".to_string(),
|
||||
uri: "https://detee.ltd/dthc/meta.json".to_string(),
|
||||
seller_fee_basis_points: 0, // usually for NFTs, can be 0 for fungible
|
||||
creators: None, // or Some(vec![Creator { ... }]) if you want to specify creators
|
||||
collection: None,
|
||||
uses: None,
|
||||
};
|
||||
|
||||
let create_metadata_account_ix = CreateMetadataAccountV3 {
|
||||
metadata: metadata_pda,
|
||||
mint: *mint_pubkey,
|
||||
mint_authority: payer_keypair.pubkey(),
|
||||
payer: payer_keypair.pubkey(),
|
||||
update_authority: (payer_keypair.pubkey(), true),
|
||||
system_program: solana_program::system_program::id(),
|
||||
rent: None,
|
||||
}
|
||||
.instruction(CreateMetadataAccountV3InstructionArgs {
|
||||
data: data_v2,
|
||||
is_mutable: true,
|
||||
collection_details: None,
|
||||
});
|
||||
|
||||
let recent_blockhash = client
|
||||
.get_latest_blockhash()
|
||||
.await
|
||||
.map_err(|e| println!("Can't get latest blockhash: {e}"))
|
||||
.ok()?;
|
||||
|
||||
let tx = Transaction::new_signed_with_payer(
|
||||
&[create_metadata_account_ix],
|
||||
Some(&payer_keypair.pubkey()),
|
||||
&[&payer_keypair],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
client
|
||||
.send_and_confirm_transaction(&tx)
|
||||
.await
|
||||
.map_err(|e| println!("Can't execute transaction: {e}"))
|
||||
.map(|s| {
|
||||
println!("Transaction signature: {}", s);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user