TVM Primitives
The tvm feature enables TON cells, builders, slices, BoC helpers, addresses,
dictionaries, and TVM stack values. It also enables tl because several public
types map cells and addresses into LiteAPI structures.
Audience: users working with offline cells, BoC payloads, TL-B models, addresses,
or get-method stack values. Prerequisites: tvm feature only; no live network
access is required unless the BoC or stack payload came from LiteClient calls.
Cells, Builders, And Slices
A cell stores up to 1023 bits and up to 4 references. Builder and
CellBuilder write values into a cell, and Slice reads them back in order.
#![allow(unused)]
fn main() {
use num_bigint::BigUint;
use tonutils::tvm::{Builder, Slice};
fn example() -> anyhow::Result<()> {
let value = BigUint::from(1u64) << 96;
let mut builder = Builder::new();
builder.store_uint::<u32>(0x12345678)?;
builder.store_uint_custom::<u8>(0b101, 3)?;
builder.store_big_uint(&value, 128)?;
let cell = builder.end_cell()?;
let mut slice = Slice::new(cell);
assert_eq!(slice.load_uint::<u32>()?, 0x12345678);
assert_eq!(slice.load_uint_custom::<u8>(3)?, 0b101);
assert_eq!(slice.load_big_uint(128)?, value);
Ok(())
}
}
Reads and writes are bounds checked. Loading too many bits or references returns an error instead of silently truncating data.
BoC
BoC helpers serialize and parse a root cell:
#![allow(unused)]
fn main() {
use tonutils::tvm::{Builder, deserialize_boc, serialize_boc};
fn example() -> anyhow::Result<()> {
let mut builder = Builder::new();
builder.store_byte(7)?;
let cell = builder.end_cell()?;
let boc = serialize_boc(&cell, true)?;
let decoded = deserialize_boc(&boc)?;
assert_eq!(decoded.hash(), cell.hash());
Ok(())
}
}
Convenience helpers convert BoC data to and from hex and base64. Current BoC support covers the crate’s ordinary-cell use cases; index table modes, cache bits, exotic cells, and official golden fixture coverage are still being expanded.
Addresses
Address parses raw workchain:hash strings and user-friendly base64 forms,
and can convert to LiteAPI AccountId:
#![allow(unused)]
fn main() {
use std::str::FromStr;
use tonutils::tvm::Address;
fn example(address: &str) -> anyhow::Result<()> {
let parsed = Address::from_str(address)?;
let account = parsed.to_account_id();
println!("{} {}", account.workchain, parsed.to_hex());
Ok(())
}
}
Address formatting exposes bounceable and test-only flags. Callers should keep test-only addresses out of mainnet workflows.
Dictionaries
HashmapE stores fixed-width BitKey values with callback-based value codecs.
The higher-level Dict wrapper supports integer keys and cell values for the
current public surface.
#![allow(unused)]
fn main() {
use tonutils::tvm::{Dict, DictValue};
fn example() -> anyhow::Result<()> {
let mut dict = Dict::new(16);
dict.set_int_key(7, DictValue::Uint(42, 32))?;
let root = dict.serialize()?;
assert!(root.is_some());
Ok(())
}
}
The dictionary encoder implements canonical labels and fork nodes. TL-B code can
use tlb::TlbHashmapE<T, N> when dictionary values implement the TL-B runtime
traits. Official TON golden fixtures and proof-friendly traversal remain TODO
items.
TL-B Models And Derive
The tvm feature exposes tonutils::tlb for typed cell models. Messages,
accounts, transactions, common transaction phases, block roots, config wrappers,
and proof wrappers are public APIs. Some deep block and shard-state families are
raw-preserving wrappers while the full upstream block.tlb generator is still
being expanded.
#![allow(unused)]
fn main() {
use tonutils::tlb::{Account, TlbDeserialize, TlbSerialize};
use tonutils::tvm::boc_to_hex;
fn example() -> anyhow::Result<()> {
let cell = Account::None.to_cell()?;
let decoded = Account::from_cell(cell.clone())?;
assert_eq!(decoded, Account::None);
println!("{}", boc_to_hex(&cell, false)?);
Ok(())
}
}
Custom TL-B structs can use the optional tlb-derive feature:
#![allow(unused)]
fn main() {
use tonutils::tlb::{Tlb, TlbDeserialize, TlbSerialize};
#[derive(Tlb)]
#[tlb(tag = "0x0f8a7ea5")]
struct Body {
query_id: u64,
}
}
The derive writes existing TlbSerialize and TlbDeserialize impls. Use
#[tlb(reference)] for ^T fields. Tags accept binary strings, 0b...,
0x..., and TL-B-style #... hex forms. Unsigned primitive fields u8,
u16, u32, u64, and u128 infer their natural bit width; use
#[tlb(bits = N)] when the TL-B width differs or for signed integer and hash
fields. Float primitive fields are rejected because the runtime does not define
TL-B float semantics.
Stack Values
TvmStack is used by contract get-method helpers. It supports nulls, integers,
cells, slices, tuples, lists, and explicit unsupported payloads for lossless
roundtrips.
#![allow(unused)]
fn main() {
use tonutils::tvm::{TvmStack, TvmStackEntry};
fn example() -> anyhow::Result<()> {
let stack = TvmStack::new(vec![TvmStackEntry::int(10)]);
let boc = stack.to_boc()?;
let decoded = TvmStack::from_boc(&boc)?;
assert_eq!(decoded.entries().len(), 1);
Ok(())
}
}
Compatibility with every liteserver runSmcMethod return shape is still being
verified with live and golden fixtures.