НОВОЕ: Helius приобретает Light Protocol
как десериализовать данные аккаунта в Solana
Блог/Разработка

Solana Dev 101 — десериализация данных аккаунта в Solana

Руководитель по работе с разработчикамиHunter Davis в LinkedIn
Чтение: 5 мин

Введение

Работать с данными в Solana может быть непросто. Данные аккаунтов и транзакций часто закодированы. Это повышает эффективность, но усложняет работу разработчиков.

Solana использует Borsh (Binary Object Representation Serializer for Hashing) для сериализации и десериализации данных. Одно из ключевых преимуществ Borsh — детерминированность: одинаковые входные данные всегда дают одинаковый сериализованный результат.

В этом руководстве мы разберем, как десериализовать данные токен-аккаунта и получить читаемые данные для дальнейшей работы. В простом примере вы разберете необработанные данные аккаунта NFT по адресу выпуска с помощью библиотеки Token Program.

Ниже показано, как мы преобразуем необработанные данные аккаунта в более читаемый вид:

Чтобы работать с полным кодом из этого руководства, клонируйте наш репозиторий deserialize-account здесь.

Требования

Для этого руководства вам понадобятся:

Настройка окружения

Клонируйте репозиторий с примером:

Код
git clone https://github.com/helius-labs/deserialize-base.git

Перейдите в каталог проекта:

Код
cd deserialize-base

Установите npm:

Код
npm install

Теперь проект настроен!

Можно переходить к реализации десериализации данных аккаунта для указанного адреса выпуска.

Этапы реализации

Выполните следующие шаги:

1. Получите данные аккаунта

Импортируем необходимые модули в файл /src/deserialize.ts:

Код
import { Connection, PublicKey } from "@solana/web3.js";

Позже вы используете их, чтобы настроить подключение к Solana, а PublicKey — чтобы указать выпуск, данные которого нужно десериализовать.

Ниже настройте основную функцию.

Также настройте подключение к Solana через URL Helius RPC и укажите выпуск, данные которого будете десериализовать в этом руководстве.

Код
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()

В приведенном выше коде обязательно замените api-key на собственный ключ Helius API. Для этого руководства также можно заменить используемый выпуск собственным примером.

Затем настройте try/catch, чтобы получить необработанные данные аккаунта для этого выпуска:

Код
try {
    let { data } = (await connection.getAccountInfo(mint)) || {};
    if (!data) {
      return;
    }
    console.log(data);
  } catch {
    return null;
  }

На этом шаге вы используете подключение, чтобы выполнить RPC-вызов к Solana для getAccountInfo. В ответ вы получите исходные данные, которые нужно будет разобрать.

Если данные не найдены, функция вернет null. В противном случае результаты поиска появятся в терминале.

Теперь выполните ts-node deserialize, чтобы увидеть результат.

Вы увидите примерно такой результат:

Десериализация нужна, чтобы преобразовать эти данные в читаемый формат.

Для этого разработчику нужно обратиться к исходному коду и найти структуру данных, которую должна возвращать создавшая их программа.

2. Настройте типы аккаунта

В этом примере нужно получить AccountInfo для выпуска SPL 6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K.

Для этого необходимо разобрать типы необработанных данных выпуска и структуру буфера из Solana Program Library. Понимание структуры данных — важнейший этап десериализации любых данных в Solana.

На изображении выше показаны определенные программой структура RawMint и MintLayout. Их можно просто скопировать в файл типов.

Теперь перейдите в каталог ./src/types.

В файле /src/types.ts настройте импорт типов:

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

Так вы определите формат и структуру необработанных данных выпуска, необходимые для десериализации данных аккаунта NFT в этом примере.

Теперь можно настроить интерфейс и структуру по аналогии с приведенными выше.

Код
// 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'),
]);

Теперь типы для необработанных данных аккаунта настроены! Импортируйте их в основной файл deserialize.ts и используйте для десериализации полученных ранее данных.

3. Десериализуйте полученные данные

Теперь вы понимаете структуру ожидаемых данных и можете настроить функцию декодирования, которая состоит всего из одной строки кода. Для этого вернитесь к файлу src/deserialize.ts.

Сначала импортируйте MintLayout из файла types.ts в основной файл deserialize.ts:

Код
import { MintLayout } from "./types";

Теперь добавьте одну строку в функцию десериализации сразу после получения данных аккаунта:

Код
const deserialize = MintLayout.decode(data)
console.log(deserialize)

Здесь MintLayout используется для декодирования данных, возвращенных функцией deserializeMint.

Выполните ts-node deserialize из папки ./src. Вы получите примерно такой результат:

Код
{
  mintAuthorityOption: 1,
  mintAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
    _bn:
  },
  supply: 1n,
  decimals: 0,
  isInitialized: true,
  freezeAuthorityOption: 1,
  freezeAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
    _bn:
  }
}

Теперь данные гораздо проще читать! На следующем шаге можно сделать результат еще аккуратнее, разбив ответ по типам.

Наконец, можно дополнительно очистить данные, приведя ответ к показанному выше виду. Для этого выполните следующее:

Код
// 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())

В приведенном выше коде нужно преобразовать только PublicKeys, возвращаемый в формате toString. Остальные данные можно вернуть в исходном формате. Поскольку формат данных известен заранее, можно сразу настроить преобразование и получить следующий результат:

Код
1
5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT
0
true
1

Эти данные можно изменить любым удобным способом.

Такой разбор просто позволяет легче читать результаты.

Полный код:

Ниже приведен полный код deserialize.ts:

Код
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();

Заключение

Теперь вы десериализовали данные аккаунта NFT в Solana! Те же методы можно применять в других сценариях, а аналогичный анализ поможет определить структуру программы для конкретных данных.

Обязательно изучите исходный код программы, данные которой хотите десериализовать, и попробуйте самостоятельно применить описанные методы.

Ресурсы

‍

Подпишитесь на Helius

Следите за новостями разработки на Solana и получайте уведомления о наших публикациях

Увеличенное изображение