NUEVO: Helius adquiere Light Protocol
cómo deserializar datos de cuentas en Solana
Blog/Desarrollo

Solana Dev 101 - Deserialización de datos de cuentas en Solana

Responsable de Relaciones con DesarrolladoresHunter Davis en LinkedIn
5 min de lectura

Introducción

Interactuar con datos en Solana puede ser difícil. Los datos de cuentas y transacciones suelen estar codificados, lo cual mejora la eficiencia, pero complica el trabajo de desarrollo.

Solana usa Borsh (serializador de representación binaria de objetos para hashing) para serializar sus datos, lo que incluye tanto la serialización como la deserialización. Una de las principales ventajas de Borsh es su determinismo, que garantiza una salida serializada uniforme para una misma entrada.

En este tutorial, aprenderás a deserializar los datos de una cuenta de tokens y devolverlos en un formato legible que puedas usar. Verás un ejemplo sencillo que desglosa la información sin procesar de la cuenta de un NFT a partir de su dirección de mint mediante la biblioteca Token Program.

A continuación, puedes ver cómo transformaremos los datos sin procesar de una cuenta en algo más legible:

Puedes consultar el código completo de este tutorial clonando nuestro repositorio deserialize-account aquí.

Requisitos previos

Estos son los requisitos previos para este tutorial:

Configuración del entorno

Clona el repositorio de ejemplo:

Código
git clone https://github.com/helius-labs/deserialize-base.git

Ve al directorio del proyecto:

Código
cd deserialize-base

Instala npm:

Código
npm install

¡Ya tienes el proyecto configurado!

Ahora puedes comenzar a crear el proceso para deserializar los datos de la cuenta de una dirección de mint determinada.

Pasos para crear la solución

Sigue estos pasos:

1. Obtén los datos de la cuenta

En nuestro archivo /src/deserialize.ts, importemos los módulos necesarios:

Código
import { Connection, PublicKey } from "@solana/web3.js";

Más adelante, usarás esto para definir nuestra conexión con Solana y el PublicKey del mint cuyos datos quieres deserializar.

Debajo, configurarás la función principal.

También configurarás nuestra conexión con Solana mediante nuestra URL RPC de Helius y podrás establecer el mint que deserializarás en el tutorial.

Código
async function deserializeMint() {
		// CONNECTION TO SOLANA USING HELIUS
    const rpc = 'https://rpc.helius.xyz/?api-key=';
    const connection = new Connection(rpc);
		// MINT THAT WE ARE DESERIALIZING
    const mint = new PublicKey('6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K');

}
deserializeMint()

Asegúrate de reemplazar api-key con tu propia clave de API de Helius en el código anterior. También puedes reemplazar el mint usado por un ejemplo propio para este tutorial.

A continuación, configurarás un bloque try/catch para obtener los datos sin procesar de la cuenta de este mint:

Código
try {
    let { data } = (await connection.getAccountInfo(mint)) || {};
    if (!data) {
      return;
    }
    console.log(data);
  } catch {
    return null;
  }

En el paso anterior, usas nuestra conexión para hacer una llamada RPC en Solana para getAccountInfo. Esto devolverá los datos iniciales que necesitas desglosar.

Si no se encuentran datos, devolverá null. De lo contrario, mostrará los resultados de la búsqueda en tu terminal.

Ahora puedes ejecutar ts-node deserialize para ver los resultados.

Deberías ver un resultado similar al siguiente:

El objetivo de la deserialización es convertir estos datos en un formato legible.

Para hacerlo, tendrás que consultar el código fuente y encontrar la estructura que espera el programa que creó los datos.

2. Configura los tipos de cuenta

En este ejemplo, quieres obtener AccountInfo para un mint de SPL 6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K.

Para hacerlo, tendrás que desglosar los tipos de los datos sin procesar del mint y el diseño del búfer que proporciona la Solana Program Library. Comprender la estructura de los datos proporcionados es un paso esencial para deserializar cualquier dato en Solana.

La imagen anterior muestra el struct RawMint y MintLayout definidos por el programa. Puedes copiarlos directamente a nuestro archivo de tipos para usarlos.

Ahora ve a nuestro directorio ./src/types.

En el archivo /src/types.ts, configura la importación de nuestros tipos:

Código
import { PublicKey } from "@solana/web3.js";
import { u32, u8, struct } from "@solana/buffer-layout";
import { publicKey, u64, bool } from "@solana/buffer-layout-utils";

Esto definirá el formato y el diseño de los datos sin procesar del mint necesarios para deserializar los datos de la cuenta del NFT de este ejemplo.

Ahora puedes configurar nuestra interfaz y nuestro diseño de forma similar a lo anterior.

