Skip to content

Commit

Permalink
wip: working example for multithreading (#58)
Browse files Browse the repository at this point in the history
* wip: working example for multithreading

* rebased with main

* cargo fmt

* added types for Arc Signer and Provider, added view function support for multi-thread
  • Loading branch information
jaswinder6991 authored May 23, 2024
1 parent 422bd6b commit c7628e3
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 15 deletions.
68 changes: 68 additions & 0 deletions near-accounts/examples/multi-thread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use near_accounts::Account;
use near_crypto::{InMemorySigner, SecretKey};
use near_primitives::{types::Gas, views::FinalExecutionOutcomeViewEnum};
use near_providers::JsonRpcProvider;
use std::sync::Arc;
mod utils;
use near_primitives::types::{AccountId, Balance};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();

// Initialization and user inputs as before

let signer_account_id: AccountId = "near-api-rs.testnet".parse::<AccountId>()?;
let signer_secret_key = "ed25519:29nYmQCZMsQeYtztXZzm57ayQt2uBHXdn2SAjK4ccMGSQaNUFNJ7Aoteno81eKTex9cGBbk1FuDuqJRsdzx34xDY".parse::<SecretKey>()?;

let provider = Arc::new(JsonRpcProvider::new("https://rpc.testnet.near.org"));
//let provider = JsonRpcProvider::new("https://rpc.testnet.near.org");
let signer = Arc::new(InMemorySigner::from_secret_key(
signer_account_id.clone(),
signer_secret_key,
));
let account = Account::new(signer_account_id, signer.clone(), provider.clone());

let contract_id: AccountId = "contract.near-api-rs.testnet".parse::<AccountId>()?;

// This spawns a new asynchronous task to handle account creation
let handle = tokio::spawn(async move {
let method_name = "set_status".to_string();
let args_json = json!({"message": "working1"});

// Amount to transfer to the new account
let gas: Gas = 100_000_000_000_000; // Example amount in yoctoNEAR
let amount: Balance = 10_000_000_000_000_000_000_000; // Example amount in yoctoNEAR

let result = account
.function_call(&contract_id, method_name, args_json, gas, amount)
.await
.expect("Reason")
.transact()
.await;

match result {
Ok(res) => match &res.final_execution_outcome {
Some(FinalExecutionOutcomeViewEnum::FinalExecutionOutcome(outcome)) => {
println!("Final Execution outcome: {:#?}", outcome);
}
Some(FinalExecutionOutcomeViewEnum::FinalExecutionOutcomeWithReceipt(
outcome_receipt,
)) => {
println!(
"Final Execution outcome with receipt: {:#?}",
outcome_receipt
);
}
None => println!("No Final execution outcome."),
},
Err(err) => println!("Error: {:#?}", err),
}
});

// You can do more work here or wait for the handle if needed
handle.await?;

Ok(())
}
36 changes: 32 additions & 4 deletions near-accounts/examples/view_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ mod utils;
use near_primitives::types::AccountId;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();

async fn single_thread() -> Result<(), Box<dyn std::error::Error>> {
let contract_id: AccountId = "contract.near-api-rs.testnet".parse::<AccountId>()?;

let provider = Arc::new(JsonRpcProvider::new("https://rpc.testnet.near.org"));
Expand All @@ -22,3 +19,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

Ok(())
}

async fn multi_thread() -> Result<(), Box<dyn std::error::Error>> {
let contract_id: AccountId = "contract.near-api-rs.testnet".parse::<AccountId>()?;

let provider = Arc::new(JsonRpcProvider::new("https://rpc.testnet.near.org"));

let args_json = json!({"account_id": "contract.near-api-rs.testnet"});
let method_name = "get_status".to_string();

let handle = tokio::spawn(async move {
let result = view_function(provider, contract_id, method_name, args_json).await;
println!("response: {:#?}", result);
});

// You can do more work here or wait for the handle if needed
handle.await?;
Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();

println!("Running single thread view function...");
single_thread().await?;

println!("Running multi thread view function...");
multi_thread().await?;

Ok(())
}
25 changes: 14 additions & 11 deletions near-accounts/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ use serde_json::Value;
use std::ops::{Add, Mul, Sub};
use std::sync::Arc;

