Compare commits
	
		
			No commits in common. "f67146aa13677045b08f13baeb235f5a9f307a99" and "8226f03e7c37099d76aba33a38a3e74f3ac29762" have entirely different histories.
		
	
	
		
			f67146aa13
			...
			8226f03e7c
		
	
		
@ -2,7 +2,6 @@ use crate::persistence::{SealError, SealedFile};
 | 
				
			|||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use serde_with::{serde_as, TimestampSeconds};
 | 
					use serde_with::{serde_as, TimestampSeconds};
 | 
				
			||||||
use std::collections::{HashMap, HashSet};
 | 
					use std::collections::{HashMap, HashSet};
 | 
				
			||||||
use std::sync::atomic::{AtomicBool, Ordering};
 | 
					 | 
				
			||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
 | 
					use std::time::{Duration, SystemTime, UNIX_EPOCH};
 | 
				
			||||||
use tokio::sync::RwLock;
 | 
					use tokio::sync::RwLock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,7 +95,6 @@ pub struct State {
 | 
				
			|||||||
    nodes: RwLock<HashMap<IP, NodeInfo>>,
 | 
					    nodes: RwLock<HashMap<IP, NodeInfo>>,
 | 
				
			||||||
    conns: RwLock<HashSet<IP>>,
 | 
					    conns: RwLock<HashSet<IP>>,
 | 
				
			||||||
    timeout: u64,
 | 
					    timeout: u64,
 | 
				
			||||||
    is_minting: AtomicBool,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl State {
 | 
					impl State {
 | 
				
			||||||
@ -104,13 +102,7 @@ impl State {
 | 
				
			|||||||
        let mut nodes = HashMap::new();
 | 
					        let mut nodes = HashMap::new();
 | 
				
			||||||
        let my_info = NodeInfo::load();
 | 
					        let my_info = NodeInfo::load();
 | 
				
			||||||
        nodes.insert(my_ip.clone(), my_info);
 | 
					        nodes.insert(my_ip.clone(), my_info);
 | 
				
			||||||
        Self {
 | 
					        Self { my_ip, timeout, nodes: RwLock::new(nodes), conns: RwLock::new(HashSet::new()) }
 | 
				
			||||||
            my_ip,
 | 
					 | 
				
			||||||
            timeout,
 | 
					 | 
				
			||||||
            nodes: RwLock::new(nodes),
 | 
					 | 
				
			||||||
            conns: RwLock::new(HashSet::new()),
 | 
					 | 
				
			||||||
            is_minting: AtomicBool::new(false),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn add_conn(&self, ip: &str) {
 | 
					    pub async fn add_conn(&self, ip: &str) {
 | 
				
			||||||
@ -211,14 +203,6 @@ impl State {
 | 
				
			|||||||
        Duration::from_secs(self.timeout)
 | 
					        Duration::from_secs(self.timeout)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn is_minting(&self) -> bool {
 | 
					 | 
				
			||||||
        self.is_minting.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_err()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn release_minting(&self) {
 | 
					 | 
				
			||||||
        self.is_minting.store(false, Ordering::SeqCst);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn get_my_info(&self) -> NodeInfo {
 | 
					    pub async fn get_my_info(&self) -> NodeInfo {
 | 
				
			||||||
        let nodes = self.nodes.read().await;
 | 
					        let nodes = self.nodes.read().await;
 | 
				
			||||||
        nodes.get(&self.my_ip).cloned().unwrap_or(NodeInfo::new_empty())
 | 
					        nodes.get(&self.my_ip).cloned().unwrap_or(NodeInfo::new_empty())
 | 
				
			||||||
@ -261,8 +245,10 @@ impl State {
 | 
				
			|||||||
    pub async fn process_node_update(&self, (node_ip, node_info): (String, NodeInfo)) -> bool {
 | 
					    pub async fn process_node_update(&self, (node_ip, node_info): (String, NodeInfo)) -> bool {
 | 
				
			||||||
        let is_update_mine = node_ip.eq(&self.my_ip);
 | 
					        let is_update_mine = node_ip.eq(&self.my_ip);
 | 
				
			||||||
        let mut nodes = self.nodes.write().await;
 | 
					        let mut nodes = self.nodes.write().await;
 | 
				
			||||||
        let is_update_new =
 | 
					        let is_update_new = nodes
 | 
				
			||||||
            nodes.get(&node_ip).map(|curr_info| node_info.is_newer_than(curr_info)).unwrap_or(true);
 | 
					            .get(&node_ip)
 | 
				
			||||||
 | 
					            .map(|curr_info| node_info.is_newer_than(&curr_info))
 | 
				
			||||||
 | 
					            .unwrap_or(true);
 | 
				
			||||||
        if is_update_new {
 | 
					        if is_update_new {
 | 
				
			||||||
            println!("Inserting: {}, {}", node_ip, node_info.to_json());
 | 
					            println!("Inserting: {}, {}", node_ip, node_info.to_json());
 | 
				
			||||||
            let _ = nodes.insert(node_ip, node_info);
 | 
					            let _ = nodes.insert(node_ip, node_info);
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@ use crate::{datastore, datastore::State, solana::SolClient};
 | 
				
			|||||||
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
 | 
					use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
 | 
				
			||||||
use chrono::{DateTime, Utc};
 | 
					use chrono::{DateTime, Utc};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use serde_json::json;
 | 
					 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const HOMEPAGE: &str = include_str!("HOMEPAGE.md");
 | 
					const HOMEPAGE: &str = include_str!("HOMEPAGE.md");
 | 
				
			||||||
@ -67,20 +66,15 @@ async fn mint(
 | 
				
			|||||||
) -> impl Responder {
 | 
					) -> impl Responder {
 | 
				
			||||||
    let recipient = req.into_inner().wallet;
 | 
					    let recipient = req.into_inner().wallet;
 | 
				
			||||||
    state.increase_mint_requests().await;
 | 
					    state.increase_mint_requests().await;
 | 
				
			||||||
 | 
					    let result =
 | 
				
			||||||
 | 
					        web::block(move || sol_client.mint(&recipient).map_err(|e| e.to_string())).await.unwrap(); // TODO: check if this can get a BlockingError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if state.is_minting() {
 | 
					    match result {
 | 
				
			||||||
        return HttpResponse::TooManyRequests().json(json!({ "error": "already mint processing" }));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let mint_res = sol_client.mint(&recipient).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    state.release_minting();
 | 
					 | 
				
			||||||
    match mint_res {
 | 
					 | 
				
			||||||
        Ok(s) => {
 | 
					        Ok(s) => {
 | 
				
			||||||
            state.increase_mints().await;
 | 
					            state.increase_mints().await;
 | 
				
			||||||
            HttpResponse::Ok().json(json!({"signature": s}))
 | 
					            HttpResponse::Ok().body(format!(r#"{{" signature": "{s} "}}"#))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Err(e) => HttpResponse::InternalServerError().json(json!({ "error": e.to_string() })),
 | 
					        Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}" }}"#)),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
#![allow(dead_code)]
 | 
					#![allow(dead_code)]
 | 
				
			||||||
use crate::{grpc::challenge::Keys, persistence::KeysFile};
 | 
					use crate::{grpc::challenge::Keys, persistence::KeysFile};
 | 
				
			||||||
use solana_client::nonblocking::rpc_client::RpcClient;
 | 
					use solana_client::rpc_client::RpcClient;
 | 
				
			||||||
use solana_program::program_pack::Pack;
 | 
					use solana_program::program_pack::Pack;
 | 
				
			||||||
use solana_sdk::{
 | 
					use solana_sdk::{
 | 
				
			||||||
    pubkey::Pubkey, signature::keypair::Keypair, signer::Signer, system_instruction,
 | 
					    pubkey::Pubkey, signature::keypair::Keypair, signer::Signer, system_instruction,
 | 
				
			||||||
@ -28,7 +28,7 @@ pub struct SolClient {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl SolClient {
 | 
					impl SolClient {
 | 
				
			||||||
    pub async fn create_new_token() -> Self {
 | 
					    pub async fn create_new_token() -> Self {
 | 
				
			||||||
        let client = RpcClient::new(RPC_URL.to_string());
 | 
					        let client = RpcClient::new(RPC_URL);
 | 
				
			||||||
        let keypair = Keypair::new();
 | 
					        let keypair = Keypair::new();
 | 
				
			||||||
        let token = create_token(&client, &keypair).await;
 | 
					        let token = create_token(&client, &keypair).await;
 | 
				
			||||||
        Self { client, keypair, token }
 | 
					        Self { client, keypair, token }
 | 
				
			||||||
@ -42,10 +42,10 @@ impl SolClient {
 | 
				
			|||||||
        self.get_keys().into()
 | 
					        self.get_keys().into()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn mint(&self, recipient: &str) -> Result<String, Box<dyn std::error::Error>> {
 | 
					    pub fn mint(&self, recipient: &str) -> Result<String, Box<dyn std::error::Error>> {
 | 
				
			||||||
        use std::str::FromStr;
 | 
					        use std::str::FromStr;
 | 
				
			||||||
        let recipient = solana_sdk::pubkey::Pubkey::from_str(recipient)?;
 | 
					        let recipient = solana_sdk::pubkey::Pubkey::from_str(recipient)?;
 | 
				
			||||||
        let associated_token_address = self.create_token_account(&recipient).await?;
 | 
					        let associated_token_address = self.create_token_account(&recipient)?;
 | 
				
			||||||
        let mint_to_instruction = mint_to(
 | 
					        let mint_to_instruction = mint_to(
 | 
				
			||||||
            &spl_token::id(),
 | 
					            &spl_token::id(),
 | 
				
			||||||
            &self.token,
 | 
					            &self.token,
 | 
				
			||||||
@ -59,32 +59,32 @@ impl SolClient {
 | 
				
			|||||||
            &[mint_to_instruction],
 | 
					            &[mint_to_instruction],
 | 
				
			||||||
            Some(&self.keypair.pubkey()),
 | 
					            Some(&self.keypair.pubkey()),
 | 
				
			||||||
            &[&self.keypair],
 | 
					            &[&self.keypair],
 | 
				
			||||||
            self.client.get_latest_blockhash().await?,
 | 
					            self.client.get_latest_blockhash()?,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        let signature = self.client.send_and_confirm_transaction(&transaction).await?;
 | 
					        let signature = self.client.send_and_confirm_transaction(&transaction)?;
 | 
				
			||||||
        Ok(signature.to_string())
 | 
					        Ok(signature.to_string())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn create_token_account(
 | 
					    fn create_token_account(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        recipient: &Pubkey,
 | 
					        recipient: &Pubkey,
 | 
				
			||||||
    ) -> Result<Pubkey, Box<dyn std::error::Error>> {
 | 
					    ) -> Result<Pubkey, Box<dyn std::error::Error>> {
 | 
				
			||||||
        let address = get_associated_token_address(recipient, &self.token);
 | 
					        let address = get_associated_token_address(recipient, &self.token);
 | 
				
			||||||
        if self.client.get_account(&address).await.is_err() {
 | 
					        if self.client.get_account(&address).is_err() {
 | 
				
			||||||
            let create_token_account_instruction = create_associated_token_account(
 | 
					            let create_token_account_instruction = create_associated_token_account(
 | 
				
			||||||
                &self.keypair.pubkey(),
 | 
					                &self.keypair.pubkey(),
 | 
				
			||||||
                recipient,
 | 
					                recipient,
 | 
				
			||||||
                &self.token,
 | 
					                &self.token,
 | 
				
			||||||
                &spl_token::id(),
 | 
					                &spl_token::id(),
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            let recent_blockhash = self.client.get_latest_blockhash().await?;
 | 
					            let recent_blockhash = self.client.get_latest_blockhash()?;
 | 
				
			||||||
            let tx = Transaction::new_signed_with_payer(
 | 
					            let tx = Transaction::new_signed_with_payer(
 | 
				
			||||||
                &[create_token_account_instruction],
 | 
					                &[create_token_account_instruction],
 | 
				
			||||||
                Some(&self.keypair.pubkey()),
 | 
					                Some(&self.keypair.pubkey()),
 | 
				
			||||||
                &[&self.keypair],
 | 
					                &[&self.keypair],
 | 
				
			||||||
                recent_blockhash,
 | 
					                recent_blockhash,
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            self.client.send_and_confirm_transaction(&tx).await?;
 | 
					            self.client.send_and_confirm_transaction(&tx)?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(address)
 | 
					        Ok(address)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -114,7 +114,7 @@ impl TryFrom<Keys> for SolClient {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        let token = Pubkey::from_str(&keys.token_address)
 | 
					        let token = Pubkey::from_str(&keys.token_address)
 | 
				
			||||||
            .map_err(|_| "Could not parse wallet address.".to_string())?;
 | 
					            .map_err(|_| "Could not parse wallet address.".to_string())?;
 | 
				
			||||||
        Ok(Self { client: RpcClient::new(RPC_URL.to_string()), keypair, token })
 | 
					        Ok(Self { client: RpcClient::new(RPC_URL), keypair, token })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -131,7 +131,7 @@ async fn wait_for_sol(client: &RpcClient, pubkey: &Pubkey) {
 | 
				
			|||||||
    println!("Waiting to receive 0.01 SOL in address {pubkey}");
 | 
					    println!("Waiting to receive 0.01 SOL in address {pubkey}");
 | 
				
			||||||
    loop {
 | 
					    loop {
 | 
				
			||||||
        sleep(Duration::from_secs(30)).await;
 | 
					        sleep(Duration::from_secs(30)).await;
 | 
				
			||||||
        match client.get_balance(pubkey).await {
 | 
					        match client.get_balance(pubkey) {
 | 
				
			||||||
            Ok(balance) => {
 | 
					            Ok(balance) => {
 | 
				
			||||||
                println!("Got {balance} lamports.");
 | 
					                println!("Got {balance} lamports.");
 | 
				
			||||||
                if balance > 10_000_000 {
 | 
					                if balance > 10_000_000 {
 | 
				
			||||||
@ -148,7 +148,7 @@ async fn create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let mint_keypair = Keypair::new();
 | 
					    let mint_keypair = Keypair::new();
 | 
				
			||||||
    let payer = Keypair::from_base58_string(&keypair.to_base58_string());
 | 
					    let payer = Keypair::from_base58_string(&keypair.to_base58_string());
 | 
				
			||||||
    let mint_rent = client.get_minimum_balance_for_rent_exemption(Mint::LEN).await.unwrap();
 | 
					    let mint_rent = client.get_minimum_balance_for_rent_exemption(Mint::LEN).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let create_mint_account_ix = system_instruction::create_account(
 | 
					    let create_mint_account_ix = system_instruction::create_account(
 | 
				
			||||||
        &payer.pubkey(),
 | 
					        &payer.pubkey(),
 | 
				
			||||||
@ -162,7 +162,7 @@ async fn create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey {
 | 
				
			|||||||
        initialize_mint(&spl_token::id(), &mint_keypair.pubkey(), &payer.pubkey(), None, 9)
 | 
					        initialize_mint(&spl_token::id(), &mint_keypair.pubkey(), &payer.pubkey(), None, 9)
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let recent_blockhash = client.get_latest_blockhash().await.unwrap();
 | 
					    let recent_blockhash = client.get_latest_blockhash().unwrap();
 | 
				
			||||||
    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.pubkey()),
 | 
				
			||||||
@ -170,7 +170,7 @@ async fn create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey {
 | 
				
			|||||||
        recent_blockhash,
 | 
					        recent_blockhash,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let signature = client.send_and_confirm_transaction(&tx).await.unwrap();
 | 
					    let signature = client.send_and_confirm_transaction(&tx).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    println!("Mint created: {}", mint_keypair.pubkey());
 | 
					    println!("Mint created: {}", mint_keypair.pubkey());
 | 
				
			||||||
    println!("Transaction signature: {}", signature);
 | 
					    println!("Transaction signature: {}", signature);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user