diff --git a/indexer/Cargo.toml b/indexer/Cargo.toml index a9c3786..8051900 100644 --- a/indexer/Cargo.toml +++ b/indexer/Cargo.toml @@ -24,4 +24,5 @@ dotenv = "0.15.0" futures = "0.3" solana-transaction-status = "1.7.0" solana-sdk = "1.7.0" -itertools = "0.10.0" \ No newline at end of file +itertools = "0.10.0" +time ="0.3.0-alpha-2" \ No newline at end of file diff --git a/indexer/README.md b/indexer/README.md index d70d5ac..25c15e8 100644 --- a/indexer/README.md +++ b/indexer/README.md @@ -12,5 +12,5 @@ diesel migration redo ``` # Create DB ``` -diesel migration redo -``` \ No newline at end of file +diesel migration run +``` diff --git a/indexer/notes.md b/indexer/notes.md new file mode 100644 index 0000000..e1bff39 --- /dev/null +++ b/indexer/notes.md @@ -0,0 +1,26 @@ +# Error RPC limit rate +``` +{ + "jsonrpc": "2.0", + "error": { + "code": 429, + "message": "Too requests for a specific RPC call, contact your app developer or support@rpcpool.com." + }, + "id": 1 +} +``` +# getEpochInfo response +``` +{ + "jsonrpc": "2.0", + "result": { + "absoluteSlot": 61766440, + "blockHeight": 61223473, + "epoch": 142, + "slotIndex": 422440, + "slotsInEpoch": 432000, + "transactionCount": 354013845 + }, + "id": 1 +} +``` diff --git a/indexer/src/decode_solana.rs b/indexer/src/decode_solana.rs index 11f351a..34de5d4 100644 --- a/indexer/src/decode_solana.rs +++ b/indexer/src/decode_solana.rs @@ -1,46 +1,38 @@ -use solana_transaction_status::{EncodedTransaction,UiTransactionEncoding}; use solana_sdk; use solana_sdk::{ - program_utils::limited_deserialize, - transaction::Transaction, - pubkey::Pubkey, - system_instruction::SystemInstruction, - instruction::CompiledInstruction, + instruction::CompiledInstruction, program_utils::limited_deserialize, pubkey::Pubkey, + system_instruction::SystemInstruction, transaction::Transaction, }; - +use solana_transaction_status::{EncodedTransaction, UiTransactionEncoding}; //use regex::Error; use solana_sdk::instruction::InstructionError; //use core::panicking::assert_failed; - -pub fn decode_transaction(blob: &str, base_mode: &str) -> Option{ +pub fn decode_transaction(blob: &str, base_mode: &str) -> Option { let transaction = match base_mode { - "base64" => { - EncodedTransaction::Binary( - blob.to_string(), - UiTransactionEncoding::Base64, - ) - } - _ => panic!("not support other base") + "base64" => EncodedTransaction::Binary(blob.to_string(), UiTransactionEncoding::Base64), + _ => panic!("not support other base"), }; transaction.decode() } -pub fn decode_instruction_data(instruction: CompiledInstruction, account_keys: Vec) -> Option> { - let id:usize = instruction.program_id_index as usize; - let program_pubkey = account_keys[id]; +pub fn decode_instruction_data( + instruction: CompiledInstruction, + account_keys: Vec, +) -> Option> { + let id: usize = instruction.program_id_index as usize; + let program_pubkey = account_keys[id]; let si; if program_pubkey == solana_sdk::system_program::id() { - si = Some(limited_deserialize::(&instruction.data)); + si = Some(limited_deserialize::(&instruction.data)); si - } - else{ + } else { None } } -pub fn get_sol_transfer_in_transaction(transaction: Transaction) -> u128{ +pub fn get_sol_transfer_in_transaction(transaction: Transaction) -> u128 { /// Todo: Check transaction is success before add to result let mut sol_transfer = 0u128; let message = &transaction.message; @@ -52,70 +44,69 @@ pub fn get_sol_transfer_in_transaction(transaction: Transaction) -> u128{ //println!("program_pubkey: {:?}, system_program_id: {:?}",program_pubkey,system_program_id); /// Todo: Implement to get transfer in the Inner Instructions - if program_pubkey==system_program_id { + if program_pubkey == system_program_id { /// If this instruction is run by system program //println!("program_pubkey: {:?}, system_program_id: {:?}",program_pubkey,system_program_id); let data = &message.instructions[0].data; /// Decode instruction data let system_instruction = - limited_deserialize::(data); + limited_deserialize::(data); match system_instruction { Ok(si) => { match si { SystemInstruction::Transfer { lamports } => { - println!("Add lamports: {}, to sol_transfer: {}", lamports, sol_transfer); + //println!("Add lamports: {}, to sol_transfer: {}", lamports, sol_transfer); sol_transfer += lamports as u128; - }, - SystemInstruction::TransferWithSeed { lamports,from_seed,from_owner } => { - println!("Add lamports: {}, to sol_transfer: {}", lamports, sol_transfer); + } + SystemInstruction::TransferWithSeed { + lamports, + from_seed, + from_owner, + } => { + //println!("Add lamports: {}, to sol_transfer: {}", lamports, sol_transfer); sol_transfer += lamports as u128; - }, + } _ => continue, } - }, - _ => continue + } + _ => continue, }; } - } sol_transfer } - - - - - - - - #[cfg(test)] mod tests { #[test] fn test_decode_transfer() { let encode_trans = "AZkhMW7dbIZfg3bvFtC60K9u19pnj8RCvZZTv5C2FHB6pWM2HLKaBk/VjrGAnalO/u26tl85eD7T6n0LxqkimgIBAAEDClrNBKMsMKt9IZ8AiJwWnXOyVj1N+ZkcCh9K8GlRngvQbX6GZxfU+TTnG855FaE8v+EXQfNVQW+lbFylHELYQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAzhkJF3mQT9yv74RHe6sNTN9GnOgE9r9iaLbKF9z4oBAgIAAQwCAAAAwNRUBwAAAAA="; //let encode_trans = "AauO9UickwsDYNWMZH2+DpsvgRXaJ6uYHedM6uMIXvepOmuC/REtcq3yKbDyicCCaOoCQvaITXluMB83Mh52YQEBAAIGdxpKE4kvtsE/HVIYAFjMuYdVmfVSPQsDDyxNrnjnlm790TnNvRMZIWiMfldkdMVvqnPfFAA5+M4xfvuyR/xg3/Gm32WPol4nQOkIkxg3cLzqAY97RTRNCoyLLFuYoeNvDzgJ2D1NxLLY37ddnFlvb8p49JufrVov/d9MuWpR+6GFDy1uAqR6+CTQmradxC1wyyjL+iSft+5XudJWwSdi7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeYUXxaZrV1d1+JF9Txvwqnk/wzUGplyS8B/j2O6m1AECBAUBAgMCAgcAAwAAAAEABQIAAAwCAAAAmA8AAAAAAAA="; - let transaction = EncodedTransaction::Binary(encode_trans.to_string(), - UiTransactionEncoding::Base64, + let transaction = + EncodedTransaction::Binary(encode_trans.to_string(), UiTransactionEncoding::Base64); + println!( + "Decode Transaction {:#?}", + &transaction.decode().unwrap().message.instructions[0].data ); - println!("Decode Transaction {:#?}", &transaction.decode().unwrap().message.instructions[0].data); let data = &transaction.decode().unwrap().message.instructions[0].data; //if program_pubkey == solana_sdk::system_program::id() { let system_instruction = - limited_deserialize::(data); + limited_deserialize::(data); println!("Decode Intruction data: {:#?}", system_instruction); match system_instruction { - Ok(si) => { - match si { - SystemInstruction::Transfer { lamports } => assert_eq!(lamports, 123000000), - SystemInstruction::TransferWithSeed { lamports,from_seed,from_owner } => panic!("Not Transfer as expected"), - _ => panic!("Not Transfer as expected"), - } + Ok(si) => match si { + SystemInstruction::Transfer { lamports } => assert_eq!(lamports, 123000000), + SystemInstruction::TransferWithSeed { + lamports, + from_seed, + from_owner, + } => panic!("Not Transfer as expected"), + _ => panic!("Not Transfer as expected"), }, - _ => panic!("Cannot decode into system instruction") + _ => panic!("Cannot decode into system instruction"), }; } } diff --git a/indexer/src/lib.rs b/indexer/src/lib.rs index da43dab..69166d3 100644 --- a/indexer/src/lib.rs +++ b/indexer/src/lib.rs @@ -1,29 +1,33 @@ -pub mod schema; -pub mod models; pub mod decode_solana; +pub mod models; +pub mod schema; #[macro_use] extern crate diesel; extern crate dotenv; -use diesel::prelude::*; +use self::models::SolanaAddress; +use self::models::SolanaBlock; use diesel::pg::PgConnection; +use diesel::prelude::*; use dotenv::dotenv; use std::env; -use self::models::SolanaBlock; -use self::models::SolanaAddress; pub fn establish_connection() -> PgConnection { dotenv().ok(); - let database_url = env::var("DATABASE_URL") - .expect("DATABASE_URL must be set"); - PgConnection::establish(&database_url) - .expect(&format!("Error connecting to {}", database_url)) + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url)) } - -pub fn create_block_record(conn: &PgConnection, block_number: u128, timestamp: u128, transaction_number: u128, sol_transfer: u128, fee: u128) -> SolanaBlock { +pub fn create_block_record( + conn: &PgConnection, + block_number: u128, + timestamp: u128, + transaction_number: u128, + sol_transfer: u128, + fee: i128, +) -> SolanaBlock { use schema::solana_block; /// Todo: use all var in u128! @@ -41,7 +45,14 @@ pub fn create_block_record(conn: &PgConnection, block_number: u128, timestamp: u .expect("Error saving new record") } -pub fn create_address_record<'a>(conn: &PgConnection, block_number: u128, timestamp: u128, address: &'a str, is_new_create: bool, balance: u128) -> usize { +pub fn create_address_record<'a>( + conn: &PgConnection, + block_number: u128, + timestamp: u128, + address: &'a str, + is_new_create: bool, + balance: u128, +) -> usize { use schema::solana_address; /// Todo: use all var in u128! @@ -57,4 +68,4 @@ pub fn create_address_record<'a>(conn: &PgConnection, block_number: u128, timest .values(&new_record) .execute(conn) .expect("Error saving new record") -} \ No newline at end of file +} diff --git a/indexer/src/main.rs b/indexer/src/main.rs index ef88b16..af971fe 100644 --- a/indexer/src/main.rs +++ b/indexer/src/main.rs @@ -2,33 +2,34 @@ // use error_chain::error_chain; use serde::Deserialize; -use serde_json::{json, Value}; +use serde_json::{json, Error as SerdeJsonError, Value}; //use std::env; use reqwest::Client; use reqwest::Response; use std::error::Error; //use tokio_postgres::{NoTls}; -use std::process::Command; use regex::Regex; +use std::process::Command; //use tokio_postgres::{NoTls}; -use indexer::{establish_connection, create_block_record,create_address_record,}; use diesel::PgConnection; -use std::time::Duration; -use std::thread; use futures::future::try_join_all; -use indexer::decode_solana::{decode_transaction,decode_instruction_data,get_sol_transfer_in_transaction}; +use indexer::decode_solana::{ + decode_instruction_data, decode_transaction, get_sol_transfer_in_transaction, +}; +use indexer::{create_address_record, create_block_record, establish_connection}; use solana_sdk::{ + program_utils::limited_deserialize, pubkey::Pubkey, system_instruction::SystemInstruction, transaction::Transaction, - pubkey::Pubkey, - system_instruction::SystemInstruction, - program_utils::limited_deserialize, }; +use std::thread; +use std::time::Duration; //use indexer::schema::solana_address::columns::{is_new_create, address}; use itertools::izip; +use std::convert::TryFrom; type TypeTimeStamp = u128; type TypeBlockSlot = u128; -type TypeTokenUnit = u128; +type TypeTokenUnit = i128; type TypeBlockHash = String; type TypeTransactionStatusOk = String; type TypeAccountPublicAddress = Pubkey; @@ -37,7 +38,6 @@ type TypeErr = Option; type TypePostTokenBalances = serde_json::Value; type TypePreTokenBalances = serde_json::Value; - // Response of getBlock RPC #[derive(Deserialize, Debug)] pub struct BlockResponse { @@ -54,7 +54,6 @@ struct BlockResult { previousBlockhash: TypeBlockHash, rewards: Vec, transactions: Vec, - } #[derive(Deserialize, Debug)] @@ -67,8 +66,8 @@ struct BlockReward { #[derive(Deserialize, Debug)] struct BlockTransaction { - meta:TransactionMeta, - transaction:[String;2], + meta: TransactionMeta, + transaction: [String; 2], } #[derive(Deserialize, Debug)] @@ -82,19 +81,18 @@ struct TransactionMeta { preBalances: Vec, preTokenBalances: TypePreTokenBalances, status: TransactionStatus, - } #[derive(Deserialize, Debug)] struct TransactionStatus { - Ok: Option + Ok: Option, } #[derive(Deserialize, Debug)] struct EpochInfoResponse { jsonrpc: String, result: EpochInfo, - id: u64 + id: u64, } #[derive(Deserialize, Debug)] @@ -104,7 +102,7 @@ struct EpochInfo { epoch: u64, slotIndex: u64, slotsInEpoch: u64, - transactionCount: u64 + transactionCount: u64, } #[derive(Deserialize, Debug)] @@ -114,47 +112,81 @@ struct Account { is_new_create: bool, } +#[derive(Deserialize, Debug)] +struct ErrorResponse { + jsonrpc: String, + error: ErrorResult, + id: u64, +} + +#[derive(Deserialize, Debug)] +struct ErrorResult { + code: i64, + message: String, +} -async fn call_rpc(gist_body: &Value)->Result> { - //let uri = "https://api.devnet.solana.com/"; +async fn call_rpc(gist_body: &Value) -> Result> { + // let uri = "https://api.devnet.solana.com/"; let uri = "https://api.mainnet-beta.solana.com/"; - let response = Client::new() - .post(uri) - .json(gist_body) - .send().await?; + let response = Client::new().post(uri).json(gist_body).send().await?; Ok(response) } +fn is_rpc_response_error(response: &str) -> bool { + let error_response: Result = serde_json::from_str(&response); + match error_response { + Ok(error_response) => { + println!("Error: {:?}", error_response); + true + } + _ => false, + } +} // Get the info of current epoch -async fn get_current_epoch_info()->Result>{ +async fn get_current_epoch_info() -> Result> { let gist_body = json!({ - "jsonrpc": "2.0", - "method": "getEpochInfo", - "id": 1 - }); - let response = call_rpc(&gist_body).await?; + "jsonrpc": "2.0", + "method": "getEpochInfo", + "id": 1 + }); + + let response = call_rpc(&gist_body).await?.text().await?; + //println!("Text: {}", response); + + if !is_rpc_response_error(&response) { + let response = + serde_json::from_str(&response).expect("EpochInfo JSON was not well-formatted"); + Ok(response) + } else { + Err(format!("Cannot parse response getEpochInfo: {}", response).into()) + } //println!("response: {:?}",response); - let response: EpochInfoResponse = response.json().await?; - Ok(response) } -async fn get_block(block_height: u64)->Result>{ +async fn get_block(block_height: u64) -> Result> { let gist_body = json!({ - "jsonrpc": "2.0", - "method": "getConfirmedBlock", - "params": [block_height, "base64"], - "id": 1 - }); + "jsonrpc": "2.0", + "method": "getConfirmedBlock", + "params": [block_height, "base64"], + "id": 1 + }); // Call RPC - let response = call_rpc(&gist_body).await?; - //println!("getConfirmedBlock response: {:?}",&response.text().await); - - // Parse the response - let result: BlockResponse = response.json().await?; - Ok(result) + let response_text = call_rpc(&gist_body).await?.text().await?; + + if !is_rpc_response_error(&response_text) { + let response = serde_json::from_str(&response_text).expect( + &(format!( + "Block JSON was not well-formatted, block_height: {:?},Block content: {}", + block_height, response_text + )), + ); + Ok(response) + } else { + Err(format!("Cannot parse response getConfirmedBlock: {}", response_text).into()) + } } // fn get_account_from_string(line: &str) -> Option{ @@ -205,12 +237,14 @@ async fn get_block(block_height: u64)->Result>{ // } /// Using solana SDK for decode transaction -fn get_address_from_encoded_transaction(encoded_transaction: &String, base_mode: &str) -> Vec { - let transaction = decode_transaction(encoded_transaction,base_mode).unwrap(); +fn get_address_from_encoded_transaction( + encoded_transaction: &String, + base_mode: &str, +) -> Vec { + let transaction = decode_transaction(encoded_transaction, base_mode).unwrap(); transaction.message.account_keys } - // fn get_accounts_in_block(br: BlockResponse) -> Vec>{ // let transactions = br.result.transactions; // @@ -248,39 +282,43 @@ fn get_address_from_encoded_transaction(encoded_transaction: &String, base_mode: // // } - - - -fn store_into_solana_block(connection: &PgConnection, responses: &Vec){ +fn store_into_solana_block(connection: &PgConnection, responses: &Vec) { for response in responses { /// Prepare metrics let transaction_number = response.result.transactions.len(); let timestamp = response.result.blockTime; let block_number = response.result.parentSlot + 1; - let sol_transfer= get_sol_transfer_in_block(&response); - println!("Sum sol transfer:{}",sol_transfer); + let sol_transfer = get_sol_transfer_in_block(&response); + //println!("Sum sol transfer:{}", sol_transfer); let fee = get_fee_in_block(&response); - let post = create_block_record( - connection, + connection, block_number, timestamp, transaction_number as u128, sol_transfer, - fee); - println!("\nSaved block {} timestamp {} with transaction number {}",post.block_number, post.timestamp, post.transaction_number); + fee, + ); + println!( + "\nSaved block {} timestamp {} with transaction number {}", + post.block_number, post.timestamp, post.transaction_number + ); } - } -fn get_accounts_from_encoded_transaction(encoded_transaction: &String, base_mode: &str, postBalances: &Vec, preBalances: &Vec) -> Vec{ +fn get_accounts_from_encoded_transaction( + encoded_transaction: &String, + base_mode: &str, + postBalances: &Vec, + preBalances: &Vec, +) -> Vec { let mut accounts = Vec::new(); - let transaction = decode_transaction(encoded_transaction,base_mode).unwrap(); + let transaction = decode_transaction(encoded_transaction, base_mode).unwrap(); let addresses = transaction.message.account_keys; - for (address,post_balance,pre_balance) in izip!(addresses,postBalances,preBalances){ - let is_new_create = (*pre_balance == 0u128); - let account = Account{ + for (address, post_balance, pre_balance) in izip!(addresses, postBalances, preBalances) { + let is_new_create = (*pre_balance == 0i128); + let account = Account { address, balance: *post_balance as u64, is_new_create, @@ -291,13 +329,13 @@ fn get_accounts_from_encoded_transaction(encoded_transaction: &String, base_mode accounts } -fn get_accounts_in_block(br: &BlockResponse) -> Vec>{ +fn get_accounts_in_block(br: &BlockResponse) -> Vec> { let transactions = &br.result.transactions; let mut accounts_in_block = Vec::new(); // Each transaction - for transaction in transactions{ + for transaction in transactions { // Get encoded transaction and base mode let encoded_transaction = &transaction.transaction[0]; let base_mode = &transaction.transaction[1]; @@ -305,21 +343,26 @@ fn get_accounts_in_block(br: &BlockResponse) -> Vec>{ let preBalances = &transaction.meta.preBalances; // Get accounts for each transaction - let accounts = get_accounts_from_encoded_transaction(encoded_transaction, base_mode,postBalances,preBalances); - print!("{:?}\n",&accounts); + let accounts = get_accounts_from_encoded_transaction( + encoded_transaction, + base_mode, + postBalances, + preBalances, + ); + //print!("{:?}\n", &accounts); accounts_in_block.push(accounts); } accounts_in_block } -fn store_into_solana_address(connection: &PgConnection, responses: &Vec){ +fn store_into_solana_address(connection: &PgConnection, responses: &Vec) { for response in responses { /// Prepare metrics let timestamp = response.result.blockTime; let block_number = response.result.parentSlot + 1; let accounts_in_block = get_accounts_in_block(response); - for accounts_in_transaction in accounts_in_block{ - for account in accounts_in_transaction{ + for accounts_in_transaction in accounts_in_block { + for account in accounts_in_transaction { let address = "".to_string(); let post = create_address_record( @@ -328,25 +371,26 @@ fn store_into_solana_address(connection: &PgConnection, responses: &Vec Result<(), Box>{ - let response = get_block(current_block_height).await?; +async fn get_record_and_store_solana_db( + connection: &PgConnection, + current_block_height: u64, +) -> Result<(), Box> { + let response = get_block(current_block_height).await?; //println!("Current block: {:?}",response); let responses = Vec::from([response]); store_into_solana_block(&connection, &responses); @@ -354,14 +398,14 @@ async fn get_record_and_store_solana_db(connection: &PgConnection, current_block Ok(()) } -pub fn get_sol_transfer_in_block(response: &BlockResponse) -> u128{ +pub fn get_sol_transfer_in_block(response: &BlockResponse) -> u128 { /// Sum all sol in transactions let mut sol_transfer = 0u128; - for transaction in &response.result.transactions{ + for transaction in &response.result.transactions { let blob = &transaction.transaction[0]; - let base_mode = &transaction.transaction[1]; + let base_mode = &transaction.transaction[1]; /// Decode transaction - let decoded_trans = decode_transaction(blob,base_mode); + let decoded_trans = decode_transaction(blob, base_mode); if let Some(decoded_trans) = decoded_trans { sol_transfer += get_sol_transfer_in_transaction(decoded_trans); } @@ -370,19 +414,19 @@ pub fn get_sol_transfer_in_block(response: &BlockResponse) -> u128{ sol_transfer } -pub fn get_fee_in_block(response: &BlockResponse) -> u128{ +pub fn get_fee_in_block(response: &BlockResponse) -> i128 { /// Sum all sol in transactions - let mut fee = 0u128; - for transaction in &response.result.transactions{ + let mut fee = 0i128; + for transaction in &response.result.transactions { fee += transaction.meta.fee; } fee } - +/// Todo: add error handle and fix bugs #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<(), Box> { /// Number of block before current block will be indexed let block_number = 10; @@ -393,21 +437,22 @@ async fn main() -> Result<(), Box> { let epoch_info = get_current_epoch_info().await?; let mut current_block_height = epoch_info.result.absoluteSlot; + //For debug only + //let mut current_block_height = 82367546; + /// For debug only // let mut current_block_height = 60422367; // let response = get_block(current_block_height).await.unwrap(); // store_into_solana_block(&connection, Vec::from([response])); - println!("block height: {}", current_block_height); - /// Get block_number block data before current time // let responses = get_blocks(current_block_height,block_number).await?; // store_into_solana_block(&connection, responses); let mut next_block_height = current_block_height; let limit_single_RPC_per_10sec = 40; - let max_RPC_call = 8; + let max_RPC_call = 2; let margin_call = 1; /// Get block from current time loop { @@ -416,31 +461,41 @@ async fn main() -> Result<(), Box> { match epoch_info { Ok(epoch_info) => current_block_height = epoch_info.result.absoluteSlot, Err(error) => { - println!("Error cannot get epoch_info: {}",error); + println!("Error cannot get epoch_info: {}", error); continue; - }, + } } - /// Check if enough data is available - if next_block_height + max_RPC_call + margin_call < current_block_height{ - println!("Data available! Indexed block {}, on-chain confirmed block {}",next_block_height,current_block_height); - let mut threads:Vec<_> = Vec::new(); - for i in 0..max_RPC_call{ + if next_block_height + max_RPC_call + margin_call < current_block_height { + println!( + "Data available! Indexed block: {}, on-chain confirmed block: {}, new block: {}.", + next_block_height, + current_block_height, + current_block_height - next_block_height + ); + let mut threads: Vec<_> = Vec::new(); + for i in 0..max_RPC_call { let thread = get_record_and_store_solana_db(&connection, next_block_height); threads.push(thread); next_block_height += 1; } try_join_all(threads).await; /// To avoid limit single RPC call per 10 sec - thread::sleep(Duration::from_millis(10000/limit_single_RPC_per_10sec*max_RPC_call)); + let sleep_time_ms = (10000 + 1000) / limit_single_RPC_per_10sec * max_RPC_call; + println!("Sleep for {}ms", sleep_time_ms); + thread::sleep(Duration::from_millis( + (10000 + 1000) / limit_single_RPC_per_10sec * max_RPC_call, + )); + } else { + println!( + "Not enought new data yet, indexed block {}, current block {}, new block {}!", + next_block_height, + current_block_height, + current_block_height - next_block_height + ); + thread::sleep(Duration::from_millis(500)); } - else{ - println!("No new data!"); - thread::sleep(Duration::from_millis(200)); - } - - } /// Get address from block data @@ -450,6 +505,5 @@ async fn main() -> Result<(), Box> { // let accounts_in_block = get_accounts_in_block(br: BlockResponse); // } //print!("{:?}",responses); - Ok(()) -} \ No newline at end of file +}