﻿{"id":668089,"date":"2025-04-18T10:52:52","date_gmt":"2025-04-18T10:52:52","guid":{"rendered":"https:\/\/gridnet.org\/wpp\/?p=668089"},"modified":"2025-04-18T11:46:48","modified_gmt":"2025-04-18T11:46:48","slug":"instant-payments-javascript-api","status":"publish","type":"post","link":"https:\/\/mag.gridnet.org\/index.php\/2025\/04\/18\/instant-payments-javascript-api\/","title":{"rendered":"Instant Payments JavaScript API"},"content":{"rendered":"<h3><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669253 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/cover.png\" alt=\"\" width=\"926\" height=\"1172\" \/><br \/>\n1. Introduction<\/h3>\n<p>Welcome to the official documentation for the GRIDNET OS State-Less Channels sub-system and its associated Off-The-Chain Payment API. This document provides UI dApp developers with the necessary understanding and technical guidance to leverage this powerful mechanism for enabling fast, cost-effective, and scalable value transfer and incentivization within their decentralized applications.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668177 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/architecture.png\" alt=\"\" width=\"610\" height=\"479\" \/><\/p>\n<h3>1.1. Purpose: The Need for Off-Chain Solutions in GRIDNET OS<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668318 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/payment-flow.png\" alt=\"\" width=\"784\" height=\"590\" \/><\/p>\n<p>GRIDNET OS provides a robust platform for executing decentralized logic and managing state through its Decentralized State Machine (DSM). However, like all blockchain-based systems, direct on-chain transactions have inherent limitations that can hinder certain types of applications:<\/p>\n<ul>\n<li>\n<h3>Scalability:<\/h3>\n<p>The number of transactions per second (TPS) that can be processed directly on the main chain is finite. High-frequency operations can quickly saturate the network&#8217;s capacity.<\/li>\n<li>\n<h3>Cost:<\/h3>\n<p>Every transaction committed to the DSM consumes resources (ERG) for processing and storage. While designed to be efficient, on-chain operations can become prohibitively expensive for very small or frequent value exchanges (micropayments).<\/li>\n<li>\n<h3>Speed &amp; Latency:<\/h3>\n<p>On-chain transactions require consensus and block finality, introducing latency. Real-time interactions demanding immediate confirmation or reward cannot solely rely on the main chain&#8217;s settlement time.<\/li>\n<\/ul>\n<p>To overcome these challenges and unlock a wider range of possibilities for UI dApps, GRIDNET OS implements a sophisticated off-chain solution: the State-Less Channels system. This system is crucial for applications involving:<\/p>\n<ul>\n<li>\n<h3>Micropayments:<\/h3>\n<p>Enabling tiny value transfers for services, content access, or rewards where on-chain fees would be disproportionately high.<\/li>\n<li>\n<h3>Incentivized Data Exchange:<\/h3>\n<p>Efficiently rewarding peers for relaying data packets in real-time, essential for decentralized communication, storage, and services like the GRIDNET OS Web Proxy or WebRTC Swarms.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669091 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/data-transmission.png\" alt=\"\" width=\"1085\" height=\"1109\" \/><\/p>\n<ul>\n<li>\n<h3>Real-time Rewards:<\/h3>\n<p>Instantly rewarding user actions within games (like the Snake dApp) or other interactive applications without waiting for block confirmations.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669096 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/game-payments-1.png\" alt=\"\" width=\"1221\" height=\"1111\" \/><\/li>\n<\/ul>\n<h3>1.2. Overview of the State-Less Channels System<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668184 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/overview.png\" alt=\"\" width=\"608\" height=\"568\" \/><\/p>\n<p>The GRIDNET OS State-Less Channels system facilitates secure value transfer between parties <em>without<\/em> requiring every individual transfer to be recorded directly on the main blockchain (the DSM).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668333 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/ARCHITECTURE-API.png\" alt=\"\" width=\"768\" height=\"804\" \/><\/p>\n<ul>\n<li>\n<h3>Analogy to Lightning Network:<\/h3>\n<p>The <em>goal<\/em> is similar to layer-2 scaling solutions like Bitcoin&#8217;s Lightning Network \u2013 enabling faster, cheaper transactions off-chain. However, the underlying mechanics in GRIDNET OS are distinct. State-Less Channels do not rely on complex routed payment channels requiring intermediate node participation in the same way.<\/li>\n<li>\n<h3>Core Idea: Secure Off-Chain Value Transfer Based on Pre-Funded Pools:<\/h3>\n<p>The system operates on the principle of<\/p>\n<h3>Multi-Dimensional Token Pools (M-DTPs)<\/h3>\n<p>. These pools represent a store of value, initially funded via an on-chain sacrificial transaction and registered on the DSM. Value is then exchanged off-chain by securely revealing pre-images (hashes or &#8220;tokens&#8221;) derived from secrets associated with the pool&#8217;s dimensions (banks). Only the initial pool setup and the final &#8220;cashing out&#8221; of accumulated off-chain tokens require direct interaction with the DSM, significantly reducing on-chain load. The &#8220;State-Less&#8221; nature refers to the fact that complex channel state negotiation and management between peers are minimized compared to traditional state channels.<\/li>\n<\/ul>\n<h3>1.3. Key Benefits<\/h3>\n<h3>1.4. GRIDNET OS&#8217; Decentralized Incentivized SOA Paradigm<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669109 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/SOA.png\" alt=\"\" width=\"1189\" height=\"1109\" \/><\/p>\n<h3>1.4.1. Introduction to Service-Oriented Architecture in GRIDNET OS<\/h3>\n<p>GRIDNET OS implements a unique approach to Service-Oriented Architecture (SOA) that fundamentally reimagines how distributed services can operate in a decentralized environment. Unlike traditional SOA implementations that rely on centralized service registries, orchestration, and payment systems, GRIDNET OS&#8217; architecture distributes all aspects of service discovery, execution, and compensation across its peer-to-peer network.<\/p>\n<p>Service-Oriented Architecture refers to a design pattern where applications are built from loosely coupled, independently deployable services that communicate through standardized interfaces. GRIDNET OS extends this concept by adding three critical dimensions:<\/p>\n<ul>\n<li>\n<strong>Full Decentralization<\/strong><br \/>\nServices operate without central authorities or single points of failure<\/li>\n<li>\n<strong>Built-in Incentivization<\/strong><br \/>\nAutomatic, fine-grained compensation for service providers<\/li>\n<li>\n<strong>Sybil-Resistant Economics<\/strong><br \/>\nGame-theoretical protection against network manipulation<\/li>\n<\/ul>\n<h3>1.4.2. Core Components of the Decentralized SOA<\/h3>\n<p>The GRIDNET OS Decentralized Incentivized SOA consists of several interconnected components:<\/p>\n<h3>Service Providers<\/h3>\n<p>Independent nodes that offer computational resources, storage capacity, bandwidth, or specialized functionality to the network. These can include:<\/p>\n<ul>\n<li>Data relay nodes<\/li>\n<li>Content delivery services<\/li>\n<li>Computational services<\/li>\n<li>Storage providers<\/li>\n<li>Specialized application services (e.g., rendering, transcoding)<\/li>\n<\/ul>\n<h3>Service Consumers<\/h3>\n<p>Any participant in the GRIDNET OS ecosystem that needs to utilize services. This could be:<\/p>\n<ul>\n<li>End-user applications (UI dApps)<\/li>\n<li>Other service providers (service composition)<\/li>\n<li>Automated agents or system components<\/li>\n<\/ul>\n<h3>Decentralized Service Registry<\/h3>\n<p>Unlike traditional SOA with centralized registries, GRIDNET OS implements service discovery through:<\/p>\n<ul>\n<li>Distributed hash tables (DHTs)<\/li>\n<li>Peer announcements via swarm protocols<\/li>\n<li>On-chain service registration in the DSM<\/li>\n<li>Path discovery mechanisms that identify capable service providers<\/li>\n<\/ul>\n<h3>State-Less Channels Incentivization Layer<\/h3>\n<p>This is where the State-Less Channels subsystem, as documented in this specification, plays a critical role. It provides:<\/p>\n<ul>\n<li>Instantaneous micropayments for service utilization<\/li>\n<li>Fine-grained compensation proportional to service quality and quantity<\/li>\n<li>Economic incentives that maintain service availability and reliability<\/li>\n<li>Sybil-resistant reward distribution through mathematical design<\/li>\n<\/ul>\n<h3>1.4.3. Incentivization Mechanism<\/h3>\n<p>Traditional SOA implementations typically rely on conventional payment systems or subscription models that operate out-of-band from the actual service calls. These systems face significant limitations in decentralized environments:<\/p>\n<ul>\n<li>High transaction costs for micropayments<\/li>\n<li>Lack of real-time compensation<\/li>\n<li>Vulnerability to free-riding and Sybil attacks<\/li>\n<li>Inability to handle high-frequency service invocations<\/li>\n<\/ul>\n<p>GRIDNET OS overcomes these limitations through its State-Less Channels system:<\/p>\n<h3>Micropayment-Based Service Economy<\/h3>\n<p>Each service interaction can be individually compensated with minimal overhead:<\/p>\n<ul>\n<li>A UI dApp consuming bandwidth from a WebRTC relay can issue Transmission Tokens for each data packet<\/li>\n<li>A computational service can receive payment proportional to processing time or complexity<\/li>\n<li>Content delivery nodes can be rewarded based on bytes transferred and delivery speed<\/li>\n<\/ul>\n<h3>Real-Time Incentives<\/h3>\n<p>Payments occur simultaneously with service delivery, creating immediate economic feedback:<\/p>\n<ul>\n<li>Service providers receive compensation instantly, without waiting for transaction settlement<\/li>\n<li>Quality of service directly correlates with economic reward<\/li>\n<li>Resource allocation can dynamically adjust based on real-time incentives<\/li>\n<\/ul>\n<h3>Proportional Compensation<\/h3>\n<p>The amount of payment can be precisely calibrated to:<\/p>\n<ul>\n<li>Value provided by the service<\/li>\n<li>Resource consumption<\/li>\n<li>Quality metrics (latency, throughput, availability)<\/li>\n<li>Position in service paths or chains<\/li>\n<\/ul>\n<h3>1.4.4. SOA Implementation Examples<\/h3>\n<p>The Decentralized Incentivized SOA paradigm enables several key services within GRIDNET OS:<\/p>\n<h3>Decentralized Web Proxy<\/h3>\n<ul>\n<li>\n<strong>Service<\/strong><br \/>\nAccess to web content through decentralized routing<\/li>\n<li>\n<strong>Providers<\/strong><br \/>\nNodes with internet connectivity willing to relay web requests<\/li>\n<li>\n<strong>Incentivization<\/strong><br \/>\nTransmission Tokens issued per request or data volume<\/li>\n<li>\n<strong>Benefits<\/strong><br \/>\nCensorship resistance, privacy enhancement, load distribution<\/li>\n<\/ul>\n<p><strong>WebRTC Swarms<\/strong><\/p>\n<ul>\n<li>\n<strong>Service<\/strong><br \/>\nReal-time media streaming and communication<\/li>\n<li>\n<strong>Providers<\/strong><br \/>\nNodes with sufficient bandwidth and network position<\/li>\n<li>\n<strong>Incentivization<\/strong><br \/>\nContinuous micropayments based on relay quality and volume<\/li>\n<li>\n<strong>Benefits<\/strong><br \/>\nResilient communication, improved geographic distribution, automatic scaling<\/li>\n<\/ul>\n<p><strong>Distributed Storage System<\/strong><\/p>\n<ul>\n<li>\n<strong>Service<\/strong><br \/>\nData persistence, backup, and retrieval<\/li>\n<li>\n<strong>Providers<\/strong><br \/>\nNodes with available disk space<\/li>\n<li>\n<strong>Incentivization<\/strong><br \/>\nPayments for storage duration and retrieval speed<\/li>\n<li>\n<strong>Benefits<\/strong><br \/>\nRedundancy without central planning, economic-driven availability<\/li>\n<\/ul>\n<p><strong>Computational Markets<\/strong><\/p>\n<ul>\n<li>\n<strong>Service<\/strong><br \/>\n Execution of computationally intensive tasks<\/li>\n<li>\n<strong>Providers<\/strong><br \/>\nNodes with spare CPU\/GPU capacity<\/li>\n<li>\n<strong>Incentivization<\/strong><br \/>\nPayment based on computational complexity and speed<\/li>\n<li>\n<strong>Benefits<\/strong><br \/>\nDistributed load, specialized hardware utilization, market-driven pricing<\/li>\n<\/ul>\n<h3>1.4.5. Advantages Over Traditional SOA<\/h3>\n<p>GRIDNET OS&#8217; Decentralized Incentivized SOA provides several key advantages:<\/p>\n<h3>Resilience and Redundancy<\/h3>\n<ul>\n<li>No single point of failure for service discovery or delivery<\/li>\n<li>Automatic adaptation to node failures through economic incentives<\/li>\n<li>Natural redundancy driven by reward mechanisms<\/li>\n<\/ul>\n<h3>Economic Efficiency<\/h3>\n<ul>\n<li>Services are priced according to actual resource costs<\/li>\n<li>Reduced overhead compared to traditional payment systems<\/li>\n<li>No need for complex billing, subscription, or account management<\/li>\n<\/ul>\n<h3>Dynamic Scaling<\/h3>\n<ul>\n<li>Service availability scales with demand through economic signals<\/li>\n<li>Automatic load balancing through incentive distribution<\/li>\n<li>Organic growth of service capacity in high-demand areas<\/li>\n<\/ul>\n<h3>Trustless Operation<\/h3>\n<ul>\n<li>No need to trust specific service providers<\/li>\n<li>Service quality enforced through economic incentives rather than contracts<\/li>\n<li>Decreased risk of service denial or censorship<\/li>\n<\/ul>\n<h3>1.4.6. Relation to State-Less Channels<\/h3>\n<p>The State-Less Channels system described in this documentation serves as the fundamental enabler of the Decentralized Incentivized SOA paradigm. By providing a mechanism for instant, trustless micropayments with minimal overhead, it creates the economic foundation upon which the entire service ecosystem operates.<\/p>\n<p>Key aspects where State-Less Channels directly support the SOA paradigm:<\/p>\n<ul>\n<li>\n<strong>Multi-Dimensionality<\/strong><br \/>\n The M-DTP structure with multiple banks allows service consumers to simultaneously incentivize multiple service providers using a single token pool<\/li>\n<li>\n<strong>Instant Verification<\/strong><br \/>\n Services can verify payment validity immediately without on-chain confirmation<\/li>\n<li>\n<strong>Path Assurance<\/strong><br \/>\n The PA1, PA2, and PA3 protocols ensure that incentives flow correctly through service chains<\/li>\n<li>\n<strong>Scalability<\/strong><br \/>\n Off-chain payments enable high-frequency service invocations without blockchain congestion<\/li>\n<li>\n<strong>Sybil Resistance<\/strong><br \/>\n Mathematical design prevents service providers from gaming the system through identity multiplication<\/li>\n<\/ul>\n<p>Leveraging State-Less Channels via this API offers significant advantages:<\/p>\n<ul>\n<li>\n<h3>Scalability &amp; Throughput:<\/h3>\n<p>Dramatically increases the potential volume of transactions\/rewards that can occur between users and services, far exceeding on-chain TPS limits.<\/li>\n<li>\n<h3>Reduced Transaction Costs:<\/h3>\n<p>Amortizes the cost of on-chain operations. Instead of paying ERG for every small transfer, costs are primarily associated with the initial Token Pool creation and the final cash-out transaction.<\/li>\n<li>\n<h3>Instantaneous (Off-Chain) Transactions:<\/h3>\n<p>Off-chain token exchanges happen almost instantly between peers, ideal for real-time applications.<\/li>\n<li>\n<h3>Enhanced Privacy:<\/h3>\n<p>Individual off-chain transfers within a channel are not broadcast publicly across the DSM. Only the aggregated cash-out transaction is visible on-chain.<\/li>\n<li>\n<h3>Sybil-Proof Incentivization:<\/h3>\n<p>Builds upon the Sybil-proof mechanics detailed in [1], allowing for fair and secure rewarding of potentially unknown or numerous peers for minuscule actions without the overhead or security risks of individual on-chain micropayments.<\/li>\n<\/ul>\n<h3>1.5. Target Audience<\/h3>\n<p>This documentation is primarily intended for<\/p>\n<h3>UI dApp developers<\/h3>\n<p>building applications on the GRIDNET OS platform. It is particularly relevant for those whose dApps require:<\/p>\n<ul>\n<li>High-frequency or low-value transactions.<\/li>\n<li>Real-time reward mechanisms.<\/li>\n<li>Incentivization for peer-to-peer data exchange or service provision.<\/li>\n<li>Interaction with systems employing off-chain payments (e.g., integrated games, services).<\/li>\n<\/ul>\n<h3>1.6. Prerequisites<\/h3>\n<p>Before diving into this documentation, developers should possess:<\/p>\n<ul>\n<li>A foundational understanding of<br \/>\n<h3>GRIDNET OS concepts<\/h3>\n<p>(DSM, IVR, DPT, VM Context, #GridScript basics).<\/li>\n<li>Proficiency in modern<br \/>\n<h3>JavaScript (ES6+)<\/h3>\n<p>, including classes, Promises, and async\/await.<\/li>\n<li>Familiarity with<br \/>\n<h3>event-driven programming paradigms<\/h3>\n<p>, as interaction with the <code>CVMContext<\/code> and the State-Less Channels Manager is heavily reliant on event listeners and callbacks.<\/li>\n<\/ul>\n<hr \/>\n<h3>2. Core Concepts<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668363 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/security-model.png\" alt=\"\" width=\"748\" height=\"726\" \/><\/p>\n<p>This section delves into the fundamental ideas and data structures that underpin the GRIDNET OS State-Less Channels system. Understanding these concepts is essential for effectively utilizing the Off-The-Chain Payment API.<\/p>\n<h3>2.1. State-Less vs. State-Full Channels (Brief Comparison)<\/h3>\n<p>While various blockchain platforms offer &#8220;state channels&#8221; for off-chain interactions, GRIDNET OS employs a<\/p>\n<h3>State-Less Channel<\/h3>\n<ul>\n<li>\n<strong>State-Full Channels (e.g., Lightning Network):<\/strong><br \/>\nTypically require participants to maintain and constantly synchronize complex channel states (balances, commitments) directly with each other. Closing the channel often involves submitting the final agreed-upon state.<\/li>\n<li>\n<h3>GRIDNET OS State-Less Channels:<\/h3>\n<p>Minimize the need for direct, continuous state synchronization <em>between peers<\/em> during the off-chain phase. The &#8220;state&#8221; is primarily represented by the pre-funded Token Pool registered on the DSM and the sequence of revealed hashes (Tokens). Peers exchange Transmission Tokens, which act as verifiable claims against the pool. The final state reconciliation happens on-chain only during the cash-out process. This approach simplifies peer interaction and potentially enhances privacy during the off-chain phase.<\/li>\n<\/ul>\n<h3>2.2. Multi-Dimensional Token Pools (M-DTPs): The Foundation<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668193 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/token-pool.png\" alt=\"\" width=\"858\" height=\"597\" \/><\/h3>\n<p>The cornerstone of the State-Less Channels system is the<\/p>\n<h3>Multi-Dimensional Token Pool (M-DTP)<\/h3>\n<p>. It acts as a secure, on-chain registered escrow of value that enables off-chain payments.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668339 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/master-seed-hash.png\" alt=\"\" width=\"1108\" height=\"815\" \/><\/p>\n<ul>\n<li>\n<h3>Rationale for Multi-Dimensionality:<\/h3>\n<p>A single-dimensional pool (a single hash chain) can only reliably serve <em>one<\/em> off-chain payment stream at a time. If Peer A is paying Peer B using a dimension, Peer A cannot safely start paying Peer C using the <em>same<\/em> dimension until Peer B has cashed out their received tokens on-chain. This creates a bottleneck. M-DTPs overcome this by providing multiple independent dimensions (Banks), allowing the pool owner to conduct simultaneous, independent off-chain payment streams with multiple different recipients using a single, pre-funded pool. This is crucial for scalability in scenarios like rewarding many data relays or game participants concurrently.<\/li>\n<li>\n<h3>Creation:<\/h3>\n<p>An M-DTP is typically created through a process involving:<\/p>\n<ol>\n<li>\n<h3>Sacrificial Transaction:<\/h3>\n<p>The intended pool owner performs an on-chain transaction, effectively locking or &#8220;sacrificing&#8221; a specific amount of GBU\/GNC. The transaction receipt serves as proof of this committed value.<\/li>\n<li>\n<h3>Off-Chain Generation:<\/h3>\n<p>Using the sacrificial transaction receipt ID and desired parameters (number of dimensions, optionally value per token), the pool structure, including all internal hash chains, is generated <em>off-chain<\/em>. This critical step requires the owner&#8217;s secret<\/p>\n<h3>MasterSeedHash<\/h3>\n<p>and is usually performed securely by the GRIDNET Token mobile app via a QR Intent process.<\/li>\n<li>\n<h3>On-Chain Registration:<\/h3>\n<p>The <em>public<\/em> data of the generated M-DTP (including the final hash for each dimension, total value, owner ID, unique Pool ID, etc., but <em>excluding<\/em> the MasterSeedHash) is then committed to the DSM.<\/li>\n<\/ol>\n<\/li>\n<li>\n<h3>On-Chain Representation:<\/h3>\n<p>The registered M-DTP data is stored as a file (typically with a <code>.pool<\/code> extension) within the owner&#8217;s State Domain on the GRIDNET OS Decentralized File System (DFS). This file can be queried by anyone to verify the pool&#8217;s parameters and current on-chain state (e.g., bank usage depths).<\/li>\n<li>\n<h3>Structure:<\/h3>\n<p>Key components of an M-DTP include its unique Token Pool ID, the Owner&#8217;s ID, the total value committed, the number of dimensions (Banks), the value assigned to each individual token (usually calculated automatically based on total value, dimensions, and dimension depth), and the array of Banks, each containing its final hash and current usage depth as known by the DSM.<\/li>\n<\/ul>\n<h3>2.3. Token Pool Banks (Dimensions)<\/h3>\n<p>Each M-DTP is composed of one or more<\/p>\n<h3>Banks<\/h3>\n<p>, also referred to as<\/p>\n<h3>Dimensions<\/h3>\n<ul>\n<li>\n<h3>Independent Hash Chains:<\/h3>\n<p>Each bank represents an independent, cryptographically generated hash chain.<\/li>\n<li>\n<h3>Generating Hashes (Tokens):<\/h3>\n<p>All hashes (tokens) within a bank are derived deterministically from a unique <em>dimension seed hash<\/em> (which is itself derived from the pool&#8217;s MasterSeedHash). This is achieved by repeatedly applying a cryptographic hash function (e.g., SHA256): <code>Hash_i = Hash(Hash_{i-1})<\/code>, starting from the dimension seed hash.<\/li>\n<li>\n<h3>Ceiling Hashes (Final Hash):<\/h3>\n<p>The <em>last<\/em> hash generated in the chain for a dimension (<code>Hash_N<\/code>) is called the ceiling or final hash. This value <em>is<\/em> stored publicly as part of the M-DTP data on the DSM and acts as the verification anchor for the entire chain within that dimension.<\/li>\n<li>\n<h3>Tracking Usage Depth:<\/h3>\n<p>The DSM maintains a record of how many tokens have been successfully cashed out from each bank. This &#8216;usage depth&#8217; indicates the highest index &#8216;i&#8217; for which <code>Hash_i<\/code> has been revealed and accepted on-chain. This is the primary mechanism preventing the same tokens (hashes) from being cashed out twice.<\/li>\n<li>\n<h3>Bank Status:<\/h3>\n<p>A bank can be &#8216;Active&#8217; (has unspent tokens) or &#8216;Depleted&#8217; (its usage depth has reached the maximum depth of the dimension).<\/li>\n<\/ul>\n<h3>2.4. Hash Chains and Tokens<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668305 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/hash-chain.png\" alt=\"\" width=\"782\" height=\"590\" \/><\/p>\n<ul>\n<li>\n<h3>Tokens as Preimages (Hashes):<\/h3>\n<p>In this system, the &#8220;tokens&#8221; exchanged off-chain are the actual hash values (preimages) from the hash chain within a specific bank.<\/li>\n<li>\n<h3>Releasing Tokens (Revealing Hashes):<\/h3>\n<p>To spend value, the pool owner reveals hashes in <em>reverse order<\/em> of their generation. Revealing <code>Hash_i<\/code> requires knowledge of the original dimension seed hash (or a previously revealed <code>Hash_{i-k}<\/code>). Due to the nature of hash functions, revealing <code>Hash_i<\/code> automatically proves knowledge of (and implicitly reveals) all subsequent hashes <code>Hash_{i+1}<\/code> through <code>Hash_N<\/code> (the final hash).<\/li>\n<li>\n<h3>Value Representation:<\/h3>\n<p>The value of each single token\/hash is uniform across all banks within a pool, determined during creation (e.g., 1 Atto, 1 GBU). The total value released is <code>NumberOfRevealedHashes * ValuePerToken<\/code>.<\/li>\n<\/ul>\n<h3>2.5. MasterSeedHash<\/h3>\n<ul>\n<li>\n<h3>The Single Secret:<\/h3>\n<p>This is the high-entropy secret generated by the owner (typically via the mobile app) when creating the M-DTP. It is the <em>only<\/em> secret required to derive <em>all<\/em> dimension seed hashes and subsequently <em>all<\/em> individual tokens (hashes) within the <em>entire<\/em> pool.<\/li>\n<li>\n<h3>Deriving Dimension Seeds:<\/h3>\n<p>A deterministic function (e.g., hashing the MasterSeedHash concatenated with the dimension index) is used to generate the starting Seed Hash for each bank&#8217;s independent hash chain.<\/li>\n<li>\n<h3>Security Implications:<\/h3>\n<p>The MasterSeedHash<\/p>\n<h3>must be kept absolutely secret<\/h3>\n<p>by the pool owner. Its compromise allows an attacker to generate and potentially spend all remaining value in the pool. It should ideally reside only within a secure environment like the GRIDNET Token mobile app.<\/li>\n<\/ul>\n<h3>2.6. Transmission Tokens (TTs)<\/h3>\n<p>While the hashes themselves represent the value, the<\/p>\n<h3>Transmission Token (TT)<\/h3>\n<p>is the data structure used to <em>communicate<\/em> the release of this value off-chain. It packages the necessary information for the recipient to verify the claim and eventually cash it out on-chain.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668309 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/TT-anatomy.png\" alt=\"\" width=\"747\" height=\"587\" \/><\/p>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>To provide proof of released value from a specific bank of a specific Token Pool, indicating the new state (usage depth) of that bank.<\/li>\n<li>\n<h3>Structure:<\/h3>\n<p>A TT (<code>CTransmissionToken<\/code> object in JS) contains:<\/p>\n<ul>\n<li><code>Revealed Hash<\/code>: The latest hash preimage being released in this transfer.<\/li>\n<li><code>Revealed Hashes Count<\/code>: How many <em>new<\/em> tokens this TT represents compared to the previously known state for this bank.<\/li>\n<li><code>Bank Index<\/code>: Identifies the specific dimension\/bank within the M-DTP.<\/li>\n<li><code>Bank Usage Depth<\/code>: The new, total depth reached in this bank <em>after<\/em> releasing the tokens represented by this TT.<\/li>\n<li><code>Token Pool ID<\/code>: Identifies the parent M-DTP.<\/li>\n<li><code>Value<\/code>: The total GBU\/Atto value represented by this specific TT.<\/li>\n<li><code>(Optional) Recipient ID<\/code>: Can specify the intended recipient.<\/li>\n<li><code>(Optional) Signature<\/code>: A signature from the Token Pool owner authenticating the TT.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Authenticated vs. Unauthenticated TTs:<\/h3>\n<p>Unauthenticated TTs rely purely on the hash chain mathematics and on-chain state tracking for security against double-spending by the <em>recipient<\/em>. Authenticated TTs add a layer of non-repudiation and origin verification, crucial for certain applications or dispute resolution, and mandatory for &#8220;Bank Updates&#8221; (where the owner reveals hashes to their <em>own<\/em> web-session to enable spending).<\/li>\n<\/ul>\n<h3>2.7. Transit Pools<\/h3>\n<p>The term<\/p>\n<h3>Transit Pool<\/h3>\n<p>doesn&#8217;t represent a distinct, stored data structure in the same way as a Token Pool.<\/p>\n<ul>\n<li>\n<h3>Concept:<\/h3>\n<p>It refers to the <em>cumulative<\/em> value represented by a sequence of off-chain Transmission Tokens exchanged since the last on-chain cash-out for a specific bank.<\/li>\n<li>\n<h3>On-Chain Representation:<\/h3>\n<p>When cashing out, typically only the <em>latest<\/em> Transmission Token received needs to be submitted to the DSM via the <code>xTTEx<\/code> GridScript command. This single TT contains the final revealed hash and the total usage depth for that bank, implicitly representing the entire &#8220;transit pool&#8221; of value accumulated off-chain since the last settlement.<\/li>\n<\/ul>\n<h3>2.8. Cashing Out<\/h3>\n<p>This is the process of converting the off-chain value represented by Transmission Tokens back into on-chain GBU\/GNC balance.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668324 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/cash-out.png\" alt=\"\" width=\"828\" height=\"758\" \/><\/p>\n<ul>\n<li>\n<h3>The Process:<\/h3>\n<p>The recipient (or the <code>CStateLessChannelsManager<\/code> autonomously) submits the latest valid Transmission Token for a specific bank\/pool to the DSM via an <code>xTTEx<\/code> GridScript instruction, usually packaged within a standard on-chain transaction.<\/li>\n<li>\n<h3>On-Chain Verification:<\/h3>\n<p>The DSM node executing the transaction verifies the TT against the on-chain state of the corresponding M-DTP file:<\/p>\n<ol>\n<li>Checks if the <code>Token Pool ID<\/code> exists and the pool is <code>Active<\/code>.<\/li>\n<li>Checks if the <code>Bank Index<\/code> is valid.<\/li>\n<li>Checks if the <code>Bank Usage Depth<\/code> in the TT is greater than the currently recorded depth for that bank (prevents replay\/double-spend).<\/li>\n<li>Cryptographically verifies the hash chain segment by repeatedly hashing the <code>Revealed Hash<\/code> for <code>Revealed Hashes Count<\/code> times and checking if it matches the <em>currently recorded final hash<\/em> for that bank state.<\/li>\n<li>(If TT is authenticated) Verifies the signature against the Token Pool owner&#8217;s public key.<\/li>\n<\/ol>\n<\/li>\n<li>\n<h3>State Update:<\/h3>\n<p>If verification succeeds, the DSM updates the bank&#8217;s usage depth in the M-DTP file on DFS and credits the <code>Value<\/code> specified in the TT to the designated recipient&#8217;s on-chain account balance.<\/li>\n<li>\n<h3>Associated Costs:<\/h3>\n<p>Executing the <code>xTTEx<\/code> command and the encompassing transaction incurs standard ERG costs on the DSM.<\/li>\n<\/ul>\n<h3>2.9. StateLessChannel Object (<code>CStateLessChannel<\/code>)<\/h3>\n<p>This JavaScript class serves as the primary high-level abstraction for UI dApp developers interacting with the off-chain payment system.<\/p>\n<ul>\n<li>\n<h3>JavaScript Abstraction:<\/h3>\n<p>It encapsulates the logic for managing interaction with a single Token Pool, hiding complexities like direct BER encoding\/decoding or GridScript command formulation.<\/li>\n<li>\n<h3>Relationship to On-Chain Data:<\/h3>\n<p>Each <code>CStateLessChannel<\/code> instance is associated with a specific <code>Token Pool ID<\/code>. It maintains a local cache (<code>mTokenPool<\/code>) of the pool&#8217;s data, which needs to be periodically synchronized (<code>synchronize()<\/code>) with the state stored on the DSM\/DFS.<\/li>\n<li>\n<h3>Ingress vs. Outgress:<\/h3>\n<p>The direction is determined relative to the local user interacting via the UI dApp:<\/p>\n<ul>\n<li>\n<h3>Ingress Channel:<\/h3>\n<p>Represents a pool owned by <em>another<\/em> party from which the local user <em>receives<\/em> payments\/rewards (e.g., Snake game rewards). The dApp typically uses this to validate incoming TTs and initiate cash-outs.<\/li>\n<li>\n<h3>Outgress Channel:<\/h3>\n<p>Represents a pool <em>owned by the local user<\/em> used to <em>send<\/em> payments to others. The dApp uses this to generate and potentially deliver TTs.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ol start=\"3\">\n<li>Architecture and Interaction Flow<\/li>\n<\/ol>\n<p>Understanding how the different parts of GRIDNET OS interact to enable State-Less Channels is key to building robust UI dApps. This section outlines the primary components involved and the typical flow of information and control between them.<\/p>\n<h3>3. Architecture and Interaction Flow<\/h3>\n<p>Understanding how the different parts of GRIDNET OS interact to enable State-Less Channels is key to building robust UI dApps. This section outlines the primary components involved and the typical flow of information and control between them.<\/p>\n<h3>3.1. System Components Overview<\/h3>\n<p>The State-Less Channels sub-system involves a collaboration between several distinct components operating at different levels:<\/p>\n<ul>\n<li>\n<h3>UI dApp (e.g., Wallet, Game):<\/h3>\n<p>The user-facing application built using web technologies (HTML, CSS, JS) running within a <code>CWindow<\/code> instance. It initiates actions (like sending a payment or requesting a cash-out) and subscribes to events to update its state and display information (e.g., received tokens, channel balance). UI dApps <em>only<\/em> interact with the system via the <code>CVMContext<\/code>.<\/li>\n<li>\n<h3>JavaScript VM Context (<code>CVMContext<\/code>):<\/h3>\n<p>The central singleton object acting as the sole gateway between UI dApps and the underlying GRIDNET OS functionalities. It manages communication with Core Nodes, handles event dispatching, provides access to various managers (like the Channels Manager), and facilitates the execution of GridScript commands originating from dApps.<\/li>\n<li>\n<h3>State-Less Channels Manager (<code>CStateLessChannelsManager<\/code>):<\/h3>\n<p>A singleton service, accessible via <code>CVMContext<\/code>, responsible for the overall management of all State-Less Channel instances within the user&#8217;s session. It handles incoming network events related to channels, routes data to the appropriate channel objects, manages a local cache of known channels, performs autonomous tasks like synchronization and automatic cash-outs, and exposes the primary API for dApps to interact with the channel system.<\/li>\n<li>\n<h3>State-Less Channel Objects (<code>CStateLessChannel<\/code>):<\/h3>\n<p>JavaScript objects, managed by the <code>CStateLessChannelsManager<\/code>, each representing a single, specific off-chain payment channel linked to a unique Multi-Dimensional Token Pool ID. It encapsulates the logic for validating\/generating Transmission Tokens, interacting with its cached <code>CTokenPool<\/code> data, and initiating requests for synchronization or cashing out.<\/li>\n<li>\n<h3>Token Pool Objects (<code>CTokenPool<\/code>, <code>CTokenPoolBank<\/code>):<\/h3>\n<p>JavaScript data structures representing the M-DTP and its individual dimensions (Banks) as loaded from the DSM or constructed locally. They contain the core cryptographic state (final hashes, usage depths) and logic for hash chain verification used by <code>CStateLessChannel<\/code>.<\/li>\n<li>\n<h3>Transmission Token Objects (<code>CTransmissionToken<\/code>):<\/h3>\n<p>JavaScript data structure representing the off-chain payment instrument, containing the revealed hash, value, bank details, etc.<\/li>\n<li>\n<h3>GRIDNET Core Nodes:<\/h3>\n<p>The distributed network nodes that maintain the Decentralized State Machine (DSM), execute #GridScript commands (like <code>xTTEx<\/code> for cashing out), manage the Decentralized File System (DFS) where Token Pool data is stored, and handle underlying network communication (UDT, WebSockets, etc.).<\/li>\n<li>\n<h3>GRIDNET Token Mobile App:<\/h3>\n<p>The user&#8217;s secure companion application. It holds sensitive keys (like the MasterSeedHash needed for pool generation), performs cryptographic operations (signing transactions, generating hashes\/tokens securely), and interacts with Core Nodes via QR Intents and secure, often onion-routed, connections to authorize critical actions.<\/li>\n<\/ul>\n<h3>3.2. Interaction Diagram (High-Level)<\/h3>\n<p><em>(Conceptual Description &#8211; A visual diagram would accompany this in full documentation)<\/em><\/p>\n<p>Imagine a layered architecture:<\/p>\n<ol>\n<li>\n<h3>UI Layer:<\/h3>\n<p>The UI dApp presents information and captures user intent.<\/li>\n<li>\n<h3>API Gateway Layer:<\/h3>\n<p>The <code>CVMContext<\/code> receives requests from the dApp and dispatches events back to it.<\/li>\n<li>\n<h3>Service Layer:<\/h3>\n<p>The <code>CStateLessChannelsManager<\/code> resides here, accessed via <code>CVMContext<\/code>. It orchestrates channel operations.<\/li>\n<li>\n<h3>Object Layer:<\/h3>\n<p><code>CStateLessChannel<\/code>, <code>CTokenPool<\/code>, <code>CTransmissionToken<\/code> objects manage the state and logic for individual channels\/tokens.<\/li>\n<li>\n<h3>Core Layer:<\/h3>\n<p>GRIDNET Core Nodes execute commands and manage the persistent DSM\/DFS state.<\/li>\n<li>\n<h3>Security Layer:<\/h3>\n<p>The Mobile App handles sensitive key operations and authorizations.<\/li>\n<\/ol>\n<p>Communication flows vertically (e.g., dApp -&gt; CVMContext -&gt; Manager) and horizontally (e.g., CVMContext &lt;-&gt; Core Node; Mobile App &lt;-&gt; Core Node). Events propagate upwards (Core -&gt; CVMContext -&gt; Manager -&gt; Channel -&gt; dApp).<\/p>\n<h3>3.3. Role of <code>CVMContext<\/code><\/h3>\n<p>Within the State-Less Channels system, <code>CVMContext<\/code> acts as the essential intermediary and event bus:<\/p>\n<ul>\n<li>\n<h3>Singleton Access Point:<\/h3>\n<p>It&#8217;s the <em>only<\/em> way for a UI dApp to access the <code>CStateLessChannelsManager<\/code> (<code>getChannelsManager()<\/code>) and other OS services.<\/li>\n<li>\n<h3>Event Dispatcher:<\/h3>\n<p>It receives low-level events from Core Nodes (e.g., via the VM Meta-Data protocol containing new TTs or pool data, or via DFS message results) and dispatches them to registered listeners, including the <code>CStateLessChannelsManager<\/code>.<\/li>\n<li>\n<h3>Processing GridScript Commands:<\/h3>\n<p>It takes requests formulated by the Manager or Channel objects (often wrapped in <code>CVMMetaGenerator<\/code> objects) and sends them to the appropriate Core Node for execution using methods like <code>processVMMetaDataKF<\/code>. This is how cash-out (<code>xTTEx<\/code>) and pool synchronization (<code>getPoolEx<\/code>) commands are initiated.<\/li>\n<\/ul>\n<h3>3.4. Role of <code>CStateLessChannelsManager<\/code><\/h3>\n<p>The Manager is the central coordinator for all off-chain payment activity:<\/p>\n<ul>\n<li>\n<h3>Central Hub:<\/h3>\n<p>Manages the lifecycle and collection of all active <code>CStateLessChannel<\/code> instances for the current user session.<\/li>\n<li>\n<h3>Event Routing:<\/h3>\n<p>Listens for relevant events from <code>CVMContext<\/code> (<code>newVMMetaDataCallback<\/code>, <code>newDFSMsgCallback<\/code>). It parses incoming data (e.g., deserializing TTs or Token Pools from BER encoding) and routes it to the correct <code>CStateLessChannel<\/code> object based on the Token Pool ID.<\/li>\n<li>\n<h3>Autonomous Operations:<\/h3>\n<p>Runs its own internal timer (<code>controllerThreadF<\/code>) to periodically trigger channel synchronization (<code>syncChannels<\/code>) and check conditions for automatic cash-outs (<code>cashOutChannels<\/code>) based on configured thresholds (<code>mCashOutChannelAfterTimout<\/code>, <code>mCashOutChannelsAtValue<\/code>).<\/li>\n<li>\n<h3>Local Cache:<\/h3>\n<p>Maintains the <code>mChannels<\/code> array, the primary list of known\/managed channel objects.<\/li>\n<li>\n<h3>API Provider:<\/h3>\n<p>Exposes functions (like <code>findChannelByID<\/code>, <code>syncAgentChannels<\/code>) that UI dApps access <em>through<\/em> the <code>CVMContext<\/code> to interact with the channel system at a higher level.<\/li>\n<\/ul>\n<h3>3.5. Role of <code>CStateLessChannel<\/code> Objects<\/h3>\n<p>Each instance represents and manages a single channel:<\/p>\n<ul>\n<li>\n<h3>Channel State:<\/h3>\n<p>Holds the locally cached <code>CTokenPool<\/code> object representing the channel&#8217;s state (final hashes, usage depths, etc.) as last known.<\/li>\n<li>\n<h3>Token Pool Interaction:<\/h3>\n<p>Contains references to the underlying <code>CTokenPool<\/code> and <code>CTokenPoolBank<\/code> logic for calculations.<\/li>\n<li>\n<h3>Core Logic:<\/h3>\n<p>Implements the primary off-chain logic:<\/p>\n<ul>\n<li><code>validateTT<\/code>: Verifies incoming Transmission Tokens against the cached pool state.<\/li>\n<li><code>getTTForPeer<\/code>\/<code>getTTWorthValue<\/code>: Generates new Transmission Tokens for sending payments (if it&#8217;s an Outgress channel).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Initiating Operations:<\/h3>\n<p>Triggers requests <em>via the Manager\/CVMContext<\/em> for:<\/p>\n<ul>\n<li><code>synchronize()<\/code>: To update its cached <code>CTokenPool<\/code> from the DSM\/DFS.<\/li>\n<li><code>cashOut()<\/code>: To initiate the on-chain settlement process.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>3.6. Interaction with the Decentralized State Machine (DSM)<\/h3>\n<p>The DSM and its associated DFS are the persistent, consensus-driven backend:<\/p>\n<ul>\n<li>\n<h3>Storing Token Pool Data:<\/h3>\n<p>Public M-DTP data (final hashes, total value, owner, ID, current bank depths) is stored as files within the DFS, typically under the owner&#8217;s State Domain (e.g., <code>\/OwnerID\/TokenPools\/PoolID.pool<\/code>).<\/li>\n<li>\n<h3>Executing Cash-Out Transactions:<\/h3>\n<p>Core Nodes execute the <code>xTTEx<\/code> #GridScript command submitted in a transaction. This involves reading the relevant Token Pool file from DFS, performing the cryptographic verification of the submitted TT, updating the bank&#8217;s usage depth in the pool file, and crediting the recipient&#8217;s on-chain balance.<\/li>\n<li>\n<h3>Reading Token Pool State:<\/h3>\n<p>The <code>getPoolEx<\/code> #GridScript command reads the <code>.pool<\/code> file from DFS and returns its BER-encoded content, enabling synchronization.<\/li>\n<\/ul>\n<h3>3.7. Interaction with the Mobile App<\/h3>\n<p>The mobile app acts as the user&#8217;s secure hardware wallet and authorization device:<\/p>\n<ul>\n<li>\n<h3>QR Intents:<\/h3>\n<p>Facilitates secure communication for operations requiring the user&#8217;s private key or the secret MasterSeedHash.<\/li>\n<li>\n<h3>Pool Generation:<\/h3>\n<p>The computationally intensive and security-critical generation of M-DTP hash chains from the MasterSeedHash happens <em>only<\/em> within the mobile app in response to a <code>genPool<\/code> QR Intent. The app returns the <em>disarmed<\/em> (public) pool data.<\/li>\n<li>\n<h3>MasterSeedHash Management:<\/h3>\n<p>Securely stores and manages the user&#8217;s MasterSeedHash(es).<\/li>\n<li>\n<h3>Signing:<\/h3>\n<p>Signs critical on-chain transactions (like the one registering a new pool or potentially cash-out requests if configured) via QR Intents.<\/li>\n<li>\n<h3>Providing &#8220;Bank Updates&#8221;:<\/h3>\n<p>Can securely reveal specific hash preimages (packaged as authenticated TTs with <code>isBankUpdate=true<\/code>) to the user&#8217;s web session via QR Intents, allowing the web UI\/dApp to spend pre-funded value from an Outgress channel without exposing the MasterSeedHash.<\/li>\n<\/ul>\n<h3>3.8. Event-Driven Communication Flow (Simplified Sequences)<\/h3>\n<ul>\n<li>\n<h3>Receiving a TT (e.g., Peer-to-Peer or Game Reward):<\/h3>\n<ol>\n<li>TT arrives at a Core Node (e.g., via WebRTC Swarm or direct connection).<\/li>\n<li>Core Node may wrap it in VM Meta-Data and send it to the relevant <code>CVMContext<\/code>.<\/li>\n<li><code>CVMContext<\/code> receives the VM Meta-Data message.<\/li>\n<li><code>CVMContext<\/code> dispatches the event to its listeners, including <code>CStateLessChannelsManager<\/code>.<\/li>\n<li><code>Manager.newVMMetaDataCallback<\/code> parses the message, identifies it as a TT\/BankUpdate, deserializes the <code>CTransmissionToken<\/code>.<\/li>\n<li>Manager finds the corresponding <code>CStateLessChannel<\/code> object by Pool ID (creating one if necessary via <code>onNewChannel<\/code> after fetching pool data).<\/li>\n<li>Manager calls <code>channel.validateTT<\/code> (potentially updating the channel&#8217;s internal state).<\/li>\n<li>Manager raises the <code>onTT<\/code> and <code>onChannelNewState<\/code> events.<\/li>\n<li><code>CVMContext<\/code> dispatches these higher-level events.<\/li>\n<li>The UI dApp&#8217;s registered listener (e.g., <code>addNewTTListener<\/code>) receives the event and updates its UI.<\/li>\n<\/ol>\n<\/li>\n<li>\n<h3>Cashing Out an Ingress Token:<\/h3>\n<ol>\n<li>UI dApp determines the need to cash out (e.g., user click, autonomous logic).<\/li>\n<li>dApp retrieves the relevant <code>CStateLessChannel<\/code> (via <code>manager.findChannelByID<\/code>).<\/li>\n<li>dApp calls <code>channel.cashOut(latestToken, myRecipientID)<\/code>.<\/li>\n<li><code>channel.cashOut<\/code> formulates a #GridScript <code>xTTEx<\/code> command.<\/li>\n<li>Channel requests execution via <code>CVMContext.processVMMetaDataKF<\/code>.<\/li>\n<li><code>CVMContext<\/code> sends the command to a Core Node.<\/li>\n<li>Core Node executes the GridScript, which involves DSM interaction (reading pool, verifying TT, updating pool state, updating balance). This occurs within an on-chain transaction context.<\/li>\n<li>Confirmation\/Result might eventually propagate back via blockchain events or receipt listeners.<\/li>\n<\/ol>\n<\/li>\n<li>\n<h3>Token Pool Creation (via Mobile App):<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668312 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/TP-creation.png\" alt=\"\" width=\"780\" height=\"699\" \/><\/h3>\n<ol>\n<li>User\/dApp initiates pool creation (e.g., in Wallet UI).<\/li>\n<li>UI dApp triggers a <code>genPool<\/code> request via <code>CVMContext.processVMMetaDataKF<\/code> (containing sacrificial receipt ID, dimensions, etc.).<\/li>\n<li>Core Node receives request, generates a specific QR Intent.<\/li>\n<li><code>CVMContext<\/code> receives the QR Intent data via event and displays it (using UI dApp helpers).<\/li>\n<li>User scans QR with Mobile App.<\/li>\n<li>Mobile App securely generates the pool using MasterSeedHash, performs necessary signing.<\/li>\n<li>Mobile App sends the <em>disarmed<\/em> pool data + authorization back to the <em>originating<\/em> Core Node (via secure onion routing).<\/li>\n<li>Core Node receives the pool data.<\/li>\n<li>Core Node sends the pool data back to <code>CVMContext<\/code> via VM Meta-Data.<\/li>\n<li><code>CVMContext<\/code> dispatches -&gt; <code>Manager.newVMMetaDataCallback<\/code> receives pool data.<\/li>\n<li>Manager potentially creates a new <code>CStateLessChannel<\/code> instance.<\/li>\n<li>Manager raises <code>onNewTokenPool<\/code>\/<code>onNewChannel<\/code> events -&gt; <code>CVMContext<\/code> dispatches -&gt; UI dApp is notified.<\/li>\n<li><em>(Separately)<\/em> User\/dApp initiates the <code>CT<\/code> (Commit Transaction) via QR to get the pool registered on-chain via DFS.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<hr \/>\n<h3>4. The <code>CStateLessChannelsManager<\/code> API (JavaScript)<\/h3>\n<p>The <code>CStateLessChannelsManager<\/code> is the primary interface for UI dApps to interact with the State-Less Channels system. It orchestrates the discovery, synchronization, and management of off-chain channels and related data. As a singleton service within the <code>CVMContext<\/code>, it ensures a consistent view and handling of channel operations across all UI dApps in a user session.<\/p>\n<h3>4.1. Accessing the Manager<\/h3>\n<p>Being a singleton managed by the <code>CVMContext<\/code>, you access the <code>CStateLessChannelsManager<\/code> instance as follows:<\/p>\n<pre>\/\/ Get the CVMContext instance (singleton)\r\nconst vmContext = CVMContext.getInstance();\r\n\r\n\/\/ Get the State-Less Channels Manager instance\r\nconst channelsManager = vmContext.getChannelsManager;\r\n\r\n\/\/ Now you can call methods on channelsManager\r\n\/\/ e.g., channelsManager.findChannelByID(...)\r\n<\/pre>\n<h3>4.2. Initialization and Lifecycle<\/h3>\n<p>The manager&#8217;s core functionality, including its autonomous operations, relies on an internal controller thread and event listeners connected to the <code>CVMContext<\/code>.<\/p>\n<ul>\n<li>\n<h3><code>initialize()<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Starts the manager&#8217;s internal controller thread (a JavaScript timer loop) responsible for periodic tasks like channel synchronization and checking auto-cash-out conditions. It also registers the necessary internal listeners (<code>newVMMetaDataCallback<\/code>, <code>newDFSMsgCallback<\/code>) with the <code>CVMContext<\/code>.<\/li>\n<li>\n<h3>Usage:<\/h3>\n<p>This method is typically called automatically during the <code>CVMContext<\/code>&#8216;s own initialization sequence. UI dApp developers usually do not need to call this directly.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>void<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>destroy()<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Stops the internal controller thread, preventing further autonomous operations. It does <em>not<\/em> automatically unregister event listeners registered by dApps.<\/li>\n<li>\n<h3>Usage:<\/h3>\n<p>Called when the <code>CVMContext<\/code> is shutting down or if explicitly needed to halt the manager&#8217;s background activity. UI dApp developers rarely need to call this.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>void<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>4.3. Channel Discovery and Management<\/h3>\n<p>These methods allow dApps to query the manager&#8217;s cache of known State-Less Channels.<\/p>\n<ul>\n<li>\n<h3><code>findChannelByID(channelID, allowFriendlyID = true)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Searches the manager&#8217;s internal list (<code>mChannels<\/code>) for a <code>CStateLessChannel<\/code> object matching the provided ID.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>channelID<\/code> (ArrayBuffer | String): The unique Token Pool ID (usually Base58Check encoded string) or a Friendly ID.<\/li>\n<li><code>allowFriendlyID<\/code> (Boolean): If <code>true<\/code>, the search will also match against the channel&#8217;s Friendly ID.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p>The <code>CStateLessChannel<\/code> object if found, otherwise <code>null<\/code>.<\/li>\n<li>\n<h3>Example:<\/h3>\n<pre>const poolId = \"2NPe49vveUrhF8WE5trVSTKRzcKPSFVdJqaFRBMKPUk\"; \/\/ Example ID\r\nconst channel = channelsManager.findChannelByID(poolId);\r\nif (channel &amp;&amp; channel.getIsReadyForVerification) {\r\n   console.log(\"Channel found and ready:\", channel.getFriendlyID);\r\n} else if (channel) {\r\n   console.log(\"Channel found but needs sync:\", channel.getFriendlyID);\r\n   \/\/ channel.synchronize(); \/\/ Optionally trigger sync\r\n} else {\r\n   console.log(\"Channel not found locally.\");\r\n   \/\/ Might need to trigger discovery via syncAgentChannels if owner is known\r\n}\r\n<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>findChannelsByOwner(ownerID, allowFriendlyID = true)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Finds all channels in the manager&#8217;s cache whose underlying Token Pool is owned by the specified <code>ownerID<\/code>.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>ownerID<\/code> (ArrayBuffer | String): The State Domain ID (or potentially Friendly ID if <code>allowFriendlyID<\/code> is true, though primarily designed for domain IDs) of the owner.<\/li>\n<li><code>allowFriendlyID<\/code> (Boolean): Allows matching <code>ownerID<\/code> against friendly IDs <em>of the owner<\/em> (less common use case).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p>An <code>Array<\/code> of <code>CStateLessChannel<\/code> objects owned by the specified ID, or an empty array if none are found.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getChannelIDs(mode = eChannelDirection.both, allowFriendlyIDs = true)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Retrieves a list of IDs for all channels currently managed by the instance, filterable by direction (relative to the local user).<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>mode<\/code> (<code>eChannelDirection<\/code> enum: <code>ingress<\/code>, <code>outgress<\/code>, <code>both<\/code>): Filters the channels based on their direction. <code>ingress<\/code> means the local user receives from the channel, <code>outgress<\/code> means the local user sends from the channel (owns the pool).<\/li>\n<li><code>allowFriendlyIDs<\/code> (Boolean): If <code>true<\/code> and a channel has a Friendly ID, that ID is returned instead of the raw Token Pool ID.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p>An <code>Array<\/code> of strings (Channel IDs or Friendly IDs).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>4.4. Synchronization<\/h3>\n<p>These methods are used to update the local cache of channel states with the latest information from the DSM\/DFS.<\/p>\n<ul>\n<li>\n<h3><code>syncAgentChannels(agentID)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Initiates a discovery and synchronization process for <em>all<\/em> State-Less Channels associated with a specific <code>agentID<\/code> (typically a State Domain ID). It does this by triggering a DFS <code>doCD<\/code> (Change Directory and List) command for the standard Token Pool directory (<code>\/agentID\/TokenPools\/<\/code>) on a GRIDNET Core node. The results (list of <code>.pool<\/code> files) arrive asynchronously via the <code>newDFSMsgCallback<\/code>. The manager then typically queues <code>doGetFile<\/code> requests for each pool found.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>agentID<\/code> (ArrayBuffer | String): The State Domain ID of the agent whose channels should be synced.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>Boolean<\/code> indicating if the initial DFS request was successfully sent (does not guarantee channels were found or synced).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>syncChannels(forceIt = false)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Iterates through all <em>currently managed<\/em> channels (<code>mChannels<\/code>) and calls the <code>synchronize()<\/code> method on each one if <code>forceIt<\/code> is true or if the time since its last sync exceeds <code>mChannelSyncInterval<\/code>.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>forceIt<\/code> (Boolean): If <code>true<\/code>, forces synchronization regardless of the last sync time.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>void<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>mChannelSyncInterval<\/code> (Property):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>A configuration value (in seconds, default 600) determining how often the manager&#8217;s controller thread attempts to automatically synchronize managed channels.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>4.5. Autonomous Operations<\/h3>\n<p>The manager performs background tasks based on configured parameters.<\/p>\n<ul>\n<li>\n<h3>Cash-out Logic:<\/h3>\n<p>The internal controller thread (<code>controllerThreadF<\/code>) periodically calls <code>cashOutChannels()<\/code>.<\/li>\n<li>\n<h3><code>cashOutChannels(forceIt = false, autoCommit = true, channelIDsp = [], abortOnNotReady = true)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>(Primarily internal, but potentially callable) Checks managed <em>ingress<\/em> channels against configured thresholds (<code>mCashOutChannelsAtValue<\/code>, <code>mCashOutChannelAfterTimout<\/code>) or forces cash-out if <code>forceIt<\/code> is true. For qualifying channels, it formulates and queues <code>xTTEx<\/code> #GridScript commands via <code>CVMContext<\/code> to cash out the latest known <code>mRecentToken<\/code>.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<p>(See method signature for details, usually called internally without parameters).<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>Boolean<\/code> indicating if any cash-out operations were initiated.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>mCashOutChannelsAtValue<\/code> (Property):<\/h3>\n<p>Configurable threshold (GBU\/Atto value) for auto cash-out.<\/li>\n<li>\n<h3><code>mCashOutChannelAfterTimout<\/code> (Property):<\/h3>\n<p>Configurable time threshold (seconds) for auto cash-out.<\/li>\n<\/ul>\n<h3>4.6. Event Subscription API<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668191 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/arch2.png\" alt=\"\" width=\"607\" height=\"572\" \/><\/p>\n<p>UI dApps subscribe to these events to react to changes in the State-Less Channel ecosystem. All listener callbacks should ideally be <code>async<\/code> functions.<\/p>\n<ul>\n<li>\n<h3><code>addNewTTListener(eventListener, appID = 0)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Triggered:<\/h3>\n<p>When the Manager successfully processes an incoming <code>CTransmissionToken<\/code> (either a standard payment\/reward or a Bank Update).<\/li>\n<li>\n<h3>Callback Argument:<\/h3>\n<p>An object <code>{ token: CTransmissionToken, isBankUpdate: Boolean }<\/code>.<\/li>\n<li>\n<h3>Purpose:<\/h3>\n<p>Allows dApps to react to received off-chain value or bank updates.<\/li>\n<li>\n<h3>Example:<\/h3>\n<pre>async function handleNewTT(event) {\r\n  console.log(`Received TT for pool ${gTools.encodeBase58Check(event.token.getTokenPoolID())}`);\r\n  if (event.isBankUpdate) {\r\n    console.log(\"It's a bank update, refreshing spendable balance.\");\r\n    \/\/ Potentially update UI related to sending capabilities\r\n  } else {\r\n    const channel = channelsManager.findChannelByID(event.token.getTokenPoolID());\r\n    const accumulated = channel ? await channel.getAccumulatedValue() : 0n;\r\n    console.log(`Value in this TT: ${event.token.getValue()}. Total accumulated off-chain: ${accumulated}`);\r\n    \/\/ Update UI with received value\r\n  }\r\n}\r\nchannelsManager.addNewTTListener(handleNewTT.bind(this), this.mID);\r\n<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>addNewTokenPoolListener(eventListener, appID = 0)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Triggered:<\/h3>\n<p>When the Manager discovers or receives data for a <code>CTokenPool<\/code> object for the <em>first time<\/em> in the current session (often as a result of <code>syncAgentChannels<\/code> or direct VM Meta-Data). Note: <code>addNewStateChannelListener<\/code> is usually triggered subsequently or concurrently.<\/li>\n<li>\n<h3>Callback Argument:<\/h3>\n<p>An object <code>{ pool: CTokenPool, requestID: Number }<\/code>.<\/li>\n<li>\n<h3>Purpose:<\/h3>\n<p>Informs dApps about the existence and initial state of a Token Pool.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>addNewStateChannelListener(eventListener, appID = 0)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Triggered:<\/h3>\n<p>When the Manager creates a new <code>CStateLessChannel<\/code> object instance to manage a discovered Token Pool. This signifies the channel is now being actively tracked.<\/li>\n<li>\n<h3>Callback Argument:<\/h3>\n<p>An object <code>{ channel: CStateLessChannel, requestID: Number }<\/code>.<\/li>\n<li>\n<h3>Purpose:<\/h3>\n<p>Allows dApps to know when a new channel becomes managed and potentially start interacting with it or updating UI lists.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>addNewTransitPoolListener(eventListener, appID = 0)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Clarification Needed:<\/h3>\n<p>The concept of a &#8220;Transit Pool&#8221; event is less distinct in the current State-Less model compared to the underlying <code>CTransmissionToken<\/code> and <code>CTokenPool<\/code> updates. This listener&#8217;s specific trigger condition might overlap significantly with TT or Receipt events.<\/p>\n<h3>It&#8217;s likely related to the <em>completion<\/em> or <em>receipt<\/em> of an on-chain cash-out (<code>xTTEx<\/code>) transaction.<\/h3>\n<p>Developers should currently rely more on <code>addNewTTListener<\/code> for off-chain updates and <code>addNewReceiptListener<\/code> for on-chain settlement confirmation. <em>Further clarification from core implementation might be needed.<\/em><\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>addNewReceiptListener(eventListener, appID = 0)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Triggered:<\/h3>\n<p>When a transaction receipt arrives via <code>CVMContext<\/code> that corresponds to a previously initiated State-Less Channel operation (e.g., a cash-out <code>xTTEx<\/code> transaction or pool registration). The manager needs internal logic to correlate receipts to channel operations.<\/li>\n<li>\n<h3>Callback Argument:<\/h3>\n<p>An object <code>{ receipt: CReceipt }<\/code> (Structure of <code>CReceipt<\/code> needs definition &#8211; likely contains TX ID, status, block info).<\/li>\n<li>\n<h3>Purpose:<\/h3>\n<p>Allows dApps to confirm that an on-chain action related to a channel (like cashing out) has been successfully finalized on the DSM.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>addStateChannelNewStateListener(eventListener, appID = 0)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Triggered:<\/h3>\n<p>When the Manager processes an event (like a new TT or a successful pool sync) that results in a change to the <em>cached state<\/em> of a managed <code>CStateLessChannel<\/code> (e.g., its <code>mTokenPool<\/code>&#8216;s bank depths are updated).<\/li>\n<li>\n<h3>Callback Argument:<\/h3>\n<p>An object <code>{ channel: CStateLessChannel, newState: Object, previousState: Object | null }<\/code>. The state objects contain key metrics like <code>availableAssets<\/code>, <code>spendableAssets<\/code>, <code>accumulatedAssets<\/code>.<\/li>\n<li>\n<h3>Purpose:<\/h3>\n<p>Enables dApps to reactively update UI elements displaying channel balances or status based on processed off-chain or synchronized on-chain data.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>4.7. Internal Callbacks (Manager&#8217;s Perspective)<\/h3>\n<p>These are the methods the Manager uses to listen to the <code>CVMContext<\/code>. UI dApp developers typically don&#8217;t interact with these directly but understanding them helps clarify the flow.<\/p>\n<ul>\n<li>\n<h3><code>newVMMetaDataCallback(metaMsg)<\/code>:<\/h3>\n<ul>\n<li>Handles incoming VM Meta-Data messages.<\/li>\n<li>Parses the data using <code>CVMMetaParser<\/code>.<\/li>\n<li>Looks specifically for <code>eVMMetaSectionType.stateLessChannels<\/code> sections.<\/li>\n<li>Deserializes elements like <code>CTransmissionToken<\/code> or <code>CTokenPool<\/code> based on <code>eVMMetaEntryType.StateLessChannelsElement<\/code> and <code>eStateLessChannelsElementType<\/code>.<\/li>\n<li>Calls internal <code>onTT<\/code> or <code>onTokenPoolReceived<\/code> methods.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>newDFSMsgCallback(dfsMsg)<\/code>:<\/h3>\n<ul>\n<li>Handles responses to DFS requests initiated by the Manager or Channels (e.g., <code>doCD<\/code>, <code>doGetFile<\/code>).<\/li>\n<li>Parses the DFS message and potential embedded VM Meta-Data (<code>dfsMsg.getData1<\/code>).<\/li>\n<li>If it&#8217;s a directory listing (<code>doCD<\/code> response), it might trigger <code>doGetFile<\/code> requests for found <code>.pool<\/code> files.<\/li>\n<li>If it&#8217;s file content (<code>doGetFile<\/code> response for a <code>.pool<\/code> file), it deserializes the <code>CTokenPool<\/code>.<\/li>\n<li>Calls internal <code>onTokenPoolReceived<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Internal Event Raisers (<code>onTT<\/code>, <code>onNewTokenPool<\/code>, etc.):<\/h3>\n<ul>\n<li>These private\/internal methods within the Manager are called by the callbacks above after successfully processing data.<\/li>\n<li>They perform core logic (e.g., finding\/updating the relevant channel object).<\/li>\n<li>They are responsible for finally raising the public events (e.g., <code>addNewTTListener<\/code>, <code>addNewStateChannelListener<\/code>) that UI dApps subscribe to.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr \/>\n<h3>5. The <code>CStateLessChannel<\/code> API (JavaScript &#8211; Key Aspects)<\/h3>\n<p>While the <code>CStateLessChannelsManager<\/code> provides overall coordination, the <code>CStateLessChannel<\/code> class represents a single, specific channel instance. UI dApps typically obtain instances of this class from the manager (e.g., via <code>findChannelByID<\/code>) rather than constructing them directly. This section highlights the most important methods and properties developers will interact with.<\/p>\n<h3>5.1. Object Lifecycle and State<\/h3>\n<p>These methods and properties relate to the creation, readiness, and basic information of a channel instance.<\/p>\n<ul>\n<li>\n<h3><code>constructor(tokenPoolID = null)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Creates a new <code>CStateLessChannel<\/code> object instance associated with a specific Token Pool ID.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>tokenPoolID<\/code> (ArrayBuffer | String): The unique ID of the Multi-Dimensional Token Pool this channel represents.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Note:<\/h3>\n<p>While constructible, instances are typically managed and provided by the <code>CStateLessChannelsManager<\/code>. Direct instantiation by a dApp is uncommon.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>synchronize()<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Initiates a request (via the Manager and <code>CVMContext<\/code>) to fetch the latest state data for the associated Token Pool from the DSM\/DFS. This updates the channel&#8217;s internal cached <code>mTokenPool<\/code> object.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<p>None.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>Boolean<\/code> indicating if the synchronization request was successfully sent. The actual data arrives asynchronously via events.<\/li>\n<li>\n<h3>Usage:<\/h3>\n<p>Call this when you need the most up-to-date on-chain state for a channel, especially before critical operations like validating a newly received high-value token or attempting a cash-out, or if the channel&#8217;s <code>getIsReadyForVerification<\/code> is false. Be mindful of rate limits.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getIsReadyForVerification<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Checks if the channel instance has successfully loaded its corresponding <code>CTokenPool<\/code> data from the DSM\/DFS (i.e., <code>mTokenPool<\/code> is not null).<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<p>None.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>Boolean<\/code>. <code>true<\/code> if the pool data is loaded and TT validation can be attempted, <code>false<\/code> otherwise.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getID()<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Returns the unique Token Pool ID (as an <code>ArrayBuffer<\/code>) associated with this channel.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getFriendlyID()<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Returns the human-readable friendly identifier assigned to the Token Pool, if one exists.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>String<\/code>, potentially empty if no friendly ID is set.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getTokenPool()<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Returns the internally cached <code>CTokenPool<\/code> object instance containing the detailed state (banks, depths, etc.) for this channel.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>CTokenPool<\/code> object or <code>null<\/code> if not yet synchronized.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getIsOutgress<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Determines if this channel represents an <em>outbound<\/em> payment stream from the perspective of the <em>currently logged-in user<\/em>. This means the logged-in user <em>owns<\/em> the underlying Token Pool. It compares the pool&#8217;s owner ID with the user&#8217;s ID from <code>CVMContext<\/code>.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>Boolean<\/code>. <code>true<\/code> if the local user owns the pool (Outgress), <code>false<\/code> if someone else owns it (Ingress), or potentially <code>false<\/code> or throws an error if the user isn&#8217;t logged in or pool data is unavailable.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Timestamps (<code>getLastTimeUsed()<\/code>, <code>getLastTimeUpdated()<\/code>, <code>getLastTimeCashedOut()<\/code>, <code>getTimeSince...()<\/code> methods):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Provide access to timestamps (Unix epoch seconds) tracking key events in the channel&#8217;s lifecycle <em>within the current session<\/em>. <code>getTimeSince...()<\/code> methods return the duration in seconds since that event.<\/li>\n<li>\n<h3>Note:<\/h3>\n<p>These are primarily informative for the local session and may reset when the session restarts. The core on-chain state is managed by the DSM.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>ping(type = eChannelLocalPingType.lastUpdate)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>(Mostly internal) Updates the internal timestamp specified by the <code>type<\/code> enum (<code>update<\/code>, <code>lastUsed<\/code>, <code>lastSync<\/code>, <code>lastCashOut<\/code>).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>5.2. Generating Transmission Tokens<\/h3>\n<p>These methods are used by UI dApps managing<\/p>\n<h3>Outgress<\/h3>\n<p>channels (where the local user owns the pool) to create TTs for sending off-chain payments.<\/p>\n<ul>\n<li>\n<h3><code>getTTForPeer(value, peerID = '', markUsed = true, reassignDimensionsIfNeeded = true)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>High-level method to generate a <code>CTransmissionToken<\/code> for a specific value destined for a specific peer. It handles the logic of finding an appropriate, available bank (dimension) within the pool, potentially assigning a free bank to the peer if none is currently assigned or if the previously assigned one is depleted\/insufficient.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>value<\/code> (BigInt | Number): The GBU\/Atto value the token should represent.<\/li>\n<li><code>peerID<\/code> (ArrayBuffer | String): The ID of the intended recipient. This helps the channel manage bank assignments. If empty, it attempts to find the first available unassigned bank with sufficient value.<\/li>\n<li><code>markUsed<\/code> (Boolean): If <code>true<\/code> (default), updates the internal state of the chosen bank as if the token was spent locally (decrements available value, increments usage depth). Set to <code>false<\/code> only for inspection\/simulation.<\/li>\n<li><code>reassignDimensionsIfNeeded<\/code> (Boolean): If <code>true<\/code> (default), allows the method to automatically assign a <em>new<\/em> free bank to the peer if their currently assigned bank is unsuitable (e.g., depleted).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p>A <code>CTransmissionToken<\/code> object on success, <code>null<\/code> if no suitable bank\/dimension could be found or assigned, or if the pool lacks sufficient <em>total<\/em> spendable value.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getTTWorthValue(value, bankID = -1, markUsed = true)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Lower-level method to generate a <code>CTransmissionToken<\/code> for a specific value from a <em>specific<\/em> bank, or the first available unassigned bank if <code>bankID<\/code> is -1. It does <em>not<\/em> perform automatic peer-to-bank assignment management like <code>getTTForPeer<\/code>.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>value<\/code> (BigInt | Number): The GBU\/Atto value.<\/li>\n<li><code>bankID<\/code> (Number): The index of the specific dimension\/bank to use. If -1, it searches for the first <em>unassigned<\/em> bank with enough value.<\/li>\n<li><code>markUsed<\/code> (Boolean): Updates the internal bank state if <code>true<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p>A <code>CTransmissionToken<\/code> object on success, <code>null<\/code> if the specified (or first found) bank lacks sufficient value or is invalid.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>5.3. Validating Transmission Tokens<\/h3>\n<p>These methods are primarily used by UI dApps managing<\/p>\n<h3>Ingress<\/h3>\n<p>channels to verify incoming TTs and check available balances.<\/p>\n<ul>\n<li>\n<h3><code>validateTT(token, updateState = true, isBankUpdate = false)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>The core method to validate an incoming <code>CTransmissionToken<\/code> against the channel&#8217;s cached <code>CTokenPool<\/code> state. It performs the necessary cryptographic hash chain verification and checks if the token represents a valid progression from the currently known usage depth of the bank.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>token<\/code> (<code>CTransmissionToken<\/code>): The token object to validate.<\/li>\n<li><code>updateState<\/code> (Boolean): If <code>true<\/code> (default) and the token is valid, updates the internal cached state of the <code>CTokenPool<\/code> (specifically, the bank&#8217;s <code>mCurrentDepth<\/code> and <code>mCurrentFinalHash<\/code>). This should generally be true when processing received payments.<\/li>\n<li><code>isBankUpdate<\/code> (Boolean): If <code>true<\/code>, indicates this token is a special update from the pool owner (via mobile app) meant to reveal <em>more<\/em> spendable assets from an <em>outgress<\/em> channel, rather than representing a payment received. It updates the bank&#8217;s <em>pre-cached<\/em> seed hash instead of its usage depth.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>BigInt<\/code> representing the <em>value<\/em> of the newly validated token segment (i.e., <code>token.getRevealedHashesCount() * tokenPool.getSingleTokenValue()<\/code>) if valid, <code>0n<\/code> if invalid (e.g., double-spend attempt, hash mismatch), or <code>-1n<\/code> if the channel is not ready (<code>mTokenPool<\/code> is null).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getAccumulatedValue()<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Calculates the total value represented by the <em>last known valid<\/em> <code>CTransmissionToken<\/code> (<code>mRecentToken<\/code>) received for this channel in the current session, relative to the pool&#8217;s <em>initial<\/em> state (or last cash-out state if known locally). Essentially, it checks how much value the <code>mRecentToken<\/code> represents if it were to be cashed out now.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>BigInt<\/code> representing the potential cash-out value based on the last token, <code>0n<\/code> if no token has been received or validated, or the pool data isn&#8217;t ready.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getLocallySpendableAssets()<\/code> (Getter):<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Relevant primarily for<\/p>\n<h3>Outgress<\/h3>\n<p>channels. Calculates the amount of value the local user can currently spend off-chain <em>without<\/em> needing further interaction with their mobile app. This relies on the depth of pre-cached seed hashes potentially provided by the mobile app as &#8220;Bank Updates&#8221;.<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>BigInt<\/code> representing the spendable value based on pre-cached data, <code>0n<\/code> if no pre-cached hashes are available beyond the current on-chain usage depth.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>5.4. Cashing Out<\/h3>\n<p>This method initiates the process of settling the off-chain value onto the main blockchain.<\/p>\n<ul>\n<li>\n<h3><code>cashOut(token, awardeeID, autoCommit = false)<\/code>:<\/h3>\n<ul>\n<li>\n<h3>Purpose:<\/h3>\n<p>Creates and sends the #GridScript <code>xTTEx<\/code> command (via the Manager and <code>CVMContext<\/code>) to a Core Node to initiate the on-chain cash-out process for the value represented by the provided <code>token<\/code>.<\/li>\n<li>\n<h3>Parameters:<\/h3>\n<ul>\n<li><code>token<\/code> (<code>CTransmissionToken<\/code>): The <em>latest<\/em> valid token received for the channel\/bank that is to be cashed out. This token implicitly covers all value since the last on-chain settlement for that bank.<\/li>\n<li><code>awardeeID<\/code> (ArrayBuffer | String): The State Domain ID of the entity who should receive the funds on-chain (usually the local user for an Ingress channel).<\/li>\n<li><code>autoCommit<\/code> (Boolean): If <code>true<\/code>, attempts to immediately trigger a full commit procedure via <code>CVMContext.commit()<\/code> after queueing the <code>xTTEx<\/code> command (less common, usually commit is handled separately).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Returns:<\/h3>\n<p><code>Boolean<\/code> indicating if the <code>xTTEx<\/code> command was successfully sent to the <code>CVMContext<\/code> for processing. It does <em>not<\/em> guarantee the cash-out succeeded on-chain. Confirmation comes via events (<code>addNewReceiptListener<\/code>).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>5.5. Bank (Dimension) Management<\/h3>\n<p>These methods provide finer control over how peers are associated with specific dimensions, primarily useful for Outgress channels in complex reward scenarios.<\/p>\n<ul>\n<li>\n<h3><code>assignPeerToBank(peerID, bankID)<\/code>:<\/h3>\n<p>Explicitly associates a peer with a bank ID in the channel&#8217;s internal map (<code>mRecipientsToBanks<\/code>).<\/li>\n<li>\n<h3><code>isBankInUse(bankID)<\/code>:<\/h3>\n<p>Checks if a specific bank ID is currently assigned to any peer in the internal map.<\/li>\n<li>\n<h3><code>findBankForUser(peerID)<\/code>:<\/h3>\n<p>Looks up the <code>CTokenPoolBank<\/code> object currently assigned to the given peer ID.<\/li>\n<li>\n<h3><code>freeBank(bankID)<\/code>:<\/h3>\n<p>Removes any association for the given bank ID from the internal map, making it available for assignment to another peer.<\/li>\n<\/ul>\n<p>I&#8217;ll convert the content into HTML with the same formatting style as your existing HTML fragment. Here&#8217;s the converted HTML:<\/p>\n<h3>5.6. Token Pool Synchronization<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-668353 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/token-pool-updates.png\" alt=\"\" width=\"1062\" height=\"748\" \/><\/p>\n<h3>5.6.1. When Token Pool Updates Are Needed<\/h3>\n<p>Token Pools stored in the web browser&#8217;s environment need to be synchronized with their authoritative state on the DSM\/DFS under several circumstances:<\/p>\n<ul>\n<li>Initial Discovery: When a UI dApp first encounters a Token Pool ID, it needs to retrieve the pool&#8217;s data to create a local CTokenPool instance.<\/li>\n<li>Periodic Refresh: The pool&#8217;s on-chain state may change due to other participants&#8217; actions (cash-outs) occurring in parallel sessions.<\/li>\n<li>Before Critical Operations: Prior to sending or validating high-value Transmission Tokens, or before cashing out.<\/li>\n<li>After Suspected Staleness: If a TT validation or generation fails unexpectedly, the local pool cache might be out of date.<\/li>\n<li>After Cash-Out Operations: After a successful cash-out transaction, the pool&#8217;s bank usage depths have changed on-chain.<\/li>\n<\/ul>\n<h3>5.6.2. Synchronization Mechanism<\/h3>\n<p>The synchronization process involves the following steps:<\/p>\n<pre>\/\/ Within a UI dApp\r\nasync function updatePoolState(channelId) {\r\n  const manager = this.mVMContext.getChannelsManager;\r\n  const channel = manager.findChannelByID(channelId);\r\n  \r\n  if (channel) {\r\n    \/\/ Trigger synchronization with on-chain state\r\n    const syncSuccess = await channel.synchronize();\r\n    \r\n    if (syncSuccess) {\r\n      console.log(\"Channel synchronized successfully\");\r\n      \/\/ Update UI with fresh data\r\n      this.updateChannelDisplay(channelId);\r\n    } else {\r\n      console.warn(\"Channel synchronization failed\");\r\n    }\r\n  }\r\n}<\/pre>\n<p>Under the hood, synchronize() calls getPoolEx via CVMContext to fetch the latest Token Pool data from the DFS. This updates the bank usage depths and other state information to match the on-chain reality.<\/p>\n<h3>5.6.3. Automatic vs. Manual Synchronization<\/h3>\n<p>The CStateLessChannelsManager provides both automatic and manual synchronization options:<\/p>\n<ul>\n<li>\n<h3>Automatic Synchronization<\/h3>\n<ul>\n<li>The manager&#8217;s internal controller thread (controllerThreadF) periodically calls syncChannels() at intervals defined by mChannelSyncInterval (default: 600 seconds).<\/li>\n<li>This ensures all managed channels are kept reasonably up-to-date without developer intervention.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Manual Synchronization<\/h3>\n<ul>\n<li>Developers should manually trigger synchronization in these cases:<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Before Sending Value: Before generating a new TT to ensure the channel has sufficient spendable value:\n<pre>\/\/ Check readiness before sending\r\nif (!channel.getIsReadyForVerification()) {\r\n  await channel.synchronize();\r\n}\r\nconst tt = await channel.getTTWorthValue(valueAtto, recipientId);<\/pre>\n<\/li>\n<li>Before Cashing Out: To ensure the most recent state is considered:\n<pre>await channel.synchronize();\r\nconst accumulatedValue = await channel.getAccumulatedValue();\r\nif (accumulatedValue &gt; 0n) {\r\n  channel.cashOut(latestToken, myDomainID);\r\n}<\/pre>\n<\/li>\n<li>After Failed Operations: If TT validation or generation fails unexpectedly:\n<pre>if (await channel.validateTT(token) === 0n) {\r\n  \/\/ Token appears invalid, synchronize and try again\r\n  await channel.synchronize();\r\n  const validationResult = await channel.validateTT(token);\r\n  \/\/ Handle result...\r\n}<\/pre>\n<\/li>\n<\/ul>\n<h3>5.6.4. Checking Synchronization Status<\/h3>\n<p>Before performing critical operations, UI dApps should check if a channel is ready for verification:<\/p>\n<pre>const channel = manager.findChannelByID(channelId);\r\nif (channel) {\r\n  if (channel.getIsReadyForVerification()) {\r\n    \/\/ Channel's local cache is valid and ready for use\r\n    proceedWithOperation();\r\n  } else {\r\n    \/\/ Channel needs synchronization\r\n    await channel.synchronize();\r\n    if (channel.getIsReadyForVerification()) {\r\n      proceedWithOperation();\r\n    } else {\r\n      \/\/ Still not ready, handle error case\r\n      showError(\"Channel data could not be synchronized\");\r\n    }\r\n  }\r\n}<\/pre>\n<h3>5.6.5. Synchronization and Events<\/h3>\n<p>When synchronization completes, the CStateLessChannelsManager raises appropriate events:<\/p>\n<ul>\n<li>If significant state changes occurred, onChannelNewState will be triggered<\/li>\n<\/ul>\n<p>UI dApps can react to these events to update their display:<\/p>\n<pre>\/\/ Register for state changes\r\nmanager.addStateChannelNewStateListener(this.handleChannelStateChange.bind(this), this.mID);\r\n\r\n\/\/ Handle state changes, including those from synchronization\r\nasync handleChannelStateChange(event) {\r\n  const channel = event.channel;\r\n  const newState = event.newState;\r\n  \r\n  \/\/ Update UI with new state information\r\n  this.updateBalanceDisplay(channel.getID(), newState.availableAssets);\r\n  this.updateSpendableDisplay(channel.getID(), newState.spendableAssets);\r\n}<\/pre>\n<h3>5.6.6. Best Practices<\/h3>\n<ul>\n<li>Responsive Synchronization: Trigger synchronization in response to user actions that will use channel data<\/li>\n<li>Avoid Over-Synchronization: Don&#8217;t synchronize on every UI update; rely on the automatic process and only manually sync before critical operations<\/li>\n<li>Graceful Degradation: Handle failed synchronization attempts gracefully, possibly by retrying once and then displaying appropriate error messages<\/li>\n<li>UI Feedback: Show synchronization status to users during critical operations to set expectations around timing<\/li>\n<li>Cached Data Awareness: Clearly distinguish in the UI between data known to be current and potentially stale data<\/li>\n<\/ul>\n<p>By applying these synchronization strategies, UI dApps can ensure they operate with the most up-to-date Token Pool state while minimizing unnecessary network traffic and providing a responsive user experience.<\/p>\n<hr \/>\n<h3>6. Under the Hood: GridScript and VM Meta-Data Protocol<\/h3>\n<p>While UI dApp developers primarily interact with the high-level <code>CStateLessChannelsManager<\/code> and <code>CStateLessChannel<\/code> JavaScript APIs, these APIs act as wrappers around lower-level system interactions involving #GridScript commands, the VM Meta-Data exchange protocol, and the Decentralized File System (DFS). Understanding this underlying flow provides deeper insight into the system&#8217;s operation.<\/p>\n<h3>6.1. Mapping JS API to GridScript<\/h3>\n<p>Many key operations initiated through the JavaScript API translate directly into specific #GridScript commands executed by GRIDNET Core nodes on the DSM. The <code>CVMContext<\/code> and <code>CStateLessChannelsManager<\/code> handle the formulation and dispatch of these commands.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669081 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/gridscript.png\" alt=\"\" width=\"1226\" height=\"1114\" \/><\/p>\n<ul>\n<li>\n<h3><code>CStateLessChannel.cashOut(token, awardeeID)<\/code> -&gt; <code>xTTEx<\/code> command:<\/h3>\n<ul>\n<li>When a dApp calls <code>cashOut()<\/code>, the <code>CStateLessChannel<\/code> object (often via the Manager) prepares the necessary parameters (the BER-encoded <code>CTransmissionToken<\/code> data and the <code>awardeeID<\/code>).<\/li>\n<li>These parameters are pushed onto the #GridScript stack.<\/li>\n<li>The <code>xTTEx<\/code> command is invoked within a transaction context (<code>BT<\/code>\/<code>CT<\/code>).<\/li>\n<li>The Core node executes <code>xTTEx<\/code>, which performs the on-chain validation, updates the Token Pool state on DFS, and adjusts the awardee&#8217;s balance on the DSM.<\/li>\n<li><em>User-friendly wrapper:<\/em> The <code>xtt<\/code> command in the Terminal Interface acts as an inline parameter wrapper for <code>xTTEx<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>CStateLessChannel.synchronize()<\/code> -&gt; <code>getPoolEx<\/code> command (via <code>getPool<\/code> wrapper):<\/h3>\n<ul>\n<li>Calling <code>synchronize()<\/code> triggers a request to fetch the latest Token Pool data.<\/li>\n<li>Internally, this results in the <code>getPoolEx<\/code> #GridScript command being executed on a Core node. The Token Pool ID is pushed onto the stack first.<\/li>\n<li><code>getPoolEx<\/code> reads the corresponding <code>.pool<\/code> file from DFS.<\/li>\n<li>The result (the BER-encoded pool data or an error\/null indicator) is packaged into a VM Meta-Data message and sent back to the originating <code>CVMContext<\/code>.<\/li>\n<li><em>User-friendly wrapper:<\/em> The <code>getPool<\/code> command in the Terminal Interface acts as an inline parameter wrapper for <code>getPoolEx<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Mobile App QR Intent for Pool Creation -&gt; <code>genPoolEx<\/code> command:<\/h3>\n<ul>\n<li>The process initiated by a UI dApp to create a pool results in a QR Intent containing specific VM Meta-Data for the Mobile App.<\/li>\n<li>The Mobile App securely generates the (disarmed) Token Pool data.<\/li>\n<li>This data is returned to the Core Node serving the user&#8217;s session.<\/li>\n<li>To register this pool on-chain, a transaction containing the <code>genPoolEx<\/code> command is ultimately created. The necessary parameters (owner ID, receipt ID, pool parameters, <em>disarmed<\/em> pool data) are pushed onto the stack before <code>genPoolEx<\/code> is called.<\/li>\n<li><code>genPoolEx<\/code> validates the parameters and writes the pool data to the appropriate DFS location.<\/li>\n<li><em>User-friendly wrapper:<\/em> The <code>genpool<\/code> command handles parsing inline parameters and invoking <code>genPoolEx<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Parameter Passing Mechanisms:<\/h3>\n<ul>\n<li>\n<h3>Stack-based:<\/h3>\n<p>Core #GridScript functions (often suffixed with <code>Ex<\/code>) typically expect parameters to be pushed onto the data stack in a specific order before they are invoked, similar to traditional Forth. The JavaScript APIs handle this internally.<\/li>\n<li>\n<h3>Inline Parameters:<\/h3>\n<p>For user convenience in the Terminal Interface, many commands have wrappers (like <code>xtt<\/code>, <code>getPool<\/code>, <code>genpool<\/code>) that accept parameters directly on the command line (e.g., <code>xtt -t &lt;token&gt; -r &lt;rewardee&gt;<\/code>). These wrappers parse the inline arguments and push them correctly onto the stack before calling their <code>Ex<\/code> counterparts.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>6.2. VM Meta-Data (<code>eVMMetaSectionType.stateLessChannels<\/code>)<\/h3>\n<p>The VM Meta-Data protocol is the primary channel for structured communication between the <code>CVMContext<\/code> (representing the UI environment) and the Core Nodes. State-Less Channels have a dedicated section type.<\/p>\n<ul>\n<li>\n<h3>Structure of <code>eVMMetaEntryType.StateLessChannelsElement<\/code>:<\/h3>\n<p>When a Core Node needs to send channel-related data <em>to<\/em> the UI (e.g., an incoming TT, a response to <code>getPoolEx<\/code>), it packages it within a VM Meta-Data message using:<\/p>\n<ul>\n<li>\n<h3>Section Type:<\/h3>\n<p><code>eVMMetaSectionType.stateLessChannels<\/code><\/li>\n<li>\n<h3>Entry Type:<\/h3>\n<p><code>eVMMetaEntryType.StateLessChannelsElement<\/code><\/li>\n<li>\n<h3>Entry Data Fields:<\/h3>\n<p>Typically contains:<\/p>\n<ol>\n<li><code>elementType<\/code> (<code>eStateLessChannelsElementType<\/code> enum): Specifies the type of payload.<\/li>\n<li><code>name<\/code> (ArrayBuffer\/String): Often the Token Pool ID or a related identifier.<\/li>\n<li><code>data<\/code> (ArrayBuffer): The BER-encoded payload (e.g., the <code>CTransmissionToken<\/code> or <code>CTokenPool<\/code> data).<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Element Types (<code>eStateLessChannelsElementType<\/code>):<\/h3>\n<p>The <code>elementType<\/code> field distinguishes the payload:<\/p>\n<ul>\n<li><code>token<\/code>: Contains BER-encoded <code>CTransmissionToken<\/code> data representing a payment\/reward.<\/li>\n<li><code>tokenPool<\/code>: Contains BER-encoded <code>CTokenPool<\/code> data (usually a response to <code>getPoolEx<\/code>).<\/li>\n<li><code>transitPool<\/code>: <em>Conceptual.<\/em> While defined, direct transmission of an aggregated &#8220;Transit Pool&#8221; structure is less common; cash-out typically uses the latest <code>token<\/code>. Events related to successful cash-out might use this type or <code>receipt<\/code>.<\/li>\n<li><code>receipt<\/code>: Contains information about a finalized on-chain transaction related to a channel operation (e.g., a cash-out receipt).<\/li>\n<li><code>bankUpdate<\/code>: Contains BER-encoded <code>CTransmissionToken<\/code> data specifically flagged as a bank update from the owner (via Mobile App), used to reveal more spendable assets for an Outgress channel.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>How <code>CVMContext<\/code> Routes Data:<\/h3>\n<ol>\n<li><code>CVMContext<\/code> receives a VM Meta-Data message from a Core Node.<\/li>\n<li>It parses the message and identifies sections\/entries.<\/li>\n<li>If it finds a section of type <code>stateLessChannels<\/code>, it iterates through its <code>StateLessChannelsElement<\/code> entries.<\/li>\n<li>It dispatches a generic <code>newVMMetaData<\/code> event containing the raw <code>metaMsg<\/code>.<\/li>\n<li>The <code>CStateLessChannelsManager<\/code>, subscribed to this event via <code>newVMMetaDataCallback<\/code>, receives the <code>metaMsg<\/code>.<\/li>\n<li>The Manager specifically looks for the <code>stateLessChannels<\/code> section, extracts the <code>elementType<\/code> and BER-encoded <code>data<\/code> from relevant entries.<\/li>\n<li>It deserializes the <code>data<\/code> into the appropriate JavaScript object (<code>CTokenPool<\/code>, <code>CTransmissionToken<\/code>).<\/li>\n<li>It then processes this object internally (e.g., finds the target <code>CStateLessChannel<\/code>) and raises the specific, higher-level API events (e.g., <code>onTT<\/code>, <code>onNewTokenPool<\/code>) for subscribed UI dApps.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<h3>6.3. Decentralized File System (DFS) Interaction<\/h3>\n<p>The DFS provides persistent, replicated storage essential for the State-Less Channels system.<\/p>\n<ul>\n<li>\n<h3>Storing Token Pools:<\/h3>\n<p>The public data of a Multi-Dimensional Token Pool, once generated and committed via <code>genPoolEx<\/code>, is stored as a regular file within the owner&#8217;s State Domain on the DFS. Conventionally, these files have a <code>.pool<\/code> extension and reside in a <code>TokenPools<\/code> subdirectory (e.g., <code>\/OwnerID\/TokenPools\/PoolID.pool<\/code>).<\/li>\n<li>\n<h3>Discovery (<code>doCD<\/code>):<\/h3>\n<p>The <code>CStateLessChannelsManager<\/code> uses the <code>doCD<\/code> DFS command (sent via <code>CVMContext<\/code>) to list the contents of an owner&#8217;s <code>\/TokenPools\/<\/code> directory. This is how it discovers the IDs (filenames) of pools belonging to a specific agent during the <code>syncAgentChannels<\/code> process.<\/li>\n<li>\n<h3>Retrieval (<code>doGetFile<\/code>):<\/h3>\n<p>Once a pool&#8217;s filename (ID) is known (either from discovery or because the dApp already knew it), the Manager or <code>CStateLessChannel<\/code> triggers a <code>doGetFile<\/code> DFS command (via <code>CVMContext<\/code>) to retrieve the file&#8217;s content.<\/li>\n<li>\n<h3>How <code>CVMContext<\/code> Routes DFS Data:<\/h3>\n<ol>\n<li><code>CVMContext<\/code> receives a DFS message response (e.g., directory listing from <code>doCD<\/code>, file content from <code>doGetFile<\/code>) from a Core Node.<\/li>\n<li>It dispatches a generic <code>newDFSMsg<\/code> event containing the <code>dfsMsg<\/code> object. Note that DFS file content responses often embed the content within a VM Meta-Data structure <em>inside<\/em> the DFS message&#8217;s <code>Data1<\/code> field.<\/li>\n<li>The <code>CStateLessChannelsManager<\/code>, subscribed via <code>newDFSMsgCallback<\/code>, receives the <code>dfsMsg<\/code>.<\/li>\n<li>It checks if the request ID matches one it initiated (<code>hasDFSRequestID<\/code>).<\/li>\n<li>It parses the message type. If it&#8217;s a directory listing, it might queue <code>doGetFile<\/code> requests. If it&#8217;s file content (<code>eDFSElementType.fileContent<\/code>), it parses the embedded VM Meta-Data, extracts the BER-encoded <code>CTokenPool<\/code> data from the appropriate field.<\/li>\n<li>It deserializes the pool data.<\/li>\n<li>It calls its internal <code>onTokenPoolReceived<\/code> method, which finds\/updates the relevant <code>CStateLessChannel<\/code> and raises events for UI dApps.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<hr \/>\n<h3>7. Practical Usage &amp; Examples (UI dApp Perspective)<\/h3>\n<p>This section provides practical code examples and outlines common scenarios for UI dApps interacting with the GRIDNET OS State-Less Channels system via the <code>CVMContext<\/code> and <code>CStateLessChannelsManager<\/code>. These examples assume they are running within the context of a class extending <code>CWindow<\/code>, where <code>this.mVMContext<\/code> refers to the <code>CVMContext<\/code> singleton and <code>this.mID<\/code> is the dApp&#8217;s process ID.<\/p>\n<h3>7.1. Setup: Getting the Manager, Subscribing to Events<\/h3>\n<p>Before interacting with channels, your dApp needs access to the manager and should subscribe to relevant events within its initialization logic (e.g., in the constructor or an <code>initialize<\/code> method).<\/p>\n<pre>class MyDApp extends CWindow {\r\n    constructor( \/* ... CWindow params *\/ ) {\r\n        super( \/* ... CWindow params *\/ );\r\n        this.mVMContext = CVMContext.getInstance();\r\n        this.mChannelsManager = this.mVMContext.getChannelsManager;\r\n        this.myChannelListeners = []; \/\/ Keep track of listener IDs for cleanup\r\n\r\n        this.initializeEventListeners();\r\n    }\r\n\r\n    initializeEventListeners() {\r\n        \/\/ Subscribe to new incoming Transmission Tokens\r\n        let listenerIdTT = this.mChannelsManager.addNewTTListener(this.handleNewTT.bind(this), this.mID);\r\n        this.myChannelListeners.push(listenerIdTT);\r\n\r\n        \/\/ Subscribe to channel state changes (e.g., balance updates after sync\/TT validation)\r\n        let listenerIdState = this.mChannelsManager.addStateChannelNewStateListener(this.handleChannelStateChange.bind(this), this.mID);\r\n        this.myChannelListeners.push(listenerIdState);\r\n\r\n        \/\/ Subscribe to cash-out confirmations (optional but recommended)\r\n        let listenerIdReceipt = this.mChannelsManager.addNewReceiptListener(this.handleReceipt.bind(this), this.mID);\r\n        this.myChannelListeners.push(listenerIdReceipt);\r\n\r\n        \/\/ Subscribe to newly managed channels (optional, e.g., for dynamic list updates)\r\n        let listenerIdNewChannel = this.mChannelsManager.addNewStateChannelListener(this.handleNewChannel.bind(this), this.mID);\r\n        this.myChannelListeners.push(listenerIdNewChannel);\r\n    }\r\n\r\n    \/\/ --- Callback Handlers (defined later) ---\r\n    async handleNewTT(event) { \/* ... *\/ }\r\n    async handleChannelStateChange(event) { \/* ... *\/ }\r\n    async handleReceipt(event) { \/* ... *\/ }\r\n    async handleNewChannel(event) { \/* ... *\/ }\r\n\r\n\r\n    closeWindow() {\r\n        \/\/ IMPORTANT: Unregister listeners when the dApp closes to prevent memory leaks\r\n        this.myChannelListeners.forEach(listenerId =&gt; {\r\n            this.mVMContext.unregisterEventListenerByID(listenerId); \/\/ Use CVMContext to unregister\r\n        });\r\n        this.myChannelListeners = [];\r\n        super.closeWindow(); \/\/ Call parent class method\r\n    }\r\n\r\n    \/\/ ... other dApp methods ...\r\n}\r\n<\/pre>\n<h3>7.2. Use Case 1: Receiving Real-time Micropayments (e.g., Game Rewards)<\/h3>\n<p>Your dApp needs to react when a new off-chain payment arrives.<\/p>\n<pre>\/\/ Inside MyDApp class\r\n\r\nasync handleNewTT(event) {\r\n    const token = event.token;\r\n    const isBankUpdate = event.isBankUpdate;\r\n    const poolIdStr = gTools.encodeBase58Check(token.getTokenPoolID());\r\n\r\n    console.log(`Received TT for pool: ${poolIdStr}, Is Bank Update: ${isBankUpdate}`);\r\n\r\n    if (isBankUpdate) {\r\n        \/\/ This is likely for an Outgress channel owned by the user,\r\n        \/\/ updating the spendable balance. React accordingly if needed.\r\n        console.log(\"Bank update received, potentially more funds available to send.\");\r\n        return;\r\n    }\r\n\r\n    \/\/ It's a potential payment\/reward for an Ingress channel\r\n    const channel = this.mChannelsManager.findChannelByID(token.getTokenPoolID());\r\n\r\n    if (!channel) {\r\n        console.warn(`Received TT for unknown channel ${poolIdStr}. Manager will attempt to sync.`);\r\n        \/\/ The manager might automatically create the channel object later\r\n        \/\/ after fetching pool data via DFS triggered by the unknown TT.\r\n        return;\r\n    }\r\n\r\n    if (channel.getIsOutgress) {\r\n        console.log(`Ignoring TT for Outgress channel ${poolIdStr} (likely sent by this user).`);\r\n        return; \/\/ Usually not interested in tokens you generated yourself\r\n    }\r\n\r\n    \/\/ --- Validate without immediately updating the channel's core state ---\r\n    \/\/ This tells you the value of *this specific token*, assuming it's valid\r\n    \/\/ relative to the *currently cached* pool state.\r\n    const newlyReceivedValue = await channel.validateTT(token, false); \/\/ false = don't update state yet\r\n\r\n    if (newlyReceivedValue &gt; 0n) {\r\n        console.log(`Valid TT received representing ${newlyReceivedValue} Atto`);\r\n\r\n        \/\/ --- Now update the channel state with this valid token ---\r\n        \/\/ This marks the token as 'seen' locally for accumulation calculation\r\n        await channel.validateTT(token, true); \/\/ true = update cached state\r\n        channel.setRecentToken = token; \/\/ Store the latest valid token\r\n\r\n        \/\/ --- Get the total potential cash-out value based on the *latest* token ---\r\n        const accumulatedValue = await channel.getAccumulatedValue();\r\n        console.log(`Total accumulated off-chain value for channel ${channel.getFriendlyID || poolIdStr}: ${accumulatedValue} Atto`);\r\n\r\n        \/\/ --- Update your UI ---\r\n        this.updateMyGameScoreDisplay(poolIdStr, accumulatedValue); \/\/ Example UI update function\r\n\r\n    } else if (newlyReceivedValue === 0n) {\r\n        console.warn(`Received TT for channel ${poolIdStr} is invalid or a replay.`);\r\n        \/\/ E.g., Double spend attempt, or hash chain mismatch. Ignore it.\r\n    } else { \/\/ -1n\r\n        console.warn(`Cannot validate TT for channel ${poolIdStr} yet, pool data not ready.`);\r\n        \/\/ Need to wait for channel.synchronize() to complete.\r\n    }\r\n}\r\n\r\nupdateMyGameScoreDisplay(channelId, accumulatedValue) {\r\n    \/\/ Find the UI element representing this channel\/score and update it\r\n    \/\/ Example: document.getElementById(`score_${channelId}`).innerText = `${gTools.attoToGNCStr(accumulatedValue)} GNC`;\r\n    console.log(`UI Update: Channel ${channelId} accumulated ${gTools.attoToGNCStr(accumulatedValue)} GNC`);\r\n}\r\n<\/pre>\n<h3>7.3. Use Case 2: Cashing Out Received Tokens<\/h3>\n<p>When the user wants to convert their accumulated off-chain rewards into on-chain balance.<\/p>\n<pre>\/\/ Inside MyDApp class\r\n\r\nasync cashOutChannel(channelId) {\r\n    const channel = this.mChannelsManager.findChannelByID(channelId);\r\n\r\n    if (!channel) {\r\n        this.showError(\"Channel not found.\");\r\n        return;\r\n    }\r\n\r\n    if (channel.getIsOutgress) {\r\n        this.showError(\"Cannot cash out from an Outgress channel.\");\r\n        return;\r\n    }\r\n\r\n    const latestToken = channel.getRecentToken;\r\n    if (!latestToken) {\r\n        this.showError(\"No valid tokens received to cash out for this channel yet.\");\r\n        return;\r\n    }\r\n\r\n    const accumulatedValue = await channel.getAccumulatedValue();\r\n    if (accumulatedValue &lt;= 0n) {\r\n        this.showError(\"Accumulated value is zero, nothing to cash out.\");\r\n        return;\r\n    }\r\n\r\n    const myDomainID = this.mVMContext.getUserID(); \/\/ Or getUserFullID()\r\n    if (!myDomainID || myDomainID.length === 0) {\r\n        this.showError(\"Cannot cash out: User ID not available. Please log in.\");\r\n        \/\/ Trigger login flow if necessary\r\n        \/\/ this.mVMContext.requestQRLogon();\r\n        return;\r\n    }\r\n\r\n    console.log(`Attempting to cash out ${accumulatedValue} Atto from channel ${channel.getFriendlyID || channelId} to ${myDomainID}`);\r\n    this.showLoadingIndicator(`Cashing out ${gTools.attoToGNCStr(accumulatedValue)} GNC...`);\r\n\r\n    \/\/ Initiate the cash-out process\r\n    const requestSent = channel.cashOut(latestToken, myDomainID, false); \/\/ false = don't auto-commit yet\r\n\r\n    if (!requestSent) {\r\n        this.hideLoadingIndicator();\r\n        this.showError(\"Failed to send cash-out request to the network.\");\r\n    } else {\r\n        console.log(\"Cash-out request queued. Waiting for confirmation via receipt listener or commit.\");\r\n        \/\/ The actual commit might happen later via the Magic Button or another dApp action.\r\n        \/\/ The handleReceipt callback will be triggered upon confirmation.\r\n    }\r\n}\r\n\r\n\/\/ Callback for transaction receipts\r\nasync handleReceipt(event) {\r\n    const receipt = event.receipt;\r\n    \/\/ TODO: Need logic to correlate this receipt specifically to our cash-out transaction.\r\n    \/\/ This might involve checking TX type, involved parties, or matching against\r\n    \/\/ a TX ID stored when cashOut() was called (if the API provided it).\r\n    \/\/ For now, assume any relevant receipt means success\/failure.\r\n    console.log(\"Received a transaction receipt:\", receipt);\r\n    this.hideLoadingIndicator();\r\n    if (receipt.status === 'success') { \/\/ Assuming receipt structure\r\n        this.showMessage(\"Cash-out successful!\");\r\n        \/\/ Optionally, re-sync the channel state or balance after confirmation\r\n        \/\/ this.mVMContext.retrieveBalance(true);\r\n    } else {\r\n        this.showError(`Cash-out failed: ${receipt.errorMessage || 'Unknown error'}`);\r\n    }\r\n}\r\n<\/pre>\n<h3>7.4. Use Case 3: Creating a Token Pool (e.g., for a Game Server\/Service)<\/h3>\n<p>Creating a pool requires an on-chain sacrificial transaction and secure generation using the MasterSeedHash, typically involving the mobile app.<\/p>\n<pre>\/\/ Inside MyDApp class (e.g., an admin panel dApp)\r\n\r\nasync createTokenPool(totalValueGNC, numDimensions, friendlyId = \"\") {\r\n    const totalValueAtto = gTools.GNCToAtto(totalValueGNC); \/\/ Convert GNC to Atto\r\n\r\n    \/\/ 1. Perform the Sacrificial Transaction (Requires separate logic\/UI)\r\n    \/\/ This would involve using CVMContext.processGridScript to send GNC\r\n    \/\/ to a specific system address or using a dedicated 'sacrifice' command.\r\n    \/\/ You need the receipt ID of this transaction.\r\n    const sacrificialReceiptId = await this.performSacrifice(totalValueAtto); \/\/ Placeholder function\r\n    if (!sacrificialReceiptId) {\r\n        this.showError(\"Sacrificial transaction failed.\");\r\n        return;\r\n    }\r\n    console.log(`Sacrifice successful, Receipt ID: ${sacrificialReceiptId}`);\r\n\r\n    \/\/ 2. Prepare the QR Intent for Mobile App Generation\r\n    const ephKeyPair = this.mVMContext.getKeyPair;\r\n    const myOwnerId = this.mVMContext.getUserFullID(); \/\/ Use full ID for ownership\r\n    const valuePerToken = 1n; \/\/ Example: 1 Atto per token\r\n\r\n    \/\/ Create a *template* CTokenPool object (most values are placeholders here)\r\n    \/\/ The mobile app calculates depths and generates hashes based on parameters\r\n    const poolTemplate = new CTokenPool(\r\n        null, \/\/ CryptoFactory not needed here\r\n        numDimensions,\r\n        myOwnerId,\r\n        sacrificialReceiptId, \/\/ Link to the sacrifice\r\n        valuePerToken,\r\n        totalValueAtto,\r\n        0n, \/\/ CurrentIndex (starts at 0)\r\n        friendlyId\r\n        \/\/ Seed\/Final\/Current hashes are generated by mobile app\r\n    );\r\n\r\n    const metaGen = new CVMMetaGenerator();\r\n    \/\/ The addGenTokenPoolRequest prepares the specific VM Meta-Data structure\r\n    \/\/ that tells the mobile app what parameters to use for generation.\r\n    metaGen.addGenTokenPoolRequest(poolTemplate);\r\n\r\n    const qr = new CQRIntent(\r\n        eQRIntentType.QRProcessVMMetaData, \/\/ Instructs mobile app to process the metadata\r\n        this.mVMContext.getConversationID(), \/\/ Target this web session\r\n        this.mVMContext.getFullNodeIP(), \/\/ Route through this node\r\n        eEndpointType.WebSockConversation\r\n    );\r\n    qr.setPubKey(ephKeyPair.public);\r\n    qr.setData(metaGen.getPackedData()); \/\/ Embed the generation request\r\n\r\n    \/\/ Display the QR code to the user\r\n    this.showQRCode(qr); \/\/ Placeholder UI function to display the QR object\r\n    console.log(\"Please scan the QR code with your GRIDNET Token app to generate the Token Pool securely.\");\r\n\r\n    \/\/ 3. Wait for the Response\r\n    \/\/ The mobile app will generate the pool, send the disarmed data back to the Core node,\r\n    \/\/ which sends it via VM Meta-Data to CVMContext -&gt; ChannelsManager.\r\n    \/\/ Your dApp will be notified via the addNewTokenPoolListener \/ addNewStateChannelListener.\r\n    \/\/ The dApp then needs to initiate the *second* transaction (BT... genPoolEx ... CT)\r\n    \/\/ using the received disarmed pool data to register it on-chain.\r\n}\r\n<\/pre>\n<h3>7.5. Use Case 4: Sending Off-Chain Rewards\/Payments (Outgress Channel)<\/h3>\n<p>Using a pool you own to send value to another peer off-chain.<\/p>\n<pre>\/\/ Inside MyDApp class\r\n\r\nasync sendOffChainPayment(poolId, recipientId, valueAtto) {\r\n    const channel = this.mChannelsManager.findChannelByID(poolId);\r\n\r\n    if (!channel) {\r\n        this.showError(`Channel ${poolId} not found or managed.`);\r\n        return;\r\n    }\r\n\r\n    if (!channel.getIsOutgress) {\r\n        this.showError(`Channel ${poolId} is not an Outgress channel you own.`);\r\n        return;\r\n    }\r\n\r\n    if (!channel.getIsReadyForVerification) {\r\n        this.showError(`Channel ${poolId} is not synchronized. Please sync first.`);\r\n        \/\/ await channel.synchronize(); \/\/ Optionally trigger sync\r\n        return;\r\n    }\r\n\r\n    console.log(`Attempting to generate TT for ${valueAtto} Atto to ${recipientId} from pool ${poolId}`);\r\n\r\n    \/\/ Use getTTForPeer for automatic bank management\r\n    const transmissionToken = await channel.getTTForPeer(valueAtto, recipientId, true); \/\/ true = mark as used locally\r\n\r\n    if (!transmissionToken) {\r\n        const spendable = await channel.getLocallySpendableAssets();\r\n        this.showError(`Failed to generate TT. Insufficient funds in available banks or no free banks. Locally Spendable: ${spendable} Atto`);\r\n        \/\/ May need a bank update from mobile app if spendable is low but total valueLeft is high\r\n        return;\r\n    }\r\n\r\n    console.log(\"Transmission Token generated successfully:\", transmissionToken);\r\n\r\n    \/\/ --- Deliver the Transmission Token ---\r\n    \/\/ This part is application-specific and depends on how you communicate with the recipient.\r\n    \/\/ Examples:\r\n    \/\/ 1. Send via WebRTC Swarm:\r\n    \/\/    const swarmId = this.mVMContext.getMainSwarmID(); \/\/ Or another specific swarm\r\n    \/\/    const success = this.mVMContext.getSwarmsManager.sendData(\r\n    \/\/        transmissionToken.getPackedData(),\r\n    \/\/        recipientId, \/\/ Target the specific peer\r\n    \/\/        swarmId\r\n    \/\/    );\r\n    \/\/    if (success) { console.log(\"TT sent via swarm.\"); } else { console.error(\"Failed to send TT via swarm.\"); }\r\n\r\n    \/\/ 2. Send via direct P2P connection (if available)\r\n    \/\/ 3. Send via a centralized intermediary (if applicable to your dApp)\r\n\r\n    this.showSuccess(`Transmission Token for ${valueAtto} Atto generated. Delivery mechanism required.`);\r\n}\r\n<\/pre>\n<h3>7.6. UI Updates based on Channel State<\/h3>\n<p>Keep the UI synchronized with the latest known channel state.<\/p>\n<pre>\/\/ Inside MyDApp class\r\n\r\nasync handleChannelStateChange(event) {\r\n    const channel = event.channel;\r\n    const newState = event.newState;\r\n    \/\/ const previousState = event.previousState; \/\/ Can be used for comparison if needed\r\n\r\n    const poolIdStr = gTools.encodeBase58Check(channel.getID());\r\n    const friendlyId = channel.getFriendlyID() || poolIdStr;\r\n\r\n    console.log(`State change detected for channel: ${friendlyId}`);\r\n\r\n    \/\/ Update UI elements associated with this channel\r\n    this.updateChannelDisplay(poolIdStr, {\r\n        accumulated: newState.accumulatedAssets, \/\/ For ingress channels (potential cash-out value)\r\n        spendable: newState.spendableAssets, \/\/ For outgress channels (what can be sent now)\r\n        availableOnChain: newState.availableAssets \/\/ Total value left according to last sync\/update\r\n    });\r\n}\r\n\r\nupdateChannelDisplay(channelId, stateData) {\r\n    \/\/ Example: Find UI elements and update their content\r\n    const elemAccumulated = document.getElementById(`channel_${channelId}_accumulated`);\r\n    const elemSpendable = document.getElementById(`channel_${channelId}_spendable`);\r\n    const elemAvailable = document.getElementById(`channel_${channelId}_available`);\r\n\r\n    if (elemAccumulated) elemAccumulated.innerText = `${gTools.attoToGNCStr(stateData.accumulated)} GNC`;\r\n    if (elemSpendable) elemSpendable.innerText = `${gTools.attoToGNCStr(stateData.spendable)} GNC`;\r\n    if (elemAvailable) elemAvailable.innerText = `${gTools.attoToGNCStr(stateData.availableOnChain)} GNC`;\r\n}\r\n<\/pre>\n<hr \/>\n<h3>8. Advanced Topics<\/h3>\n<p>This section explores some of the more intricate aspects of the State-Less Channels system, including its underlying security model, error handling, performance characteristics, and security considerations.<\/p>\n<h3>8.1. Sybil-Proofing Mechanics<\/h3>\n<p>A fundamental requirement for any decentralized incentivization system operating in an open network is resistance to Sybil attacks, where a single malicious entity creates numerous fake identities to gain disproportionate influence or rewards.<\/p>\n<p>The GRIDNET OS State-Less Channels system achieves Sybil-proofing primarily through the design of its<\/p>\n<h3>reward function<\/h3>\n<p>and the inherent properties of the<\/p>\n<h3>path assurance protocols<\/h3>\n<p>(PA1, PA2, PA3) used for data propagation, as detailed comprehensively in our research [1].<\/p>\n<ul>\n<li>\n<h3>Key Principles:<\/h3>\n<ul>\n<li>\n<h3>Investment-Based Rewards:<\/h3>\n<p>The core reward mechanism ties potential earnings to the verifiable &#8220;stake&#8221; or investment represented by the value and depth of the Token Pools involved (specifically the <code> ABI<\/code> value used in the identity rating function <code>e<\/code>). Creating numerous low-value Sybil identities to participate in a path yields significantly lower expected rewards compared to using a single, well-funded identity.<\/li>\n<li>\n<h3>Path Integrity:<\/h3>\n<p>The path assurance mechanisms ensure that the sequence of intermediaries recorded in the Transmission Token&#8217;s journey (implicitly or explicitly depending on the protocol variant) cannot be easily tampered with without invalidating cryptographic checks performed during the on-chain cash-out (<code>xTTEx<\/code>).<\/li>\n<li>\n<h3>Reward Function Design:<\/h3>\n<p>The specific mathematical formulation of the reward function <code>FA<\/code> ensures that concentrating investment into a single identity for a given path maximizes potential reward compared to distributing the same total investment across multiple Sybil identities within that same path.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>In Essence:<\/h3>\n<p>While the system cannot <em>prevent<\/em> the creation of Sybil identities at the network level, it makes <em>using<\/em> them within the incentivized State-Less Channel data flows economically irrational for profit-maximizing agents.<\/li>\n<li>\n<h3>Further Reading:<\/h3>\n<p>For a rigorous mathematical proof and detailed breakdown of the algorithms and game-theoretical analysis, please refer to Section 7 (&#8220;Proof of sybil-proofness&#8221;) and Section 6 (&#8220;Reward function&#8221;, &#8220;Routing mechanism&#8221;) of the SPIDE research paper [1].<\/li>\n<\/ul>\n<h3>8.2. Error Handling<\/h3>\n<p>Developers should anticipate potential issues when working with off-chain systems and network interactions.<\/p>\n<ul>\n<li>\n<h3>Invalid Transmission Tokens:<\/h3>\n<ul>\n<li>\n<h3>Cause:<\/h3>\n<p>Malformed data, failed hash chain verification (indicating tampering or an incorrect sequence), invalid signature (on authenticated TTs).<\/li>\n<li>\n<h3>Detection:<\/h3>\n<p>The <code>CStateLessChannel.validateTT()<\/code> method will return <code>0n<\/code>.<\/li>\n<li>\n<h3>Handling:<\/h3>\n<p>The receiving UI dApp should simply discard or ignore invalid tokens. Attempting to cash them out via <code>xTTEx<\/code> will fail on-chain.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Insufficient Funds:<\/h3>\n<ul>\n<li>\n<h3>Sending (Outgress):<\/h3>\n<p><code>channel.getTTForPeer()<\/code> or <code>channel.getTTWorthValue()<\/code> will return <code>null<\/code>. The dApp should check the return value and inform the user. They might need a &#8220;Bank Update&#8221; from their mobile app if sufficient value exists in the pool overall but not in currently pre-cached banks (<code>channel.getLocallySpendableAssets()<\/code> vs. <code>channel.getTokenPool().getValueLeft()<\/code>).<\/li>\n<li>\n<h3>Cashing Out (Ingress):<\/h3>\n<p>If a recipient tries to cash out a token representing more value than <em>currently<\/em> available in the bank <em>on-chain<\/em> (e.g., due to a race condition or delay in state update), the <code>xTTEx<\/code> command will fail during DSM execution.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Double Spends \/ Replays:<\/h3>\n<ul>\n<li>\n<h3>Off-Chain:<\/h3>\n<p><code>channel.validateTT()<\/code> will return <code>0n<\/code> if the incoming token&#8217;s <code>bankUsageDepth<\/code> is less than or equal to the currently cached depth for that bank.<\/li>\n<li>\n<h3>On-Chain:<\/h3>\n<p>The <code>xTTEx<\/code> command inherently prevents double-spending by verifying the token&#8217;s <code>bankUsageDepth<\/code> against the authoritative state stored on the DSM. Any attempt to cash out a token representing already spent depth will be rejected by consensus.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Network Issues &amp; Timeouts:<\/h3>\n<ul>\n<li>Requests sent via <code>CVMContext<\/code> (e.g., for <code>synchronize()<\/code> or <code>cashOut()<\/code>) involve network communication and may fail or time out.<\/li>\n<li>\n<h3>Handling:<\/h3>\n<p>JavaScript Promises returned by async API calls will reject. Methods returning simple success indicators (like <code>synchronize()<\/code>) will return <code>false<\/code>. UI dApps must implement standard error handling (<code>try...catch<\/code> for async\/await, checking return values) and potentially implement retry logic or inform the user.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Synchronization Issues (Stale Cache):<\/h3>\n<ul>\n<li>\n<h3>Cause:<\/h3>\n<p>The local <code>CTokenPool<\/code> cache within a <code>CStateLessChannel<\/code> might not reflect the absolute latest on-chain state if a cash-out occurred recently but the channel hasn&#8217;t been synced.<\/li>\n<li>\n<h3>Effect:<\/h3>\n<p><code>validateTT()<\/code> might incorrectly validate a token that <em>would<\/em> be rejected on-chain, or <code>getAccumulatedValue()<\/code> might report a higher value than actually cashable. <code>getTTForPeer()<\/code> might fail even if funds <em>were<\/em> available on-chain.<\/li>\n<li>\n<h3>Mitigation:<\/h3>\n<p>Use <code>getIsReadyForVerification<\/code> to ensure initial data is loaded. Call <code>channel.synchronize()<\/code> periodically or before critical operations, especially cash-outs, if high accuracy is required. The <code>CStateLessChannelsManager<\/code> performs periodic background synchronization.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>8.3. Performance and Scalability Considerations<\/h3>\n<p>The State-Less Channels system is designed for high performance and scalability compared to pure on-chain transactions.<\/p>\n<ul>\n<li>\n<h3>Off-Chain Speed:<\/h3>\n<p>Transmission Token validation (<code>validateTT<\/code>) and generation (<code>getTT...<\/code>) are purely local cryptographic operations (primarily hashing) and are extremely fast. The main latency is network delivery time between peers.<\/li>\n<li>\n<h3>On-Chain Bottlenecks:<\/h3>\n<p>The primary performance limitations are the frequency and cost of on-chain operations:<\/p>\n<ul>\n<li><em>Token Pool Creation (<code>genPoolEx<\/code>):<\/em> A one-time cost per pool, involving writing data to DFS.<\/li>\n<li><em>Cashing Out (<code>xTTEx<\/code>):<\/em> Requires an on-chain transaction, consuming ERG and subject to DSM throughput (TPS).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Optimizations:<\/h3>\n<ul>\n<li>\n<h3>Batching Cash-Outs:<\/h3>\n<p>Recipients are incentivized to delay cashing out until a significant value is accumulated or the channel dimension is nearly depleted, reducing the frequency of on-chain transactions.<\/li>\n<li>\n<h3>Multi-Dimensionality:<\/h3>\n<p>Allows many parallel off-chain streams using a single pool, significantly increasing the <em>effective<\/em> off-chain TPS supported by a single on-chain pool registration.<\/li>\n<li>\n<h3>State-Less Design:<\/h3>\n<p>Reduces the need for constant peer-to-peer state synchronization messages compared to some other channel designs.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Developer Considerations:<\/h3>\n<p>Design dApps to minimize unnecessary cash-outs. Choose an appropriate number of dimensions for M-DTPs based on expected concurrent interactions. Rely on the Manager&#8217;s autonomous features where possible.<\/li>\n<\/ul>\n<h3>8.4. Security<\/h3>\n<p>Security relies on a combination of cryptographic primitives, consensus rules, and operational security practices.<\/p>\n<ul>\n<li>\n<h3>Mobile App Trust:<\/h3>\n<p>The GRIDNET Token mobile app is the primary custodian of the user&#8217;s private keys and the critical MasterSeedHash for owned Token Pools. Its security is paramount. Compromise of the mobile app could lead to the loss of funds secured by M-DTPs generated from its MasterSeedHash.<\/li>\n<li>\n<h3>QR Intent Security:<\/h3>\n<p>While QR codes themselves are just data, the <em>process<\/em> involving them is designed for security. Sensitive operations initiated via QR require confirmation and cryptographic signing <em>within<\/em> the secure mobile app environment <em>after<\/em> the QR is scanned. The response from the mobile app back to the Core node is typically onion-routed and end-to-end encrypted.<\/li>\n<li>\n<h3>Signature Verification:<\/h3>\n<ul>\n<li><em>Authenticated TTs:<\/em> Provide non-repudiation and proof of origin from the pool owner. The signature is verified against the pool&#8217;s public key (if available\/published). <code>xTTEx<\/code> on-chain performs this verification if a signature is present.<\/li>\n<li><em>Unauthenticated TTs:<\/em> Rely solely on the hash chain math and the DSM&#8217;s state tracking for validity regarding <em>value<\/em> and <em>double-spending<\/em>. They do not cryptographically prove origin from the pool owner.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Hash Chain Integrity:<\/h3>\n<p>The security against fabricating tokens relies on the pre-image resistance and collision resistance of the underlying cryptographic hash function (e.g., SHA256).<\/li>\n<li>\n<h3>DSM Consensus:<\/h3>\n<p>The ultimate security against on-chain double-spending and invalid state transitions relies on the integrity and Sybil-resistance of the underlying GRIDNET OS consensus mechanism.<\/li>\n<li>\n<h3>Full Node Honesty:<\/h3>\n<p>For <em>unauthenticated<\/em> TTs, there&#8217;s a theoretical risk: if a malicious node (e.g., the one serving the recipient&#8217;s session) intercepts an unauthenticated TT <em>before<\/em> the legitimate recipient caches it out, <em>and<\/em> that node knows the recipient&#8217;s ID, it <em>could<\/em> attempt to cash it out to itself first. Using authenticated TTs or ensuring prompt cash-out by the recipient mitigates this specific, more complex attack vector. Standard TTs used for payments between distinct parties are usually unauthenticated for efficiency. Bank Updates <em>must<\/em> be authenticated.<\/li>\n<\/ul>\n<hr \/>\n<h3>9. Appendices<\/h3>\n<h3>9.1. Glossary<\/h3>\n<ul>\n<li>\n<h3>Atto:<\/h3>\n<p>The smallest indivisible unit of GRIDNET&#8217;s native currency (GBU). Used for precise value representation in Token Pools.<\/li>\n<li>\n<h3>Bank (Dimension):<\/h3>\n<p>An independent hash chain within a Multi-Dimensional Token Pool, used to manage a distinct off-chain payment stream.<\/li>\n<li>\n<h3>Cash Out:<\/h3>\n<p>The on-chain process of redeeming the value represented by off-chain Transmission Tokens, resulting in an update to the recipient&#8217;s on-chain GBU balance and the Token Pool&#8217;s state on the DSM.<\/li>\n<li>\n<h3>Ceiling Hash (Final Hash):<\/h3>\n<p>The final, publicly known hash value anchoring a specific Bank&#8217;s hash chain within a Token Pool, stored on the DSM.<\/li>\n<li>\n<h3>CStateLessChannel:<\/h3>\n<p>The JavaScript class representing a single State-Less Channel instance within the UI dApp environment, managing interaction with a specific Token Pool.<\/li>\n<li>\n<h3>CStateLessChannelsManager:<\/h3>\n<p>The JavaScript singleton class managing all State-Less Channel instances, handling events, synchronization, and autonomous operations within the UI dApp environment.<\/li>\n<li>\n<h3>CVMContext:<\/h3>\n<p>The central JavaScript singleton acting as the gateway between UI dApps and the underlying GRIDNET OS functionalities.<\/li>\n<li>\n<h3>DFS (Decentralized File System):<\/h3>\n<p>GRIDNET OS&#8217;s integrated, decentralized storage layer where Token Pool data files are stored.<\/li>\n<li>\n<h3>DPT (Decentralized Processing Thread):<\/h3>\n<p>An execution context within GRIDNET OS, associated with an IVR, responsible for running code (#GridScript).<\/li>\n<li>\n<h3>DSM (Decentralized State Machine):<\/h3>\n<p>The core consensus-driven engine of GRIDNET OS, responsible for processing transactions and maintaining the global state, including Token Pool data stored on DFS.<\/li>\n<li>\n<h3>GBU (GRIDNET Basic Unit):<\/h3>\n<p>The primary native currency\/asset of the GRIDNET OS ecosystem.<\/li>\n<li>\n<h3>GridScript:<\/h3>\n<p>The specialized, Forth-like programming language used by GRIDNET Core nodes and DPTs to execute instructions and interact with the DSM.<\/li>\n<li>\n<h3>IVR (Isolated VM Realm):<\/h3>\n<p>A sandboxed execution environment associated with a DPT, operating on a copy of the System Trie (Private VM Realm) or directly affecting the main state (Global VM Realm in Commitment Mode).<\/li>\n<li>\n<h3>M-DTP (Multi-Dimensional Token Pool):<\/h3>\n<p>The core data structure for State-Less Channels, registered on-chain, containing multiple independent hash chains (Banks\/Dimensions) derived from a single MasterSeedHash, representing a pre-funded store of value for off-chain payments.<\/li>\n<li>\n<h3>MasterSeedHash:<\/h3>\n<p>The high-entropy secret held by the Token Pool owner (usually in the Mobile App), used to generate all hashes (tokens) within all dimensions of an M-DTP.<\/p>\n<h3>Must be kept secret.<\/h3>\n<\/li>\n<li>\n<h3>Receipt ID:<\/h3>\n<p>The unique identifier of an on-chain transaction (e.g., the sacrificial transaction used to fund a Token Pool).<\/li>\n<li>\n<h3>Sacrificial Transaction:<\/h3>\n<p>An on-chain transaction where the sender locks value, the receipt of which is then used to authorize the creation of a Token Pool of equivalent value.<\/li>\n<li>\n<h3>SeedHash (Dimension Seed Hash):<\/h3>\n<p>The starting secret hash for a specific Bank\/Dimension&#8217;s hash chain, deterministically derived from the MasterSeedHash.<\/li>\n<li>\n<h3>State-Less Channel:<\/h3>\n<p>The logical off-chain payment channel facilitated by an M-DTP and the exchange of TTs, minimizing peer-to-peer state synchronization requirements during the off-chain phase.<\/li>\n<li>\n<h3>TT (Transmission Token):<\/h3>\n<p>The data structure (<code>CTransmissionToken<\/code> object) exchanged off-chain, representing a specific amount of value released from a specific Bank of an M-DTP. It contains the revealed hash and updated bank state information needed for verification and eventual cash-out.<\/li>\n<li>\n<h3>Transit Pool:<\/h3>\n<p>A conceptual term referring to the accumulated off-chain value represented by a sequence of TTs for a single bank since the last on-chain cash-out. Usually, only the <em>latest<\/em> TT is needed to represent the entire Transit Pool when cashing out.<\/li>\n<li>\n<h3>Usage Depth:<\/h3>\n<p>An integer value stored on-chain for each Bank, indicating how many tokens (hashes) have been successfully revealed and cashed out from that Bank&#8217;s hash chain. This prevents double-spending.<\/li>\n<\/ul>\n<h3>9.2. Enum Definitions (JavaScript)<\/h3>\n<p>These enums define constants used within the State-Less Channels API:<\/p>\n<ul>\n<li>\n<h3><code>eChannelDirection<\/code><\/h3>\n<p>: Defines the perspective of a channel relative to the local user.<\/p>\n<ul>\n<li><code>ingress<\/code>: The local user is the recipient of funds via this channel.<\/li>\n<li><code>outgress<\/code>: The local user owns the pool and sends funds via this channel.<\/li>\n<li><code>both<\/code>: Used for filtering, not typically assigned to a channel instance.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>eTokenPoolStatus<\/code><\/h3>\n<p>: Overall status of a Multi-Dimensional Token Pool.<\/p>\n<ul>\n<li><code>active<\/code>: The pool is operational and has spendable value.<\/li>\n<li><code>depleted<\/code>: All dimensions\/banks within the pool have been fully cashed out on-chain.<\/li>\n<li><code>banned<\/code>: The pool has been marked as invalid or banned by the system (e.g., due to detected fraud).<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>eTokenPoolBankStatus<\/code><\/h3>\n<p>: Status of an individual dimension\/bank within a Token Pool.<\/p>\n<ul>\n<li><code>active<\/code>: The bank has unspent tokens.<\/li>\n<li><code>depleted<\/code>: All tokens in this specific bank have been cashed out on-chain.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>eStateLessChannelsElementType<\/code><\/h3>\n<p>: Used within the VM Meta-Data protocol to identify the type of channel-related payload.<\/p>\n<ul>\n<li><code>token<\/code>: Payload is a <code>CTransmissionToken<\/code> representing a standard payment\/reward.<\/li>\n<li><code>tokenPool<\/code>: Payload is a <code>CTokenPool<\/code> object&#8217;s public data.<\/li>\n<li><code>transitPool<\/code>: (See Glossary\/API clarification).<\/li>\n<li><code>receipt<\/code>: Payload contains details of an on-chain transaction receipt related to a channel operation.<\/li>\n<li><code>bankUpdate<\/code>: Payload is a <code>CTransmissionToken<\/code> specifically flagged as revealing pre-cached hashes for an Outgress channel.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>eChannelLocalPingType<\/code><\/h3>\n<p>: Used internally by <code>CStateLessChannel.ping()<\/code> to specify which timestamp to update.<\/p>\n<ul>\n<li><code>update<\/code>: General update timestamp.<\/li>\n<li><code>lastUsed<\/code>: Timestamp for when a TT was generated from the channel.<\/li>\n<li><code>lastSync<\/code>: Timestamp for when <code>synchronize()<\/code> was last initiated.<\/li>\n<li><code>lastCashOut<\/code>: Timestamp for when <code>cashOut()<\/code> was last initiated.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>9.3. Relevant GridScript Commands<\/h3>\n<p>These are the low-level commands executed by the DSM, typically invoked via the JavaScript API wrappers:<\/p>\n<ul>\n<li>\n<h3><code>genPoolEx<\/code>:<\/h3>\n<p>(Requires parameters on stack: OwnerID, ReceiptID, DimensionsCount, TokenValue, FriendlyID, DisarmedPoolData) Registers a new, pre-generated (disarmed) Multi-Dimensional Token Pool on the DFS, validating it against the provided sacrificial transaction receipt.<\/p>\n<ul>\n<li><em>Wrapper:<\/em> <code>genpool<\/code> (accepts inline parameters)<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>xTTEx<\/code>:<\/h3>\n<p>(Requires parameters on stack: BER-encoded Transmission Token, optional RewardeeID) Processes an off-chain Transmission Token for on-chain cash-out. Verifies the token against the Token Pool state on DFS, updates the bank&#8217;s usage depth, and credits the rewardee&#8217;s on-chain balance.<\/p>\n<ul>\n<li><em>Wrapper:<\/em> <code>xtt<\/code> (accepts inline parameters)<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3><code>getPoolEx<\/code>:<\/h3>\n<p>(Requires TokenPool ID on stack) Retrieves the BER-encoded public data of a specified Token Pool from the DFS.<\/p>\n<ul>\n<li><em>Wrapper:<\/em> <code>getPool<\/code> (accepts inline parameters)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>9.4. Links<\/h3>\n<ul>\n<li>\n<h3>Research Papers:<\/h3>\n<ul>\n<li>Skowro\u0144ski, R.; Brzezi\u0144ski, J. SPIDE: Sybil-proof, incentivized data exchange. <em>Clust. Comput.<\/em><br \/>\n<h3>2022<\/h3>\n<p>, <em>25<\/em>, 2241\u20132270. DOI:10.1007\/s10586-021-03411-3. Available online: <a href=\"https:\/\/www.researchgate.net\/publication\/356419641_SPIDE_sybil-proof_incentivized_data_exchange\">https:\/\/www.researchgate.net\/publication\/356419641_SPIDE_sybil-proof_incentivized_data_exchange<\/a> (accessed [Date])<\/li>\n<li>Skowro\u0144ski, R.; Brzezi\u0144ski, J. UI dApps Meet Decentralized Operating Systems. <em>Electronics<\/em><br \/>\n<h3>2022<\/h3>\n<p>, <em>11<\/em>, 3004. DOI:10.3390\/electronics11193004. Available online: <a href=\"https:\/\/www.mdpi.com\/2079-9292\/11\/19\/3004\">https:\/\/www.mdpi.com\/2079-9292\/11\/19\/3004<\/a> (accessed [Date])<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Code Examples:<\/h3>\n<ul>\n<li>\n<h3>Wallet UI dApp:<\/h3>\n<p>[Link to GRIDNET OS GitHub Repository &#8211; Wallet dApp source] (Requires specific link once available) &#8211; Demonstrates receiving tokens, displaying accumulated value, and initiating cash-outs.<\/li>\n<li>\n<h3>GridCraft &#8211; Illustrates how Transmission Tokens can be used to reward players for collecting dynamic Gold Veins in the ground.<\/h3>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Tutorials:<\/h3>\n<ul>\n<li>\n<h3>GRIDNET OS Magazine &#8211; #GridScript Basics and Micropayments:<\/h3>\n<p><a href=\"https:\/\/gridnet.org\/wpp\/index.php\/2021\/06\/11\/gridscript-basics-and-micropayments-from-the-users-perspective\/\">https:\/\/gridnet.org\/wpp\/index.php\/2021\/06\/11\/gridscript-basics-and-micropayments-from-the-users-perspective\/<\/a> (Provides practical Terminal examples related to pool creation and cashing out).<\/li>\n<li>\n<h3>GRIDNET OS UI dApp Development Tutorial:<\/h3>\n<p>[Link to Tutorial] (Placeholder &#8211; A comprehensive tutorial covering dApp setup, CVMContext usage, and potentially basic channel interaction).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr \/>\n<h3>10. GRIDNET OS State-Less Channels Security Threat Model<\/h3>\n<p>This comprehensive security threat model analyzes the GRIDNET OS State-Less Channels system, focusing on its security architecture, potential attack vectors, and defensive mechanisms. The system employs multiple layers of security through cryptographic primitives, compartmentalization, and verification protocols to protect off-chain transactions.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669222 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/thread-model-overview.png\" alt=\"\" width=\"991\" height=\"863\" \/><\/p>\n<h3>10.1. Trust Boundaries &amp; Security Zones<\/h3>\n<p>As illustrated in the first diagram, the system is divided into three distinct security zones:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669225 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/security-zones.png\" alt=\"\" width=\"1197\" height=\"969\" \/><\/p>\n<h3>High Security Zone (Mobile App)<\/h3>\n<ul>\n<li>Contains the most sensitive cryptographic material: MasterSeedHash and Dimension Seeds<\/li>\n<li>Hardware-backed secure storage for private keys<\/li>\n<li>Limited interface with other zones through controlled channels (QR Intents)<\/li>\n<\/ul>\n<h3>Medium Security Zone (Browser\/UI dApp)<\/h3>\n<ul>\n<li>Receives only the necessary subset of hash tokens via Bank Updates<\/li>\n<li>Maintains local cache of pool state (public metadata and limited revealed hashes)<\/li>\n<li>Shadow DOM isolation for UI components<\/li>\n<\/ul>\n<h3>Public Zone (Blockchain\/DSM)<\/h3>\n<ul>\n<li>Only contains fully public data: ceiling hashes, bank usage depths, pool metadata<\/li>\n<li>Provides consensus validation for cash-out operations<\/li>\n<\/ul>\n<p>The security architecture enforces strict information flow between zones, with higher security zones only revealing controlled subsets of data to lower security zones.<\/p>\n<h3>10.2. Reverse Hash Chain Security Model<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669229 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/hash-chain-2.png\" alt=\"\" width=\"1224\" height=\"951\" \/><\/p>\n<p>A core security mechanism in the system is the reverse hash chain:<\/p>\n<ul>\n<li>During pool creation, a sequence of hashes is generated in one direction:<br \/>\nHash_0 (Seed) \u2192 Hash_1 \u2192 Hash_2 \u2192 &#8230; \u2192 Hash_N (Final\/Ceiling)<\/li>\n<li>Only the Final Hash (Hash_N) is published publicly on the blockchain<\/li>\n<li>For spending, hashes are revealed in reverse order (N-1, N-2, etc.)<\/li>\n<\/ul>\n<p>The security property that makes this work is the one-way nature of cryptographic hash functions: given Hash_i, it&#8217;s computationally infeasible to derive Hash_{i-1}. This means:<\/p>\n<ul>\n<li>Revealing Hash_i does NOT compromise Hash_{i-1}<\/li>\n<li>Early hashes in the chain maintain their secrecy even as later hashes are revealed<\/li>\n<li>Each revealed hash can be verified against the public ceiling hash<\/li>\n<\/ul>\n<p>This enables secure, off-chain value transfer with on-chain anchoring.<\/p>\n<h3>10.3. Token Pool Compartmentalization<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669232 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/token-pool-compartmentation.png\" alt=\"\" width=\"1189\" height=\"949\" \/><\/p>\n<p>The system further enhances security through Multi-Dimensional Token Pools (M-DTPs):<\/p>\n<ul>\n<li>Each pool has multiple independent banks\/dimensions<\/li>\n<li>Each bank has its own separate hash chain derived from the MasterSeedHash<\/li>\n<li>The mobile app controls precisely which hash segments from which banks are revealed<\/li>\n<li>UI dApp is only given access to specific hash segments needed for current operations<\/li>\n<\/ul>\n<p>This compartmentalization ensures that:<\/p>\n<ul>\n<li>Compromise of one bank doesn&#8217;t affect others<\/li>\n<li>Only a limited subset of value is exposed to the medium-security browser environment<\/li>\n<li>The browser environment never has access to the MasterSeedHash or dimension seeds<\/li>\n<li>Risk is isolated to specific revealed hash segments<\/li>\n<\/ul>\n<h3>10.4. Attack Vectors &amp; Threat Analysis<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669235 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/attack-vectors.png\" alt=\"\" width=\"1257\" height=\"1133\" \/><\/h3>\n<p>The threat model identifies five primary attack vectors:<\/p>\n<h3>Attack Vector 1: Mobile App Compromise<\/h3>\n<ul>\n<li>Threat: Extraction of MasterSeedHash or dimension seeds<\/li>\n<li>Impact: Total compromise of all banks in affected token pools<\/li>\n<li>Mitigations: Hardware-backed secure storage, biometric protection, limited export capability<\/li>\n<\/ul>\n<h3>Attack Vector 2: Browser\/UI dApp Compromise<\/h3>\n<ul>\n<li>Threat: Extraction of revealed hashes from bank updates<\/li>\n<li>Impact: Limited to already-revealed tokens in specific banks<\/li>\n<li>Mitigations: Limited bank updates, shadow DOM isolation, request signing<\/li>\n<\/ul>\n<h3>Attack Vector 3: Replay Attacks<\/h3>\n<ul>\n<li>Threat: Reuse of previously revealed TTs to claim value multiple times<\/li>\n<li>Impact: Double-spending of the same token value<\/li>\n<li>Mitigations: On-chain bank usage depth tracking, validation in xTTEx execution<\/li>\n<\/ul>\n<h3>Attack Vector 4: Man-in-the-Middle<\/h3>\n<ul>\n<li>Threat: Intercepting TTs during off-chain transmission<\/li>\n<li>Impact: Unauthorized party could attempt to cash out tokens<\/li>\n<li>Mitigations: Optional TT recipient ID, authenticated TTs, secure transmission channels<\/li>\n<\/ul>\n<h3>Attack Vector 5: Cryptographic Attacks<\/h3>\n<ul>\n<li>Threat: Finding hash function collisions or preimages<\/li>\n<li>Impact: Potential forgery of tokens<\/li>\n<li>Mitigations: Strong cryptographic hash functions with high preimage resistance<\/li>\n<\/ul>\n<h3>10.5. Defense-in-Depth Model<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-669247 aligncenter\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2025\/04\/model.png\" alt=\"\" width=\"1067\" height=\"1029\" \/><\/p>\n<p>The State-Less Channels system implements defense-in-depth with four security layers:<\/p>\n<h3>Layer 1: Cryptographic Primitives<\/h3>\n<ul>\n<li>One-way hash functions (SHA-256)<\/li>\n<li>Public key cryptography for signatures<\/li>\n<li>Reverse hash chains for secure revelation<\/li>\n<\/ul>\n<h3>Layer 2: Multi-Dimensional Structure<\/h3>\n<ul>\n<li>Multiple independent banks isolate risk<\/li>\n<li>Limited bank depth exposure through controlled updates<\/li>\n<li>Compartmentalized token pools<\/li>\n<\/ul>\n<h3>Layer 3: Security Domain Separation<\/h3>\n<ul>\n<li>Mobile app isolation of critical secrets<\/li>\n<li>Shadow DOM segregation in browser<\/li>\n<li>QR Intent protocol for secure cross-domain communication<\/li>\n<\/ul>\n<h3>Layer 4: Verification &amp; Validation<\/h3>\n<ul>\n<li>On-chain depth tracking prevents double-spending<\/li>\n<li>DSM consensus validation for all cash-outs<\/li>\n<li>Optional TT signatures for authentication<\/li>\n<\/ul>\n<h3>10.6. Conclusion<\/h3>\n<p>The GRIDNET OS State-Less Channels system demonstrates a sophisticated security architecture that:<\/p>\n<ul>\n<li>Compartmentalizes risk through multi-dimensional token pools<\/li>\n<li>Minimizes trusted computing base by keeping critical secrets in secure hardware<\/li>\n<li>Provides cryptographic guarantees through one-way hash functions<\/li>\n<li>Prevents double-spending through on-chain depth tracking<\/li>\n<li>Limits exposure by selective revelation of hash tokens<\/li>\n<\/ul>\n<p>The core innovation of using reverse hash chains allows for secure off-chain value transfer while maintaining strong cryptographic guarantees about the security and integrity of the system, even if parts of it are compromised.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction Welcome to the official documentation for the GRIDNET OS State-Less Channels sub-system and its associated Off-The-Chain Payment API. This document&#8230;<\/p>\n","protected":false},"author":1,"featured_media":669266,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[125],"tags":[],"class_list":["post-668089","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-documentation"],"_links":{"self":[{"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts\/668089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/comments?post=668089"}],"version-history":[{"count":38,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts\/668089\/revisions"}],"predecessor-version":[{"id":669306,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts\/668089\/revisions\/669306"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/media\/669266"}],"wp:attachment":[{"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/media?parent=668089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/categories?post=668089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/tags?post=668089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}