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á todos los detalles 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 en crudo que registramos anteriormente al Laboratorio (o mediante curl si pasas "xdrFormat": "json" como un parámetro adicional a getLedgerEntries) y ver todos los posibles campos. También puedes profundizar en ellos en el 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 trustline 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 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
.limit()
.toString()}`,
);

Datos del contrato

Supongamos que hemos desplegado el [increment example contract] y queremos averiguar qué valor está almacenado en la clave de ledger COUNTER. Para crear la clave:

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

const getLedgerKeySymbol = (
contractId: string,
symbolText: string,
): xdr.LedgerKey => {
return xdr.LedgerKey.contractData(
new xdr.LedgerKeyContractData({
contract: new Address(contractId).toScAddress(),
key: xdr.ScVal.scvSymbol(symbolText),
// The increment contract stores its state in persistent storage,
// but other contracts may use temporary storage
// (xdr.ContractDataDurability.temporary()).
durability: xdr.ContractDataDurability.persistent(),
}),
);
};

const ledgerKey = getLedgerKeySymbol(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI",
"COUNTER",
);

Código Wasm del contrato

Para entender esto, necesitamos comprender cómo funciona la implementación de contratos inteligentes:

  • Cuando despliegas un contrato, primero el código se "instala" (es decir, se sube a la blockchain), creando una LedgerEntry con el byte-código Wasm que se puede identificar de manera única por su hash (es decir, el hash del código subido).
  • Luego, cuando una instancia de contrato se "instancia," 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 en sí, para ver qué hash de código está referenciando.
  2. Luego, podemos buscar el código de bytes Wasm sin procesar usando ese hash.

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

import { Contract } from "@stellar/stellar-sdk";

function getLedgerKeyContractCode(contractId): xdr.LedgerKey {
return new Contract(contractId).getFootprint();
}

console.log(
getLedgerKeyContractCode(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI",
),
);

Una vez que tengamos la entrada del ledger (a través de getLedgerEntries, ver abajo), podemos extraer el hash de 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.

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

function getLedgerKeyWasmId(
contractData: xdr.ContractDataEntry,
): xdr.LedgerKey {
const wasmHash = contractData.val().instance().executable().wasmHash();

return xdr.LedgerKey.contractCode(
new xdr.LedgerKeyContractCode({
hash: wasmHash,
}),
);
}

Ahora, finalmente tenemos un LedgerKey que corresponde al código de bytes Wasm que ha sido implementado 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 código de bytes del contrato real implementado:

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

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

Realmente obteniendo los datos de entrada del ledger

Una vez que hemos aprendido a crear y analizar estos (lo cual ya hemos hecho anteriormente), el proceso para realmente obtenerlos es siempre idéntico. Si conoces el tipo de clave que has obtenido, aplicas el método de acceso correspondiente una vez que los has 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 trustline = response.entries[1].trustline();
const contractData = response.entries[2].contractData();

Ahora, finalmente tenemos un LedgerKey que corresponde al código de bytes Wasm que ha sido implementado bajo el ContractId con el que comenzamos hace tanto tiempo. Este LedgerKey puede ser usado en una solicitud final al punto final de Stellar-RPC.

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

Luego puedes inspeccionarlos en consecuencia. Cada una de las entradas anteriores sigue el XDR para esa estructura 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 comprender XDR

Si no quieres parsear el XDR programáticamente, también puedes aprovechar tanto el Stellar CLI como el Stellar Lab 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"
}
}