Call a program (read-only)
Execute a read-only program call and get its return value — no transaction, no fee, no keys.
POST /programs/{programId}/viewHow calling programs works on Solana
Coming from Ethereum, expect two differences:
- Writes are transactions. There is no separate "contract call" API for state changes — you build an instruction, sign it, and submit it via send.
- Most reads don't need a call at all. Program state lives in accounts, so the usual way to "read a contract" is just reading accounts — Get an account or List program accounts.
The remaining case: programs (especially Anchor programs) expose view functions that compute a value on-chain — an oracle price, a quote, an entitlement check. This endpoint executes one via simulation and hands you the return value. Nothing lands on-chain, nothing is signed, nothing costs a network fee.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
data | string | Yes | The instruction data, base64-encoded (for Anchor: the view method's discriminator + args, as produced by your program's client library). |
accounts | array | Yes | The accounts the instruction reads, in the order the program expects: { "address": "...", "writable": false, "signer": false }. |
payer | string | No | Address to simulate as fee payer. Defaults to a funded placeholder — only set this if the program checks the payer's identity. |
Example
Calling a lending program's view function that returns a wallet's current deposit value:
curl -X POST https://api.sarg.am/v1/solana/programs/LendZqTs7gn5CjSJJT3zXcTQyEN2BSK9BbA6iDgc4Fj/view \
-H "Authorization: Bearer $MAINLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": "Y2FsY3VsYXRlX3VzZXJfZGVwb3NpdA==",
"accounts": [
{ "address": "7Xq3mZvUkPqRSPY2ZRegjxUmjcSDCBL8HbGyWjcJt2gV", "writable": false, "signer": false },
{ "address": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", "writable": false, "signer": false }
]
}'{
"success": true,
"returnData": {
"base64": "AOH1BQAAAAA=",
"programId": "LendZqTs7gn5CjSJJT3zXcTQyEN2BSK9BbA6iDgc4Fj"
},
"computeUnits": 8420,
"logs": [
"Program LendZqTs7gn5CjSJJT3zXcTQyEN2BSK9BbA6iDgc4Fj invoke [1]",
"Program return: LendZqTs7gn5CjSJJT3zXcTQyEN2BSK9BbA6iDgc4Fj AOH1BQAAAAA=",
"Program LendZqTs7gn5CjSJJT3zXcTQyEN2BSK9BbA6iDgc4Fj success"
]
}Response fields
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the call executed without error. Failures return success: false with an error object and logs, same as simulate. |
returnData.base64 | string | null | The program's return value. Decoding it requires the program's IDL — it's your program's type, not ours. null if the program returned nothing. |
computeUnits | number | Compute consumed by the call. |
logs | array | Full program log output. |
Decoding tip: for Anchor programs, deserialize
returnData.base64with the return type from your IDL. In this example,AOH1BQAAAAA=is a little-endianu64—100000000, i.e. 100 USDC at 6 decimals.
Errors
code | When |
|---|---|
invalid_address | The program ID or an account address isn't valid base58. |
invalid_parameter | data isn't valid base64, or accounts is malformed. |
not_found | The address isn't a program. |
Under the hood
Builds a throwaway transaction around your instruction, runs
simulateTransaction with signature verification off and a fresh blockhash,
and extracts the returnData — the pattern Anchor's .view() uses, minus the
client-side setup.