> 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>
