Разбор метаданных
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Стандарт метаданных, который включает NFT, коллекции NFT и Jettons, описан в TON Enhancement Proposal 64 [TEP-64] (https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md).
В TON сущности могут иметь три типа метаданных: on-chain, semi-chain, и off-chain.
- On-chain метаданные: хранятся внутри блокчейна, включая название, атрибуты и изображение.
- Off-chain метаданные: хранятся с помощью ссылки на файл метаданных, размещенного вне блокчейна.
- Semi-chain метаданные: гибрид между этими дв умя способами, который позволяет хранить небольшие поля, такие как имена или атрибуты, внутри блокчейне, в то время как изображение хранятся за пределами блокчейна и при этом только ссылка на него.
Кодирование данных Snake
Формат кодирования Snake позволяет часть данных хранить в стандартной ячейке, а оставшуюся часть - в дочерней ячейке (рекурсивно). Формат кодирования Snake должен иметь префикс в виде байта 0x00. Схема TL-B:
tail#_ {bn:#} b:(bits bn) = SnakeData ~0;
cons#_ {bn:#} {n:#} b:(bits bn) next:^(SnakeData ~n) = SnakeData ~(n + 1);
Формат Snake используется для хранения дополнительных данных в ячейке, когда данные превышают максимальный размер, который можно хранить в одной ячейке. Это достигается путем хранения части данных в корневой ячейке, а оставшиеся части - в первой дочерней ячейке, и так продолжается рекурсивно до тех пор, пока все данные не будут сохранены.
Вот пример кодирования и декодирования формата Snake в TypeScript:
export function makeSnakeCell(data: Buffer): Cell {
const chunks = bufferToChunks(data, 127)
if (chunks.length === 0) {
return beginCell().endCell()
}
if (chunks.length === 1) {
return beginCell().storeBuffer(chunks[0]).endCell()
}
let curCell = beginCell()
for (let i = chunks.length - 1; i >= 0; i--) {
const chunk = chunks[i]
curCell.storeBuffer(chunk)
if (i - 1 >= 0) {
const nextCell = beginCell()
nextCell.storeRef(curCell)
curCell = nextCell
}
}
return curCell.endCell()
}
export function flattenSnakeCell(cell: Cell): Buffer {
let c: Cell | null = cell;
const bitResult = new BitBuilder();
while (c) {
const cs = c.beginParse();
if (cs.remainingBits === 0) {
break;
}
const data = cs.loadBits(cs.remainingBits);
bitResult.writeBits(data);
c = c.refs && c.refs[0];
}
const endBits = bitResult.build();
const reader = new BitReader(endBits);
return reader.loadBuffer(reader.remaining / 8);
}
Следует отметить, что префикс 0x00
байт в корневой ячейке не всегда требуется при использовании формата snake, как в случае с off-chain содержимым NFT. Также ячейки заполняются байтами вместо битов для упрощения анализа. Чтобы избежать проблемы добавления ссылки (в пределах следующей дочерней ячейки) на ссылку после того, как она уже была записана в родительскую ячейку, snake ячейка строится в обратном порядке.
Кодирование Chunked
Формат кодирования chunked используется для хранения данных с помощью словарной структуры данных, начиная с chunk_index и заканчивая chunk. Кодировка chunked должна иметь префикс из байта 0x01
. Схема TL-B:
chunked_data#_ data:(HashMapE 32 ^(SnakeData ~0)) = ChunkedData;
Вот пример декодирования данных в формате chunked с помощью TypeScript:
interface ChunkDictValue {
content: Buffer;
}
export const ChunkDictValueSerializer = {
serialize(src: ChunkDictValue, builder: Builder) {},
parse(src: Slice): ChunkDictValue {
const snake = flattenSnakeCell(src.loadRef());
return { content: snake };
},
};
export function ParseChunkDict(cell: Slice): Buffer {
const dict = cell.loadDict(
Dictionary.Keys.Uint(32),
ChunkDictValueSerializer
);
let buf = Buffer.alloc(0);
for (const [_, v] of dict) {
buf = Buffer.concat([buf, v.content]);
}
return buf;
}
Атрибуты метаданных NFT
Атрибут | Тип | Условие | Описание |
---|---|---|---|
uri | ASCII string | необязательный параметр | URI, указывающий на JSON-документ с метаданными, который используется в формате "Semi-chain content layout". |
name | UTF8 string | необязательный параметр | идентифицирует asset |
description | UTF8 string | необязательный параметр | описывает актив |
image | ASCII string | необязательный параметр | URI, указывающий на ресурс с типом mime image |
image_data | binary* | необязательный параметр | либо двоичное представление изображения для on-chain размещения, либо base64 для off-chain размещения |
Атрибуты метаданных Jetton
uri
- Необязательный параметр. Используется в формате "Semi-chain content layout". Строка ASCII. URI, указывающий на JSON-документ с метаданными.Имя
- Необязательный параметр. Строка в формате UTF8. Идентифицирует asset.description
- Необязательный параметр. Строка в формате UTF8. Описывает asset.image
- Необязательный параметр. Строка ASCII. URI, указывающий на ресурс с типом mime image.image_data
- Необязательный параметр. Либо двоичное представление изображения для onchain размещения, либо base64 для offchain размещения.symbol
- Необязательный параметр. Строка в формате UTF8. Символ токена - например, "XMPL". Используется в форме "Вы получили 99 XMPL".decimals
- Необязательный параметр. Если не указано, по умолчанию используется значение 9. Строковое значение с числом от 0 до 255, кодированное в UTF8. Количество десятичных знаков, которые использует токен — например, 8, означает разделить количество токенов на 100000000 для получения его пользовательского представления.amount_style
- Необязательный параметр. Необходим для внешних приложений, чтобы они понимали формат отображения количества jetton.
- "n" - количество jetton (значение по умолчанию). Если у пользователя 100 токенов с десятичным числом 0, то отображается, что у пользователя 100 токенов
- "n-of-total" - количество jetton из общего количества выпущенных jetton. Например, totalSupply Jetton = 1000. У пользователя есть 100 jetton в jetton wallet. Например, должно отображаться в кошельке пользователя как 100 из 1000 или любым другим текстовым или графическим способом, чтобы показать конкретное значение в общем контексте.
- "%" - процент от общего количества выпускаемых jetton. Например, totalSupply Jetton = 1000. У пользователя есть 100 jetton в jetton wallet. Например, должно отображаться в кошельке пользователя как 10%.
render_type
- Необязательный параметр. Необходим для внешних приложений, чтобы они понимали к какой группе относится jetton и как его отображать.
- "currency" - отображать как валюту (значение по умолчанию).
- "game" - отображать для игр. Будет отображаться как NFT, но при этом отображать количество jetton, учитывая параметр
amount_style
Атрибут | Тип | Условие | Описание |
---|---|---|---|
uri | ASCII string | необязательный параметр | URI, указывающий на JSON-документ с метаданными, который используется в формате "Semi-chain content layout". |
name | UTF8 string | необязательный параметр | идентифицирует asset |
description | UTF8 string | необязательный параметр | описывает asset |
image | ASCII string | необязательный параметр | URI, указывающий на ресурс с типом mime image |
image_data | binary* | необязательный параметр | либо двоичное представление изображения для on-chain размещения, либо base64 для off-chain размещения |
symbol | UTF8 string | необязательный параметр | символ токена - например, "XMPL" и используется в форме "Вы получили 99 XMPL" |
decimals | UTF8 string | необязательный параметр | количество десятичных знаков, которые использует токен. Если не указано, по умолчанию используется значение 9. Строковое значение с числом от 0 до 255, например 8, означает, что количество токенов должно быть разделено на 100000000 для получения его пользовательского представления. |
amount_style | необязательный параметр | необходим внешним приложениям, чтобы они понимали формат отображения количества jetton. Определяется с помощью n, n-of-total, %. | |
render_type |