Solana Account Archive: consultar el estado de una cuenta en cualquier slot
Autor: Alchemy

El Account Archive responde getAccountInfo para cualquier cuenta de Solana en cualquier slot histórico (con excepción de las vote accounts y los sysvars por slot), con una ventana de cobertura histórica profunda y en constante crecimiento que nunca se poda. Usa el parámetro slot para leer el estado en un punto en el tiempo, o lastUpdateBeforeSlot / firstUpdateAfterSlot para recorrer el historial de actualizaciones de una cuenta. Las lecturas se sirven con una latencia mediana del orden de microsegundos.
Solana solo recuerda el presente
Hay un detalle sobre Solana que sorprende incluso a builders con experiencia: un validador almacena exactamente una copia de cada cuenta, la más reciente. Cada escritura sobrescribe el estado anterior en el mismo lugar, así que en el momento en que se toca una cuenta, lo que era antes desaparece. Incluso para un slot del que el nodo todavía tiene los bloques completos, el estado de la cuenta en ese slot ya no existe en ningún lugar de la máquina.
Esto es una característica, no un defecto. Es parte de por qué Solana es rápida. Pero significa que toda una clase de preguntas razonables no tienen respuesta, como:
- Debugging: "Nuestra liquidación se disparó en el slot 285,401,337. ¿Cuál era la cuenta del oracle de precio exactamente en ese slot?"
- Backtesting: "Reconstruir las reservas de este pool en cada punto de los últimos seis meses."
- Auditorías: "Demostrar qué tenía esta token account el 3 de marzo."
- Recuperación: "Nuestro indexer estuvo caído cuatro horas. Reconstruir exactamente las transiciones de estado que nos perdimos."
Podrías pensar que getBlock cubre esto, pero no es así. Devuelve las transacciones de un slot pasado y sus balances pre/post, no los datos de la cuenta. Para la mayoría de las aplicaciones, el estado que importa vive en los bytes de datos: el order book, el price feed, la posición o la configuración.
Solana Account Archive trae de vuelta el historial completo. Responde getAccountInfo para cualquier cuenta en cualquier slot desde julio de 2025, usando las mismas formas de solicitud y respuesta que ya usas. Dos cosas lo distinguen. El archivo nunca se poda, así que la ventana consultable solo crece con el tiempo. Y omite la contabilidad interna de la propia chain por slot (vote accounts y un puñado de sysvars que se reescriben en cada slot), ya que eso es ruido, no historial útil para quienes construyen aplicaciones.
La API: getAccountInfo, extendido
Deliberadamente no inventamos un nuevo método. El archivo habla JSON-RPC estándar e implementa getAccountInfo con todas las opciones de configuración que ya conoces: encoding (base64, base58, base64+zstd, jsonParsed), commitment, dataSlice, y minContextSlot, más tres parámetros nuevos y mutuamente excluyentes:
Estos tres también son mutuamente excluyentes con minContextSlot; combinarlo con cualquiera de ellos se rechaza. Si omites los tres, obtienes un getAccountInfo normal con el estado más reciente; el archivo es un superconjunto compatible. Aquí hay una lectura completa en un punto en el tiempo, el estado de una token account en el slot 400,000,000:
curl $ARCHIVE_URL -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getAccountInfo",
"params": [
"3emsAVdmGKERbHjmGfQ6oZ1e35dkf5iYcS6U4CPKFVaa",
{ "encoding": "jsonParsed", "slot": 400000000 }
]
}'La respuesta tiene la forma estándar de getAccountInfo:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"context": { "apiVersion": "4.1.0", "slot": 400000000 },
"value": {
"lamports": 2040821,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"data": {
"program": "spl-token",
"parsed": {
"info": {
"isNative": false,
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"owner": "7VHUFJHWu2CuExkJcJrzhQPJ2oygupTWkL2A2For4BmE",
"state": "initialized",
"tokenAmount": {
"amount": "1056153754430274",
"decimals": 6,
"uiAmount": 1056153754.430274,
"uiAmountString": "1056153754.430274"
}
},
"type": "account"
},
"space": 165
},
"executable": false,
"rentEpoch": 18446744073709551615,
"space": 165
}
}
}Nota la semántica: slot: S significa el estado a partir de S. Si la cuenta se escribió por última vez en el slot S - 40,000 y no se tocó desde entonces, obtienes esa escritura, exactamente lo que habría visto cualquier programa que se ejecutara en el slot S. Y jsonParsed también funciona con estado histórico: se aplican los mismos decoders que usa un nodo RPC estándar sobre los bytes históricos, así que una token account de los inicios de la ventana de cobertura vuelve decodificada, no opaca.
Un iterador sobre el historial de una cuenta
lastUpdateBeforeSlot y firstUpdateAfterSlot convierten al archivo en un iterador sobre cada transición de estado de una cuenta.
lastUpdateBeforeSlot devuelve el slot real de la escritura encontrada en context.slot, así que cada respuesta es el cursor para la siguiente solicitud:
# Walk every state transition of an account, newest to oldest.
cursor = current_slot + 1
while True:
try:
result = rpc("getAccountInfo", [pubkey, {"lastUpdateBeforeSlot": cursor}])
except RpcError as e:
if e.code == -32020: # walked past the edge of coverage; done
break
raise
slot = result["context"]["slot"] # the slot this write landed at
handle(slot, result["value"]) # value is null if this write closed the account
cursor = slot # strictly-before: no overlap, no gapsEl recorrido tiene exactamente un punto de detención: el error -32020, que significa que el cursor pasó el borde de la cobertura del archivo. Un valor null en el camino significa lo mismo que siempre significa en getAccountInfo: la cuenta no existía a partir de ese slot; en este caso, porque la escritura en context.slot la eliminó. Vuelve a pasar ese slot como cursor y el recorrido continúa a través de la vida anterior de la cuenta.
firstUpdateAfterSlot hace lo inverso: en lugar de retroceder en el tiempo, avanza, devolviendo la siguiente escritura estrictamente posterior a un slot dado. Es ideal para un indexer que se está poniendo al día desde un slot conocido y quiere cada estado intermedio, no solo el más reciente.
Entre los dos, puedes recorrer todo el ciclo de vida de una cuenta: cada cambio de balance, cada mutación de datos, cada cambio de propiedad, con el slot exacto en que ocurrió cada uno.
Registrar nuevas escrituras a medida que ocurren
Registrar el estado hacia adelante es la parte fácil. El archivo escucha la red a través de un Geyser stream y registra las escrituras de cuentas a medida que ocurren, con dos reglas que mantienen el registro confiable:
Solo los slots finalizados entran al archivo. Solana bifurca constantemente en la punta, y un bloque que parece real durante unos segundos puede simplemente desaparecer. El archivo retiene las actualizaciones de cada slot hasta que la red lo finaliza, así que el registro permanente contiene únicamente lo que realmente ocurrió.
Nada se pierde silenciosamente. Cada bloque de Solana nombra a su padre, así que cualquier bloque que el stream se pierda (un hipo, una reconexión, un despliegue de servicio) se detecta de inmediato y se rellena.
La capa de almacenamiento subyacente es una historia aparte. Lo que importa aquí es el resultado: las lecturas en un punto en el tiempo son lo suficientemente rápidas para estar en una ruta caliente, con una latencia mediana del orden de microsegundos (medida en nuestra capa de servicio interna).
Reconstruyendo el último año
Ingerir datos desde hoy en adelante te da un archivo que será útil el próximo año. Nosotros quisimos también el último año, lo que significa reconstruir el estado de las cuentas para decenas de millones de slots que ya habían ocurrido, en una chain que no conserva historial. Y es mucho historial: Solana produce un bloque aproximadamente cada 400 ms, cerca de 216,000 slots por día. En un año eso son ~78 millones de slots, cientos de miles de millones de actualizaciones de cuentas, y más de un petabyte de datos de cuentas sin procesar, con cada slot conteniendo miles de escrituras de cuentas con el payload de datos completo adjunto.
Por qué "simplemente parsear las transacciones" no funciona
Existe un atajo tentador: obtener los bloques históricos y decodificar qué le hizo cada transacción a cada cuenta. Falla por una razón fundamental que vale la pena interiorizar: una transacción de Solana no es una descripción de un cambio de estado; es la invocación de un programa.
Lo que realmente le sucede a una cuenta depende de la ejecución del programa: CPIs que se ramifican hacia otros programas, sysvars leídos a mitad de ejecución, medición de compute, la semántica precisa del runtime en ese slot. El bloque registra qué cuentas tocó una transacción y cómo se movieron los balances, pero los bytes de datos, la parte que realmente te interesa, se determinan solo ejecutando el código.
Hay una sola manera fiel de saber qué le hizo una transacción a una cuenta: ejecutarla, con el runtime real, contra el estado real sobre el que se ejecutó.
Replay: volver a ejecutar la chain
Así que eso es lo que hacemos. El pipeline de backfill es, en esencia, un validador que revive la historia:
- Arrancar desde un snapshot confiable. La Solana Foundation mantiene archivos públicos de snapshots históricos: capturas completas de cada cuenta en un slot dado. Cargar el snapshot en el slot
Anos da el estado completo y canónico de varios cientos de millones de cuentas en ese momento. - Reproducir cada bloque hacia adelante. Desde
A + 1, cada bloque histórico se ejecuta a través del runtime real del validador: ejecución real, no simulación, no parseo de logs. Cada transacción se ejecuta; las escrituras de cuentas que produce el runtime se capturan e indexan, slot por slot. - Detenerse en el siguiente snapshot y demostrarlo. Este es el paso que hace que todo el proceso sea confiable. Cuando el replay llega al slot
B, donde existe el siguiente snapshot canónico, comparamos nuestro estado final reproducido contra él, incluyendo el accounts lattice hash: un compromiso criptográfico sobre el conjunto completo de cuentas que la propia red calcula y acuerda. Si un solo byte de una sola cuenta diverge en algún punto del rango, los hashes no coincidirán y el rango se rechaza. No asumimos que el replay es correcto; cada rango de backfill se verifica contra la verdad de consenso antes de confiar en él.
Los bloques antiguos necesitan el runtime de su época
Aquí está la complicación que hace que el replay sea genuinamente difícil: la semántica de ejecución de Solana está versionada en el tiempo. Los feature gates se activan en épocas específicas, las reglas de compute budget cambian, se agregan syscalls, se corrigen comportamientos de casos límite. Una transacción de hace doce meses debe reproducirse con un runtime que se comporte exactamente como lo hacía el cluster en ese slot. Reproducirla con el validador de hoy hará que el paso 3 te diga, en voz alta, que fabricaste una historia que nunca ocurrió.
En la práctica, la flota de backfill ejecuta varios linajes de validadores fijados en versiones específicas, cada uno responsable de la época que puede reproducir fielmente, con el trabajo dividido a lo largo de los límites de época para que cada fragmento comience y termine en un snapshot verificable. Extender el archivo más atrás en el tiempo es en gran medida cuestión de levantar la época correcta del runtime y pagar el cómputo del replay. Y como cada fragmento alineado a una época es independiente, el historial es perfectamente paralelizable; hacer el backfill de un año es principalmente una cuestión de cuántos workers de replay se ejecutan a la vez.
Confianza, verificada continuamente
El backfill verificado por hashes cubre el pasado; una preocupación aparte es si la ruta de servicio se mantiene honesta en producción. Por eso un watchdog independiente valida cruzadamente y de forma continua las respuestas del archivo contra nodos RPC en vivo, a través de la misma API pública que usarías. La exactitud es primordial para nosotros, así que se reverifica cada minuto que el servicio está en funcionamiento. Un enfoque de múltiples capas: hashes anclados en consenso para el historial de backfill, escrituras condicionadas a la finalización en la punta, y validación cruzada en vivo continua por encima, asegura que puedas confiar en un registro de la verdad que avanza en el tiempo.
Qué puedes construir con esto
Cada pregunta del inicio de este post ahora es una llamada a la API:
- "¿Cuál era la cuenta del oracle exactamente en ese slot?" Un solo
getAccountInfoconslotconfigurado. Obtén el estado exacto de cada cuenta que leyó una transacción fallida, en el slot en que se ejecutó. Ya no hace falta reconstruir los inputs del oracle a partir de capturas de pantalla y conjeturas. - "Reconstruir las reservas de este pool durante seis meses." Muestrea la cuenta del pool en una cadencia de slots fija y haz backtesting contra lo que realmente estaba en la chain, no una aproximación armada a partir de eventos de trade.
- "Demostrar qué tenía esta token account el 3 de marzo." "A partir del slot S, la cuenta X contenía exactamente estos bytes." Eso es respondible, y anclado a hashes que la propia red acordó.
- "Reconstruir las transiciones de estado que nuestro indexer se perdió." Avanza página por página con
firstUpdateAfterSlotdesde tu último slot conocido y recibe cada estado intermedio, en orden.
Y una que la introducción no preguntó: historial de balances y posiciones sin ejecutar un indexer en absoluto. Recorre una token account hacia atrás con lastUpdateBeforeSlot y tienes su línea de tiempo completa. Para el historial de holdings de tokens de una wallet completa en un slot pasado, ver también historial de balances de tokens en Solana.
Empieza ahora
Solana se mantiene rápida manteniendo a los validadores livianos y enfocados en el estado actual. El estado histórico de las cuentas simplemente ha vivido en otro lugar, y hasta ahora el ecosistema ha tenido que trabajar alrededor de eso. Solana Account Archive cambia eso. Con ingesta en vivo condicionada a la finalización y un pipeline de backfill que reejecuta el historial a través de runtimes fieles a cada época y demuestra el resultado contra hashes de consenso, el getAccountInfo histórico se convierte en solo otra llamada RPC: mismo método, misma forma de respuesta, un parámetro adicional.
En un próximo post profundizaremos en la capa de almacenamiento: cómo se organiza en disco un año de escrituras de cuentas de Solana para que tanto la ingesta de nuevas actualizaciones como la respuesta a consultas en un punto en el tiempo se mantengan rápidas. Todo lo que el archivo indexa está comprimido, almacenado con al menos 3 réplicas por redundancia, y nunca se poda, así que la ventana consultable solo crece.
Empieza con Solana, y contáctanos si tu caso de uso necesita historial más profundo, o si quieres explorar soluciones especializadas y precios a escala.
Preguntas frecuentes
¿Cómo obtengo el estado de una cuenta de Solana en un slot específico?
Llama a getAccountInfo en el Account Archive con la pubkey de la cuenta y un parámetro slot en el objeto de configuración: getAccountInfo(pubkey, { "slot": S }). La respuesta tiene la forma estándar de getAccountInfo y devuelve el estado de la cuenta a partir del slot S, la última escritura en o antes de S.
¿Cómo obtengo el historial completo de actualizaciones de una cuenta de Solana?
Recorre con los parámetros de cursor. getAccountInfo(pubkey, { "lastUpdateBeforeSlot": S }) devuelve la escritura más reciente estrictamente anterior a S, con el slot real de la escritura en context.slot; vuelve a pasar ese slot como el siguiente cursor para recorrer hacia atrás cada transición de estado. firstUpdateAfterSlot recorre hacia adelante de la misma manera.
¿Cuál es la diferencia entre slot, lastUpdateBeforeSlot y firstUpdateAfterSlot?
slot es una lectura en un punto en el tiempo: el estado a partir del slot S, inclusive. lastUpdateBeforeSlot y firstUpdateAfterSlot son cursores de historial excluyentes: la escritura más cercana estrictamente antes o estrictamente después de S. Los tres son mutuamente excluyentes; omítelos todos para obtener una lectura normal del estado más reciente.
¿La codificación jsonParsed funciona con el estado histórico de las cuentas?
Sí. Se aplican los mismos decoders de cuentas que usa un nodo RPC estándar de Solana sobre los bytes históricos, así que las token accounts, mints y otras cuentas de programas conocidos vuelven parseadas en cualquier slot dentro de la cobertura. Todas las codificaciones estándar funcionan: base64, base58, base64+zstd, y jsonParsed, además de dataSlice.
¿Hasta qué punto en el pasado puedo consultar?
La cobertura actualmente se extiende hasta julio de 2025, y el backfill la va extendiendo más atrás con el tiempo. El historial nunca se poda, así que todo lo indexado permanece consultable y la ventana solo crece.
¿Cómo se sabe que los datos históricos son correctos?
Los rangos de backfill se producen reejecutando cada transacción a través del runtime del validador de la época correspondiente, y el estado resultante se verifica contra los propios artefactos de consenso de la red, incluyendo el accounts lattice hash de los snapshots canónicos. La ingesta en vivo solo confirma slots finalizados, y un watchdog independiente valida cruzadamente y de forma continua los resultados servidos contra nodos RPC en vivo.
¿Se cubren todas las cuentas?
Todas las cuentas excepto la contabilidad interna de la chain por slot: las vote accounts y los tres sysvars que se reescriben en cada slot (SlotHashes, SlotHistory, RecentBlockhashes) quedan excluidos del índice. Las cuentas de programas, token accounts, mints, PDAs, wallets, y el resto de los sysvars (Clock, Rent, etc.) están todos cubiertos.
¿Necesito un nuevo SDK o cliente?
No. Cualquier cliente JSON-RPC de Solana funciona. El archivo implementa getAccountInfo estándar, y los parámetros históricos son solo campos adicionales en el objeto de configuración existente.
Boletín de Alchemy
Entérate primero de los lanzamientos
Suscríbete a nuestro boletín
Recibe las últimas actualizaciones de productos y recursos de Alchemy
Al ingresar tu correo electrónico, aceptas recibir nuestras comunicaciones de marketing y actualizaciones de productos. Reconoces que Alchemy procesa la información que recibimos de acuerdo con nuestro Aviso de Privacidad. Puedes cancelar tu suscripción en cualquier momento.
Artículos relacionados

Glamsterdam: la guía completa para desarrolladores de Ethereum
Glamsterdam ya está en Sepolia. La guía completa sobre lo que significa para los desarrolladores y cómo Alchemy se preparó para la actualización de la red.

¿Con qué proveedor de RPC deberías construir en Tokio?
Comparamos cinco de los proveedores de RPC que sirven Tokio en cinco cadenas. Así se comparan, y dónde importan las diferencias para los equipos sensibles a la latencia.

Diseño de lecturas RPC de Solana para velocidad y confiabilidad líderes en la industria
Alchemy tiene la latencia de lectura de Solana más baja: 9.21 ms, cerca de 26% más rápido que el siguiente proveedor.