DOCUMENTATION

Complete API reference, protocol specification, SDK examples, and developer guides for the Vettor blockchain.

DOCUMENTATION

Protocol specification and developer reference for the VTT blockchain. Covers architecture, consensus, tokenomics, smart contracts, compliance, governance, cross-chain messaging, and the full JSON-RPC API.

PROTOCOL OVERVIEW

Vettor (VTT) is a Layer 1 blockchain designed for tokenizing real-world assets (RWA). It combines protocol-level compliance controls with the permissionless innovation of public blockchains.

The target architecture follows a relay chain + application chains model. The relay chain provides shared security, consensus finality, and cross-chain message routing. Application chains connect to the relay chain for interoperability while maintaining their own state and execution environments.

VTT uses an account-based model (not UTXO). Each account has a balance, nonce (sequence number), and optional contract code. This model is simpler for token management and smart contract interactions.

CRYPTOGRAPHIC PRIMITIVES

SignaturesEd25519 — 32-byte seeds, 32-byte public keys, 64-byte signatures
HashingBLAKE3 — 32-byte output, used for block hashes, state roots, address derivation
SerializationBorsh (Binary Object Representation Serializer for Hashing) — deterministic, no schema overhead
Addresses20 bytes = last 20 bytes of BLAKE3(public_key), displayed as 0x + 40 hex chars

ARCHITECTURE DIAGRAM

RELAY CHAIN
SHARED SECURITYVALIDATOR SETCROSS-CHAIN ROUTINGFINALITY GADGETEPOCH MANAGEMENTTREASURY
CHAIN 1(RWA)
ASSET TOKENIZATION
COMPLIANCE RULES
FRACTIONAL OWNERSHIP
CHAIN 2(DEFI)
DEX / AMM
LENDING POOLS
YIELD FARMING
CHAIN N(CUSTOM)
WASM CONTRACTS
CUSTOM LOGIC
DAPP RUNTIME
EACH CHAIN HAS ITS OWN CONSENSUS PARAMS · GAS CONFIG · COMPLIANCE RULES · STATE

STORAGE (ROCKSDB)

Chain state and block data are persisted to disk using RocksDB. The --data-dir <path> flag enables persistent storage. Without it, state is held in-memory only (useful for dev/test).

StateDB uses a write-through cache: reads check the in-memory cache first, then fall back to RocksDB. On restart with an existing data directory, the node resumes from the last persisted state.

COLUMN FAMILIES
accountsAccount balances and nonces
assetsTokenized RWA asset metadata and supplies
poolsDEX / AMM liquidity pool state
validatorsValidator registrations and stake data
contractsWASM contract code and storage
governanceOn-chain governance proposals and votes
chain_metaBlock headers, receipts, and chain metadata

CONSENSUS (DPOS)

VTT uses Delegated Proof of Stake (DPoS) consensus. Token holders delegate their VTT to validators who produce blocks and validate transactions. The protocol elects the top 21 validators by total stake each epoch.

CONSENSUS PARAMETERS

Active validators21
Block time3 seconds
Blocks per epoch1,200 (~1 hour)
Min self-stake100,000 VTT
Unbonding period21 days
Block productionRound-robin among active validators

VALIDATOR ELECTION

At the start of each epoch, the protocol selects the top 21 validators by total stake (self-stake + delegations). In case of a tie in total stake, validators are ordered by their address (lexicographic, ascending). Validators must maintain at least 100,000 VTT in self-stake to be eligible.

Block production follows a round-robin schedule. Each validator gets assigned specific slots within the epoch. If a validator misses their slot, the slot is skipped and the next validator produces on their turn.

SLASHING

OFFENSEPENALTYDETAILS
Double signing5% of stakeSigning two different blocks at the same height. Immediate slash, validator jailed.
Downtime (>50%)0.1% per epochMissing more than 50% of assigned slots in an epoch. Accumulates each epoch.

BFT FINALITY

Vettor uses a BFT-style finality tracker requiring 2/3+1 validator votes to finalize a block. After producing or importing a block, validators broadcast FinalityVote messages containing the voter address, block hash, block number, and signature.

A block is considered finalized when it receives votes from more than two-thirds of active validators. Finalized blocks cannot be reverted by chain reorganizations.

FINALITY VOTE
Threshold2/3 + 1 of active validators
Message typeFinalityVote (voter, block_hash, block_number, signature)
TriggerBroadcast after producing or importing a block
GuaranteeFinalized blocks are irreversible

TOKEN ECONOMICS

The VTT token has 18 decimal places (like Ethereum wei). All amounts in the protocol are stored as unsigned 128-bit integers. For display, 1.0 VTT = 1,000,000,000,000,000,000 raw units (1e18).

SUPPLY & ALLOCATION

Total supply1,000,000,000 VTT (1 billion)
Decimal places18 (u128 storage)
ALLOCATION%AMOUNTNOTES
Validator rewards30%300,000,000 VTTEmitted over time as block rewards
Ecosystem20%200,000,000 VTTGrants, partnerships, integrations
Team15%150,000,000 VTT4-year vesting schedule
Public sale15%150,000,000 VTTLaunchpad distribution
Foundation10%100,000,000 VTTLong-term protocol stewardship
Treasury10%100,000,000 VTTOn-chain governance controlled

INFLATION & STAKING REWARDS

Annual inflation target5%
Staking ratio target60% of total supply
If staking < 60%Rewards increase (up to 2x multiplier) to incentivize staking
If staking > 60%Rewards decrease (0.5x multiplier) to reduce excess staking

REWARD DISTRIBUTION

Block rewards80% to block producer, 20% to treasury
Gas fees70% burned (deflationary), 30% to block producer

GAS & FEES

Every transaction consumes gas. The total fee is gas_used * gas_price. Gas prices are denominated in gwei (1 gwei = 1e9 raw units). The minimum gas price is 1 gwei.

GAS COST TABLE

OPERATIONGAS COSTNOTES
min_gas_price1 gwei (1e9)Minimum accepted gas price per unit
base_transfer21,000Simple VTT transfer (no contract call)
cost_per_byte16Per byte of transaction calldata
storage_read200Read a storage slot
storage_write5,000Write to an existing storage slot
storage_write_new20,000Write to a new (previously empty) slot
host_call_base100Base cost for any host function call
transfer2,100Internal VTT transfer from contract
log_base375Base cost to emit a log event
log_per_byte8Per byte of log data
compliance_check1,000Run a compliance validation
asset_mint10,000Mint new asset tokens
asset_transfer5,000Transfer tokenized asset between accounts
oracle_read500Read an oracle price feed

FEE CALCULATION EXAMPLE

// Simple transfer
gas_used  = 21,000 (base_transfer)
gas_price = 1 gwei = 1,000,000,000 raw units

total_fee = 21,000 * 1,000,000,000 = 21,000,000,000,000 raw units
          = 0.000021 VTT

// Of that fee:
//   70% burned    = 0.0000147 VTT (removed from supply)
//   30% producer  = 0.0000063 VTT (paid to block producer)

SMART CONTRACTS

VTT executes smart contracts via a WASM virtual machine powered by Wasmer 5. Contracts are compiled to WebAssembly and deployed on-chain. Any language that compiles to WASM can be used (Rust recommended).

CONTRACT REQUIREMENTS

VM engineWasmer 5 (Cranelift backend)
Required exportmemory — the contract must export its linear memory
Method returnsi32 — 0 = success, non-zero = error code

ARGUMENT PASSING

When calling a contract method, arguments are written into the contract's linear memory starting at offset 0:

Bytes [0..8]Length of arguments data (u64, little-endian)
Bytes [8..8+len]Arguments data (typically JSON or Borsh encoded)

HOST FUNCTIONS

Contracts interact with the blockchain through imported host functions. Each call has a base gas cost of 100 plus operation-specific costs.

FUNCTIONSIGNATUREDESCRIPTION
host_storage_read(key_ptr: i32, key_len: i32, val_ptr: i32, val_max: i32) -> i32Read a value from contract storage. Returns bytes written, 0 if not found, -1 on error (buffer too small or out of gas).
host_storage_write(key_ptr, key_len, val_ptr, val_len) -> ()Write a value to contract storage. No return value. Traps on out of gas.
host_caller(no params) -> i64Returns first 8 bytes of caller address as i64. Use host_caller_address for the full 20-byte address.
host_caller_address(out_ptr: i32) -> i32Writes the full 20-byte caller address to out_ptr. Returns 0 on success, -1 on error.
host_block_number() -> i64Returns the current block number.
host_block_timestamp() -> i64Returns the current block Unix timestamp (milliseconds).
host_chain_id() -> i32Returns the chain ID.
host_emit_log(data_ptr, data_len) -> ()Emit a log event with arbitrary data.
host_gas_remaining() -> i64Returns remaining gas for this execution.
host_consume_gas(amount: i64) -> i32Manually consume gas (for custom metering). Returns 0 on success, -1 if out of gas.

DEPLOYMENT & EXECUTION

Contracts are deployed and called through dedicated transaction actions:

ACTIONFIELDSDESCRIPTION
DeployContractcode: Vec<u8>, init_data: Vec<u8>Deploy WASM bytecode. Contract address derived from BLAKE3(sender + nonce). Code hash stored as BLAKE3 of bytecode.
CallContractcontract: Address, method: String, args: Vec<u8>, value: AmountInvoke an exported method on a deployed contract. Can attach VTT value.

CONTRACT STORAGE

Storage modelKey-value store per contract (isolated from other contracts)
PersistenceStorage persists across calls and blocks (on-chain state)
Code hashBLAKE3 hash of WASM bytecode — used for verification and deduplication
Read cost200 gas per storage_read
Write cost (existing)5,000 gas per storage_write to an existing slot
Write cost (new)20,000 gas per storage_write to a previously empty slot

MINIMAL CONTRACT EXAMPLE (RUST)

#![no_std]
#![no_main]

extern "C" {
    fn host_storage_read(key_ptr: *const u8, key_len: i32, val_ptr: *mut u8, val_max: i32) -> i32;
    fn host_storage_write(key_ptr: *const u8, key_len: i32, val_ptr: *const u8, val_len: i32);
    fn host_emit_log(data_ptr: *const u8, data_len: i32);
}

#[no_mangle]
pub extern "C" fn increment() -> i32 {
    let key = b"counter";
    let mut buf = [0u8; 8];

    unsafe {
        // Read current value
        let len = host_storage_read(key.as_ptr(), key.len() as i32, buf.as_mut_ptr(), 8);
        let current = if len > 0 {
            u64::from_le_bytes(buf)
        } else {
            0
        };

        // Increment and write back
        let next = (current + 1).to_le_bytes();
        host_storage_write(key.as_ptr(), key.len() as i32, next.as_ptr(), 8);

        // Log the event
        let msg = b"incremented";
        host_emit_log(msg.as_ptr(), msg.len() as i32);
    }

    0 // success
}

ASSET TOKENIZATION (RWA)

Vettor is a DLT infrastructure layer for the distribution, trading and governance of regulated financial instruments that represent economic rights over real world assets. The platform is explicitly not a substitute for the regulated vehicles that legally hold the underlying assets, nor for the authorized registrars that maintain the legal ledger of ownership.

A Vettor token represents an economic right (cash flow, capital gain, limited voting rights) over a regulated vehicle that holds or controls the underlying asset. Tokens do not grant direct ownership or any real right over the asset itself. Each on-chain asset records its jurisdiction (ISO 3166-1 alpha-2 code) and the legal entity issuing the financial instrument, anchoring the token to its off-chain legal wrapper.

THREE-LAYER ARCHITECTURE

The Vettor model separates three distinct layers. Each must be built on the right foundation; blurring them is the primary source of regulatory and operational risk in tokenization projects.

