Skip to main content

getLedgerEntries

For reading the current value of ledger entries directly.

This method enables the retrieval of various ledger states, such as accounts, trustlines, offers, data, claimable balances, and liquidity pools. It also provides direct access to inspect a contract's current state, its code, or any other ledger entry. This serves as a primary method to access your contract data which may not be available via events or simulateTransaction.

To fetch contract wasm byte-code, use the ContractCode ledger entry key.

Params

(1)

Please note that parameter structure within the request must contain named parameters as a by-name object, and not as positional arguments in a by-position array

1. keys (required)

Array containing the keys of the ledger entries you wish to retrieve. (an array of serialized base64 strings)

array[string]

Array containing ledger keys. The maximum number of ledger keys accepted is 200.

Result

(getLedgerEntriesResult)
latestLedger
number
required

The sequence number of the latest ledger known to Soroban RPC at the time it handled the request.

entries
array[object]

Array of objects containing all found ledger entries

key
string

The key of the ledger entry (serialized in a base64 string).

xdr
string

The current value of the given ledger entry (serialized in a base64 string).

lastModifiedLedgerSeq
number

The ledger sequence number of the last time this entry was updated.

liveUntilLedgerSeq
number

Sequence number of the ledger.

Examples

Example request to the getNetwork method for a Counter(Address) ledger entry.

Request

curl -X POST \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getLedgerEntries",
"params": {
"keys": [
"AAAABgAAAAHMA/50/Q+w3Ni8UXWm/trxFBfAfl6De5kFttaMT0/ACwAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAAAg4dbAxsGAGICfBG3iT2cKGYQ6hK4sJWzZ6or1C5v6GAAAAAE="
]
}
}' \
https://soroban-testnet.stellar.org | jq

Result

{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"entries": [
{
"key": "AAAAB+qfy4GuVKKfazvyk4R9P9fpo2n9HICsr+xqvVcTF+DC",
"xdr": "AAAABgAAAAAAAAABzAP+dP0PsNzYvFF1pv7a8RQXwH5eg3uZBbbWjE9PwAsAAAAQAAAAAQAAAAIAAAAPAAAAB0NvdW50ZXIAAAAAEgAAAAAAAAAAIOHWwMbBgBiAnwRt4k9nChmEOoSuLCVs2eqK9Qub+hgAAAABAAAAAwAAAAw=",
"lastModifiedLedgerSeq": 2552504
}
],
"latestLedger": 2552990
}
}

Generating keys Parameters

The example above is querying a deployment of the increment example contract to find out what value is stored in the COUNTER ledger entry. This value can be derived using the following code snippets. You should be able to extrapolate from the provided examples how to get keys parameters for other types and values.

Python

note

If you are using the Python stellar_sdk to generate these keys, you will need to install the latest version of the SDK. This can be done like so:

pip install --upgrade stellar-sdk
from stellar_sdk import xdr, scval, Address

def get_ledger_key_symbol(contract_id: str, symbol_text: str) -> str:
ledger_key = xdr.LedgerKey(
type=xdr.LedgerEntryType.CONTRACT_DATA,
contract_data=xdr.LedgerKeyContractData(
contract=Address(contract_id).to_xdr_sc_address(),
key=scval.to_symbol(symbol_text),
durability=xdr.ContractDataDurability.PERSISTENT
),
)
return ledger_key.to_xdr()

print(
get_ledger_key_symbol(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI",
"COUNTER"
)
)

JavaScript

If you are using the JavaScript stellar-sdk to generate these keys, you will need to install the latest pre-release version of the SDK. This can be done like so:

yarn add @stellar/stellar-sdk
import { xdr, Address } from "@stellar/stellar-sdk";

const getLedgerKeySymbol = (contractId, symbolText) => {
const ledgerKey = xdr.LedgerKey.contractData(
new xdr.LedgerKeyContractData({
contract: new Address(contractId).toScAddress(),
key: xdr.ScVal.scvSymbol(symbolText),
durability: xdr.ContractDataDurability.persistent(),
}),
);
return ledgerKey.toXDR("base64");
};

console.log(
getLedgerKeySymbol(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI",
"COUNTER",
),
);

Requesting an Account

note

This functionality is included in the JavaScript stellar-sdk package as SorobanRpc.Server.getAccount(address).

Accounts are stored as ledger entries, so we can use this method to look up an account along with it's current sequence number.

import { xdr, Keypair } from '@stellar/stellar-sdk'

