[решено] Как вы расшифровываете данные, хранящиеся в смарт-контракте TON?
-
Используя [ton.cx исследователь](https://ton.cx/address/EQD0vdSA_NedR9uvbgN9EikRX - suesDxGeFg69XQMavfLqIw) в качестве примера, когда вы нажимаете на вкладку Контракт , в разделе Данные отображается много информации. К сожалению, все это в шестнадцатеричном формате.
Как я могу получить данные в более удобочитаемом виде?
-
В 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
Это должно помочь вам начать. Просто обязательно изучите все связанные концепции.