Layer 1 — Legal ownership (off-chain)
Regulated vehicle holds the underlying asset: SPV under Italian Law 130/1999 (art. 7.1 for real estate proceeds), closed-end real estate AIF managed by an authorized SGR, or SICAF. Supervised by the competent authority (Consob / Banca d'Italia in Italy).
Layer 2 — Economic rights (financial instruments)
The vehicle issues notes, units or shares that grant investors defined economic rights (share of income, capital gains on disposal, limited voting on extraordinary matters). Rights are defined by the vehicle's statute, fund regulation, indenture and subscription agreements.
Layer 3 — DLT registry (Vettor infrastructure)
The financial instruments are registered on a DLT registry maintained by an authorized registrar ("responsabile del registro per la circolazione digitale" in Italy, enrolled with Consob under Law 52/2023 implementing the EU DLT Pilot Regime). Vettor provides the DLT infrastructure; the registrar provides the legal effect of transfers.

VEHICLE OPTIONS

The first production deployment targets Italian jurisdiction and the SPV framework introduced by art. 7.1 of Law 130/1999(added by the 2019 Decreto Crescita), which enables securitization of proceeds from real estate. The vehicle issues notes that are natively financial instruments, eligible for DLT registration under Italian Law 52/2023. Alternative vehicles for future deployments include closed-end real estate AIFs managed by authorized SGRs and, for smaller operations (< 25M AUM), Simple Investment Companies (SIS).

REGISTRAR PARTNERSHIP MODEL

In its initial configuration Vettor operates in partnership with entities already authorized by Consob as registrars for the digital circulation of financial instruments. The partner maintains the legal registry and provides the regulated settlement layer; Vettor provides the chain, wallet infrastructure, secondary trading venue and on-chain governance tooling. Each legal transfer on the partner's registry is mirrored by a corresponding token transfer on Vettor, preserving 1:1 alignment between on-chain state and legal ownership.

ONBOARDING FLOW

1. Originator submits asset proposal
2. Legal and technical due diligence
3. Asset conveyed to or controlled by the regulated vehicle (SPV L.130 / AIF)
4. Vehicle issues financial instruments (notes / units)
5. Instruments registered on the DLT registry by the authorized registrar
6. Token emitted on Vettor mirroring the registrar's entry 1:1
7. Primary distribution and secondary trading via Vettor
8. Lifecycle events (distributions, governance votes, disposition) flow between the registrar and the chain

ASSET CLASSIFICATIONS

Equity — Shares, stock tokens, equity stakes
Debt — Bonds, notes, loan participations
RealEstate — Property tokens, REIT shares, land titles
Commodity — Gold, oil, agricultural products
Fund — Fund shares, ETF tokens, pooled investments
IntellectualProperty — Patents, royalties, licensing rights
CarbonCredit — Verified carbon credits, environmental offsets
Invoice — Invoice factoring, receivables
Custom — Any other asset type (string label)

ASSET LIFECYCLE

DRAFT
ACTIVE
FROZEN
MATURED
REDEEMED
DRAFTInitial state, asset metadata being configured. Can be deleted before activation.
ACTIVETradeable. Transfers and compliance checks enforced.
FROZENTemporarily halted (regulatory action, issuer request). Can be unfrozen back to Active.
MATUREDAsset reached maturity date (e.g. bond expiry). No longer tradeable.
REDEEMEDFinal state. Tokens exchanged for underlying value.

ASSET METADATA

FIELDTYPEDESCRIPTION
jurisdictionStringISO 3166-1 alpha-2 code (e.g. IT, LU, CH, US)
legal_entityStringSPV name and registration number holding the underlying asset
decimalsu8Decimal places for display (max 18)
origin_chainu32Chain ID where the asset was originally issued
compliance_policyStringPolicy identifier for transfer restrictions
valuation_oracleStringOracle feed ID for price/valuation data
documentsDocument[]Attached legal/regulatory documents
metadata_uriStringIPFS/HTTP URI for extended off-chain metadata

DOCUMENT TYPES

Prospectus — Offering document describing the asset and terms
TermSheet — Summary of key financial terms
Valuation — Third-party valuation report
LegalOpinion — Legal counsel opinion on the offering
AuditReport — Financial or technical audit
RegulatoryApproval — Regulatory approval documents
DeedOfTransfer — Deed of transfer / conferment to SPV
Encumbrance — Legal encumbrance registered in property registry
Custom — Any other document type

COMPLIANCE & IDENTITY

VTT supports both permissioned and permissionless chains. Application chains can enforce identity requirements and transfer restrictions at the protocol level.

Identity is managed through an on-chain DID (Decentralized Identifier) system. Authorized issuers (KYC providers, regulators) attach verifiable claims to identities. Asset transfers are validated against both sender and receiver claims before execution.

CLAIM TYPES

CLAIMDESCRIPTION
KYCKnow Your Customer verification completed
AMLClearedAnti-Money Laundering check passed
AccreditedInvestorVerified accredited investor status (SEC Rule 501)
QualifiedPurchaserQualified purchaser status for private funds
JurisdictionCountry/region jurisdiction claim (ISO 3166)
CustomApplication-specific claim with string label

CLAIM STRUCTURE

interface IdentityClaim {
  claim_type: ClaimType;    // KYC | AMLCleared | AccreditedInvestor | ...
  issuer: Address;          // Address of the claim issuer
  subject: Address;         // Address the claim is about
  issued_at: u64;           // Unix timestamp of issuance
  expires_at: u64;          // Unix timestamp of expiration (0 = no expiry)
  revoked: boolean;         // Whether the claim has been revoked
  data: Vec<u8>;            // Optional additional data (e.g. jurisdiction code)
}

TRANSFER VALIDATION

When a tokenized asset transfer is submitted, the protocol validates both parties against the asset's compliance policy. The check verifies:

  1. Sender has required claims (not expired, not revoked)
  2. Receiver has required claims (not expired, not revoked)
  3. Neither party is on a deny list
  4. Transfer amount is within any configured limits
  5. Asset is in Active status (not frozen/matured/redeemed)

GOVERNANCE

VTT includes on-chain governance allowing stakers to propose and vote on protocol changes. Voting power is proportional to staked VTT. Only staked tokens count for voting.

GOVERNANCE PARAMETERS

Voting period201,600 blocks (~7 days at 3s/block)
Quorum33% of total staked VTT must participate
Pass threshold50% + 1 of votes cast (excluding abstain)
Execution delayImmediate after voting period ends (if passed)

PROPOSAL TYPES

TYPEDESCRIPTION
ParameterChangeModify a whitelisted protocol parameter. Unknown keys are rejected at proposal creation time. See the full key list below.
RegisterChainRegister a new application chain on the relay. On execution a RegisteredChain record is persisted and exposed via vtt_listRegisteredChains. Cross-chain message routing is not yet live — see Multichain notes below.
TreasurySpendAllocate funds from the on-chain treasury to an address
ProtocolUpgradeSchedule a runtime upgrade at a specific block height

PARAMETERCHANGE WHITELIST

The executor rejects ParameterChange proposals whose key is not in this whitelist (prevents typos from quietly becoming no-op signals). Values are parsed according to the type shown.

KEYTYPEMEANING
bridge_relayerAddressOnly address allowed to submit BridgeDeposit.
treasury_addressAddressReceives burned gas share, drives SetKycApproval + SetAddressJurisdiction.
min_gas_priceu128 (raw Amount)Minimum accepted gas price for transactions.
base_transfer_costu64Baseline gas cost charged for a Transfer.
cost_per_byteu64Gas charged per byte of transaction payload.
slash_double_sign_bpsu16 (0..=10000)Penalty in basis points when a double-sign is detected.
slash_downtime_bpsu16 (0..=10000)Penalty in basis points for downtime beyond threshold.
downtime_threshold_pctu8 (0..=100)% of expected slots a validator can miss before being slashed.
unbonding_period_secsu64Seconds a stake remains locked after unbonding.
max_holders_per_assetu32Cap on unique non-zero holders per asset (0 = unlimited).
jurisdiction_whitelistCSV ISO 3166-1 α-2Only allow AssetTransfers where both parties have a whitelisted country.
jurisdiction_blacklistCSV ISO 3166-1 α-2Reject AssetTransfers where either party is in a blacklisted country.

PROPOSAL LIFECYCLE

ACTIVE
PASSED
REJECTED
EXECUTED
ACTIVEVoting is open. Stakers can vote Yes / No / Abstain.
PASSEDVoting ended. Quorum met and majority voted Yes.
REJECTEDVoting ended. Quorum not met or majority voted No.
EXECUTEDProposal action has been applied to the chain.

ASSET GOVERNANCE

Beyond protocol-level governance, VTT supports per-asset governance allowing token holders of any tokenized asset to propose and vote on actions specific to that asset. Voting power is proportional to token holdings (not staked VTT).

This enables asset-specific decisions such as revenue distribution, issuer changes, and signal votes without requiring protocol-wide governance proposals.

ASSET GOVERNANCE PARAMETERS

Voting period201,600 blocks (~7 days at 3s/block)
Quorum33% of total asset supply must participate
Pass threshold (standard)>50% of yes+no votes (51% for rounding)
Pass threshold (critical)67% supermajority for ChangeIssuer, DisposeAsset and FinalizeRedemption
Voting weight1 token = 1 vote (proportional to holdings)
Double-vote preventionEach address can vote once per proposal

PROPOSAL ACTION TYPES

ACTIONTHRESHOLDDESCRIPTION
DistributeRevenue>50%Distribute VTT revenue to all holders pro-rata. Amount taken from proposer on execution.
ChangeIssuer67% supermajorityTransfer the issuer role to a new address. Critical action requiring higher threshold.
Signal>50%Generic text proposal (signal vote). No on-chain execution, used for community sentiment.
DisposeAsset67% supermajorityAuthorize disposition of the underlying asset or wind-down of the regulated vehicle. Freezes the token and marks it Redeemed. Actual sale is executed off-chain by the vehicle's directors following normal legal procedure.
FinalizeRedemption67% supermajorityForce-close a RedemptionPending asset once the redemption window has elapsed. Transitions the asset to Redeemed; any unclaimed balance in the redemption pool is swept to the treasury so it isn't locked forever.

TRANSACTION ACTIONS

Asset governance uses four dedicated transaction actions:

ACTIONFIELDSDESCRIPTION
DistributeRevenueasset_id: H256, total_amount: AmountDirect distribution by issuer (no vote required)
ProposeAssetActionasset_id: H256, action: AssetProposalAction, description: StringCreate a new proposal (only token holders)
VoteAssetProposalproposal_id: H256, vote: Vote (Yes/No/Abstain)Cast vote weighted by token holdings
FinalizeAssetProposalproposal_id: H256Execute a passed proposal after voting ends

REVENUE DISTRIBUTION

Revenue distribution sends VTT to all holders of a tokenized asset, pro-rata based on their holdings at the time of execution. There are two paths:

  1. Direct (issuer) — The asset issuer submits a DistributeRevenue transaction directly. The amount is deducted from the sender's balance and distributed immediately.
  2. Governed (proposal) — Any token holder proposes a DistributeRevenue action via ProposeAssetAction. If the proposal passes quorum and threshold, the distribution executes on finalization.

BLOCK REWARDS

VTT uses an inflation-based reward model to incentivize block production and staking. Block rewards are newly minted tokens distributed each block. The inflation rate is dynamic, targeting a specific staking ratio to balance security with token supply growth.

INFLATION MODEL

Base annual inflation5% of total supply
Target staking ratio60% of total supply staked
If staking < 60%Rewards increase (up to 2x multiplier) to incentivize staking
If staking > 60%Rewards decrease (down to 0.5x multiplier) to discourage excess
If staking = 0%Maximum 2x multiplier applied
Epochs per year~8,760 (1-hour epochs, 1,200 blocks each)

EPOCH REWARD CALCULATION

// Epoch reward formula (from vtt-consensus/src/rewards.rs)
//
// base_rate = 50 per mille (5% annual)
//
// If staking_ratio == 0%:
//   adjusted = base_rate × 2 (max incentive)
// Else:
//   adjusted = clamp(60 × base_rate / staking_ratio, base_rate/2, base_rate×2)
//
// epoch_reward = total_supply × adjusted / (1000 × 8760)

// Example at 60% staking (target):
//   adjusted = 60 × 50 / 60 = 50
//   epoch_reward = 1,000,000,000 × 50 / (1000 × 8760) ≈ 5,708 VTT per epoch

BLOCK REWARD SPLIT

Block producer80% of block reward
Protocol treasury20% of block reward

GAS FEE SPLIT

Burned (deflationary)70% of gas fees — permanently removed from supply
Block producer30% of gas fees — additional producer income

The burn mechanism creates deflationary pressure that partially offsets the inflation from block rewards. At high network utilization, the 70% gas burn can exceed new token issuance, making VTT net-deflationary.

BRIDGE SYSTEM

The VTT bridge enables cross-chain asset transfers between the VTT chain and external EVM chains (Ethereum, Base). It uses a lock/mint and burn/release model with a relayer service monitoring events on both sides.

ARCHITECTURE

wVTT contractERC-20 wrapped VTT on Ethereum (mintable by bridge)
VTTBridge contractSolidity contract handling deposits and releases on EVM side
RelayerOff-chain service monitoring both chains, submitting proofs
Supported chainsEthereum mainnet, Base

BRIDGE WITHDRAW (VTT → ETHEREUM)

To move tokens from VTT to an external chain, submit a BridgeWithdraw transaction. This burns the tokens on the VTT chain. The relayer detects the event and calls the bridge contract on the destination chain to release or mint equivalent tokens.

FIELDTYPEDESCRIPTION
tokenH256H256::ZERO for native VTT, or asset ID for tokens (e.g. vUSDT)
amountAmount (u128)Amount to withdraw (burned on VTT chain)
destination_chainu32EVM chain ID (1 = Ethereum mainnet, 8453 = Base, 11155111 = Sepolia)
destination_addressAddress (20 bytes)Recipient address on the external EVM chain

RELAYER FLOW

VTT CHAIN
1. User submits BridgeWithdraw tx
2. Tokens burned on VTT chain
3. Withdrawal event recorded
RELAYER
← monitors
4. Detects withdrawal via vtt_getBridgeWithdrawals
5. Submits release tx to EVM
ETHEREUM / BASE
← relayed
6. VTTBridge.release() called
7. wVTT minted to destination address

BRIDGE DEPOSIT (ETHEREUM → VTT)

To move tokens from Ethereum to VTT, the user deposits wVTT (or supported tokens) into the VTTBridge contract on Ethereum. The relayer detects the deposit event and mints equivalent tokens on the VTT chain to the specified recipient address.

CROSS-CHAIN MESSAGING

Vettor's architecture supports cross-chain communication through a relay-mediated messaging protocol. Messages are routed through the relay chain, which verifies inclusion proofs before delivering to the destination chain.

PAYLOAD TYPES

TYPEDESCRIPTION
VttTransferTransfer native VTT tokens to another chain
AssetTransferTransfer a tokenized asset to another chain
DataMessageArbitrary data message (for contract-to-contract calls)

MESSAGE LIFECYCLE

SOURCE CHAIN
1. Tx with CrossChain action submitted
2. Message added to source outbox
3. Outbox Merkle root included in block header
RELAY CHAIN
← reads root
4. Relay verifies inclusion proof
5. Message relayed to destination
DEST CHAIN
← forwarded
6. Delivered to dest inbox
7. Executed on dest chain
PENDING
RELAYED
DELIVERED
FAILED

MECHANICS

Each chain maintains an outbox and an inbox. Outgoing messages are collected in the outbox and their Merkle root is included in the block header. The relay chain reads these roots and forwards messages to destination chain inboxes with inclusion proofs.

Validators are assigned to relay duties through a deterministic shuffle per epoch, ensuring fair distribution of cross-chain relay work among the active set.

ORACLE SYSTEM

VTT includes a native oracle module for bringing off-chain data on-chain. Oracles are critical for RWA valuation, compliance checks, and DeFi applications. The system uses quorum-based aggregation with multiple authorized sources.

FEED TYPES

AssetValuation — NAV or appraised value of a tokenized asset
MarketPrice — Market price of a tradeable token (e.g. VTT/USD)
InterestRate — Reference interest rates (SOFR, EURIBOR, etc.)
Custom — Application-specific data feeds

AGGREGATION MECHANICS

Authorized sourcesOracle nodes permissioned per feed
Aggregation methodMedian of all submitted values (outlier resistant)
Quorum requiredConfigurable per feed (minimum sources before update)
Max stalenessConfigurable per feed (rejects reads if data too old)
Gas cost500 gas per oracle read from a contract

DEX / AMM

VTT includes a native Automated Market Maker (AMM) built directly into the protocol layer. It implements a constant-product formula identical to Uniswap v2, giving any application chain access to trustless token swaps without deploying external contracts.

Pools are identified by a deterministic pool_id derived from the BLAKE3 hash of the two sorted token identifiers (H256). This means a given token pair always maps to exactly one pool address — there are no duplicate markets.

CONSTANT PRODUCT FORMULA

x · y = k
x — reserve of token A
y — reserve of token B
k — constant (invariant); must hold after every swap (post-fee)
Output for a swap of Δx in: Δy = y · Δx_after_fee / (x + Δx_after_fee)

FEE STRUCTURE

Total swap fee0.3% (30 bps) of amount in
LP share0.25% (25 bps) — added back to reserves, accrues to LPs
Protocol share0.05% (5 bps) — sent to on-chain treasury
Fee tokenDeducted from token_in before AMM invariant calculation

LP TOKENS

When liquidity is added to a pool, the provider receives LP tokens representing their proportional share of the reserves. LP tokens are first-class on-chain assets (same type as tokenized RWA assets) and are transferable.

The first depositor receives sqrt(amount_a * amount_b) LP tokens. The initial 1,000 LP tokens are permanently burned to prevent price manipulation on empty pools. Subsequent depositors receive LP tokens proportional to their contribution relative to total reserves.

Minimum liquidity1,000 LP tokens burned on first deposit (per pool)
LP token formula (first)sqrt(amount_a × amount_b) − 1000
LP token formula (subsequent)min(amount_a / reserve_a, amount_b / reserve_b) × lp_supply
WithdrawalReturns proportional share of both reserves at time of burn

LIQUIDITY MINING

Total reward pool50,000,000 VTT (5% of supply)
Distribution period12 months from mainnet launch
Distribution modelMasterChef-style: per-block reward split by pool weight
ClaimingRewards accumulate per block; claimable at any time
Pool weightsGovernance-controlled; VTT/vUSDT pool has highest initial weight

REVENUE SHARE (VTT-REV)

VTT-REV is a fixed-supply on-chain asset representing a perpetual claim on protocol fee revenue. Holders receive a pro-rata share of the 0.05% protocol fee collected from every swap across all pools.

Token symbolVTT-REV
Total supply10,000 (fixed, no minting after genesis)
Entitlement per token0.01% of all protocol DEX fees
DistributionProtocol fee accrues to rev-share vault; claimable per token

vUSDT — NATIVE STABLECOIN

vUSDT is the native stablecoin of the VTT ecosystem. It is a protocol-minted asset pegged 1:1 to USD, used as the primary quote currency in DEX pools and as a settlement medium for RWA transactions.

SymbolvUSDT
Total supply100,000,000 (100M)
Decimals6
Peg mechanism1:1 USD collateral held by VTT Foundation (audited quarterly)
Primary poolVTT / vUSDT — anchor liquidity pool for price discovery

POOL CREATION

PermissionlessAny account can create a pool for any two distinct token IDs
pool_id derivationBLAKE3(sort(token_a, token_b)) — deterministic, one pool per pair
Native VTT token IDH256::zero() — all 32 bytes are 0x00
Creation feeGovernance-controlled; initial value is 1,000 VTT (burned)

NETWORK

VTT nodes communicate over a peer-to-peer network built on libp2p. The network layer handles peer discovery, block propagation, transaction gossip, and cross-chain relay messages.

NETWORK STACK

TransportTCP
EncryptionNoise protocol (XX handshake pattern)
MultiplexingYamux
Pub/subGossipsub (block and transaction propagation)
Peer discoveryKademlia DHT
Default port30333
Max peers50

BLOCK SYNC PROTOCOL

When a new peer connects, both sides exchange a StatusMessage containing best block number, best block hash, and genesis hash. If a node is behind, it sends a BlockRangeRequest for missing blocks (up to 100 per batch). The peer responds with a BlockRangeResponse containing the requested blocks.

Blocks are imported sequentially and sync continues until the node is caught up. Single block requests (BlockRequest / BlockResponse) are also supported for on-demand block fetching.

SYNC MESSAGES
StatusMessageExchanged on connect — best block number, hash, genesis hash
BlockRangeRequestRequest a range of blocks (max 100 per batch)
BlockRangeResponseResponse with requested block range
BlockRequestRequest a single block by hash or number
BlockResponseResponse with the requested block

PROMETHEUS METRICS

Validators and nodes expose Prometheus-compatible metrics on a configurable HTTP port. Metrics are returned in Prometheus text format on the root endpoint.

Default port9615 (configurable via --metrics-port)
EndpointGET http://localhost:9615/
FormatPrometheus text exposition format
AVAILABLE METRICS
block_heightCurrent chain height
connected_peersNumber of connected P2P peers
txpool_sizePending transactions in the mempool
blocks_importedTotal blocks imported since start
transactions_executedTotal transactions executed since start
current_epochCurrent consensus epoch number
active_validatorsNumber of active validators in the current set
block_import_durationTime taken to import the last block
PART II

API REFERENCE

Complete JSON-RPC 2.0 developer reference. Query chain state, submit transactions, manage tokenized assets, interact with governance, staking, DEX, and more.

API OVERVIEW

The node exposes a JSON-RPC 2.0 API over HTTP POST. Every request follows the standard JSON-RPC envelope:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "vtt_methodName",
  "params": [...]
}

