diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 835c3da9..4acb3570 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -9,13 +9,16 @@ anyhow = "1.0" borsh = "0.10" maplit = "1.0" near-units = "0.2.0" +near-jsonrpc-primitives = "0.17" +near-primitives = "0.17" serde = "1.0" serde_with = "1" serde_json = { version = "1.0" } tokio = { version = "1.10.0", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3.5", features = ["env-filter"] } -workspaces = { path = "../workspaces" } +workspaces = { path = "../workspaces", features = ["experimental"] } + [[example]] name = "async_transaction" @@ -49,6 +52,34 @@ path = "src/croncat.rs" name = "various_queries" path = "src/various_queries.rs" +[[example]] +name = "genesis_config" +path = "src/genesis_config.rs" + +[[example]] +name = "validators_ordered" +path = "src/validators_ordered.rs" + +[[example]] +name = "protocol_config" +path = "src/protocol_config.rs" + +[[example]] +name = "changes_in_block" +path = "src/changes_in_block.rs" + +[[example]] +name = "changes" +path = "src/changes.rs" + +[[example]] +name = "receipt" +path = "src/receipt.rs" + +[[example]] +name = "tx_status" +path = "src/tx_status.rs" + [[example]] name = "noop" path = "src/noop.rs" diff --git a/examples/src/changes.rs b/examples/src/changes.rs new file mode 100644 index 00000000..edd8b3d7 --- /dev/null +++ b/examples/src/changes.rs @@ -0,0 +1,42 @@ +use near_primitives::{types::BlockReference, views::StateChangesRequestView}; +use serde_json::json; + +const STATUS_MSG_WASM_FILEPATH: &str = "./examples/res/status_message.wasm"; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + let wasm = std::fs::read(STATUS_MSG_WASM_FILEPATH)?; + let contract = worker.dev_deploy(&wasm).await?; + + let outcome = contract + .call("set_status") + .args_json(json!({ + "message": "hello_world", + })) + .transact() + .await?; + + let block_ref = { + let hash = near_primitives::hash::CryptoHash(outcome.outcome().block_hash.0); + BlockReference::BlockId(near_primitives::types::BlockId::Hash(hash)) + }; + + let state_changes = { + StateChangesRequestView::ContractCodeChanges { + account_ids: vec![contract.id().clone()], + } + }; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let res = worker.changes(block_ref, state_changes).await?; + + // Example output: + // + // StateChangesInBlock RpcStateChangesInBlockResponse { + // block_hash: 5SnL82tfQX1NtsSuqU5334ThZxM1B5KkUWUbeeMvVNRH, + // changes: [], + // } + println!("StateChangesInBlock {res:#?}"); + Ok(()) +} diff --git a/examples/src/changes_in_block.rs b/examples/src/changes_in_block.rs new file mode 100644 index 00000000..f2adb074 --- /dev/null +++ b/examples/src/changes_in_block.rs @@ -0,0 +1,52 @@ +use near_primitives::types::BlockReference; +use serde_json::json; + +const STATUS_MSG_WASM_FILEPATH: &str = "./examples/res/status_message.wasm"; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + let wasm = std::fs::read(STATUS_MSG_WASM_FILEPATH)?; + let contract = worker.dev_deploy(&wasm).await?; + + let outcome = contract + .call("set_status") + .args_json(json!({ + "message": "hello_world", + })) + .transact() + .await?; + + let block_ref = { + let hash = near_primitives::hash::CryptoHash(outcome.outcome().block_hash.0); + BlockReference::BlockId(near_primitives::types::BlockId::Hash(hash)) + }; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let res = worker.changes_in_block(block_ref).await?; + + // Example output: + // + // StateChangesInBlockByType RpcStateChangesInBlockByTypeResponse { + // block_hash: 7ifRdyBsJMXVyp8zw8uGdBMaRShiXuD6yghrp66jqrst, + // changes: [ + // AccountTouched { + // account_id: AccountId( + // "dev-20230822100117-44171728969098", + // ), + // }, + // AccessKeyTouched { + // account_id: AccountId( + // "dev-20230822100117-44171728969098", + // ), + // }, + // DataTouched { + // account_id: AccountId( + // "dev-20230822100117-44171728969098", + // ), + // }, + // ], + // } + println!("StateChangesInBlockByType {res:#?}"); + Ok(()) +} diff --git a/examples/src/genesis_config.rs b/examples/src/genesis_config.rs new file mode 100644 index 00000000..f3b81ad8 --- /dev/null +++ b/examples/src/genesis_config.rs @@ -0,0 +1,87 @@ +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let genesis_config = worker.genesis_config().await?; + + // Example output: + // + // GenesisConfig GenesisConfig { + // protocol_version: 60, + // genesis_time: 2023-08-22T10:05:32.129104Z, + // chain_id: "test-chain-5oKXo", + // genesis_height: 0, + // num_block_producer_seats: 50, + // num_block_producer_seats_per_shard: [ + // 50, + // ], + // avg_hidden_validator_seats_per_shard: [ + // 0, + // ], + // dynamic_resharding: false, + // protocol_upgrade_stake_threshold: Ratio { + // numer: 4, + // denom: 5, + // }, + // epoch_length: 500, + // gas_limit: 1000000000000000, + // min_gas_price: 100000000, + // max_gas_price: 10000000000000000000000, + // block_producer_kickout_threshold: 90, + // chunk_producer_kickout_threshold: 90, + // online_min_threshold: Ratio { + // numer: 9, + // denom: 10, + // }, + // online_max_threshold: Ratio { + // numer: 99, + // denom: 100, + // }, + // gas_price_adjustment_rate: Ratio { + // numer: 1, + // denom: 100, + // }, + // validators: [ + // AccountInfo { + // account_id: AccountId( + // "test.near", + // ), + // public_key: ed25519:4Q4fpCWcsVFj3WT7xkCt45qwW84hskFB4SRMHAQfuCne, + // amount: 50000000000000000000000000000000, + // }, + // ], + // transaction_validity_period: 100, + // protocol_reward_rate: Ratio { + // numer: 1, + // denom: 10, + // }, + // max_inflation_rate: Ratio { + // numer: 1, + // denom: 20, + // }, + // total_supply: 2050000000000000000000000000000000, + // num_blocks_per_year: 31536000, + // protocol_treasury_account: AccountId( + // "test.near", + // ), + // fishermen_threshold: 10000000000000000000000000, + // minimum_stake_divisor: 10, + // shard_layout: V0( + // ShardLayoutV0 { + // num_shards: 1, + // version: 0, + // }, + // ), + // num_chunk_only_producer_seats: 300, + // minimum_validators_per_shard: 1, + // max_kickout_stake_perc: 100, + // minimum_stake_ratio: Ratio { + // numer: 1, + // denom: 6250, + // }, + // use_production_config: false, + // } + println!("GenesisConfig {:#?}", genesis_config); + Ok(()) +} diff --git a/examples/src/protocol_config.rs b/examples/src/protocol_config.rs new file mode 100644 index 00000000..ca555d9c --- /dev/null +++ b/examples/src/protocol_config.rs @@ -0,0 +1,292 @@ +const STATUS_MSG_WASM_FILEPATH: &str = "./examples/res/status_message.wasm"; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + let wasm = std::fs::read(STATUS_MSG_WASM_FILEPATH)?; + let contract = worker.dev_deploy(&wasm).await?; + + let outcome = contract + .call("set_status") + .args_json(serde_json::json!({ + "message": "hello_world", + })) + .transact() + .await?; + + let block_reference = { + let hash = outcome.outcome().block_hash; + near_primitives::types::BlockReference::BlockId(near_primitives::types::BlockId::Hash( + near_primitives::hash::CryptoHash(hash.0), + )) + }; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let protocol_config = worker.protocol_config(block_reference).await?; + + // Example output: + // + // ProtocolConfig ProtocolConfigView { + // protocol_version: 60, + // genesis_time: 2023-08-22T10:07:46.377793Z, + // chain_id: "test-chain-trbrQ", + // genesis_height: 0, + // num_block_producer_seats: 50, + // num_block_producer_seats_per_shard: [ + // 50, + // ], + // avg_hidden_validator_seats_per_shard: [ + // 0, + // ], + // dynamic_resharding: false, + // protocol_upgrade_stake_threshold: Ratio { + // numer: 4, + // denom: 5, + // }, + // epoch_length: 500, + // gas_limit: 1000000000000000, + // min_gas_price: 100000000, + // max_gas_price: 10000000000000000000000, + // block_producer_kickout_threshold: 90, + // chunk_producer_kickout_threshold: 90, + // online_min_threshold: Ratio { + // numer: 9, + // denom: 10, + // }, + // online_max_threshold: Ratio { + // numer: 99, + // denom: 100, + // }, + // gas_price_adjustment_rate: Ratio { + // numer: 1, + // denom: 100, + // }, + // runtime_config: RuntimeConfigView { + // storage_amount_per_byte: 10000000000000000000, + // transaction_costs: RuntimeFeesConfigView { + // action_receipt_creation_config: Fee { + // send_sir: 108059500000, + // send_not_sir: 108059500000, + // execution: 108059500000, + // }, + // data_receipt_creation_config: DataReceiptCreationConfigView { + // base_cost: Fee { + // send_sir: 36486732312, + // send_not_sir: 36486732312, + // execution: 36486732312, + // }, + // cost_per_byte: Fee { + // send_sir: 17212011, + // send_not_sir: 17212011, + // execution: 17212011, + // }, + // }, + // action_creation_config: ActionCreationConfigView { + // create_account_cost: Fee { + // send_sir: 3850000000000, + // send_not_sir: 3850000000000, + // execution: 3850000000000, + // }, + // deploy_contract_cost: Fee { + // send_sir: 184765750000, + // send_not_sir: 184765750000, + // execution: 184765750000, + // }, + // deploy_contract_cost_per_byte: Fee { + // send_sir: 6812999, + // send_not_sir: 6812999, + // execution: 64572944, + // }, + // function_call_cost: Fee { + // send_sir: 2319861500000, + // send_not_sir: 2319861500000, + // execution: 2319861500000, + // }, + // function_call_cost_per_byte: Fee { + // send_sir: 2235934, + // send_not_sir: 2235934, + // execution: 2235934, + // }, + // transfer_cost: Fee { + // send_sir: 115123062500, + // send_not_sir: 115123062500, + // execution: 115123062500, + // }, + // stake_cost: Fee { + // send_sir: 141715687500, + // send_not_sir: 141715687500, + // execution: 102217625000, + // }, + // add_key_cost: AccessKeyCreationConfigView { + // full_access_cost: Fee { + // send_sir: 101765125000, + // send_not_sir: 101765125000, + // execution: 101765125000, + // }, + // function_call_cost: Fee { + // send_sir: 102217625000, + // send_not_sir: 102217625000, + // execution: 102217625000, + // }, + // function_call_cost_per_byte: Fee { + // send_sir: 1925331, + // send_not_sir: 1925331, + // execution: 1925331, + // }, + // }, + // delete_key_cost: Fee { + // send_sir: 94946625000, + // send_not_sir: 94946625000, + // execution: 94946625000, + // }, + // delete_account_cost: Fee { + // send_sir: 147489000000, + // send_not_sir: 147489000000, + // execution: 147489000000, + // }, + // delegate_cost: Fee { + // send_sir: 200000000000, + // send_not_sir: 200000000000, + // execution: 200000000000, + // }, + // }, + // storage_usage_config: StorageUsageConfigView { + // num_bytes_account: 100, + // num_extra_bytes_record: 40, + // }, + // burnt_gas_reward: Ratio { + // numer: 3, + // denom: 10, + // }, + // pessimistic_gas_price_inflation_ratio: Ratio { + // numer: 103, + // denom: 100, + // }, + // }, + // wasm_config: VMConfigView { + // ext_costs: ExtCostsConfigView { + // base: 264768111, + // contract_loading_base: 35445963, + // contract_loading_bytes: 216750, + // read_memory_base: 2609863200, + // read_memory_byte: 3801333, + // write_memory_base: 2803794861, + // write_memory_byte: 2723772, + // read_register_base: 2517165186, + // read_register_byte: 98562, + // write_register_base: 2865522486, + // write_register_byte: 3801564, + // utf8_decoding_base: 3111779061, + // utf8_decoding_byte: 291580479, + // utf16_decoding_base: 3543313050, + // utf16_decoding_byte: 163577493, + // sha256_base: 4540970250, + // sha256_byte: 24117351, + // keccak256_base: 5879491275, + // keccak256_byte: 21471105, + // keccak512_base: 5811388236, + // keccak512_byte: 36649701, + // ripemd160_base: 853675086, + // ripemd160_block: 680107584, + // ed25519_verify_base: 210000000000, + // ed25519_verify_byte: 9000000, + // ecrecover_base: 278821988457, + // log_base: 3543313050, + // log_byte: 13198791, + // storage_write_base: 64196736000, + // storage_write_key_byte: 70482867, + // storage_write_value_byte: 31018539, + // storage_write_evicted_byte: 32117307, + // storage_read_base: 56356845750, + // storage_read_key_byte: 30952533, + // storage_read_value_byte: 5611005, + // storage_remove_base: 53473030500, + // storage_remove_key_byte: 38220384, + // storage_remove_ret_value_byte: 11531556, + // storage_has_key_base: 54039896625, + // storage_has_key_byte: 30790845, + // storage_iter_create_prefix_base: 0, + // storage_iter_create_prefix_byte: 0, + // storage_iter_create_range_base: 0, + // storage_iter_create_from_byte: 0, + // storage_iter_create_to_byte: 0, + // storage_iter_next_base: 0, + // storage_iter_next_key_byte: 0, + // storage_iter_next_value_byte: 0, + // touching_trie_node: 16101955926, + // read_cached_trie_node: 2280000000, + // promise_and_base: 1465013400, + // promise_and_per_promise: 5452176, + // promise_return: 560152386, + // validator_stake_base: 911834726400, + // validator_total_stake_base: 911834726400, + // contract_compile_base: 0, + // contract_compile_bytes: 0, + // alt_bn128_g1_multiexp_base: 713000000000, + // alt_bn128_g1_multiexp_element: 320000000000, + // alt_bn128_g1_sum_base: 3000000000, + // alt_bn128_g1_sum_element: 5000000000, + // alt_bn128_pairing_check_base: 9686000000000, + // alt_bn128_pairing_check_element: 5102000000000, + // }, + // grow_mem_cost: 1, + // regular_op_cost: 822756, + // limit_config: VMLimitConfig { + // max_gas_burnt: 300000000000000, + // max_stack_height: 16384, + // contract_prepare_version: V1, + // initial_memory_pages: 1024, + // max_memory_pages: 2048, + // registers_memory_limit: 1073741824, + // max_register_size: 104857600, + // max_number_registers: 100, + // max_number_logs: 100, + // max_total_log_length: 16384, + // max_total_prepaid_gas: 300000000000000, + // max_actions_per_receipt: 100, + // max_number_bytes_method_names: 2000, + // max_length_method_name: 256, + // max_arguments_length: 4194304, + // max_length_returned_data: 4194304, + // max_contract_size: 4194304, + // max_transaction_size: 4194304, + // max_length_storage_key: 2048, + // max_length_storage_value: 4194304, + // max_promises_per_function_call_action: 1024, + // max_number_input_data_dependencies: 128, + // max_functions_number_per_contract: Some( + // 10000, + // ), + // wasmer2_stack_limit: 204800, + // max_locals_per_contract: Some( + // 1000000, + // ), + // account_id_validity_rules_version: V1, + // }, + // }, + // account_creation_config: AccountCreationConfigView { + // min_allowed_top_level_account_length: 32, + // registrar_account_id: AccountId( + // "registrar", + // ), + // }, + // }, + // transaction_validity_period: 100, + // protocol_reward_rate: Ratio { + // numer: 1, + // denom: 10, + // }, + // max_inflation_rate: Ratio { + // numer: 1, + // denom: 20, + // }, + // num_blocks_per_year: 31536000, + // protocol_treasury_account: AccountId( + // "test.near", + // ), + // fishermen_threshold: 10000000000000000000000000, + // minimum_stake_divisor: 10, + // } + println!("ProtocolConfig {protocol_config:#?}"); + Ok(()) +} diff --git a/examples/src/receipt.rs b/examples/src/receipt.rs new file mode 100644 index 00000000..c838982c --- /dev/null +++ b/examples/src/receipt.rs @@ -0,0 +1,40 @@ +use near_jsonrpc_primitives::types::receipts::ReceiptReference; + +const STATUS_MSG_WASM_FILEPATH: &str = "./examples/res/status_message.wasm"; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + let wasm = std::fs::read(STATUS_MSG_WASM_FILEPATH)?; + let contract = worker.dev_deploy(&wasm).await?; + + let outcome = contract + .call("set_status") + .args_json(serde_json::json!({ + "message": "hello_world", + })) + .transact() + .await?; + + let receipt_ref = { + let mut ids = outcome.outcome().receipt_ids.clone(); + if ids.is_empty() { + println!("no receipt ids present"); + return Ok(()); + } + + println!("receipts found: {ids:?}"); + + ReceiptReference { + receipt_id: near_primitives::hash::CryptoHash( + ids.pop().expect("expected at least one receipt id").0, + ), + } + }; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let resp = worker.receipt(receipt_ref).await?; + + println!("ReceiptView: {resp:?}"); + Ok(()) +} diff --git a/examples/src/ref_finance.rs b/examples/src/ref_finance.rs index 7b74341a..82540751 100644 --- a/examples/src/ref_finance.rs +++ b/examples/src/ref_finance.rs @@ -132,7 +132,7 @@ async fn create_pool_with_liquidity( .await? .into_result()?; - deposit_tokens(owner, &ref_finance, tokens).await?; + deposit_tokens(owner, ref_finance, tokens).await?; owner .call(ref_finance.id(), "add_liquidity") diff --git a/examples/src/tx_status.rs b/examples/src/tx_status.rs new file mode 100644 index 00000000..756c7f2c --- /dev/null +++ b/examples/src/tx_status.rs @@ -0,0 +1,309 @@ +use near_jsonrpc_primitives::types::transactions::TransactionInfo; +use near_primitives::hash::CryptoHash; +use serde_json::json; + +const STATUS_MSG_WASM_FILEPATH: &str = "./examples/res/status_message.wasm"; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + let wasm = std::fs::read(STATUS_MSG_WASM_FILEPATH)?; + let contract = worker.dev_deploy(&wasm).await?; + + let outcome = contract + .call("set_status") + .args_json(json!({ + "message": "hello_world", + })) + .transact() + .await?; + + let tx_info = { + let outcome = outcome.outcome(); + TransactionInfo::TransactionId { + hash: CryptoHash(outcome.transaction_hash.0), + account_id: outcome.executor_id.clone(), + } + }; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let resp = worker.tx_status(tx_info).await?; + + // Example outcome: + // + // FinalExecutionOutcomeWithReceiptView FinalExecutionOutcomeWithReceiptView { + // final_outcome: FinalExecutionOutcome { + // status: SuccessValue(''), + // transaction: SignedTransactionView { + // signer_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // public_key: ed25519:5WMgq6gKZbAr7xBZmXJHjnj4C3UZkNJ4F5odisUBFcRh, + // nonce: 2000001, + // receiver_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // actions: [ + // FunctionCall { + // method_name: "set_status", + // args: FunctionArgs( + // [ + // 123, + // 34, + // 109, + // 101, + // 115, + // 115, + // 97, + // 103, + // 101, + // 34, + // 58, + // 34, + // 104, + // 101, + // 108, + // 108, + // 111, + // 95, + // 119, + // 111, + // 114, + // 108, + // 100, + // 34, + // 125, + // ], + // ), + // gas: 10000000000000, + // deposit: 0, + // }, + // ], + // signature: ed25519:25z5farfJh4ccYoLJeJtKTrfEfecWSXqksafEnFCA724NHaGZWowtpKxGdMZTYSzzpAJ3iT6sWNyEF2oC2u1CvCR, + // hash: HWRjprUXTN7fhnvzMaDxXBXbJTVqvbW8j56PvfyL8uB6, + // }, + // transaction_outcome: ExecutionOutcomeWithIdView { + // proof: [ + // MerklePathItem { + // hash: 8a7iJ6vWjvwHKFLXPETciDbZtdHeHaX6xPqVT42CrEfi, + // direction: Right, + // }, + // ], + // block_hash: BeMy3czUnz7EndbaSSHTSZ7WhozdAxSRAtYYqCo5XSSo, + // id: HWRjprUXTN7fhnvzMaDxXBXbJTVqvbW8j56PvfyL8uB6, + // outcome: ExecutionOutcomeView { + // logs: [], + // receipt_ids: [ + // ByE39xUGnYHrfVsNyxTgDjkPY7yFFLCHQcUb7m5Qiwkp, + // ], + // gas_burnt: 2427999257690, + // tokens_burnt: 242799925769000000000, + // executor_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // status: SuccessReceiptId(ByE39xUGnYHrfVsNyxTgDjkPY7yFFLCHQcUb7m5Qiwkp), + // metadata: ExecutionMetadataView { + // version: 1, + // gas_profile: None, + // }, + // }, + // }, + // receipts_outcome: [ + // ExecutionOutcomeWithIdView { + // proof: [ + // MerklePathItem { + // hash: 5hxa61Hv5a82HUh2qWVSVEVB5f2txx4JpmbXK5qmdwnv, + // direction: Left, + // }, + // ], + // block_hash: BeMy3czUnz7EndbaSSHTSZ7WhozdAxSRAtYYqCo5XSSo, + // id: ByE39xUGnYHrfVsNyxTgDjkPY7yFFLCHQcUb7m5Qiwkp, + // outcome: ExecutionOutcomeView { + // logs: [ + // "A", + // ], + // receipt_ids: [ + // AhbLBVzfPa2ebNkTtdTyK1pB6zE6Srucwob32UCNFS5E, + // ], + // gas_burnt: 2666186302694, + // tokens_burnt: 266618630269400000000, + // executor_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // status: SuccessValue(''), + // metadata: ExecutionMetadataView { + // version: 3, + // gas_profile: Some( + // [ + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "BASE", + // gas_used: 2647681110, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "CONTRACT_LOADING_BASE", + // gas_used: 35445963, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "CONTRACT_LOADING_BYTES", + // gas_used: 26988192750, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "LOG_BASE", + // gas_used: 3543313050, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "LOG_BYTE", + // gas_used: 13198791, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "READ_CACHED_TRIE_NODE", + // gas_used: 4560000000, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "READ_MEMORY_BASE", + // gas_used: 10439452800, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "READ_MEMORY_BYTE", + // gas_used: 254689311, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "READ_REGISTER_BASE", + // gas_used: 5034330372, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "READ_REGISTER_BYTE", + // gas_used: 5716596, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "STORAGE_READ_BASE", + // gas_used: 56356845750, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "STORAGE_READ_KEY_BYTE", + // gas_used: 154762665, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "STORAGE_WRITE_BASE", + // gas_used: 64196736000, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "STORAGE_WRITE_KEY_BYTE", + // gas_used: 352414335, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "STORAGE_WRITE_VALUE_BYTE", + // gas_used: 1737038184, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "TOUCHING_TRIE_NODE", + // gas_used: 32203911852, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "UTF8_DECODING_BASE", + // gas_used: 3111779061, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "UTF8_DECODING_BYTE", + // gas_used: 291580479, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "WASM_INSTRUCTION", + // gas_used: 11695476540, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "WRITE_MEMORY_BASE", + // gas_used: 8411384583, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "WRITE_MEMORY_BYTE", + // gas_used: 201559128, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "WRITE_REGISTER_BASE", + // gas_used: 5731044972, + // }, + // CostGasUsed { + // cost_category: "WASM_HOST_COST", + // cost: "WRITE_REGISTER_BYTE", + // gas_used: 220490712, + // }, + // ], + // ), + // }, + // }, + // }, + // ExecutionOutcomeWithIdView { + // proof: [], + // block_hash: AG5nJGsWxCtAHPzq3m7NsTnSdSmQaxeLwffvFKMeWT9b, + // id: AhbLBVzfPa2ebNkTtdTyK1pB6zE6Srucwob32UCNFS5E, + // outcome: ExecutionOutcomeView { + // logs: [], + // receipt_ids: [], + // gas_burnt: 223182562500, + // tokens_burnt: 0, + // executor_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // status: SuccessValue(''), + // metadata: ExecutionMetadataView { + // version: 3, + // gas_profile: Some( + // [], + // ), + // }, + // }, + // }, + // ], + // }, + // receipts: [ + // ReceiptView { + // predecessor_id: AccountId( + // "system", + // ), + // receiver_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // receipt_id: AhbLBVzfPa2ebNkTtdTyK1pB6zE6Srucwob32UCNFS5E, + // receipt: Action { + // signer_id: AccountId( + // "dev-20230822130616-84011708140052", + // ), + // signer_public_key: ed25519:5WMgq6gKZbAr7xBZmXJHjnj4C3UZkNJ4F5odisUBFcRh, + // gas_price: 0, + // output_data_receivers: [], + // input_data_ids: [], + // actions: [ + // Transfer { + // deposit: 1051867810978932100000, + // }, + // ], + // }, + // }, + // ], + // } + println!("FinalExecutionOutcomeWithReceiptView {resp:#?}"); + Ok(()) +} diff --git a/examples/src/validators_ordered.rs b/examples/src/validators_ordered.rs new file mode 100644 index 00000000..bb9e6b5e --- /dev/null +++ b/examples/src/validators_ordered.rs @@ -0,0 +1,23 @@ +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let worker = workspaces::sandbox().await?; + + // NOTE: this API is under the "experimental" flag and no guarantees are given. + let validators = worker.validators_ordered(None).await?; + + // Example output: + // + // Validators [ + // V1( + // ValidatorStakeViewV1 { + // account_id: AccountId( + // "test.near", + // ), + // public_key: ed25519:HguH1hFyR4voJUomR67QqxACtSo3sYTMXtJ9oSzFSoYy, + // stake: 50000000000000000000000000000000, + // }, + // ), + // ] + println!("Validators {validators:#?}"); + Ok(()) +} diff --git a/workspaces/Cargo.toml b/workspaces/Cargo.toml index 46ebaf14..b954a74d 100644 --- a/workspaces/Cargo.toml +++ b/workspaces/Cargo.toml @@ -39,6 +39,7 @@ near-primitives = "0.17" near-jsonrpc-primitives = "0.17" near-jsonrpc-client = { version = "0.6", features = ["sandbox"] } near-sandbox-utils = "0.6.2" +near-chain-configs = { version = "0.17.0", optional = true } [build-dependencies] near-sandbox-utils = "0.6.2" @@ -60,6 +61,7 @@ default = ["install", "interop_sdk"] install = [] # Install the sandbox binary during compile time interop_sdk = ["near-sdk"] unstable = ["cargo_metadata"] +experimental = ["near-chain-configs"] [package.metadata.docs.rs] features = ["unstable"] diff --git a/workspaces/src/network/testnet.rs b/workspaces/src/network/testnet.rs index 9a65373b..3f015940 100644 --- a/workspaces/src/network/testnet.rs +++ b/workspaces/src/network/testnet.rs @@ -88,6 +88,7 @@ impl TopLevelAccountCreator for Testnet { status: near_primitives::views::FinalExecutionStatus::SuccessValue(Vec::new()), details: ExecutionDetails { transaction: ExecutionOutcome { + transaction_hash: CryptoHash::default(), block_hash: CryptoHash::default(), logs: Vec::new(), receipt_ids: Vec::new(), diff --git a/workspaces/src/result.rs b/workspaces/src/result.rs index be27e631..b36b95ea 100644 --- a/workspaces/src/result.rs +++ b/workspaces/src/result.rs @@ -409,6 +409,9 @@ impl From for ViewResultDetails { #[derive(Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub struct ExecutionOutcome { + /// The hash of the transaction that generated this outcome. + pub transaction_hash: CryptoHash, + /// The hash of the block that generated this outcome. pub block_hash: CryptoHash, /// Logs from this transaction or receipt. pub logs: Vec, @@ -521,6 +524,7 @@ impl Value { impl From for ExecutionOutcome { fn from(view: ExecutionOutcomeWithIdView) -> Self { ExecutionOutcome { + transaction_hash: CryptoHash(view.id.0), block_hash: CryptoHash(view.block_hash.0), logs: view.outcome.logs, receipt_ids: view diff --git a/workspaces/src/rpc/client.rs b/workspaces/src/rpc/client.rs index 2fcd20dd..91632779 100644 --- a/workspaces/src/rpc/client.rs +++ b/workspaces/src/rpc/client.rs @@ -26,6 +26,22 @@ use near_primitives::views::{ AccessKeyView, BlockView, FinalExecutionOutcomeView, QueryRequest, StatusResponse, }; +#[cfg(feature = "experimental")] +use { + near_chain_configs::{GenesisConfig, ProtocolConfigView}, + near_jsonrpc_primitives::types::{ + changes::RpcStateChangesInBlockByTypeResponse, changes::RpcStateChangesInBlockResponse, + receipts::ReceiptReference, transactions::TransactionInfo, + }, + near_primitives::{ + types::MaybeBlockId, + views::{ + validator_stake_view::ValidatorStakeView, FinalExecutionOutcomeWithReceiptView, + ReceiptView, StateChangesRequestView, + }, + }, +}; + use crate::error::{Error, ErrorKind, RpcErrorCode}; use crate::operations::TransactionStatus; use crate::result::Result; @@ -330,6 +346,102 @@ impl Client { } } +#[cfg(feature = "experimental")] +impl Client { + pub(crate) async fn changes_in_block( + &self, + block_reference: BlockReference, + ) -> Result { + let resp = self + .rpc_client + .call( + methods::EXPERIMENTAL_changes_in_block::RpcStateChangesInBlockRequest { + block_reference, + }, + ) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + + Ok(resp) + } + + pub(crate) async fn changes( + &self, + block_reference: BlockReference, + state_changes_request: StateChangesRequestView, + ) -> Result { + let resp = self + .rpc_client + .call( + methods::EXPERIMENTAL_changes::RpcStateChangesInBlockByTypeRequest { + block_reference, + state_changes_request, + }, + ) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + Ok(resp) + } + + pub(crate) async fn genesis_config(&self) -> Result { + let resp = self + .rpc_client + .call(methods::EXPERIMENTAL_genesis_config::RpcGenesisConfigRequest) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + Ok(resp) + } + + pub(crate) async fn protocol_config( + &self, + block_reference: BlockReference, + ) -> Result { + let resp = self + .rpc_client + .call( + methods::EXPERIMENTAL_protocol_config::RpcProtocolConfigRequest { block_reference }, + ) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + Ok(resp) + } + + pub(crate) async fn receipt(&self, receipt_reference: ReceiptReference) -> Result { + let resp = self + .rpc_client + .call(methods::EXPERIMENTAL_receipt::RpcReceiptRequest { receipt_reference }) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + Ok(resp) + } + + pub(crate) async fn tx_status( + &self, + transaction_info: TransactionInfo, + ) -> Result { + let resp = self + .rpc_client + .call(methods::EXPERIMENTAL_tx_status::RpcTransactionStatusRequest { transaction_info }) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + Ok(resp) + } + + pub(crate) async fn validators_ordered( + &self, + block_id: MaybeBlockId, + ) -> Result> { + let resp = self + .rpc_client + .call( + methods::EXPERIMENTAL_validators_ordered::RpcValidatorsOrderedRequest { block_id }, + ) + .await + .map_err(|e| RpcErrorCode::QueryFailure.custom(e))?; + Ok(resp) + } +} + pub(crate) async fn access_key( client: &Client, account_id: near_primitives::account::id::AccountId, diff --git a/workspaces/src/worker/impls.rs b/workspaces/src/worker/impls.rs index 1aee4896..233e8df8 100644 --- a/workspaces/src/worker/impls.rs +++ b/workspaces/src/worker/impls.rs @@ -8,11 +8,26 @@ use crate::rpc::query::{ GasPrice, Query, QueryChunk, ViewAccessKey, ViewAccessKeyList, ViewAccount, ViewBlock, ViewCode, ViewFunction, ViewState, }; -use crate::types::{AccountId, InMemorySigner, PublicKey}; +use crate::types::{AccountId, Balance, InMemorySigner, PublicKey}; use crate::worker::Worker; use crate::{Account, Network}; -use near_primitives::types::Balance; +#[cfg(feature = "experimental")] +use { + near_chain_configs::{GenesisConfig, ProtocolConfigView}, + near_jsonrpc_primitives::types::{ + changes::{RpcStateChangesInBlockByTypeResponse, RpcStateChangesInBlockResponse}, + receipts::ReceiptReference, + transactions::TransactionInfo, + }, + near_primitives::{ + types::{BlockReference, MaybeBlockId}, + views::{ + validator_stake_view::ValidatorStakeView, FinalExecutionOutcomeWithReceiptView, + ReceiptView, StateChangesRequestView, + }, + }, +}; impl Clone for Worker { fn clone(&self) -> Self { @@ -173,6 +188,58 @@ where } } +#[cfg(feature = "experimental")] +impl Worker +where + T: NetworkClient, +{ + pub async fn changes_in_block( + &self, + block_reference: BlockReference, + ) -> Result { + self.client().changes_in_block(block_reference).await + } + + pub async fn changes( + &self, + block_reference: BlockReference, + state_changes_request: StateChangesRequestView, + ) -> Result { + self.client() + .changes(block_reference, state_changes_request) + .await + } + + pub async fn genesis_config(&self) -> Result { + self.client().genesis_config().await + } + + pub async fn protocol_config( + &self, + block_reference: BlockReference, + ) -> Result { + self.client().protocol_config(block_reference).await + } + + pub async fn receipt(&self, receipt_reference: ReceiptReference) -> Result { + self.client().receipt(receipt_reference).await + } + + pub async fn tx_status( + &self, + transaction_info: TransactionInfo, + ) -> Result { + self.client().tx_status(transaction_info).await + } + + pub async fn validators_ordered( + &self, + block_id: MaybeBlockId, + ) -> Result> { + self.client().validators_ordered(block_id).await + } +} + impl Worker where T: Network + 'static,