NOVO: Helius adquire a Light Protocol
como desserializar dados de conta na Solana
Blog/Desenvolvimento

Solana Dev 101 — Desserializando dados de conta na Solana

Líder de Relações com DesenvolvedoresHunter Davis no LinkedIn
5 min de leitura

Introdução

Interagir com dados na Solana pode ser desafiador. Os dados de contas e transações costumam ser codificados, o que é bom para a eficiência, mas ruim para a sanidade dos desenvolvedores.

A Solana usa Borsh (Binary Object Representation Serializer for Hashing) para serializar seus dados, incluindo os processos de serialização e desserialização. Uma das principais vantagens do Borsh é seu determinismo, que garante uma saída serializada consistente para a mesma entrada.

Neste tutorial, veremos como desserializar os dados de uma conta de token e retornar dados legíveis que você possa utilizar. Usaremos um exemplo simples para decompor as informações brutas da conta de um NFT com base em seu endereço de mint usando a biblioteca Token Program.

Veja abaixo como transformaremos dados brutos de conta em algo mais legível:

Você pode acompanhar o código completo deste tutorial clonando nosso repositório deserialize-account aqui.

Pré-requisitos

Estes são os pré-requisitos para este tutorial:

Configuração do ambiente

Clone o repositório de exemplo:

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

Acesse o diretório do projeto:

Código
cd deserialize-base

Instale o npm:

Código
npm install

Agora o projeto está configurado!

Você já pode começar a criar a lógica para desserializar os dados da conta de um endereço de mint específico.

Etapas de implementação

Siga estas etapas:

1. Busque os dados da conta

No arquivo /src/deserialize.ts, vamos importar os módulos necessários:

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

Você usará isso mais adiante para definir nossa conexão com a Solana e o PublicKey do mint cujos dados deseja desserializar.

Logo abaixo, você configurará a função principal.

Você também configurará nossa conexão com a Solana usando a URL do RPC da Helius e poderá definir o mint que será desserializado no 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()

No código acima, substitua api-key pela sua própria chave de API da Helius. Se preferir, você também pode substituir o mint usado por um exemplo próprio neste tutorial.

Em seguida, você configurará um bloco try/catch para buscar os dados brutos da conta desse mint:

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

Na etapa acima, você está usando nossa conexão para fazer uma chamada RPC na Solana para getAccountInfo. Isso retornará os dados iniciais que precisam ser decompostos.

Se nenhum dado for encontrado, o retorno será null. Caso contrário, os resultados da busca serão exibidos no terminal.

Agora você pode executar ts-node deserialize para ver os resultados.

Você deverá ver um resultado semelhante ao seguinte:

O objetivo da desserialização aqui é converter esses dados em um formato legível.

Para fazer isso, você precisa consultar o código-fonte e encontrar o layout que o programa responsável pela criação dos dados espera fornecer.

2. Configure os tipos de conta

Neste exemplo, você quer obter o AccountInfo de um mint SPL 6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K.

Para isso, você precisará decompor os tipos dos dados brutos do mint e o layout do buffer fornecidos pela Solana Program Library. Entender a estrutura dos dados fornecidos é uma etapa essencial para desserializar qualquer dado na Solana.

A imagem acima mostra a struct RawMint e o MintLayout definidos pelo programa. Você pode simplesmente copiá-los para nosso arquivo de tipos.

Agora, acesse nosso diretório ./src/types.

No arquivo /src/types.ts, configure a importação dos nossos 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";

Isso definirá o formato e o layout brutos do mint necessários para desserializar os dados da conta do NFT neste exemplo.

Agora você pode configurar nossa interface e nosso layout de forma semelhante ao exemplo acima.

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'),
]);

Agora você configurou nossos tipos para as informações brutas da conta! Já pode importá-los no arquivo principal deserialize.ts e usá-los para desserializar os dados retornados anteriormente.

3. Desserialize os dados retornados

Agora que você entende a estrutura dos dados esperados, pode configurar nossa função de decodificação, que requer apenas uma linha de código. Volte ao arquivo src/deserialize.ts para configurá-la.

Primeiro, no arquivo principal deserialize.ts, importe nosso MintLayout do arquivo types.ts:

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

Agora basta adicionar uma única linha à nossa função de desserialização, logo abaixo do trecho em que você busca os dados da conta:

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

Isso usa nosso MintLayout para decodificar os dados retornados pela função deserializeMint.

Você pode executar ts-node deserialize na pasta ./src e obterá um resultado semelhante ao seguinte:

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

Agora está muito mais legível! Na próxima etapa, você pode organizar melhor o resultado decompondo a resposta de acordo com os tipos retornados.

Por fim, você ainda pode limpar esses dados ajustando a resposta ao formato mostrado acima. Para isso, faça o seguinte:

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

No código acima, você só precisa converter o PublicKeys retornado em um formato toString. Os demais dados podem ser retornados no formato em que foram recebidos. Como o formato dos dados é conhecido, também podemos configurar isso antecipadamente, o que retornará o seguinte:

Código
1
5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT
0
true
1

Você pode ajustar esses dados como preferir.

Isso apenas os decompõe em um formato que facilita a leitura dos resultados.

Código completo:

Veja aqui o 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();

Conclusão

Agora você desserializou os dados da conta de um NFT na Solana! Você pode aplicar os mesmos métodos a outros casos de uso e adotar técnicas de pesquisa semelhantes para descobrir a estrutura do programa responsável pelos dados.

Consulte o código-fonte do programa cujos dados você deseja desserializar e tente aplicar esses métodos por conta própria.

Recursos

‍

Assine a Helius

Acompanhe as novidades mais recentes do desenvolvimento Solana e receba atualizações quando publicarmos

Imagem ampliada