All method names are prefixed with vtt_. Parameters are passed as a JSON array in positional order. Responses return a result field on success or an error object on failure.

Amounts are represented as hex-encoded 128-bit unsigned integers with 18 decimal places. For example, 1.0 VTT = 1000000000000000000 (1e18) = 0xDE0B6B3A7640000 in hex.

Addresses are 20 bytes encoded as 0x + 40 hex characters, derived from the BLAKE3 hash of the Ed25519 public key (last 20 bytes of the 32-byte hash).

RATE LIMITING

The vtt_sendTransaction method is rate-limited to 10 calls per second globally. Exceeding the limit returns JSON-RPC error code -32005 ("Rate limit exceeded"). Other read-only RPC methods are not rate-limited.

Limited methodvtt_sendTransaction
Rate10 calls/second (global)
Error code-32005 (Rate limit exceeded)
Read methodsNot rate-limited

CONNECTION

The VTT node listens for JSON-RPC requests on the configured HTTP port. The default endpoint for a local node is:

DEFAULT NODE ENDPOINT
http://127.0.0.1:9944

The VTT web application uses a BFF (Backend-for-Frontend) proxy at /api/rpc which forwards requests to the node. This allows the browser to communicate with the node without CORS issues and enables server-side middleware (rate limiting, caching, etc.).

When building external tools or scripts, point directly to the node endpoint. All requests must be HTTP POST with Content-Type: application/json.

QUICK TEST
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_chainStatus","params":[]}'

CHAIN METHODS

vtt_chainStatus

Returns the current status of the chain including height, head hash, validator count, and total stake.

PARAMETERS

No parameters.

RETURNS — ChainStatus
FIELDTYPEDESCRIPTION
chain_idnumberChain identifier
heightnumberCurrent block height
head_hashstringHash of the latest block (0x-prefixed hex)
validator_countnumberNumber of active validators
total_stakestringTotal staked VTT (hex-encoded u128, 18 decimals)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_chainStatus","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "chain_id": 1,
    "height": 128456,
    "head_hash": "0x9f3a...b2c1",
    "validator_count": 21,
    "total_stake": "0x56bc75e2d63100000"
  }
}
vtt_chainHeight

Returns the current block height as a plain number. Lightweight alternative to vtt_chainStatus when you only need the height.

PARAMETERS

No parameters.

RETURNS — number
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_chainHeight","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": 128456
}

BLOCK METHODS

vtt_getBlock

Retrieves a block by its hash. Returns null if the block is not found.