const getLedgerKeyAccount = (address) => {
const ledgerKey = xdr.LedgerKey.account(
new xdr.LedgerKeyAccount({
accountId: Keypair.fromPublicKey(address).xdrPublicKey(),
})
)
return ledgerKey.toXDR('base64')
}

console.log(getLedgerKeyAccount(
'GCU5YE6IVBOEZ5LUU5N2NB55VPB5YZNFERT65SSTVXTNMS7IEQWXKBM2'
))

# OUTPUT: AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQ==

We then take our output from this function, and use it as the element in the keys array parameter in our call to the getLedgerEntries method.

{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getLedgerEntries",
"params": {
"keys": ["AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQ=="]
}
}

And the response we get contains the LedgerEntryData with the current information about this account.

{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"entries": [
{
"key": "AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQ==",
"xdr": "AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQAAABdIdugAAAWpygAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA",
"lastModifiedLedgerSeq": "164303"
}
],
"latestLedger": 246819
}
}

We can then parse this result as an xdr.LedgerEntryData type.

const parsed = xdr.LedgerEntryData.fromXDR(
"AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQAAABdIdugAAAWpygAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA",
"base64",
);
console.log(parsed);

Requesting a Contract's Wasm Code

This can be a bit tricky to wrap your head around, but the conventions do make sense once you let it sink in.

In the previous examples, the COUNTER key was used as a LedgerKey while the incremented value was stored in a LedgerEntry. "Ledger Entry" is the relevant term to keep in mind during this discussion. That LedgerEntry was stored on the Stellar ledger, and was associated with a corresponding LedgerKey. LedgerKey: LedgerEntry works the same way you would think of almost any key: value storage system.

How Soroban Contract Deployment Works

When you deploy a contract, first the code is "installed" (i.e. it is uploaded onto the blockchain). This creates a LedgerEntry containing the Wasm byte-code, which is uniquely identified by its hash (that is, the hash of the uploaded code itself). Then, when the contract is "deployed," we create a LedgerEntry with a reference to that code's hash. So fetching the contract code is a two-step process:

  1. First, we look up the contract itself, to see which code hash it is referencing.
  2. Then, we can look up the raw Wasm byte-code using that hash.

Request the LedgerKey for the Contract Code

Python
from stellar_sdk import xdr, Address

def get_ledger_key_contract_code(contract_id: str) -> str:
ledger_key = xdr.LedgerKey(
type=xdr.LedgerEntryType.CONTRACT_DATA,
contract_data=xdr.LedgerKeyContractData(
contract=Address(contract_id).to_xdr_sc_address(),
key=xdr.SCVal(xdr.SCValType.SCV_LEDGER_KEY_CONTRACT_INSTANCE),
durability=xdr.ContractDataDurability.PERSISTENT
)
)
return ledger_key.to_xdr()

print(
get_ledger_key_contract_code(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI"
)
)
# OUTPUT: AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB
JavaScript
import { Contract } from "@stellar/stellar-sdk";

function getLedgerKeyContractCode(contractId) {
const instance = new Contract(contractId).getFootprint();
return instance.toXDR("base64");
}

console.log(
getLedgerKeyContractCode(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI",
),
);
// OUTPUT: AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB

We then take our output from this function, and use it as the element in the keys array parameter in our call to the getLedgerEntries method.

{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getLedgerEntries",
"params": {
"keys": ["AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB"]
}
}

And the response we get contains the LedgerEntryData that can be used to find the hash we must use to request the Wasm byte-code. This hash is the LedgerKey that's been associated with the deployed contract code.

{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"entries": [
{
"key": "AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB",
"xdr": "AAAABgAAAAAAAAABn4yVRAXOeXa1t1POzdT8tEcNP55alAOrUOq9vJIRJeIAAAAUAAAAAQAAABMAAAAA5DNtbckOGVRsNVb8L7X/lIhAOy2o5G6GkLKXvc7W8foAAAAA",
"lastModifiedLedgerSeq": "261603"
}
],
"latestLedger": 262322
}
}

Request the ContractCode Using the Retrieved LedgerKey

Now take the xdr field from the previous response's result object, and create a LedgerKey from the hash contained inside.

Python
from stellar_sdk import xdr

