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 1.4.1",
|
||||||
"hyper-rustls 0.27.3",
|
"hyper-rustls 0.27.3",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
|
"mpl-token-metadata",
|
||||||
"prost",
|
"prost",
|
||||||
"prost-types",
|
"prost-types",
|
||||||
"public-ip",
|
"public-ip",
|
||||||
@ -2879,6 +2880,19 @@ version = "1.12.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
|
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]]
|
[[package]]
|
||||||
name = "multimap"
|
name = "multimap"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -2968,6 +2982,17 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
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]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@ -4471,7 +4496,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"num-bigint 0.4.6",
|
"num-bigint 0.4.6",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
@ -4500,7 +4525,7 @@ dependencies = [
|
|||||||
"itertools 0.12.1",
|
"itertools 0.12.1",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"percentage",
|
"percentage",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
@ -4586,7 +4611,7 @@ dependencies = [
|
|||||||
"console",
|
"console",
|
||||||
"dialoguer",
|
"dialoguer",
|
||||||
"log",
|
"log",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"qstring",
|
"qstring",
|
||||||
@ -4906,7 +4931,7 @@ checksum = "cfd8e539a9963c2914ff8426dfe92351a902892aea465cd507e36d638ca0b7d6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"log",
|
"log",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"serde",
|
"serde",
|
||||||
@ -4933,7 +4958,7 @@ dependencies = [
|
|||||||
"itertools 0.12.1",
|
"itertools 0.12.1",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"merlin",
|
"merlin",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"serde",
|
"serde",
|
||||||
@ -4963,7 +4988,7 @@ dependencies = [
|
|||||||
"itertools 0.12.1",
|
"itertools 0.12.1",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"merlin",
|
"merlin",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"serde",
|
"serde",
|
||||||
@ -5017,7 +5042,7 @@ checksum = "68034596cf4804880d265f834af1ff2f821ad5293e41fa0f8f59086c181fc38e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_matches",
|
"assert_matches",
|
||||||
"borsh 1.5.1",
|
"borsh 1.5.1",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
"spl-token",
|
"spl-token",
|
||||||
@ -5032,7 +5057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "714b53f7312c2802c62f14bc8a07916c2c872761e3d6be97e99fd432be7799ca"
|
checksum = "714b53f7312c2802c62f14bc8a07916c2c872761e3d6be97e99fd432be7799ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh 1.5.1",
|
"borsh 1.5.1",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
"spl-associated-token-account-client",
|
"spl-associated-token-account-client",
|
||||||
@ -5128,7 +5153,7 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7b28bed65356558133751cc32b48a7a5ddfc59ac4e941314630bbed1ac10532"
|
checksum = "d7b28bed65356558133751cc32b48a7a5ddfc59ac4e941314630bbed1ac10532"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
"spl-program-error-derive",
|
"spl-program-error-derive",
|
||||||
@ -5183,7 +5208,7 @@ checksum = "70a0f06ac7f23dc0984931b1fe309468f14ea58e32660439c1cef19456f5d0e3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
@ -5198,7 +5223,7 @@ checksum = "d9c10f3483e48679619c76598d4e4aebb955bc49b0a5cc63323afbf44135c9bf"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
@ -5222,7 +5247,7 @@ checksum = "c0b788a8c34a917b68b4ed2cdec255d03cc09ccba21545dac39c08a97fce640f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"num-derive",
|
"num-derive 0.4.2",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
|
@ -22,6 +22,7 @@ solana-program = "2.0"
|
|||||||
solana-sdk = "2.0"
|
solana-sdk = "2.0"
|
||||||
spl-associated-token-account = "5.0"
|
spl-associated-token-account = "5.0"
|
||||||
spl-token = "6.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 = { version = "1.40", features = ["macros", "rt-multi-thread", "fs"] } # this can be "full"
|
||||||
tokio-stream = { version = "0.1", features = ["sync"] }
|
tokio-stream = { version = "0.1", features = ["sync"] }
|
||||||
# sgx poc dependencies
|
# sgx poc dependencies
|
||||||
|
133
src/solana.rs
133
src/solana.rs
@ -1,5 +1,10 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::{grpc::challenge::Keys, persistence::KeysFile};
|
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_client::nonblocking::rpc_client::RpcClient;
|
||||||
use solana_program::program_pack::Pack;
|
use solana_program::program_pack::Pack;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
@ -127,40 +132,48 @@ impl TryFrom<KeysFile> for SolClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wait_for_enough_sol(client: &RpcClient, pubkey: &Pubkey) {
|
async fn create_token(client: &RpcClient, payer_keypair: &Keypair) -> Pubkey {
|
||||||
println!("Waiting for at least 0.01 SOL in address {pubkey}");
|
// #1 top up the payer
|
||||||
loop {
|
println!("Waiting for at least 0.01 SOL in address {}", payer_keypair.pubkey());
|
||||||
match client.get_balance(pubkey).await {
|
while !has_enough_lamports(client, &payer_keypair.pubkey(), 10_000_000).await {
|
||||||
Ok(balance) => {
|
|
||||||
println!("Got {balance} lamports.");
|
|
||||||
if balance > 10_000_000 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!("Could not get balance: {e:?}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sleep(Duration::from_secs(30)).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 create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey {
|
async fn has_enough_lamports(client: &RpcClient, pubkey: &Pubkey, threshold: u64) -> bool {
|
||||||
loop {
|
match client.get_balance(pubkey).await {
|
||||||
wait_for_enough_sol(client, &keypair.pubkey()).await;
|
Ok(balance) => {
|
||||||
match create_token_int(client, keypair).await {
|
println!("{pubkey} needs {threshold} and has {balance}");
|
||||||
None => sleep(Duration::from_secs(30)).await,
|
balance >= threshold
|
||||||
Some(pubkey) => {
|
}
|
||||||
println!("Mint created: {pubkey}");
|
Err(e) => {
|
||||||
return pubkey;
|
println!("Could not get balance: {e:?}");
|
||||||
}
|
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 mint_keypair = Keypair::new();
|
||||||
let payer = Keypair::from_base58_string(&keypair.to_base58_string());
|
|
||||||
let mint_rent = client
|
let mint_rent = client
|
||||||
.get_minimum_balance_for_rent_exemption(Mint::LEN)
|
.get_minimum_balance_for_rent_exemption(Mint::LEN)
|
||||||
.await
|
.await
|
||||||
@ -168,7 +181,7 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
|||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
let create_mint_account_ix = system_instruction::create_account(
|
let create_mint_account_ix = system_instruction::create_account(
|
||||||
&payer.pubkey(),
|
&payer_keypair.pubkey(),
|
||||||
&mint_keypair.pubkey(),
|
&mint_keypair.pubkey(),
|
||||||
mint_rent,
|
mint_rent,
|
||||||
Mint::LEN as u64,
|
Mint::LEN as u64,
|
||||||
@ -176,7 +189,7 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
|||||||
);
|
);
|
||||||
|
|
||||||
let init_mint_ix =
|
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}"))
|
.map_err(|e| println!("Can't initialize mint: {e}"))
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
@ -185,10 +198,11 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| println!("Can't get latest blockhash: {e}"))
|
.map_err(|e| println!("Can't get latest blockhash: {e}"))
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
let tx = Transaction::new_signed_with_payer(
|
let tx = Transaction::new_signed_with_payer(
|
||||||
&[create_mint_account_ix, init_mint_ix],
|
&[create_mint_account_ix, init_mint_ix],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer_keypair.pubkey()),
|
||||||
&[&payer, &mint_keypair],
|
&[&payer_keypair, &mint_keypair],
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -202,3 +216,64 @@ async fn create_token_int(client: &RpcClient, keypair: &Keypair) -> Option<Pubke
|
|||||||
})
|
})
|
||||||
.ok()
|
.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