PARAMETERS
NAMETYPEDESCRIPTION
hashstringBlock hash (0x-prefixed, 64 hex chars)
RETURNS — BlockInfo | null
FIELDTYPEDESCRIPTION
hashstringBlock hash
numbernumberBlock number (height)
parent_hashstringHash of the parent block
state_rootstringMerkle root of the state trie
transactions_rootstringMerkle root of the transactions trie
validatorstringAddress of the block producer
epochnumberEpoch number
slotnumberSlot number within the epoch
timestampnumberUnix timestamp (seconds)
gas_limitnumberMaximum gas for the block
gas_usednumberTotal gas consumed by transactions
tx_countnumberNumber of transactions in the block
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getBlock","params":["0x9f3a...b2c1"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "hash": "0x9f3a...b2c1",
    "number": 128456,
    "parent_hash": "0x8e2b...a1d0",
    "state_root": "0x1234...5678",
    "transactions_root": "0xabcd...ef01",
    "validator": "0x0101010101010101010101010101010101010101",
    "epoch": 642,
    "slot": 3,
    "timestamp": 1711900800,
    "gas_limit": 30000000,
    "gas_used": 1250000,
    "tx_count": 15
  }
}
vtt_getBlockByNumber

Retrieves a block by its height number. Returns null if no block exists at that height.

PARAMETERS
NAMETYPEDESCRIPTION
numbernumberBlock height (0-indexed)
RETURNS — BlockInfo | null
FIELDTYPEDESCRIPTION
hashstringBlock hash
numbernumberBlock number (height)
parent_hashstringHash of the parent block
state_rootstringMerkle root of the state trie
transactions_rootstringMerkle root of the transactions trie
validatorstringAddress of the block producer
epochnumberEpoch number
slotnumberSlot number within the epoch
timestampnumberUnix timestamp (seconds)
gas_limitnumberMaximum gas for the block
gas_usednumberTotal gas consumed by transactions
tx_countnumberNumber of transactions in the block
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getBlockByNumber","params":[128456]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "hash": "0x9f3a...b2c1",
    "number": 128456,
    "parent_hash": "0x8e2b...a1d0",
    "state_root": "0x1234...5678",
    "transactions_root": "0xabcd...ef01",
    "validator": "0x0101010101010101010101010101010101010101",
    "epoch": 642,
    "slot": 3,
    "timestamp": 1711900800,
    "gas_limit": 30000000,
    "gas_used": 1250000,
    "tx_count": 15
  }
}

ACCOUNT METHODS

vtt_getBalance

Returns the native VTT balance for an address as a hex-encoded u128 string with 18 decimal places.

PARAMETERS
NAMETYPEDESCRIPTION
addressstringAccount address (0x + 40 hex chars)
RETURNS — string
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getBalance","params":["0x0101010101010101010101010101010101010101"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x56bc75e2d63100000"
}
vtt_getAccount

Returns full account information including balance, nonce, and whether the account is a smart contract.

PARAMETERS
NAMETYPEDESCRIPTION
addressstringAccount address (0x + 40 hex chars)
RETURNS — AccountInfo
FIELDTYPEDESCRIPTION
addressstringThe account address
balancestringNative VTT balance (hex-encoded u128, 18 decimals)
noncenumberTransaction count / sequence number for replay protection
is_contractbooleanTrue if this address holds WASM contract code
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getAccount","params":["0x0101010101010101010101010101010101010101"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "address": "0x0101010101010101010101010101010101010101",
    "balance": "0x56bc75e2d63100000",
    "nonce": 42,
    "is_contract": false
  }
}
vtt_getStakingInfo

Returns staking information for a validator address, including self-stake, total stake, commission, active status, and list of delegations. Returns null if the address is not a validator.

PARAMETERS
NAMETYPEDESCRIPTION
addressstringValidator address (0x + 40 hex chars)
RETURNS — StakingInfo | null
FIELDTYPEDESCRIPTION
addressstringValidator address
self_stakestringValidator's own stake (hex u128, 18 decimals)
total_stakestringTotal delegated + self stake (hex u128, 18 decimals)
commission_bpsnumberCommission rate in basis points (100 = 1%)
activebooleanWhether the validator is in the active set
delegationsDelegationInfo[]List of delegations to this validator
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getStakingInfo","params":["0x0101010101010101010101010101010101010101"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "address": "0x0101010101010101010101010101010101010101",
    "self_stake": "0x56bc75e2d63100000",
    "total_stake": "0x1b1ae4d6e2ef500000",
    "commission_bps": 500,
    "active": true,
    "delegations": [
      { "delegator": "0xabcd...1234", "amount": "0xDE0B6B3A7640000" },
      { "delegator": "0x5678...ef01", "amount": "0x1BC16D674EC80000" }
    ]
  }
}

TRANSACTION METHODS

vtt_sendTransaction

Submits a signed transaction to the mempool. The transaction must be fully serialized using Borsh encoding, signed with Ed25519, and hex-encoded. Returns the transaction hash on success.

PARAMETERS
NAMETYPEDESCRIPTION
txHexstringHex-encoded signed transaction bytes (payload + 64-byte signature + 32-byte public key)
RETURNS — string
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_sendTransaction","params":["0a0b0c...signed_tx_hex"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x7f8a3c...transaction_hash"
}
vtt_getTransaction

Retrieves a confirmed transaction by its hash. Returns null if not found.

PARAMETERS
NAMETYPEDESCRIPTION
hashstringTransaction hash (0x-prefixed, 64 hex chars)
RETURNS — TransactionInfo | null
FIELDTYPEDESCRIPTION
hashstringTransaction hash
block_numbernumberBlock that included this transaction
fromstringSender address
tostring | nullRecipient address (null for contract deploys)
action_typestringAction type (Transfer, Stake, DeployContract, etc.)
amountstringVTT amount transferred (hex u128, 18 decimals)
gas_usednumberGas consumed by execution
status"success" | "fail"Execution result
timestampnumberUnix timestamp (seconds)
payload_hexstringRaw Borsh-encoded payload as hex
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getTransaction","params":["0x7f8a3c..."]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "hash": "0x7f8a3c...abcd",
    "block_number": 128456,
    "from": "0x0101010101010101010101010101010101010101",
    "to": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
    "action_type": "Transfer",
    "amount": "0xDE0B6B3A7640000",
    "gas_used": 21000,
    "status": "success",
    "timestamp": 1711900800,
    "payload_hex": "01000000..."
  }
}
vtt_listTransactions

Returns a paginated list of recent transactions across the entire chain, ordered by most recent first.

PARAMETERS
NAMETYPEDESCRIPTION
pagenumberPage number (1-indexed)
limitnumberItems per page (max 100)
RETURNS — PaginatedResult<TransactionInfo>
FIELDTYPEDESCRIPTION
itemsTransactionInfo[]Array of transactions for this page
totalnumberTotal number of transactions
pagenumberCurrent page number
page_sizenumberItems per page
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_listTransactions","params":[1, 20]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "items": [
      {
        "hash": "0x7f8a...",
        "block_number": 128456,
        "from": "0x0101...0101",
        "to": "0xabcd...abcd",
        "action_type": "Transfer",
        "amount": "0xDE0B6B3A7640000",
        "gas_used": 21000,
        "status": "success",
        "timestamp": 1711900800,
        "payload_hex": "01000000..."
      }
    ],
    "total": 543210,
    "page": 1,
    "page_size": 20
  }
}
vtt_getTransactionsByAddress

Returns paginated transactions for a specific address (both sent and received).

PARAMETERS
NAMETYPEDESCRIPTION
addressstringAccount address (0x + 40 hex chars)
pagenumberPage number (1-indexed)
limitnumberItems per page (max 100)
RETURNS — PaginatedResult<TransactionInfo>
FIELDTYPEDESCRIPTION
itemsTransactionInfo[]Array of transactions for this page
totalnumberTotal transactions involving this address
pagenumberCurrent page number
page_sizenumberItems per page
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getTransactionsByAddress","params":["0x0101010101010101010101010101010101010101", 1, 20]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "items": [ ... ],
    "total": 87,
    "page": 1,
    "page_size": 20
  }
}
vtt_txPoolSize

Returns the number of transactions currently waiting in the mempool (transaction pool).

PARAMETERS

No parameters.

RETURNS — number
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_txPoolSize","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": 42
}

VALIDATOR METHODS

vtt_getValidators

Returns the list of all active validators in the current epoch with their stake and commission info.

PARAMETERS

No parameters.

RETURNS — ValidatorInfo[]
FIELDTYPEDESCRIPTION
addressstringValidator address
total_stakestringTotal stake including delegations (hex u128, 18 decimals)
self_stakestringValidator's own stake (hex u128, 18 decimals)
commission_bpsnumberCommission rate in basis points (500 = 5%)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getValidators","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "address": "0x0101010101010101010101010101010101010101",
      "total_stake": "0x1b1ae4d6e2ef500000",
      "self_stake": "0x56bc75e2d63100000",
      "commission_bps": 500
    },
    {
      "address": "0x0202020202020202020202020202020202020202",
      "total_stake": "0xad78ebc5ac6200000",
      "self_stake": "0x56bc75e2d63100000",
      "commission_bps": 300
    }
  ]
}

ASSET METHODS

vtt_getAsset

Returns information about a registered asset (tokenized RWA) by its ID. Returns null if not found.

PARAMETERS
NAMETYPEDESCRIPTION
idstringAsset ID (0x-prefixed, 64 hex chars / 32 bytes)
RETURNS — AssetInfo | null
FIELDTYPEDESCRIPTION
idstringUnique asset identifier
namestringHuman-readable asset name
symbolstringToken ticker symbol
issuerstringAddress of the asset issuer
total_supplystringTotal supply (hex u128, using asset decimals)
statusstringAsset status (active, frozen, retired)
decimalsnumberDecimal places for display
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getAsset","params":["0xabc123..."]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "0xabc123...",
    "name": "Milan Office Tower A",
    "symbol": "MOTA",
    "issuer": "0x0101010101010101010101010101010101010101",
    "total_supply": "0x52b7d2dcc80cd2e4000000",
    "status": "active",
    "decimals": 18
  }
}
vtt_getAssetBalance

Returns the balance of a specific asset for a given address, including available and locked amounts.

PARAMETERS
NAMETYPEDESCRIPTION
assetIdstringAsset ID (0x-prefixed, 64 hex chars)
addressstringOwner address (0x + 40 hex chars)
RETURNS — AssetBalanceInfo
FIELDTYPEDESCRIPTION
asset_idstringThe asset ID
ownerstringThe owner address
availablestringAvailable (unlocked) balance (hex u128)
lockedstringLocked balance (e.g. in escrow or vesting)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getAssetBalance","params":["0xabc123...", "0x0101...0101"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "asset_id": "0xabc123...",
    "owner": "0x0101010101010101010101010101010101010101",
    "available": "0xDE0B6B3A7640000",
    "locked": "0x0"
  }
}
vtt_listAssets

Returns all registered assets on the chain.

PARAMETERS

No parameters.

RETURNS — AssetInfo[]
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_listAssets","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "id": "0xabc123...",
      "name": "Milan Office Tower A",
      "symbol": "MOTA",
      "issuer": "0x0101...0101",
      "total_supply": "0x52b7d2dcc80cd2e4000000",
      "status": "active",
      "decimals": 18
    }
  ]
}

GOVERNANCE METHODS

vtt_listProposals

Returns all governance proposals on the chain, in any status (pending, active, passed, rejected, executed).

PARAMETERS

No parameters.

RETURNS — ProposalInfo[]
FIELDTYPEDESCRIPTION
idstringProposal ID (0x-prefixed, 64 hex chars)
proposerstringAddress of the proposal creator
descriptionstringHuman-readable proposal description
action_typestringType of governance action
statusstringCurrent status (pending, active, passed, rejected, executed)
votes_yesstringTotal yes vote weight (hex u128)
votes_nostringTotal no vote weight (hex u128)
votes_abstainstringTotal abstain vote weight (hex u128)
created_atnumberCreation timestamp (unix seconds)
voting_endnumberVoting deadline (unix seconds)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_listProposals","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "id": "0xdeadbeef...",
      "proposer": "0x0101...0101",
      "description": "Increase max validators to 50",
      "action_type": "ParameterChange",
      "status": "active",
      "votes_yes": "0x56bc75e2d63100000",
      "votes_no": "0x0",
      "votes_abstain": "0xDE0B6B3A7640000",
      "created_at": 1711800000,
      "voting_end": 1712404800
    }
  ]
}
vtt_getProposal

