> For the complete documentation index, see [llms.txt](https://wiki.solaxy.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.solaxy.io/using-custom-code/rpc-client-setup.md).

# RPC Client Setup

To initialize your client, please pass in the URL in [Access Information](/developer-resources/access-information.md).

* Client Template

  <pre class="language-rust" data-overflow="wrap"><code class="lang-rust">pub(crate) struct SampleClient {
      rpc: WsClient,
      node_client: NodeClient,
  }

  impl SampleClient {
      pub(crate) async fn new(rpc_addr: String, rest_addr: String) -> Self {
          let rpc_socket: SocketAddr = rpc_addr.parse().unwrap();
          let rpc = WsClientBuilder::default()
              .build(&#x26;format!("ws://127.0.0.1:{}", rpc_socket.port()))
              .await
              .unwrap();

          let rest_socket: SocketAddr = rest_addr.parse().unwrap();
          let node_client =
              NodeClient::new_unchecked(&#x26;format!("&#x3C;http://127.0.0.1>:{}", rest_socket.port()));

          Self { rpc, node_client }
      }

      pub(crate) async fn svm_query_state(&#x26;self) -> anyhow::Result&#x3C;String> {
          self.rpc
              .request("queryModuleState", rpc_params![])
              .await
              .map_err(|e| anyhow!("Failed to query SVM state: {e}"))
      }

      #[allow(dead_code)]
      pub(crate) async fn svm_get_slot(&#x26;self) -> anyhow::Result&#x3C;u64> {
          self.rpc
              .request("getSlot", rpc_params![])
              .await
              .map_err(|e| anyhow!("Failed to get slot: {e}"))
      }

      pub(crate) async fn svm_get_account_info(&#x26;self, pubkey: Pubkey) -> anyhow::Result&#x3C;Account> {
          let res: Response&#x3C;Option&#x3C;UiAccount>> = self
              .rpc
              .request("getAccountInfo", rpc_params![pubkey])
              .await
              .map_err(|e| anyhow!("Failed to get account info: {e}"))?;
          res.value
              .ok_or_else(|| anyhow!("Failed to get account info"))?
              .decode()
              .ok_or_else(|| anyhow!("Failed to decode account info"))
      }

      pub(crate) async fn svm_get_account_balance(&#x26;self, pubkey: Pubkey) -> anyhow::Result&#x3C;u64> {
          self.rpc
              .request("getBalance", rpc_params![pubkey])
              .await
              .map_err(|e| anyhow!("Failed to get account balance: {e}"))
      }

      pub(crate) async fn svm_get_latest_blockhash(&#x26;self) -> anyhow::Result&#x3C;Hash> {
          self.rpc
              .request("getLatestBlockhash", rpc_params![])
              .await
              .map_err(|e| anyhow!("Failed to get blockhash: {e}"))
      }

      pub(crate) async fn svm_send_transaction(&#x26;self, tx: &#x26;Transaction) -> anyhow::Result&#x3C;Hash> {
          let raw_tx = serialize_and_encode(tx, UiTransactionEncoding::Base58)?;
          self.rpc
              .request("sendTransaction", rpc_params![raw_tx])
              .await
              .map_err(|e| anyhow!("Failed to send transaction: {e}"))
      }

      pub(crate) async fn get_minimum_balance_for_rent_exemption(
          &#x26;self,
          data_len: usize,
      ) -> anyhow::Result&#x3C;u64> {
          self.rpc
              .request("getMinimumBalanceForRentExemption", rpc_params![data_len])
              .await
              .map_err(|e| anyhow!("Failed to get rent balance: {e}"))
      }

      pub(crate) async fn get_fee_for_message(&#x26;self, message: Message) -> anyhow::Result&#x3C;u64> {
          self.rpc
              .request("getFeeForMessage", rpc_params![message])
              .await
              .map_err(|e| anyhow!("Failed to get fee for message: {e}"))
      }

      pub(crate) async fn simulate_call_message(
          &#x26;self,
          transactions: &#x26;[Transaction],
      ) -> anyhow::Result&#x3C;u64> {
          let raw_txs = transactions
              .iter()
              .map(|tx| borsh::to_vec(tx).expect("Failed to serialize transaction"))
              .collect();

          let msg = svm::call::CallMessage {
              transactions: raw_txs,
          };

          let user = TestUser::&#x3C;SvmRollupSpec>::generate_with_default_balance();

          let partial_transaction: PartialTransaction =
              sov_rollup_apis::PartialTransaction::&#x3C;SvmRollupSpec> {
                  sender_pub_key: user.private_key().pub_key(),
                  details: sov_modules_api::transaction::TxDetails {
                      max_priority_fee_bips: PriorityFeeBips::ZERO,
                      max_fee: TEST_DEFAULT_MAX_FEE,
                      gas_limit: None,
                      chain_id: config_chain_id(),
                  },
                  encoded_call_message: &#x3C;RT as EncodeCall&#x3C;SVM&#x3C;SvmRollupSpec>>>::encode_call(msg),
                  gas_price: None,
                  sequencer: None,
                  generation: 0,
              }
              .try_into()
              .unwrap();

          let simulation_result = self
              .node_client
              .client
              .simulate(&#x26;SimulateBody {
                  body: partial_transaction,
              })
              .await
              .map_err(|e| anyhow!("Failed to simulate call message: {e}"))?
              .data
              .clone()
              .unwrap();

          let simulation_result_parsed: SimulateExecutionContainer&#x3C;SvmRollupSpec> =
              simulation_result.try_into()?;

          let tx_consumption = simulation_result_parsed
              .apply_tx_result
              .transaction_consumption;
          let base_fee = tx_consumption.base_fee_value();
          let priority_fee = tx_consumption.priority_fee();
          Ok(base_fee.0 + priority_fee.0)
      }

      pub(crate) async fn get_total_fee_for_transaction(
          &#x26;self,
          transaction: &#x26;Transaction,
      ) -> anyhow::Result&#x3C;u64> {
          let call_message_gas_fee_estimate =
              self.simulate_call_message(&#x26;[transaction.clone()]).await?;
          let svm_gas_fee_estimate = self
              .get_fee_for_message(transaction.message.clone())
              .await?;
          Ok(call_message_gas_fee_estimate + svm_gas_fee_estimate)
      }
  }
  </code></pre>
* Initializing the Client

  <pre class="language-rust" data-overflow="wrap"><code class="lang-rust">let client = TestClient::new(config.rpc.rpc_addr, config.rpc.rest_addr).await;
  </code></pre>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.solaxy.io/using-custom-code/rpc-client-setup.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
