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 | ||||||
|  | |||||||
							
								
								
									
										131
									
								
								src/solana.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										131
									
								
								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()); | ||||||
|  |     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 { |     match client.get_balance(pubkey).await { | ||||||
|         Ok(balance) => { |         Ok(balance) => { | ||||||
|                 println!("Got {balance} lamports."); |             println!("{pubkey} needs {threshold} and has {balance}"); | ||||||
|                 if balance > 10_000_000 { |             balance >= threshold | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|         } |         } | ||||||
|         Err(e) => { |         Err(e) => { | ||||||
|             println!("Could not get balance: {e:?}"); |             println!("Could not get balance: {e:?}"); | ||||||
|             } |             false | ||||||
|         } |  | ||||||
|         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; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 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