Returns a single governance proposal by its ID. Returns null if not found.

PARAMETERS
NAMETYPEDESCRIPTION
idstringProposal ID (0x-prefixed, 64 hex chars)
RETURNS — ProposalInfo | null
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getProposal","params":["0xdeadbeef..."]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "0xdeadbeef...",
    "proposer": "0x0101...0101",
    "description": "Increase max validators to 50",
    "action_type": "ParameterChange",
    "status": "active",
    "votes_yes": "0x56bc75e2d63100000",
    "votes_no": "0x0",
    "votes_abstain": "0xDE0B6B3A7640000",
    "created_at": 1711800000,
    "voting_end": 1712404800
  }
}

ASSET GOVERNANCE METHODS

vtt_getAssetProposals

Returns all governance proposals for a specific tokenized asset. Includes active, passed, rejected, and executed proposals.

PARAMETERS
NAMETYPEDESCRIPTION
assetIdstringAsset ID (0x-prefixed, 64 hex chars / 32 bytes)
RETURNS — AssetProposalInfo[]
FIELDTYPEDESCRIPTION
idstringProposal ID (0x + 64 hex)
asset_idstringTarget asset ID
proposerstringAddress of the proposal creator
action_typestringProposal action (DistributeRevenue, ChangeIssuer, Signal)
descriptionstringHuman-readable description
statusstringCurrent status (Active, Passed, Rejected, Executed)
votes_yesstringTotal yes vote weight (hex u128)
votes_nostringTotal no vote weight (hex u128)
votes_abstainstringTotal abstain vote weight (hex u128)
voting_endnumberBlock number when voting ends
created_atnumberBlock number when proposal was created
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getAssetProposals","params":["0xabc123..."]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "id": "0xdeadbeef...",
      "asset_id": "0xabc123...",
      "proposer": "0x0101...0101",
      "action_type": "DistributeRevenue",
      "description": "Distribute Q1 2026 rental income",
      "status": "Active",
      "votes_yes": "0x56bc75e2d63100000",
      "votes_no": "0x0",
      "votes_abstain": "0xDE0B6B3A7640000",
      "voting_end": 302400,
      "created_at": 100800
    }
  ]
}
vtt_getAssetProposal

Returns a single asset governance proposal by its proposal ID. Returns null if not found.

PARAMETERS
NAMETYPEDESCRIPTION
proposalIdstringProposal ID (0x-prefixed, 64 hex chars)
RETURNS — AssetProposalInfo | null
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getAssetProposal","params":["0xdeadbeef..."]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "0xdeadbeef...",
    "asset_id": "0xabc123...",
    "proposer": "0x0101...0101",
    "action_type": "DistributeRevenue",
    "description": "Distribute Q1 2026 rental income",
    "status": "Active",
    "votes_yes": "0x56bc75e2d63100000",
    "votes_no": "0x0",
    "votes_abstain": "0xDE0B6B3A7640000",
    "voting_end": 302400,
    "created_at": 100800
  }
}

BRIDGE METHODS

vtt_getBridgeWithdrawals

Returns all bridge withdrawal events. Used by the bridge relayer to monitor pending withdrawals that need to be relayed to external chains.

PARAMETERS

No parameters.

RETURNS — BridgeWithdrawalInfo[]
FIELDTYPEDESCRIPTION
tx_hashstringTransaction hash of the BridgeWithdraw tx on VTT
block_numbernumberBlock that included the withdrawal
senderstringAddress that initiated the withdrawal on VTT
tokenstringToken ID (0x000...0 = native VTT, or asset ID)
amountstringAmount withdrawn/burned (hex u128)
destination_chainnumberEVM chain ID (1 = Ethereum, 8453 = Base)
destination_addressstringRecipient address on the external chain
timestampnumberUnix timestamp (seconds)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getBridgeWithdrawals","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "tx_hash": "0x7f8a3c...abcd",
      "block_number": 128456,
      "sender": "0x0101010101010101010101010101010101010101",
      "token": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "amount": "0xDE0B6B3A7640000",
      "destination_chain": 1,
      "destination_address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
      "timestamp": 1711900800
    }
  ]
}

CONFIG METHODS

vtt_getConsensusParams

Returns the current consensus parameters of the chain, including epoch length, block time, validator limits, staking requirements, and slashing configuration.

PARAMETERS

No parameters.

RETURNS — ConsensusParamsRpc
FIELDTYPEDESCRIPTION
epoch_lengthnumberBlocks per epoch (e.g. 1200)
block_time_msnumberTarget block time in milliseconds (e.g. 3000)
active_validatorsnumberMaximum active validators per epoch (e.g. 21)
min_self_stakestringMinimum self-stake to be a validator (hex u128, 18 decimals)
unbonding_period_secsnumberUnbonding period in seconds
slash_double_sign_bpsnumberDouble-sign slash penalty in basis points
slash_downtime_bpsnumberDowntime slash penalty in basis points per epoch
downtime_threshold_pctnumberMissed slot percentage to trigger downtime slash
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getConsensusParams","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "epoch_length": 1200,
    "block_time_ms": 3000,
    "active_validators": 21,
    "min_self_stake": "0x152D02C7E14AF6800000",
    "unbonding_period_secs": 1814400,
    "slash_double_sign_bps": 500,
    "slash_downtime_bps": 10,
    "downtime_threshold_pct": 50
  }
}
vtt_getGasConfig

Returns the current gas configuration of the chain, including minimum gas price and base costs.

PARAMETERS

No parameters.

RETURNS — GasConfigRpc
FIELDTYPEDESCRIPTION
min_gas_pricestringMinimum accepted gas price (hex u128, 18 decimals)
base_transfer_costnumberGas units for a simple VTT transfer (e.g. 21000)
cost_per_bytenumberGas units per byte of calldata (e.g. 16)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getGasConfig","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "min_gas_price": "0x3B9ACA00",
    "base_transfer_cost": 21000,
    "cost_per_byte": 16
  }
}

DEX / SWAP METHODS

vtt_listPools

Returns all AMM liquidity pools currently registered on-chain. Each pool holds two token reserves and tracks its LP token supply.

PARAMETERS

No parameters.

RETURNS — PoolInfo[]
FIELDTYPEDESCRIPTION
pool_idH256Deterministic pool identifier — BLAKE3(sort(token_a, token_b))
token_aH256First token ID (0x000...0 = native VTT)
token_bH256Second token ID
reserve_astringReserve of token A (hex u128)
reserve_bstringReserve of token B (hex u128)
lp_supplystringTotal LP tokens minted for this pool (hex u128)
fee_bpsnumberSwap fee in basis points — always 30 (0.3%)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_listPools","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "pool_id": "0x3a5b8c2f1e9d4a7b6c0f2e1d3a8b9c4d5e6f7a0b1c2d3e4f5a6b7c8d9e0f1a2b",
      "token_a": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "token_b": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
      "reserve_a": "0x56bc75e2d63100000",
      "reserve_b": "0x1b1ae4d6e2ef500000",
      "lp_supply": "0x8ac7230489e80000",
      "fee_bps": 30
    }
  ]
}
vtt_getPool

Returns details for a single AMM pool by its pool_id (H256). Returns null if the pool does not exist.

PARAMETERS
NAMETYPEDESCRIPTION
pool_idH256The pool identifier (32-byte hex string)
RETURNS — PoolInfo | null
FIELDTYPEDESCRIPTION
pool_idH256Deterministic pool identifier
token_aH256First token ID (0x000...0 = native VTT)
token_bH256Second token ID
reserve_astringReserve of token A (hex u128)
reserve_bstringReserve of token B (hex u128)
lp_supplystringTotal LP tokens minted (hex u128)
fee_bpsnumberSwap fee in basis points (30)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getPool","params":["0x3a5b8c2f1e9d4a7b6c0f2e1d3a8b9c4d5e6f7a0b1c2d3e4f5a6b7c8d9e0f1a2b"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "pool_id": "0x3a5b8c2f1e9d4a7b6c0f2e1d3a8b9c4d5e6f7a0b1c2d3e4f5a6b7c8d9e0f1a2b",
    "token_a": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "token_b": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "reserve_a": "0x56bc75e2d63100000",
    "reserve_b": "0x1b1ae4d6e2ef500000",
    "lp_supply": "0x8ac7230489e80000",
    "fee_bps": 30
  }
}
vtt_getSwapQuote

Returns a price quote for swapping token_in through the given pool. Uses the constant-product formula (x·y=k) with the 0.3% fee applied before the invariant calculation.

PARAMETERS
NAMETYPEDESCRIPTION
pool_idH256Pool to route the swap through
token_inH256Token being sold (0x000...0 = native VTT)
amount_instringAmount of token_in as a decimal string (raw units, no hex)
RETURNS — SwapQuote
FIELDTYPEDESCRIPTION
amount_instringInput amount echoed back (hex u128)
amount_outstringExpected output after fees (hex u128)
price_impact_bpsnumberPrice impact in basis points
feestringTotal fee charged (hex u128, 0.3% of amount_in)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getSwapQuote","params":["0x3a5b8c2f1e9d4a7b6c0f2e1d3a8b9c4d5e6f7a0b1c2d3e4f5a6b7c8d9e0f1a2b","0x0000000000000000000000000000000000000000000000000000000000000000","1000000000000000000"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "amount_in": "0xDE0B6B3A7640000",
    "amount_out": "0x2B5E3AF16B1880000",
    "price_impact_bps": 12,
    "fee": "0x2386F26FC10000"
  }
}

LAUNCHPAD METHODS

vtt_getLaunchpadInfo

Returns the current status of the VTT token sale / launchpad, including pricing, supply, and time window.

PARAMETERS

No parameters.

RETURNS — LaunchpadInfo
FIELDTYPEDESCRIPTION
activebooleanWhether the sale is currently active
price_per_vttstringPrice per VTT token in stablecoin (hex u128)
total_supplystringTotal tokens allocated for sale (hex u128)
soldstringTokens already sold (hex u128)
capstringHard cap for the sale (hex u128)
start_timenumberSale start timestamp (unix seconds)
end_timenumberSale end timestamp (unix seconds)
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getLaunchpadInfo","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "active": true,
    "price_per_vtt": "0x2386F26FC10000",
    "total_supply": "0x52b7d2dcc80cd2e4000000",
    "sold": "0x1b1ae4d6e2ef500000",
    "cap": "0x295be96e64066972000000",
    "start_time": 1711800000,
    "end_time": 1714392000
  }
}

NETWORK METHODS

vtt_getNetworkStats

Returns historical network statistics (TPS, gas usage, total stake, block times) for a given time period. Used for charting and monitoring.

PARAMETERS
NAMETYPEDESCRIPTION
periodstringTime period: "1h", "24h", "7d", or "30d"
RETURNS — NetworkStats
FIELDTYPEDESCRIPTION
tps{ timestamp: number; value: number }[]Transactions per second over time
gas_usage{ timestamp: number; value: number }[]Gas usage per block over time
total_stake{ timestamp: number; value: string }[]Total staked VTT over time (hex u128)
block_times{ timestamp: number; value: number }[]Block production time in milliseconds
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getNetworkStats","params":["24h"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tps": [
      { "timestamp": 1711900000, "value": 45 },
      { "timestamp": 1711900060, "value": 52 }
    ],
    "gas_usage": [
      { "timestamp": 1711900000, "value": 12500000 }
    ],
    "total_stake": [
      { "timestamp": 1711900000, "value": "0x56bc75e2d63100000" }
    ],
    "block_times": [
      { "timestamp": 1711900000, "value": 2000 }
    ]
  }
}
vtt_getOracle

Returns information about an oracle price feed by its feed ID, including the latest reported value and quorum requirements. Returns null if the feed does not exist.