type ArcProviderSendSync = Arc<dyn Provider + Send + Sync>;
type ArcSignerSendSync = Arc<dyn Signer + Send + Sync>;

///This struct represent a Transaction Sender used specifically if you want to send transactions manually.
/// This gives user more control over how they want to send their transactions to the NEAR network for examples, asyn, sync or advanced.
/// It is only used by function_call method from Account for now to enable this flexibility.
#[derive(Clone)]
pub struct TransactionSender {
pub signed_transaction: SignedTransaction,
provider: Arc<dyn Provider>,
provider: ArcProviderSendSync,
}

impl TransactionSender {
Expand All @@ -40,7 +43,7 @@ impl TransactionSender {
/// # Returns
///
/// A new `Account` instance.
pub fn new(signed_transaction: SignedTransaction, provider: Arc<dyn Provider>) -> Self {
pub fn new(signed_transaction: SignedTransaction, provider: ArcProviderSendSync) -> Self {
Self {
signed_transaction,
provider,
Expand Down Expand Up @@ -112,8 +115,8 @@ impl TransactionSender {
/// Represents a NEAR account, encapsulating account ID, signer, and provider for blockchain interaction.
pub struct Account {
pub account_id: AccountId,
pub signer: Arc<dyn Signer>, // Use your Signer abstraction
pub provider: Arc<dyn Provider>, // Use your Provider abstraction
pub signer: ArcSignerSendSync, // Use your Signer abstraction
pub provider: ArcProviderSendSync, // Use your Provider abstraction
}

/// Represents the balance details of a NEAR account.
Expand All @@ -139,8 +142,8 @@ impl Account {
/// A new `Account` instance.
pub fn new(
account_id: AccountId,
signer: Arc<dyn Signer>,
provider: Arc<dyn Provider>,
signer: ArcSignerSendSync,
provider: ArcProviderSendSync,
) -> Self {
Self {
account_id,
Expand Down Expand Up @@ -457,7 +460,7 @@ impl Account {
///
/// A `Result` containing the result of the function call or an error if the operation fails.
pub async fn view_function(
provider: Arc<dyn Provider>,
provider: ArcProviderSendSync,
contract_id: AccountId,
method_name: String,
args: Value,
Expand Down Expand Up @@ -494,7 +497,7 @@ pub async fn view_function(
///
/// A `Result` containing the contract's state filtered by the specified prefix, or an error if the query fails.
pub async fn view_state(
provider: Arc<dyn Provider>,
provider: ArcProviderSendSync,
contract_id: AccountId,
prefix: Option<String>,
) -> Result<near_primitives::views::ViewStateResult, Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -526,7 +529,7 @@ pub async fn view_state(
///
/// A `Result` containing a list of access keys for the specified account, or an error if the operation fails.
pub async fn get_access_key(
provider: Arc<dyn Provider>,
provider: ArcProviderSendSync,
account_id: AccountId,
) -> Result<near_primitives::views::AccessKeyList, Box<dyn std::error::Error>> {
let query_request = QueryRequest::ViewAccessKeyList { account_id };
Expand All @@ -552,7 +555,7 @@ pub async fn get_access_key(
///
/// A `Result` containing the state of the specified account, or an error if the query fails.
pub async fn state(
provider: Arc<dyn Provider>,
provider: ArcProviderSendSync,
account_id: AccountId,
) -> Result<near_primitives::views::AccountView, Box<dyn std::error::Error>> {
let query_request = QueryRequest::ViewAccount { account_id };
Expand All @@ -578,7 +581,7 @@ pub async fn state(
///
/// A `Result` containing the balance details of the account, structured as `AccountBalance`, or an error if the query fails.
pub async fn get_account_balance(
provider: Arc<dyn Provider>,
provider: ArcProviderSendSync,
account_id: AccountId,
) -> Result<AccountBalance, Box<dyn std::error::Error>> {
// Assuming `experimental_protocol_config` and `state` are async functions you can call on the provider
Expand Down

0 comments on commit c7628e3

Please sign in to comment.