Skip to content

Commit

Permalink
chore: add examples to repo (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
miraclx authored Dec 22, 2021
1 parent 3a2bde7 commit 34acf7d
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ near-chain-configs = "0.11.0"
near-jsonrpc-primitives = "0.11.0"

[dev-dependencies]
near-crypto = "0.11.0"
tokio = { version = "1.1", features = ["rt", "macros"] }

[features]
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ let tx_status = mainnet_client.call(tx_status_request).await?;
println!("{:?}", tx_status);
```

Check out [`the examples folder`](https://github.com/near/near-jsonrpc-client-rs/tree/examples) for a comprehensive list of helpful demos. You can run the examples with `cargo`. For example: `cargo run --example view_account`.

For all intents and purposes, the predefined structures in `methods` should suffice, if you find that they
don't or you crave extra flexibility, well, you can opt in to use the generic constructor `methods::any()` with the `any` feature flag.

Expand Down
43 changes: 43 additions & 0 deletions examples/access_keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
use near_primitives::types::BlockReference;

mod utils;

fn indent(indentation: usize, s: String) -> String {
let mut lines = s.split_inclusive("\n");
let mut r = lines.next().unwrap().to_string();
for l in lines {
r.push_str(&" ".repeat(indentation));
r.push_str("> ");
r.push_str(l);
}
r
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://rpc.mainnet.near.org");

let account_id = utils::input("Enter the Account ID whose keys we're listing: ")?.parse()?;

let access_key_query_response = client
.call(methods::query::RpcQueryRequest {
block_reference: BlockReference::latest(),
request: near_primitives::views::QueryRequest::ViewAccessKeyList { account_id },
})
.await?;

if let QueryResponseKind::AccessKeyList(response) = access_key_query_response.kind {
for access_key in response.keys {
println!("🔑[{}]", access_key.public_key);
println!(" \u{21b3} nonce: {}", access_key.access_key.nonce);
println!(
" \u{21b3} permission: {}",
indent(18, format!("{:#?}", access_key.access_key.permission))
);
}
}

Ok(())
}
47 changes: 47 additions & 0 deletions examples/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use near_jsonrpc_client::errors::{
JsonRpcError::ServerError, JsonRpcServerError::ResponseStatusError,
JsonRpcServerResponseStatusError::Unauthorized,
};
use near_jsonrpc_client::{auth, methods, JsonRpcClient};
use near_primitives::types::{BlockReference, Finality};

async fn unauthorized() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://testnet.rpc.near.dev/");

let response = client.call(methods::status::RpcStatusRequest).await;

debug_assert!(
matches!(
response,
Err(ServerError(ResponseStatusError(Unauthorized)))
),
"got {:?}",
response
);

Ok(())
}

async fn authorized() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://testnet.rpc.near.dev/")
.auth(auth::ApiKey::new("399ba741-e939-4ffa-8c3c-306ec36fa8de"));

let request = methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
};

let response = client.call(request).await?;

println!("{:?}", response);

Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
unauthorized().await?;

authorized().await?;

Ok(())
}
98 changes: 98 additions & 0 deletions examples/contract_change_method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
use near_jsonrpc_primitives::types::transactions::TransactionInfo;
use near_primitives::transaction::{Action, FunctionCallAction, Transaction};
use near_primitives::types::BlockReference;

use serde_json::json;
use tokio::time;

mod utils;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://rpc.testnet.near.org");

let signer_account_id = utils::input("Enter the signer Account ID: ")?.parse()?;
let signer_secret_key = utils::input("Enter the signer's private key: ")?.parse()?;

let signer = near_crypto::InMemorySigner::from_secret_key(signer_account_id, signer_secret_key);

let access_key_query_response = client
.call(methods::query::RpcQueryRequest {
block_reference: BlockReference::latest(),
request: near_primitives::views::QueryRequest::ViewAccessKey {
account_id: signer.account_id.clone(),
public_key: signer.public_key.clone(),
},
})
.await?;

let current_nonce = match access_key_query_response.kind {
QueryResponseKind::AccessKey(access_key) => access_key.nonce,
_ => Err("failed to extract current nonce")?,
};

let other_account = utils::input("Enter the account to be rated: ")?;
let rating = utils::input("Enter a rating: ")?.parse::<f32>()?;

let transaction = Transaction {
signer_id: signer.account_id.clone(),
public_key: signer.public_key.clone(),
nonce: current_nonce + 1,
receiver_id: "nosedive.testnet".parse()?,
block_hash: access_key_query_response.block_hash,
actions: vec![Action::FunctionCall(FunctionCallAction {
method_name: "rate".to_string(),
args: json!({
"account_id": other_account,
"rating": rating,
})
.to_string()
.into_bytes(),
gas: 100_000_000_000_000, // 100 TeraGas
deposit: 0,
})],
};

let request = methods::broadcast_tx_async::RpcBroadcastTxAsyncRequest {
signed_transaction: transaction.sign(&signer),
};

let sent_at = time::Instant::now();
let tx_hash = client.call(request).await.unwrap();

loop {
let response = client
.call(methods::tx::RpcTransactionStatusRequest {
transaction_info: TransactionInfo::TransactionId {
hash: tx_hash,
account_id: signer.account_id.clone(),
},
})
.await;
let received_at = time::Instant::now();
let delta = (received_at - sent_at).as_secs();

if delta > 60 {
Err("time limit exceeded for the transaction to be recognized")?;
}

match response {
Err(err) => match err.handler_error()? {
methods::tx::RpcTransactionError::UnknownTransaction { .. } => {
time::sleep(time::Duration::from_secs(2)).await;
continue;
}
err => Err(err)?,
},
Ok(response) => {
println!("response gotten after: {}s", delta);
println!("response: {:#?}", response);
break;
}
}
}

Ok(())
}
33 changes: 33 additions & 0 deletions examples/contract_view_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
use near_primitives::types::{AccountId, BlockReference, Finality};
use near_primitives::views::QueryRequest;

mod utils;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://rpc.testnet.near.org");

let contract_id: AccountId =
utils::input("Enter the contract whose code we're downloading: ")?.parse()?;

let request = methods::query::RpcQueryRequest {
block_reference: BlockReference::Finality(Finality::Final),
request: QueryRequest::ViewCode {
account_id: contract_id.clone(),
},
};

let response = client.call(request).await?;

if let QueryResponseKind::ViewCode(result) = response.kind {
let path = format!("/tmp/{}.wasm", contract_id);
println!("⚙️ [{}]", contract_id);
println!("🏋 size: {} bytes", result.code.len());
std::fs::write(&path, result.code)?;
println!("💾 saved to: {}", path);
}

Ok(())
}
46 changes: 46 additions & 0 deletions examples/contract_view_method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
use near_primitives::types::{BlockReference, Finality, FunctionArgs};
use near_primitives::views::QueryRequest;

use serde::Deserialize;
use serde_json::{from_slice, json};

mod utils;

#[derive(Debug, Deserialize)]
pub struct AccountStatus {
pub rating: f32,
pub given: u64,
pub received: u64,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://rpc.testnet.near.org");

let account_id = utils::input("Enter the account to view: ")?;

let request = methods::query::RpcQueryRequest {
block_reference: BlockReference::Finality(Finality::Final),
request: QueryRequest::CallFunction {
account_id: "nosedive.testnet".parse()?,
method_name: "status".to_string(),
args: FunctionArgs::from(
json!({
"account_id": account_id,
})
.to_string()
.into_bytes(),
),
},
};

let response = client.call(request).await?;

if let QueryResponseKind::CallResult(result) = response.kind {
println!("{:#?}", from_slice::<AccountStatus>(&result.result)?);
}

Ok(())
}
17 changes: 17 additions & 0 deletions examples/query_final_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_primitives::types::{BlockReference, Finality};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://rpc.testnet.near.org");

let request = methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
};

let response = client.call(request).await?;

println!("{:?}", response);

Ok(())
}
15 changes: 15 additions & 0 deletions examples/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#![allow(unused)]

use std::io::{self, Write};

pub fn input(query: &str) -> io::Result<String> {
print!("{}", query);
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(input.trim().to_owned())
}

fn main() {
panic!("not a binary")
}
26 changes: 26 additions & 0 deletions examples/view_account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
use near_primitives::types::{AccountId, BlockReference, Finality};
use near_primitives::views::QueryRequest;

mod utils;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = JsonRpcClient::connect("https://rpc.mainnet.near.org");

let account_id: AccountId = utils::input("Enter an Account ID to lookup: ")?.parse()?;

let request = methods::query::RpcQueryRequest {
block_reference: BlockReference::Finality(Finality::Final),
request: QueryRequest::ViewAccount { account_id },
};

let response = client.call(request).await?;

if let QueryResponseKind::ViewAccount(result) = response.kind {
println!("{:#?}", result);
}

Ok(())
}

0 comments on commit 34acf7d

Please sign in to comment.