Transfers

One of the key applications that can take advantage of Pod’s lightning-fast nature is processing payment transactions.

This guide demonstrates how to make payments on the POD Network using the Pod Rust SDK. We’ll cover the entire process, from checking balances to sending transactions and monitoring their status.

For sending and receiving payments with an ethereum-compatible wallet, see Getting Started.

Prerequisites

Before starting, ensure you have:

  • An account with funds on the pod devnet network, or use the faucet.
  • pod Rust SDK installed.
 

Initialize credentials

First, we need to import all the necessary pod SDK libraries and Alloy types

use eyre::Result; use alloy_primitives::{Address, U256}; use std::str::FromStr; #[tokio::main] async fn main() -> Result<()> { let rpc_url = "https://rpc.v1.dev.pod.network"; let private_key_hex = "your-private-key"; // ... }

Initialize provider

Second, we initialize the provider

use eyre::Result; use std::sync::Arc; use alloy_signer::k256::ecdsa::SigningKey; use pod_sdk::PrivateKeySigner; use alloy_network::EthereumWallet; use alloy_primitives::Address; use alloy_transport::http::Http; use alloy_provider::{Provider, HttpProvider}; use crate::provider; /// Builds the Pod Provider from the given RPC URL (HTTP) and hex-encoded private key. pub async fn build_pod_provider( rpc_url: &str, private_key_hex: &str ) -> Result { // 1) Decode the private key into raw bytes let private_key_bytes = hex::decode(private_key_hex)?; // 2) Create a SigningKey let signing_key = SigningKey::from_slice(&private_key_bytes)?; // 3) Wrap it into a `pod_sdk::PrivateKeySigner` let signer = PrivateKeySigner::from_signing_key(signing_key); // 4) Construct an EthereumWallet using that signer let wallet = EthereumWallet::new(signer); // 5) Create an HTTP transport let transport = Http::new(rpc_url)?; // 6) Build the final provider. This is a Pod-aware extension of a typical `HttpProvider`. let pod_provider = provider::PodProviderBuilder::new() .with_recommended_fillers() .wallet(wallet) .on_http(transport) .await?; Ok(pod_provider) }

Send the transaction

Now, we need to send our transaction to the client and broadcast it to the pod network

use eyre::Result; use alloy_primitives::{Address, U256}; use std::time::SystemTime; use network::PodTransactionRequest; use pod_sdk::TransactionBuilder; use alloy_rpc_types_eth::transaction_request::TransactionRequest; /// Builds and sends a transaction to the given `recipient` with the specified `value`. /// Returns the (pending) transaction hash and the `start_time` for later receipt fetching. pub async fn send_payment_tx( pod_provider: &P, from_address: Address, recipient: Address, value: U256 ) -> Result<(H256, u128)> { // 1) Build the transaction object let tx = PodTransactionRequest::default() .with_from(from_address) .with_to(recipient) .with_value(value); println!("Built transaction: {:?}", tx); // 2) Capture the time when we send the transaction let start_time = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH)? .as_micros() as u128; // 3) Send the transaction let pending_tx = pod_provider.send_transaction(tx.into()).await?; let tx_hash = pending_tx.tx_hash(); println!("Transaction sent. Hash: {:?}", tx_hash); Ok((tx_hash, start_time)) }

Wait for the confirmation and get the receipt

Finally, we wait for the transaction to be confirmed and fetch the receipts

use eyre::Result; use alloy_rpc_types_eth::H256; use std::time::SystemTime; use network::PodTransactionReceipt; use pod_core::time::SystemClock; use alloy_primitives::TxKind; pub async fn wait_for_receipts_and_verify( pod_provider: &P, recipient: Address, start_time: u128 ) -> Result<()> { // 1) Get newly confirmed receipts since `start_time` let receipts = pod_provider.get_confirmed_receipts(start_time).await?; let committee = pod_provider.get_committee().await?; // 2) Inspect each receipt for receipt in receipts { // Confirm it's calling `recipient` if receipt.transaction().to == TxKind::Call(recipient) { // Attempt to verify with the committee if matches!(receipt.verify(&committee), Ok(true)) { println!("Found verified receipt: {:?}", receipt); } } } // 3) Wait for past perfect time => transaction is final let now = SystemClock.now().as_seconds(); println!("Waiting for chain's past perfect time to reach {}...", now); pod_provider.wait_past_perfect_time(now as u64).await?; println!("Perfect time reached. Transaction final and cannot be reversed."); Ok(()) }

Putting it all together

The following code snipped gives the full sequence of events from sending the transaction to waiting for the confirmation

use eyre::Result; use alloy_primitives::{Address, U256}; use std::str::FromStr; #[tokio::main] async fn main() -> Result<()> { // 1) Set RPC URL and private key let rpc_url = "https://rpc.v1.dev.pod.network"; let private_key_hex = "your-private-key"; // 2) Build the Pod provider (from the Rust SDK approach) let pod_provider = build_pod_provider(&rpc_url, &private_key_hex).await?; // 3) Let's define your 'from' (sender) address and the 'to' (recipient) // Typically, you already know your "from_address" from the private key, but // you can also query it from the signer if needed. // For example, if your `build_pod_provider` can return the signer's address. // We'll assume you already know it: let from_address = Address::from_str("0xSender...")?; let recipient = Address::from_str("0xabcDEF...")?; // 4) Send a payment transaction let value_wei = U256::from(1_000_000u64); // 1,000,000 Wei for example let (tx_hash, start_time) = send_payment_tx( &pod_provider, from_address, recipient, value_wei ).await?; println!("Transaction hash: {:?}, start_time: {}", tx_hash, start_time); // 5) Wait for confirmation & verify wait_for_receipts_and_verify(&pod_provider, recipient, start_time).await?; println!("Transaction fully confirmed!"); Ok(()) }