Código
// Defining RawMint from https://github.com/solana-labs/solana-program-library/blob/48fbb5b7c49ea35848442bba470b89331dea2b2b/token/js/src/state/mint.ts#L31 //
export interface RawMint {
    mintAuthorityOption: 1 | 0;
    mintAuthority: PublicKey;
    supply: bigint;
    decimals: number;
    isInitialized: boolean;
    freezeAuthorityOption: 1 | 0;
    freezeAuthority: PublicKey;
}

// Defining Buffer Layout from https://github.com/solana-labs/solana-program-library/blob/48fbb5b7c49ea35848442bba470b89331dea2b2b/token/js/src/state/mint.ts#L31 //

/** Buffer layout for de/serializing a mint */
export const MintLayout = struct([
    u32('mintAuthorityOption'),
    publicKey('mintAuthority'),
    u64('supply'),
    u8('decimals'),
    bool('isInitialized'),
    u32('freezeAuthorityOption'),
    publicKey('freezeAuthority'),
]);

¡Ya configuraste nuestros tipos para la información sin procesar de la cuenta! Ahora puedes importarlos en nuestro archivo principal deserialize.ts y usarlos para deserializar los datos que devolviste antes.

3. Deserializa los datos devueltos

Ahora que comprendes la estructura de los datos esperados, puedes configurar nuestra función de decodificación, que requiere una sola línea de código. Vuelve al archivo src/deserialize.ts para configurarla.

Primero, en nuestro archivo principal deserialize.ts, importa MintLayout desde nuestro archivo types.ts:

Código
import { MintLayout } from "./types";

Ahora solo tienes que agregar una línea a nuestra función de deserialización, justo debajo de donde obtienes los datos de la cuenta:

Código
const deserialize = MintLayout.decode(data)
console.log(deserialize)

Esto usa nuestro MintLayout para decodificar los datos devueltos en nuestra función deserializeMint.

Puedes ejecutar ts-node deserialize desde tu carpeta ./src y obtendrás un resultado similar al siguiente:

Código
{
  mintAuthorityOption: 1,
  mintAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
    _bn:
  },
  supply: 1n,
  decimals: 0,
  isInitialized: true,
  freezeAuthorityOption: 1,
  freezeAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
    _bn:
  }
}

¡Esto es mucho más legible! Puedes ordenarlo un poco más si, en el siguiente paso, desglosas la respuesta según sus tipos.

Por último, puedes depurar aún más estos datos ajustando la respuesta para que coincida con lo que se muestra arriba. Puedes hacerlo de la siguiente manera:

Código
// Breaking down the response //
    console.log(deserialize.mintAuthorityOption)
    console.log(deserialize.mintAuthority.toString())
    console.log(deserialize.decimals)
    console.log(deserialize.isInitialized)
    console.log(deserialize.freezeAuthorityOption)
    console.log(deserialize.freezeAuthority.toString())

En el código anterior, solo necesitas convertir el valor PublicKeys devuelto en formato toString. Los demás datos pueden devolverse en el formato en que se reciben. Como conocemos el formato esperado de los datos, también podemos configurarlo de antemano, lo que devolverá lo siguiente:

Código
1
5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT
0
true
1

Puedes ajustar estos datos como prefieras.

Esto simplemente los desglosa en un formato que te permite leer mejor los resultados.

Código completo:

Consulta aquí el código completo de deserialize.ts:

Código
import { Connection, PublicKey } from "@solana/web3.js";
import { RawMint, MintLayout } from "./types";

async function deserializeMint() {
  const rpc =
    "https://rpc.helius.xyz/?api-key=";
  const connection = new Connection(rpc);
  const mint = new PublicKey("6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K");

  try {
    let { data } = (await connection.getAccountInfo(mint)) || {};
    if (!data) {
      return;
    }
		// Data returned.
    console.log(data);
		// Deserialize Data.
    const deserialize = MintLayout.decode(data)

    // Breaking down the response //
    console.log(deserialize.mintAuthorityOption)
    console.log(deserialize.mintAuthority.toString())
    console.log(deserialize.decimals)
    console.log(deserialize.isInitialized)
    console.log(deserialize.freezeAuthorityOption)
    console.log(deserialize.freezeAuthority.toString)

  } catch {
    return null;
  }
}
deserializeMint();

Conclusión

¡Ya deserializaste datos de la cuenta de un NFT en Solana! Puedes aplicar los mismos métodos a otros casos de uso y usar técnicas de investigación similares para determinar la estructura del programa correspondiente a los datos.

Asegúrate de consultar el código fuente del programa cuyos datos quieres deserializar e intenta aplicar estos métodos por tu cuenta.

Recursos

‍

Suscríbete a Helius

Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos

Imagen ampliada