PARAMETERS
NAMETYPEDESCRIPTION
feedIdstringOracle feed identifier (e.g. 'VTT/USD')
RETURNS — OracleFeedInfo | null
FIELDTYPEDESCRIPTION
feed_idstringFeed identifier
namestringHuman-readable feed name
latest_valuestring | nullLatest reported value (null if no data yet)
updated_atnumberLast update timestamp (unix seconds)
quorumnumberMinimum number of oracle sources required
sourcesnumberCurrent number of reporting sources
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getOracle","params":["VTT/USD"]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "feed_id": "VTT/USD",
    "name": "VTT / US Dollar",
    "latest_value": "0.85",
    "updated_at": 1711900800,
    "quorum": 3,
    "sources": 5
  }
}
vtt_getNodeMetrics

Returns current node metrics. Useful for monitoring dashboards and alerting systems.

PARAMETERS

No parameters.

RETURNS — NodeMetrics
FIELDTYPEDESCRIPTION
block_heightnumberCurrent chain height
connected_peersnumberNumber of connected P2P peers
txpool_sizenumberPending transactions in the mempool
blocks_importednumberTotal blocks imported since node start
transactions_executednumberTotal transactions executed since node start
current_epochnumberCurrent consensus epoch number
active_validatorsnumberNumber of active validators in the current set
CURL EXAMPLE
curl -X POST http://127.0.0.1:9944 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"vtt_getNodeMetrics","params":[]}'
RESPONSE
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "block_height": 84210,
    "connected_peers": 12,
    "txpool_size": 3,
    "blocks_imported": 84210,
    "transactions_executed": 152847,
    "current_epoch": 70,
    "active_validators": 21
  }
}

TYPES REFERENCE

Complete TypeScript type definitions for all JSON-RPC response objects. These mirror the Rust types defined in vtt-rpc/src/types.rs.

BlockInfo

interface BlockInfo {
  hash: string;           // Block hash (0x + 64 hex)
  number: number;         // Block height
  parent_hash: string;    // Parent block hash
  state_root: string;     // State trie Merkle root
  transactions_root: string; // Tx trie Merkle root
  validator: string;      // Block producer address (0x + 40 hex)
  epoch: number;          // Epoch number
  slot: number;           // Slot within the epoch
  timestamp: number;      // Unix timestamp (seconds)
  gas_limit: number;      // Max gas for block
  gas_used: number;       // Gas consumed
  tx_count: number;       // Transaction count
}

ChainStatus

interface ChainStatus {
  chain_id: number;       // Chain identifier
  height: number;         // Current block height
  head_hash: string;      // Latest block hash
  validator_count: number; // Active validator count
  total_stake: string;    // Total staked VTT (hex u128, 18 decimals)
  total_burned: string;   // Cumulative VTT burned from gas fees (hex u128)
  total_minted: string;   // Cumulative VTT minted as block rewards (hex u128)
}

AccountInfo

interface AccountInfo {
  address: string;        // Account address (0x + 40 hex)
  balance: string;        // VTT balance (hex u128, 18 decimals)
  nonce: number;          // Transaction sequence number
  is_contract: boolean;   // True if WASM contract
}

ValidatorInfo

interface ValidatorInfo {
  address: string;        // Validator address
  total_stake: string;    // Total stake (self + delegations)
  self_stake: string;     // Validator's own stake
  commission_bps: number; // Commission in basis points (500 = 5%)
}

StakingInfo

interface StakingInfo {
  address: string;        // Validator address
  self_stake: string;     // Own stake (hex u128)
  total_stake: string;    // Total stake including delegations
  commission_bps: number; // Commission (basis points)
  active: boolean;        // In active validator set
  delegations: DelegationInfo[];
}

interface DelegationInfo {
  delegator: string;      // Delegator address
  amount: string;         // Delegated amount (hex u128)
}

AssetInfo

interface AssetInfo {
  id: string;             // Asset ID (0x + 64 hex / 32 bytes)
  name: string;           // Human-readable name
  symbol: string;         // Token ticker
  issuer: string;         // Issuer address
  total_supply: string;   // Total supply (hex u128)
  status: string;         // "active" | "frozen" | "retired"
  decimals: number;       // Decimal places
}

AssetBalanceInfo

interface AssetBalanceInfo {
  asset_id: string;       // Asset ID
  owner: string;          // Owner address
  available: string;      // Available balance (hex u128)
  locked: string;         // Locked balance (hex u128)
}

TransactionInfo

interface TransactionInfo {
  hash: string;           // Transaction hash
  block_number: number;   // Containing block height
  from: string;           // Sender address
  to: string | null;      // Recipient (null for deploys)
  action_type: string;    // "Transfer" | "Stake" | "Swap" | "BridgeWithdraw" | ...
  amount: string;         // VTT amount (hex u128, 18 decimals)
  nonce: number;          // Sender's sequence number
  gas_price: string;      // Gas price per unit (hex u128, 18 decimals)
  gas_limit: number;      // Maximum gas for this tx
  timestamp: number;      // Unix timestamp (seconds)

  // Swap-specific fields (present only for Swap transactions)
  swap_pool_id?: string;  // Pool ID (hex, 0x + 64 chars)
  swap_token_in?: string; // Token being sold (hex, 0x + 64 chars)
  swap_min_out?: string;  // Minimum output amount (hex u128)
}

PaginatedResult<T>

interface PaginatedResult<T> {
  items: T[];             // Items for current page
  total: number;          // Total item count
  page: number;           // Current page number
  page_size: number;      // Items per page
}

ProposalInfo

interface ProposalInfo {
  id: string;             // Proposal ID (0x + 64 hex)
  proposer: string;       // Creator address
  description: string;    // Proposal description
  action_type: string;    // Governance action type
  status: string;         // "pending" | "active" | "passed" | "rejected" | "executed"
  votes_yes: string;      // Yes vote weight (hex u128)
  votes_no: string;       // No vote weight (hex u128)
  votes_abstain: string;  // Abstain vote weight (hex u128)
  created_at: number;     // Creation timestamp (unix seconds)
  voting_end: number;     // Voting deadline (unix seconds)
}

SwapPool

interface SwapPool {
  id: string;             // Pool ID
  token_a: string;        // First token (asset ID or "VTT")
  token_b: string;        // Second token
  reserve_a: string;      // Reserve of token A (hex u128)
  reserve_b: string;      // Reserve of token B (hex u128)
  total_liquidity: string; // Total LP tokens (hex u128)
  fee_bps: number;        // Swap fee (basis points, 30 = 0.3%)
}

SwapQuote

interface SwapQuote {
  amount_in: string;      // Input amount (hex u128)
  amount_out: string;     // Expected output (hex u128)
  price_impact_bps: number; // Price impact (basis points)
  fee: string;            // Swap fee (hex u128)
}

LaunchpadInfo

interface LaunchpadInfo {
  active: boolean;        // Sale currently active
  price_per_vtt: string;  // Price per VTT (hex u128)
  total_supply: string;   // Tokens allocated for sale (hex u128)
  sold: string;           // Tokens sold so far (hex u128)
  cap: string;            // Hard cap (hex u128)
  start_time: number;     // Sale start (unix seconds)
  end_time: number;       // Sale end (unix seconds)
}

NetworkStats

interface NetworkStats {
  tps: { timestamp: number; value: number }[];
  gas_usage: { timestamp: number; value: number }[];
  total_stake: { timestamp: number; value: string }[];
  block_times: { timestamp: number; value: number }[];
}

OracleFeedInfo

interface OracleFeedInfo {
  feed_id: string;        // Feed identifier
  name: string;           // Human-readable name
  latest_value: string | null; // Latest value (null if no data)
  updated_at: number;     // Last update (unix seconds)
  quorum: number;         // Min required sources
  sources: number;        // Current reporting sources
}

AssetProposalInfo

interface AssetProposalInfo {
  id: string;             // Proposal ID (0x + 64 hex)
  asset_id: string;       // Target asset ID
  proposer: string;       // Creator address
  action_type: string;    // "DistributeRevenue" | "ChangeIssuer" | "Signal"
  description: string;    // Human-readable description
  status: string;         // "Active" | "Passed" | "Rejected" | "Executed"
  votes_yes: string;      // Yes vote weight (hex u128, token-weighted)
  votes_no: string;       // No vote weight (hex u128)
  votes_abstain: string;  // Abstain vote weight (hex u128)
  voting_end: number;     // Block number when voting ends
  created_at: number;     // Block number when created
}

BridgeWithdrawalInfo

interface BridgeWithdrawalInfo {
  tx_hash: string;        // Transaction hash on VTT chain
  block_number: number;   // Block that included the withdrawal
  sender: string;         // Sender address on VTT
  token: string;          // Token ID (0x000...0 = VTT, or asset ID)
  amount: string;         // Amount burned (hex u128)
  destination_chain: number; // EVM chain ID (1, 8453, etc.)
  destination_address: string; // Recipient on external chain
  timestamp: number;      // Unix timestamp (seconds)
}

ConsensusParamsRpc

interface ConsensusParamsRpc {
  epoch_length: number;       // Blocks per epoch
  block_time_ms: number;      // Target block time (ms)
  active_validators: number;  // Max active validators
  min_self_stake: string;     // Min self-stake (hex u128, 18 decimals)
  unbonding_period_secs: number; // Unbonding period (seconds)
  slash_double_sign_bps: number; // Double-sign slash (bps)
  slash_downtime_bps: number; // Downtime slash per epoch (bps)
  downtime_threshold_pct: number; // Missed slot % to trigger slash
}

GasConfigRpc

interface GasConfigRpc {
  min_gas_price: string;      // Minimum gas price (hex u128)
  base_transfer_cost: number; // Gas for simple transfer
  cost_per_byte: number;      // Gas per calldata byte
}

TRANSACTION GUIDE

Transactions on VTT are serialized using Borsh (Binary Object Representation Serializer for Hashing) and signed with Ed25519. The full signed transaction is the concatenation of the serialized payload, the 64-byte signature, and the 32-byte public key.

PAYLOAD STRUCTURE

Every transaction payload contains these fields, serialized in order:

interface TransactionPayload {
  chainId: number;      // u32 — prevents replay across chains
  nonce: bigint;        // u64 — sender's sequence number
  gasPrice: Amount;     // u128 — price per unit of gas (18 decimals)
  gasLimit: bigint;     // u64 — maximum gas units
  action: TransactionAction; // enum — what the tx does
}

// Amount is a u128 with 18 decimal places
interface Amount {
  raw: bigint;          // e.g. 1000000000000000000n = 1.0 VTT
}

BORSH ENCODING RULES

u8: 1 byte, little-endian
u16: 2 bytes, little-endian
u32: 4 bytes, little-endian
u64: 8 bytes, little-endian
u128: 16 bytes, little-endian (used for Amount)
String: u32 length prefix + UTF-8 bytes
Vec<T>: u32 length prefix + elements
Enum: u8 variant index + variant fields
Struct: fields in declaration order, no padding
Fixed bytes: written directly (addresses = 20 bytes, hashes = 32 bytes)

ACTION TYPES

The action field is a Borsh enum. The first byte is the variant index, followed by the variant-specific fields. Here are all 21 action types:

