Saltar al contenido principal

getLedgerEntries

For reading the current value of ledger entries directly.

This method enables querying live ledger state: 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

(2)

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]

An array of LedgerKeys. The maximum number of ledger keys accepted is 200.

2. xdrFormat

Lets the user choose the format in which the response should be returned - either as unpacked JSON or as base64-encoded XDR strings. Note that you should not rely on any schema for the JSON, as it will change when the underlying XDR changes.

string

Specifies whether XDR should be encoded as Base64 (default or 'base64') or JSON ('json').

Result

(getLedgerEntriesResult)
latestLedger
number
required

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

entries
array[object]

Array of objects containing all found ledger entries

key
string

The LedgerKey corresponding to the ledger entry (base64 string).

xdr
string

The key's current LedgerEntryData value (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
}
}

Creando claves del ledger

El ledger de Stellar es, en cierto modo, esencialmente un almacén de pares clave-valor. Las claves son instancias de LedgerKey y los valores son instancias de LedgerEntry. Un producto interesante del diseño interno del almacén es que la clave es un subconjunto de la entrada: más adelante veremos más sobre esto.

El método getLedgerEntries devuelve los "valores" (o "entradas") para un conjunto dado de "claves". Las claves del ledger vienen en muchas formas, y repasaremos las más comúnmente utilizadas en esta página junto con tutoriales sobre cómo crear y usarlas.

Tipos de LedgerKey

La fuente de verdad siempre debe ser el XDR definido en el protocolo. LedgerKey son un tipo de unión definido en Stellar-ledger-entries.x. Hay 10 formas diferentes que puede tomar una clave de ledger:

  1. Cuenta: define holísticamente una cuenta de Stellar, incluyendo su saldo, firmantes, etc. (ver Cuentas)
  2. Línea de confianza: define una línea de saldo para un activo no nativo emitido en la red (ver changeTrustOp)
  3. Oferta: define una oferta hecha en el DEX de Stellar (ver Liquidez en Stellar)
  4. Datos de Cuenta: define entradas de datos clave-valor adjuntas a una cuenta (ver manageDataOp)
  5. Saldo reclamable: define un saldo que puede o no ser reclamable activamente (ver Saldos Reclamables)
  6. Fondo de Liquidez: define la configuración de un fondo de liquidez constante nativo entre dos activos (ver Liquidez en Stellar)
  7. Datos de Contrato: define un conjunto de datos que se almacena en un contrato bajo una clave
  8. Código de Contrato: define el bytecode Wasm de un contrato
  9. Ajuste de Configuración: define la configuración de red actualmente activa
  10. TTL: define el tiempo de vida de una entrada de datos de contrato o código asociada

Nos enfocaremos en un subconjunto de estos para obtener el máximo valor, pero una vez que entiendas cómo crear y analizar algunas claves y entradas, puedes extrapolar a todas ellas.

Cuentas

Para obtener una cuenta, todo lo que necesitas es su clave pública:

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

const publicKey = "GALAXYVOIDAOPZTDLHILAJQKCVVFMD4IKLXLSZV5YHO7VY74IWZILUTO";
const accountLedgerKey = xdr.LedgerKey.ledgerKeyAccount(
new xdr.LedgerKeyAccount({
accountId: Keypair.fromPublicKey(publicKey).xdrAccountId(),
}),
);
console.log(accountLedgerKey.toXDR("base64"));

Esto te dará los detalles completos de la cuenta.

const accountEntryData = (
await s.getLedgerEntries(accountLedgerKey)
).entries[0].account();

Si solo quieres echar un vistazo a la estructura, puedes pasar el valor base64 crudo que hemos registrado arriba al Laboratorio (o a través de curl si pasas "xdrFormat": "json" como un parámetro adicional a getLedgerEntries) y ver todos los campos posibles. También puedes explorarlos en código, por supuesto:

console.log(
`Account ${publicKey} has ${accountEntryData
.balance()
.toString()} stroops of XLM and is on sequence number ${accountEntryData
.seqNum()
.toString()}`,
);

Líneas de confianza

Una línea de confianza es una entrada de saldo para cualquier activo no nativo (como USDC de Circle). Para obtener una, necesitas el propietario de la línea de confianza (una clave pública como para Cuentas) y el activo en cuestión:

const trustlineLedgerKey = xdr.LedgerKey.ledgerKeyTrustLine(
new xdr.LedgerKeyTrustLine({
accountId: Keypair.fromPublicKey(publicKey).xdrAccountId(),
asset: new Asset(
"USDC",
"GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
).toTrustLineXDRObject(),
}),
);

Al igual que en una cuenta, la entrada resultante tiene un saldo, pero también tiene un límite y banderas para controlar cuánto de ese activo se puede mantener. El activo, sin embargo, puede ser un activo emitido o un fondo de liquidez:

let asset: string;
let rawAsset = trustlineEntryData.asset();

switch (rawAsset.switch().value) {
case AssetType.assetTypeCreditAlphanum4().value:
asset = Asset.fromOperation(
xdr.Asset.assetTypeCreditAlphanum4(rawAsset.alphaNum4()),
).toString();
break;

case AssetType.assetTypeCreditAlphanum12().value:
asset = Asset.fromOperation(
xdr.Asset.assetTypeCreditAlphanum12(rawAsset.alphaNum12()),
).toString();
break;

case AssetType.assetTypePoolShare().value:
asset = rawAsset.liquidityPoolId().toXDR("hex");
break;
}