def get_ledger_key_wasm_id(contract_code_ledger_entry_data: str) -> str:
# First, we dig the wasm_id hash out of the xdr we received from RPC
contract_code_wasm_hash = xdr.LedgerEntryData.from_xdr(
contract_code_ledger_entry_data
).contract_data.val.instance.executable.wasm_hash
# Now, we can create the `LedgerKey` as we've done in previous examples
ledger_key = xdr.LedgerKey(
type=xdr.LedgerEntryType.CONTRACT_CODE,
contract_code=xdr.LedgerKeyContractCode(
hash=contract_code_wasm_hash
),
)
return ledger_key.to_xdr()

print(
get_ledger_key_wasm_id(
"AAAABgAAAAAAAAABn4yVRAXOeXa1t1POzdT8tEcNP55alAOrUOq9vJIRJeIAAAAUAAAAAQAAABMAAAAA5DNtbckOGVRsNVb8L7X/lIhAOy2o5G6GkLKXvc7W8foAAAAA"
)
)
# OUTPUT: AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6
JavaScript
import { xdr } from "@stellar/stellar-sdk";

function getLedgerKeyWasmId(contractCodeLedgerEntryData) {
const entry = xdr.LedgerEntryData.fromXDR(
contractCodeLedgerEntryData,
"base64",
);

const wasmHash = entry
.contractData()
.val()
.instance()
.executable()
.wasmHash();

let ledgerKey = xdr.LedgerKey.contractCode(
new xdr.LedgerKeyContractCode({
hash: wasmHash,
}),
);

return ledgerKey.toXDR("base64");
}

console.log(
getLedgerKeyWasmId(
"AAAABgAAAAAAAAABn4yVRAXOeXa1t1POzdT8tEcNP55alAOrUOq9vJIRJeIAAAAUAAAAAQAAABMAAAAA5DNtbckOGVRsNVb8L7X/lIhAOy2o5G6GkLKXvc7W8foAAAAA",
),
);
// OUTPUT: AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6

Now, finally we have a LedgerKey that correspond to the Wasm byte-code that has been deployed under the ContractId we started out with so very long ago. This LedgerKey can be used in a final request to the Soroban-RPC endpoint.

{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getLedgerEntries",
"params": {
"keys": ["AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6"]
}
}

And the response we get contains (even more) LedgerEntryData that we can decode and parse to get the actual, deployed, real-life contract byte-code. We'll leave that exercise up to you. You can check out what is contained using the "View XDR" page of the Stellar Lab.

{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"entries": [
{
"key": "AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6",
"xdr": "AAAABwAAAADkM21tyQ4ZVGw1Vvwvtf+UiEA7LajkboaQspe9ztbx+gAAAkgAYXNtAQAAAAEVBGACfn4BfmADfn5+AX5gAAF+YAAAAhkEAWwBMAAAAWwBMQAAAWwBXwABAWwBOAAAAwUEAgMDAwUDAQAQBhkDfwFBgIDAAAt/AEGAgMAAC38AQYCAwAALBzUFBm1lbW9yeQIACWluY3JlbWVudAAEAV8ABwpfX2RhdGFfZW5kAwELX19oZWFwX2Jhc2UDAgqnAQSSAQIBfwF+QQAhAAJAAkACQEKOutCvhtQ5QgEQgICAgABCAVINAEKOutCvhtQ5QgEQgYCAgAAiAUL/AYNCBFINASABQiCIpyEACyAAQQFqIgBFDQFCjrrQr4bUOSAArUIghkIEhCIBQgEQgoCAgAAaQoSAgICgBkKEgICAwAwQg4CAgAAaIAEPCwAACxCFgICAAAALCQAQhoCAgAAACwQAAAALAgALAHMOY29udHJhY3RzcGVjdjAAAAAAAAAAQEluY3JlbWVudCBpbmNyZW1lbnRzIGFuIGludGVybmFsIGNvdW50ZXIsIGFuZCByZXR1cm5zIHRoZSB2YWx1ZS4AAAAJaW5jcmVtZW50AAAAAAAAAAAAAAEAAAAEAB4RY29udHJhY3RlbnZtZXRhdjAAAAAAAAAAFAAAAAAAbw5jb250cmFjdG1ldGF2MAAAAAAAAAAFcnN2ZXIAAAAAAAAGMS43Ni4wAAAAAAAAAAAACHJzc2RrdmVyAAAALzIwLjMuMSNiYTA0NWE1N2FmOTcxZmM4M2U0NzU3NDZiNTlhNTAzYjdlZjQxNjQ5AA==",
"lastModifiedLedgerSeq": 368441,
"liveUntilLedgerSeq": 2442040
}
],
"latestLedger": 370940
}
}