INDEXACTIONFIELDS
0Transferto: Address (20 bytes), amount: Amount (u128)
1DeployContractcode: Vec<u8> (WASM bytecode), initData: Vec<u8>
2CallContractcontract: Address (20 bytes), method: String, args: Vec<u8>, value: Amount (u128)
3Stakevalidator: Address (20 bytes), amount: Amount (u128)
4Unstakevalidator: Address (20 bytes), amount: Amount (u128)
5GovernanceVoteproposalId: H256 (32 bytes), vote: u8 (0=Yes, 1=No, 2=Abstain)
6CreateAssetClassname: String, symbol: String, metadataUri: String, totalSupply: Amount (u128)
7AssetTransferassetId: H256 (32 bytes), to: Address (20 bytes), amount: Amount (u128)
8CrossChainTransferdestinationChain: u32, to: Address (20 bytes), payload: CrossChainPayload
9CreatePooltoken_a: H256, token_b: H256, amount_a: Amount, amount_b: Amount
10AddLiquiditypool_id: H256, amount_a: Amount, amount_b: Amount, min_lp: Amount
11RemoveLiquiditypool_id: H256, lp_amount: Amount, min_a: Amount, min_b: Amount
12Swappool_id: H256, token_in: H256, amount_in: Amount, min_amount_out: Amount
13ClaimRevenuepool_id: H256
14ClaimMiningRewardspool_id: H256
15DistributeRevenueasset_id: H256, total_amount: Amount (u128)
16ProposeAssetActionasset_id: H256, action: AssetProposalAction, description: String
17VoteAssetProposalproposal_id: H256, vote: u8 (0=Yes, 1=No, 2=Abstain)
18FinalizeAssetProposalproposal_id: H256
19BridgeWithdrawtoken: H256, amount: Amount, destination_chain: u32, destination_address: Address
20GovernanceProposedescription: String, action_type: String, param_key?: String, param_value?: String, recipient?: Address, amount?: Amount
21FreezeAssetasset_id: H256. Issuer-only. Blocks transfers until unfrozen.
22UnfreezeAssetasset_id: H256. Issuer-only. Restores transferability after FreezeAsset.
23SubmitSlashingEvidenceevidence: Vec<u8> — Borsh-serialized DoubleSignEvidence. Any sender can relay; executor verifies and applies a 5% slash idempotently.
24FundRedemptionPoolasset_id: H256, amount: Amount. Issuer deposits VTT into the pool for a RedemptionPending asset so holders can claim their pro-rata share.
25ClaimRedemptionasset_id: H256. Holder burns their tokens and receives the pro-rata share of the redemption_pool. Last claim transitions asset to Redeemed.
26SetKycApprovaladdress: Address, approved: bool. Treasury/admin-only. Toggles on-chain KYC flag required for transfers of regulated assets.
27BridgeDepositsource_tx_hash: H256, source_chain: u32, recipient: Address, token: H256, amount: Amount. Relayer-only. Credits an external-chain deposit onto VTT with replay protection.
28SetAddressJurisdictionaddress: Address, country: String (ISO 3166-1 alpha-2). Treasury/admin-only. Stamps the on-chain jurisdiction used by the governance whitelist/blacklist enforcement at AssetTransfer. Empty string clears the mapping.
29CreateOracleFeedfeed_id: H256, name: String, feed_type: String ("price:<pair>", "rate:<name>", "asset:<hex>" or custom), authorized_sources: Vec<Address>, quorum: u8, max_staleness_ms: u64. Treasury/admin-only. Registers a new oracle feed.
30SubmitOracleValuefeed_id: H256, value: Amount. Sender must be one of the feed's authorized sources. When the quorum is reached the feed's latest value is updated via median aggregation.

CROSS-CHAIN PAYLOAD VARIANTS

The CrossChainTransfer action contains a nested enum for the cross-chain payload:

INDEXVARIANTFIELDS
0VttTransferamount: Amount (u128)
1AssetTransferassetId: H256 (32 bytes), amount: Amount (u128)
2ContractCallcontract: Address (20 bytes), method: String, args: Vec<u8>, value: Amount (u128)

SIGNING & SUBMITTING

The signing process:

  1. Serialize the TransactionPayload to Borsh bytes
  2. Sign the payload bytes with your Ed25519 private key (seed) to get a 64-byte signature
  3. Concatenate: payload_bytes || signature (64 bytes) || public_key (32 bytes)
  4. Hex-encode the full byte array
  5. Submit via vtt_sendTransaction
JAVASCRIPT — BUILD & SIGN A TRANSFER
import { serializeTransactionPayload } from "@/lib/crypto/borsh";
import { signTransaction } from "@/lib/wallet/transaction";
import { generateKeypair } from "@/lib/wallet/keypair";

// 1. Generate or import a keypair
const wallet = await generateKeypair();
console.log("Address:", wallet.addressHex);
// e.g. "0x7a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b"

// 2. Get account nonce
const account = await rpc.getAccount(wallet.addressHex);
const nonce = BigInt(account.nonce);

// 3. Build the payload
const payload = {
  chainId: 1,
  nonce: nonce,
  gasPrice: { raw: 1000000000n },        // 1 gwei
  gasLimit: 21000n,
  action: {
    type: "Transfer" as const,
    to: hexToBytes("abcdefabcdefabcdefabcdefabcdefabcdefabcd"),
    amount: { raw: 1000000000000000000n }, // 1.0 VTT
  },
};

// 4. Sign and encode
const signed = await signTransaction(payload, wallet.seed, wallet.publicKey);

// 5. Submit
const txHash = await rpc.sendTransaction(signed.encodedHex);
console.log("Tx hash:", txHash);
SIGNED TRANSACTION WIRE FORMAT
Bytes 0..NBorsh-encoded TransactionPayload
Bytes N..N+64Ed25519 signature (64 bytes)
Bytes N+64..N+96Ed25519 public key (32 bytes)

ACTION EXAMPLES

STAKE 100 VTT TO A VALIDATOR
const payload = {
  chainId: 1,
  nonce: 5n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 50000n,
  action: {
    type: "Stake" as const,
    validator: hexToBytes("0101010101010101010101010101010101010101"),
    amount: { raw: 100000000000000000000n }, // 100 VTT
  },
};
VOTE YES ON A GOVERNANCE PROPOSAL
const payload = {
  chainId: 1,
  nonce: 6n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 50000n,
  action: {
    type: "GovernanceVote" as const,
    proposalId: hexToBytes("deadbeefdeadbeefdeadbeefdeadbeef" +
                           "deadbeefdeadbeefdeadbeefdeadbeef"),
    vote: 0, // 0 = Yes, 1 = No, 2 = Abstain
  },
};
CREATE A TOKENIZED ASSET (RWA)
const payload = {
  chainId: 1,
  nonce: 7n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 200000n,
  action: {
    type: "CreateAssetClass" as const,
    name: "Milan Office Tower A",
    symbol: "MOTA",
    metadataUri: "ipfs://QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
    totalSupply: { raw: 100000000000000000000000n }, // 100,000 tokens
  },
};
TRANSFER A TOKENIZED ASSET
const payload = {
  chainId: 1,
  nonce: 8n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 50000n,
  action: {
    type: "AssetTransfer" as const,
    assetId: hexToBytes("abc123..." + "0".repeat(38)), // 32 bytes
    to: hexToBytes("abcdefabcdefabcdefabcdefabcdefabcdefabcd"),
    amount: { raw: 500000000000000000000n }, // 500 tokens
  },
};
DEPLOY A WASM SMART CONTRACT
const wasmBytes = new Uint8Array(fs.readFileSync("contract.wasm"));
const initArgs = new TextEncoder().encode('{"owner":"0x0101..."}');

const payload = {
  chainId: 1,
  nonce: 9n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 5000000n,
  action: {
    type: "DeployContract" as const,
    code: wasmBytes,
    initData: initArgs,
  },
};
CALL A SMART CONTRACT
const args = new TextEncoder().encode('{"recipient":"0xabcd...","amount":"1000"}');

const payload = {
  chainId: 1,
  nonce: 10n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 500000n,
  action: {
    type: "CallContract" as const,
    contract: hexToBytes("abcdefabcdefabcdefabcdefabcdefabcdefabcd"),
    method: "transfer",
    args: args,
    value: { raw: 0n }, // no VTT sent with call
  },
};
CROSS-CHAIN VTT TRANSFER
const payload = {
  chainId: 1,
  nonce: 11n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 100000n,
  action: {
    type: "CrossChainTransfer" as const,
    destinationChain: 2,
    to: hexToBytes("abcdefabcdefabcdefabcdefabcdefabcdefabcd"),
    payload: {
      type: "VttTransfer" as const,
      amount: { raw: 10000000000000000000n }, // 10 VTT
    },
  },
};
DISTRIBUTE REVENUE TO ASSET HOLDERS
const payload = {
  chainId: 1,
  nonce: 12n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 500000n,
  action: {
    type: "DistributeRevenue" as const,
    assetId: hexToBytes("abc123..." + "0".repeat(38)), // 32 bytes
    totalAmount: { raw: 10000000000000000000000n }, // 10,000 VTT
  },
};
PROPOSE ASSET ACTION (REVENUE DISTRIBUTION VIA VOTE)
const payload = {
  chainId: 1,
  nonce: 13n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 200000n,
  action: {
    type: "ProposeAssetAction" as const,
    assetId: hexToBytes("abc123..." + "0".repeat(38)),
    action: {
      type: "DistributeRevenue" as const,
      totalAmount: { raw: 5000000000000000000000n }, // 5,000 VTT
    },
    description: "Distribute Q1 2026 rental income to all holders",
  },
};
VOTE ON ASSET PROPOSAL
const payload = {
  chainId: 1,
  nonce: 14n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 50000n,
  action: {
    type: "VoteAssetProposal" as const,
    proposalId: hexToBytes("deadbeef..." + "0".repeat(48)), // 32 bytes
    vote: 0, // 0 = Yes, 1 = No, 2 = Abstain
  },
};
BRIDGE WITHDRAW (VTT TO ETHEREUM)
const payload = {
  chainId: 1,
  nonce: 15n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 100000n,
  action: {
    type: "BridgeWithdraw" as const,
    token: new Uint8Array(32), // H256::ZERO = native VTT
    amount: { raw: 5000000000000000000n }, // 5 VTT
    destinationChain: 1, // Ethereum mainnet
    destinationAddress: hexToBytes("abcdefabcdefabcdefabcdefabcdefabcdefabcd"),
  },
};
DEX SWAP
const payload = {
  chainId: 1,
  nonce: 16n,
  gasPrice: { raw: 1000000000n },
  gasLimit: 200000n,
  action: {
    type: "Swap" as const,
    poolId: hexToBytes("3a5b8c2f..." + "0".repeat(48)), // 32 bytes
    tokenIn: new Uint8Array(32), // H256::ZERO = native VTT
    amountIn: { raw: 1000000000000000000n }, // 1 VTT
    minAmountOut: { raw: 2800000000000000000n }, // min 2.8 tokens out
  },
};

WALLET GUIDE

VTT uses Ed25519 for cryptographic signing and BLAKE3 for address derivation. A wallet consists of a 32-byte seed (private key), from which the public key and address are derived.

KEYPAIR STRUCTURE

interface WalletKeypair {
  seed: Uint8Array;       // 32-byte Ed25519 seed (KEEP SECRET)
  publicKey: Uint8Array;  // 32-byte Ed25519 public key
  address: Uint8Array;    // 20-byte VTT address
  publicKeyHex: string;   // "0x" + 64 hex chars
  addressHex: string;     // "0x" + 40 hex chars
}

ADDRESS DERIVATION

The address derivation process:

  1. Start with a 32-byte seed (random or imported)
  2. Derive the Ed25519 public key (32 bytes) from the seed
  3. Compute BLAKE3(publicKey) to get a 32-byte hash
  4. Take the last 20 bytes (bytes 12..32) as the address
  5. Encode as 0x + 40 hex characters
// Address derivation (from blake3.ts)
import { blake3 } from "@noble/hashes/blake3";

function addressFromPublicKey(publicKey: Uint8Array): Uint8Array {
  const hash = blake3(publicKey);  // 32-byte BLAKE3 hash
  return hash.slice(12, 32);       // last 20 bytes
}

// Result: 0x + 40 hex chars = 20-byte address

GENERATE A NEW KEYPAIR

import { generateKeypair } from "@/lib/wallet/keypair";

const wallet = await generateKeypair();

console.log("Seed (KEEP SECRET):", bytesToHex(wallet.seed));
console.log("Public Key:", wallet.publicKeyHex);
console.log("Address:", wallet.addressHex);

// Example output:
// Seed: "a1b2c3d4...64 hex chars"
// Public Key: "0x9f8e7d6c5b4a3...64 hex chars"
// Address: "0x7a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b"

IMPORT FROM SEED

import { importFromHexSeed } from "@/lib/wallet/keypair";