console.log(
`Account ${publicKey} has ${trustlineEntryData
.balance()
.toString()} stroops of ${asset} with a limit of ${trustlineEntryData
.balance()
.toString()}`,
);

Datos de Contrato

Supongamos que hemos desplegado el [incrementar ejemplo de contrato] y queremos averiguar qué valor está almacenado en la clave del ledger COUNTER. Para crear la clave:

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"
)
)

Código de Contrato Wasm

Para entender esto, necesitamos comprender cómo funciona el despliegue de contratos inteligentes:

  • Cuando despliegas un contrato, primero el código se "instala" (es decir, se carga en la blockchain), creando una LedgerEntry con el bytecode Wasm que puede ser identificado de manera única por su hash (es decir, el hash del código subido).
  • Luego, cuando una instancia de contrato es "instanciada," creamos una LedgerEntry con una referencia al hash de ese código. Esto significa que muchos contratos pueden apuntar al mismo código Wasm.

Por lo tanto, obtener el código del contrato es un proceso de dos pasos:

  1. Primero, buscamos el contrato mismo, para ver a qué hash de código está haciendo referencia.
  2. Luego, podemos buscar el bytecode Wasm crudo usando ese hash.

1. Encuentra la clave del ledger para la instancia del contrato

from stellar_sdk import xdr, Address

def get_ledger_key_contract_code(contract_id: str) -> xdr.LedgerKey:
return 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
)
)

print(get_ledger_key_contract_code(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI"
))

Una vez que tengamos la entrada del ledger (a través de getLedgerEntries, ver abajo), podemos extraer el hash Wasm:

2. Solicita el ContractCode utilizando el LedgerKey recuperado

Ahora toma el campo xdr del objeto result de la respuesta anterior, y crea un LedgerKey a partir del hash contenido dentro.

from stellar_sdk import xdr

def get_ledger_key_wasm_id(
# received from getLedgerEntries and decoded
contract_data: xdr.ContractDataEntry
) -> xdr.LedgerKey:
# First, we dig the wasm_id hash out of the xdr we received from RPC
wasm_hash = 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=wasm_hash
),
)
return ledger_key

Ahora, finalmente tenemos un LedgerKey que corresponde al bytecode Wasm que ha sido desplegado bajo el contractId con el que comenzamos hace tanto tiempo. Este LedgerKey puede ser utilizado en una solicitud final a getLedgerEntries. En esa respuesta obtendremos un LedgerEntryData correspondiente a un ContractCodeEntry que contendrá el bytecode del contrato real, desplegado y en la vida real:

const theHashData: xdr.ContractDataEntry = await getLedgerEntries(
getLedgerKeyContractCode("C..."),
).entries[0].contractData();

const theCode: Buffer = await getLedgerEntries(getLedgerKeyWasmId(theHashData))
.entries[0].contractCode()
.code();

Obteniendo realmente los datos de la entrada del ledger

Una vez que hayamos aprendido a crear y analizar estos (lo cual ya hemos hecho antes), el proceso para obtenerlos es siempre idéntico. Si conoces el tipo de clave que obtuviste, aplicas el método de acceso correspondiente una vez que los hayas recibido del método getLedgerEntries:

const s = new Server("https://soroban-testnet.stellar.org");

// assume key1 is an account, key2 is a trustline, and key3 is contract data
const response = await s.getLedgerEntries(key1, key2, key3);

const account = response.entries[0].account();
const contractData = response.entries[2].contractData();
const contractCode = response.entries[1].contractCode();

Ahora, finalmente tenemos un LedgerKey que corresponde al bytecode Wasm que ha sido desplegado bajo el ContractId con el que comenzamos hace tanto tiempo. Este LedgerKey puede ser utilizado en una solicitud final al punto final Stellar-RPC.

{
"jsonrpc": "2.0",
"id": 12345,
"method": "getLedgerEntries",
"params": {
"keys": [
"AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6",
"AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB"
"AAAABgAAAAAAAAABn4yVRAXOeXa1t1POzdT8tEcNP55alAOrUOq9vJIRJeIAAAAUAAAAAQAAABMAAAAA5DNtbckOGVRsNVb8L7X/lIhAOy2o5G6GkLKXvc7W8foAAAAA"
]
}
}

Luego puedes inspeccionarlos según sea necesario. Cada una de las entradas anteriores sigue el XDR para esa estructura de LedgerEntryData con precisión. Por ejemplo, el AccountEntry está en Stellar-ledger-entries.x#L191 y puedes usar .seqNum() para acceder a su número de secuencia actual, como hemos mostrado. En JavaScript, puedes ver los métodos apropiados en la definición de tipo.

Ver y entender XDR

Si no deseas analizar el XDR programáticamente, también puedes aprovechar tanto el CLI de Stellar como el Laboratorio de Stellar para obtener una vista legible por humanos de las claves y entradas del ledger. Por ejemplo,

echo 'AAAAAAAAAAAL76GC5jcgEGfLG9+nptaB9m+R44oweeN3EcqhstdzhQ==' | stellar xdr decode --type LedgerKey --output json-formatted
{
"account": {
"account_id": "GAF67IMC4Y3SAEDHZMN57J5G22A7M34R4OFDA6PDO4I4VINS25ZYLBZZ"
}
}