RPC Client Setup

To initialize your client, please pass in the URL in Access Information.

  • Client Template

    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(&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(&format!("<http://127.0.0.1>:{}", rest_socket.port()));
    
            Self { rpc, node_client }
        }
    
        pub(crate) async fn svm_query_state(&self) -> anyhow::Result<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(&self) -> anyhow::Result<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(&self, pubkey: Pubkey) -> anyhow::Result<Account> {
            let res: Response<Option<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(&self, pubkey: Pubkey) -> anyhow::Result<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(&self) -> anyhow::Result<Hash> {
            self.rpc
                .request("getLatestBlockhash", rpc_params![])
                .await
                .map_err(|e| anyhow!("Failed to get blockhash: {e}"))
        }
    
        pub(crate) async fn svm_send_transaction(&self, tx: &Transaction) -> anyhow::Result<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(
            &self,
            data_len: usize,
        ) -> anyhow::Result<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(&self, message: Message) -> anyhow::Result<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(
            &self,
            transactions: &[Transaction],
        ) -> anyhow::Result<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::<SvmRollupSpec>::generate_with_default_balance();
    
            let partial_transaction: PartialTransaction =
                sov_rollup_apis::PartialTransaction::<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: <RT as EncodeCall<SVM<SvmRollupSpec>>>::encode_call(msg),
                    gas_price: None,
                    sequencer: None,
                    generation: 0,
                }
                .try_into()
                .unwrap();
    
            let simulation_result = self
                .node_client
                .client
                .simulate(&SimulateBody {
                    body: partial_transaction,
                })
                .await
                .map_err(|e| anyhow!("Failed to simulate call message: {e}"))?
                .data
                .clone()
                .unwrap();
    
            let simulation_result_parsed: SimulateExecutionContainer<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(
            &self,
            transaction: &Transaction,
        ) -> anyhow::Result<u64> {
            let call_message_gas_fee_estimate =
                self.simulate_call_message(&[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)
        }
    }
  • Initializing the Client

    let client = TestClient::new(config.rpc.rpc_addr, config.rpc.rest_addr).await;

Last updated

Was this helpful?