Решено
В TON нет единого формата хранения данных. Каждый смарт-контракт может иметь свой собственный способ хранения / кодирования своих данных. Возьмем [смарт-контракт NFT item](https://github.com/ton-blockchain/token-contract/blob/main/nft/nft - item.fc#L19-L47) в качестве примера. Он хранит свои данные в следующем формате:
;;
;; Storage
;;
;; uint64 index
;; MsgAddressInt collection_address
;; MsgAddressInt owner_address
;; cell content
;;
И у контракта есть две внутренние функции для фактической загрузки и сохранения своих данных:
(int, int, slice, slice, cell) load_data() {
slice ds = get_data().begin_parse();
var (index, collection_address) = (ds~load_uint(64), ds~load_msg_addr());
if (ds.slice_bits() > 0) {
return (-1, index, collection_address, ds~load_msg_addr(), ds~load_ref());
} else {
return (0, index, collection_address, null(), null()); ;; nft not initialized yet
}
}
() store_data(int index, slice collection_address, slice owner_address, cell content) impure {
set_data(
begin_cell()
.store_uint(index, 64)
.store_slice(collection_address)
.store_slice(owner_address)
.store_ref(content)
.end_cell()
);
}
Данные хранятся в виде "ячейки", которая может иметь произвольный формат и может ссылаться на другие вложенные ячейки. Ищите концепцию "Мешка с ячейками" в белой книге.
Однако вам не следует пытаться декодировать данные смарт-контракта напрямую, даже если вы знаете формат сохраненных данных. Правильным способом было бы использовать "общедоступный API" контракта посредством вызова его методов get. В контракте NFT item есть [метод получения](https://github.com/ton-blockchain/token - contract/blob/main/nft/nft-item.fc#L137-L144) именно для этой цели:
;;
;; GET Methods
;;
(int, int, slice, slice, cell) get_nft_data() method_id {
(int init?, int index, slice collection_address, slice owner_address, cell content) = load_data();
return (init?, index, collection_address, owner_address, content);
}
Он вернет вам все необходимые данные в декодированном виде.
И [здесь](https://github.com/slavafomin/tonweb/blob/typescripted/src/contract/token/nft/nft - item.ts#L83-L109) - это то, как вы бы проанализировали результат этого метода get:
// Calling the get-method
const result = await this.provider.call2(
myAddress.toString(),
'get_nft_data'
);
// Parsing the data returned by it
const isInitialized = (
(expectBN(result[0]).toNumber() === -1)
);
const index = expectBN(result[1]).toNumber();
const collectionAddress = (
parseAddressFromCell(result[2])
);
const ownerAddress = (isInitialized
? parseAddressFromCell(result[3])
: null
);
const contentCell = result[4];
// Single NFT without a collection
const contentUri = ((isInitialized && !collectionAddress) ?
parseOffchainUriCell(contentCell) :
null
);
Кроме того, некоторые массивы данных хранятся в виде двоичных строк и требуют некоторого нетривиального синтаксического анализа с использованием TL-B schemas. Каждая библиотека предоставит вам несколько утилит для использования. Один из таких инструментов обычно называется "CellSlice", который позволяет вам считывать и декодировать биты битовой строки вручную.
Рассмотрим этот пример из TonWeb:
// Encoding some data as a cell
const cell = new Cell();
cell.bits.writeUint('100500', 32);
cell.bits.writeString('Hello World');
// Reading the data from cell (bit-string)
const slice = new CellSlice(cell);
slice.loadUint(32); // 100500
slice.loadString(); // Hello World
slice.isEmpty(); // true
Это должно помочь вам начать. Просто обязательно изучите все связанные концепции.