// Import from a 64-character hex seed (32 bytes)
const wallet = await importFromHexSeed(
  "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
);

console.log("Address:", wallet.addressHex);
// Deterministic: same seed always produces the same address

SIGNING MESSAGES

import { sign, verify, getPublicKey } from "@/lib/crypto/ed25519";

// Sign arbitrary data
const message = new TextEncoder().encode("Hello VTT");
const signature = await sign(message, seed);

// Verify
const publicKey = await getPublicKey(seed);
const valid = await verify(signature, message, publicKey);
console.log("Valid:", valid); // true

CRYPTOGRAPHIC LIBRARIES

VTT uses audited, pure-JavaScript implementations from the @noble family:

@noble/ed25519 — Ed25519 key generation, signing, verification
@noble/hashes/blake3 — BLAKE3 hashing for address derivation

ERROR CODES

When an RPC call fails, the response contains an error object with a numeric code and a human-readable message. Standard JSON-RPC 2.0 error codes apply, plus VTT-specific codes.

CODEMEANINGDESCRIPTION
-32700Parse errorInvalid JSON in request body
-32600Invalid requestJSON is valid but not a proper JSON-RPC 2.0 request
-32601Method not foundThe method name does not exist
-32602Invalid paramsWrong number or type of parameters
-32603Internal errorUnexpected server-side error
-32000Transaction rejectedTransaction failed validation (bad signature, low balance, nonce mismatch)
-32001Nonce too lowTransaction nonce is less than account nonce (replay)
-32002Insufficient balanceSender cannot cover amount + gas fees
-32003Gas limit exceededGas limit exceeds block gas limit
-32004Invalid signatureEd25519 signature verification failed
-32005Pool fullTransaction pool is at capacity, try again later
ERROR RESPONSE EXAMPLE
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Nonce too low: expected 43, got 42"
  }
}
HANDLING ERRORS IN JAVASCRIPT
import { VttRpcClient, RpcError } from "@/lib/rpc/client";

const client = new VttRpcClient("http://127.0.0.1:9944");

try {
  const result = await client.call("vtt_getBalance", ["0x0101...0101"]);
  console.log("Balance:", result);
} catch (err) {
  if (err instanceof RpcError) {
    console.error(`RPC error ${err.code}: ${err.message}`);
    // Handle specific error codes
    if (err.code === -32001) {
      console.error("Nonce mismatch — re-fetch account nonce");
    }
  }
}

SDK EXAMPLES

JAVASCRIPT / TYPESCRIPT

Full example: query chain status, fetch account info, list validators, get blocks.

// === VTT JSON-RPC Client — JavaScript ===

const RPC_URL = "http://127.0.0.1:9944";

async function rpcCall(method, params = []) {
  const res = await fetch(RPC_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
  });
  const json = await res.json();
  if (json.error) throw new Error(`RPC ${json.error.code}: ${json.error.message}`);
  return json.result;
}

// Chain status
const status = await rpcCall("vtt_chainStatus");
console.log("Height:", status.height);
console.log("Validators:", status.validator_count);

// Account balance
const balance = await rpcCall("vtt_getBalance", [
  "0x0101010101010101010101010101010101010101",
]);
const vttBalance = Number(BigInt(balance)) / 1e18;
console.log("Balance:", vttBalance, "VTT");

// Full account info
const account = await rpcCall("vtt_getAccount", [
  "0x0101010101010101010101010101010101010101",
]);
console.log("Nonce:", account.nonce);
console.log("Is contract:", account.is_contract);

// Get block by number
const block = await rpcCall("vtt_getBlockByNumber", [100]);
if (block) {
  console.log("Block hash:", block.hash);
  console.log("Tx count:", block.tx_count);
  console.log("Validator:", block.validator);
}

// List validators
const validators = await rpcCall("vtt_getValidators");
for (const v of validators) {
  const stake = Number(BigInt(v.total_stake)) / 1e18;
  console.log(`${v.address}: ${stake} VTT staked, ${v.commission_bps / 100}% commission`);
}

// Paginated transactions
const txPage = await rpcCall("vtt_listTransactions", [1, 10]);
console.log(`Showing ${txPage.items.length} of ${txPage.total} transactions`);
for (const tx of txPage.items) {
  console.log(`${tx.hash} — ${tx.action_type} — ${tx.status}`);
}

// List assets (RWA tokens)
const assets = await rpcCall("vtt_listAssets");
for (const a of assets) {
  console.log(`${a.symbol} (${a.name}) — status: ${a.status}`);
}

// Governance proposals
const proposals = await rpcCall("vtt_listProposals");
for (const p of proposals) {
  console.log(`[#${p.id.slice(0, 10)}] ${p.description} — ${p.status}`);
}

// Swap quote
const quote = await rpcCall("vtt_getSwapQuote", [
  "VTT",
  "0xabc123...",
  "0xDE0B6B3A7640000",
]);
console.log("Expected output:", quote.amount_out);
console.log("Price impact:", quote.price_impact_bps, "bps");

PYTHON

Full example using the requests library.

# === VTT JSON-RPC Client — Python ===

import requests
import json

RPC_URL = "http://127.0.0.1:9944"

def rpc_call(method: str, params: list = None) -> dict:
    """Send a JSON-RPC 2.0 request to the VTT node."""
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": method,
        "params": params or [],
    }
    resp = requests.post(RPC_URL, json=payload)
    resp.raise_for_status()
    data = resp.json()
    if "error" in data:
        raise Exception(f"RPC error {data['error']['code']}: {data['error']['message']}")
    return data["result"]


# Chain status
status = rpc_call("vtt_chainStatus")
print(f"Height: {status['height']}")
print(f"Validators: {status['validator_count']}")
print(f"Chain ID: {status['chain_id']}")

# Account balance (amounts are hex-encoded u128 with 18 decimals)
balance_hex = rpc_call("vtt_getBalance", [
    "0x0101010101010101010101010101010101010101"
])
balance_vtt = int(balance_hex, 16) / 1e18
print(f"Balance: {balance_vtt:.4f} VTT")

# Full account info
account = rpc_call("vtt_getAccount", [
    "0x0101010101010101010101010101010101010101"
])
print(f"Nonce: {account['nonce']}")
print(f"Is contract: {account['is_contract']}")

# Get block by number
block = rpc_call("vtt_getBlockByNumber", [100])
if block:
    print(f"Block #{block['number']}: {block['hash']}")
    print(f"  Validator: {block['validator']}")
    print(f"  Transactions: {block['tx_count']}")
    print(f"  Gas: {block['gas_used']}/{block['gas_limit']}")

# List validators
validators = rpc_call("vtt_getValidators")
for v in validators:
    stake = int(v["total_stake"], 16) / 1e18
    commission = v["commission_bps"] / 100
    print(f"{v['address']}: {stake:.2f} VTT staked, {commission}% commission")

# Paginated transaction list
tx_page = rpc_call("vtt_listTransactions", [1, 10])
print(f"\nShowing {len(tx_page['items'])} of {tx_page['total']} transactions")
for tx in tx_page["items"]:
    amount = int(tx["amount"], 16) / 1e18
    print(f"  {tx['hash'][:16]}... {tx['action_type']} {amount:.4f} VTT [{tx['status']}]")

# Staking info for a validator
staking = rpc_call("vtt_getStakingInfo", [
    "0x0101010101010101010101010101010101010101"
])
if staking:
    print(f"\nValidator {staking['address']}")
    print(f"  Active: {staking['active']}")
    print(f"  Self stake: {int(staking['self_stake'], 16) / 1e18:.2f} VTT")
    print(f"  Total stake: {int(staking['total_stake'], 16) / 1e18:.2f} VTT")
    print(f"  Delegations: {len(staking['delegations'])}")

# List assets (tokenized RWAs)
assets = rpc_call("vtt_listAssets")
for a in assets:
    supply = int(a["total_supply"], 16) / (10 ** a["decimals"])
    print(f"{a['symbol']} ({a['name']}): {supply:.2f} total supply — {a['status']}")

# Governance proposals
proposals = rpc_call("vtt_listProposals")
for p in proposals:
    print(f"Proposal {p['id'][:16]}... — {p['status']}")
    print(f"  {p['description']}")
    yes = int(p["votes_yes"], 16) / 1e18
    no = int(p["votes_no"], 16) / 1e18
    print(f"  Votes: {yes:.2f} yes / {no:.2f} no")

# DEX swap pools
pools = rpc_call("vtt_listPools")
for pool in pools:
    ra = int(pool["reserve_a"], 16) / 1e18
    rb = int(pool["reserve_b"], 16) / 1e18
    print(f"Pool {pool['id'][:16]}... {pool['token_a']}/{pool['token_b']}")
    print(f"  Reserves: {ra:.2f} / {rb:.2f}, Fee: {pool['fee_bps']}bps")

# Swap quote
quote = rpc_call("vtt_getSwapQuote", [
    "VTT", "0xabc123...", "0xDE0B6B3A7640000"
])
out_amount = int(quote["amount_out"], 16) / 1e18
print(f"Swap quote: {out_amount:.4f} out, impact: {quote['price_impact_bps']}bps")

# Launchpad info
launchpad = rpc_call("vtt_getLaunchpadInfo")
print(f"\nLaunchpad active: {launchpad['active']}")
sold = int(launchpad["sold"], 16) / 1e18
total = int(launchpad["total_supply"], 16) / 1e18
print(f"  Sold: {sold:.2f} / {total:.2f} VTT")

# Network stats
stats = rpc_call("vtt_getNetworkStats", ["24h"])
if stats["tps"]:
    latest_tps = stats["tps"][-1]["value"]
    print(f"\nLatest TPS: {latest_tps}")
if stats["block_times"]:
    latest_bt = stats["block_times"][-1]["value"]
    print(f"Latest block time: {latest_bt}ms")

# Oracle feed
oracle = rpc_call("vtt_getOracle", ["VTT/USD"])
if oracle:
    print(f"\n{oracle['name']}: {oracle['latest_value']}")
    print(f"  Sources: {oracle['sources']}/{oracle['quorum']} quorum")

CLI TOOLS

The Vettor platform ships three command-line binaries: vtt-validator (block-producing node), vtt-node (non-producing full node), and vtt-cli (client tool for querying and transacting).

VTT-VALIDATOR

vtt-validator [FLAGS]
  --rpc-port <port>       RPC server port (default: 9944)
  --port <port>           P2P network port (default: 30333)
  --seed <hex>            Validator private key (64 hex chars)
  --genesis <path>        Path to genesis JSON file
  --data-dir <path>       Path to RocksDB data directory
  --bootnodes <addrs>     Comma-separated bootnode multiaddresses
  --metrics-port <port>   Prometheus metrics port (default: 9615)
  --testnet               Use built-in testnet genesis config
  --dev                   Use built-in dev genesis config

Environment: VALIDATOR_SEED (fallback if --seed not provided)

VTT-NODE

Same flags as vtt-validator, but does not produce blocks. Used for RPC endpoints, indexers, and full-node infrastructure.

vtt-node [FLAGS]
  --rpc-port <port>       RPC server port (default: 9944)
  --port <port>           P2P network port (default: 30333)
  --genesis <path>        Path to genesis JSON file
  --data-dir <path>       Path to RocksDB data directory
  --bootnodes <addrs>     Comma-separated bootnode multiaddresses
  --metrics-port <port>   Prometheus metrics port (default: 9615)
  --testnet               Use built-in testnet genesis config
  --dev                   Use built-in dev genesis config

VTT-CLI

vtt-cli <command> [OPTIONS]
  keygen [--seed <hex>]           Generate or derive a keypair
  balance <address>               Query account balance
  account <address>               Query full account info
  block <hash|number>             Query block by hash or number
  status                          Query chain status
  validators                      List active validators
  genesis [--testnet]             Export genesis JSON
  stake --validator <addr> --amount <vtt> --seed <hex>    Stake VTT
  unstake --validator <addr> --amount <vtt> --seed <hex>  Unstake VTT

Global: --rpc <url>  (default: http://127.0.0.1:9944)

START BUILDING

Launch the explorer to browse live chain data, or open the dApp to interact with staking, governance, assets, and DEX.