Create a small balance reader with an explicit network, public account and commitment level.
An agent tool should expose a narrow operation and validate its arguments before making a request. This function reads a public account through Solana’s getBalance method and returns the integer amount in lamports with the RPC context. It can be connected to a tool-calling application after its inputs and errors have been tested.
Before you start
Python 3.10 or later; this example uses only its standard library.
A base58 public account address that decodes to 32 bytes.
Access to the selected Solana RPC endpoint. Public endpoints have rate limits.
Build and check
Start on Devnet and choose the commitment required by your application.
Change the account field and inspect the generated request and validation function.
Run the file and keep the network, commitment, lamports and context together.
Before attaching the function to an agent, define the allowed arguments and handle RPC errors, timeouts and rate limits in the host application.
Limits to understand
This recipe does not sign or submit transactions and does not need a private key.
Devnet and Mainnet beta are separate networks. A balance on one is not a balance on the other.
Keep lamports as an integer. The preview validates the address shape and length, not the account’s purpose or existence.
ADJUST THE EXAMPLE
Change a setting. Inspect the result.
This browser preview builds code locally. It does not contact an API or run the code.
Default example ready.
Python example
"""Read an account balance without signing or sending a transaction."""
import json
from urllib.request import Request, urlopen
NETWORK = "devnet"
COMMITMENT = "finalized"
ADDRESS = "11111111111111111111111111111111"
ENDPOINTS = {"devnet": "https://api.devnet.solana.com", "mainnet-beta": "https://api.mainnet-beta.solana.com"}
def validate_address(address):
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
if not 32 <= len(address) <= 44 or any(c not in alphabet for c in address):
raise ValueError("Expected a base58 public account address.")
number = 0
for char in address:
number = number * 58 + alphabet.index(char)
decoded_length = (number.bit_length() + 7) // 8 + len(address) - len(address.lstrip("1"))
if decoded_length != 32:
raise ValueError("Expected a 32-byte public account address.")
def get_balance(address=ADDRESS, network=NETWORK, commitment=COMMITMENT):
validate_address(address)
if network not in ENDPOINTS or commitment not in {"processed", "confirmed", "finalized"}:
raise ValueError("Unsupported network or commitment.")
body = {"jsonrpc": "2.0", "id": 1, "method": "getBalance", "params": [address, {"commitment": commitment}]}
request = Request(ENDPOINTS[network], data=json.dumps(body).encode(), headers={"Content-Type": "application/json"})
with urlopen(request, timeout=15) as reply:
data = json.load(reply)
if not isinstance(data, dict):
raise RuntimeError("The RPC response must be a JSON object.")
if "error" in data:
raise RuntimeError(f"RPC error: {data['error']}")
result = data.get("result")
value = result.get("value") if isinstance(result, dict) else None
if type(value) is not int or value < 0:
raise RuntimeError("RPC response did not contain a non-negative lamport balance.")
return {"network": network, "commitment": commitment, "address": address, "lamports": value, "context": data["result"].get("context", {})}
if __name__ == "__main__":
print(json.dumps(get_balance(), indent=2))
What to verify after running
Only getBalance is requested; no transaction or signing method is present.
Invalid addresses and unsupported networks are rejected before a network request.
Large lamport values remain integers, and a JSON-RPC error stops processing.
Request or format preview
Illustrative preview. No provider response, price or balance is fetched.