﻿{"id":835510,"date":"2026-02-18T18:57:53","date_gmt":"2026-02-18T18:57:53","guid":{"rendered":"https:\/\/gridnet.org\/wpp\/?p=835510"},"modified":"2026-02-20T07:57:38","modified_gmt":"2026-02-20T07:57:38","slug":"talking-to-the-blockchain-cvmcontext-deep-dive","status":"publish","type":"post","link":"https:\/\/mag.gridnet.org\/index.php\/2026\/02\/18\/talking-to-the-blockchain-cvmcontext-deep-dive\/","title":{"rendered":"Talking to the Blockchain \u2014 CVMContext Deep Dive"},"content":{"rendered":"<h2>I. What CVMContext Is \u2014 And Why It Matters<\/h2>\n<p>Every revolution needs a bridge between worlds. The steam engine needed the drive shaft. The internet needed the browser. And GRIDNET OS \u2014 the world&#8217;s first fully decentralized operating system \u2014 needs <code>CVMContext<\/code>.<\/p>\n<p><code>CVMContext<\/code> (defined in <code>\/lib\/VMContext.js<\/code>) is the <strong>singular JavaScript singleton<\/strong> that connects your UI dApp, running inside a Shadow DOM in the user&#8217;s browser, to the entire decentralized stack beneath: the blockchain state machine, the decentralized filesystem, cryptographic identity, WebRTC swarms, consensus tasks, and more. It is not merely an API wrapper. It is the beating heart of every GRIDNET OS application \u2014 the central nervous system through which all signals flow.<\/p>\n<p>If you are a web developer building on GRIDNET OS, this is <strong>the<\/strong> document you need. Every method. Every event. Every pattern. From first connection to final commit.<\/p>\n<p>The architecture is deceptively simple. Your dApp is standard HTML, CSS, and JavaScript \u2014 skills you already have. <code>CVMContext<\/code> bridges that familiar world to the decentralized one. It communicates with GRIDNET Core full-nodes over WebSocket, serializing commands through the <strong>VM Meta Data Protocol<\/strong> (BER-encoded ASN.1) and the <strong>DFS Protocol<\/strong> for filesystem operations. The result is that your JavaScript code can navigate directories, read files, send value, deploy contracts, and subscribe to blockchain events \u2014 all through a clean, event-driven API.<\/p>\n<pre>\n\/\/ The most important line in any GRIDNET OS dApp\nconst ctx = CVMContext.getInstance();\n<\/pre>\n<p>That single call returns the global singleton. There is only ever one <code>CVMContext<\/code> \u2014 it manages the WebSocket connection, the session key negotiation, the filesystem abstraction, the swarm manager, the channels manager, the keychain, and all event dispatch. Everything flows through it.<\/p>\n<p><!-- Architecture Diagram --><\/p>\n<h2>II. Connection Lifecycle \u2014 From Boot to Ready<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-connection-lifecycle.png\" alt=\"Connection lifecycle from WebSocket handshake to session establishment\" style=\"width:100%;border-radius:8px;\" \/><figcaption>The connection lifecycle: WebSocket establishment, cryptographic handshake, session key negotiation, and VM thread spawning.<\/figcaption><\/figure>\n<p>When GRIDNET OS boots in the browser, the bootloader instantiates <code>CVMContext<\/code> with one or more full-node URIs. What follows is a carefully orchestrated dance of connection, cryptography, and state synchronization.<\/p>\n<h3>Phase 1: WebSocket Connection<\/h3>\n<p>The <code>CVMContext<\/code> constructor stores the provided node URIs and starts an internal controller thread (a JavaScript interval at ~2000ms) that manages state transitions. When the context enters the <code>active<\/code> state, it selects a node URI \u2014 either the &#8220;closest&#8221; one (based on a time-seeded hash heuristic) for the first connection, or a random one for reconnections \u2014 and opens a WebSocket.<\/p>\n<pre>\n\/\/ The bootloader does this internally:\nconst ctx = new CVMContext(['wss:\/\/node1.gridnet.org:26039', 'wss:\/\/node2.gridnet.org:26039']);\nctx.initialize();\n<\/pre>\n<h3>Phase 2: Hello Handshake &amp; Key Exchange<\/h3>\n<p>Once the WebSocket opens, <code>CVMContext<\/code> automatically sends a <strong>Hello Request<\/strong> containing a <code>CSessionDescription<\/code> with the browser&#8217;s ephemeral X25519 public key and a random challenge. The full-node responds with its own <code>CSessionDescription<\/code>. Through ECDH (Elliptic Curve Diffie-Hellman), both parties derive a shared <strong>session key<\/strong> used for all subsequent communication via ChaCha20-Poly1305 AEAD encryption.<\/p>\n<h3>Phase 3: System Thread Spawning<\/h3>\n<p>After the session key is established, the full-node spawns a <strong>System Thread<\/strong> \u2014 a dedicated decentralized processing thread for this connection. The thread ID is communicated back to <code>CVMContext<\/code>, which stores it. From this point, all GridScript commands execute within this thread&#8217;s context.<\/p>\n<h3>Connection States<\/h3>\n<p>The connection progresses through states defined by <code>eConnectionState<\/code>:<\/p>\n<pre>\n\/\/ Monitor connection state changes\nCVMContext.getInstance().addConnectionStatusChangedListener(function(state) {\n    switch(state) {\n        case eConnectionState.disconnected:\n            console.log('Disconnected from GRIDNET Core');\n            break;\n        case eConnectionState.connecting:\n            console.log('Connecting...');\n            break;\n        case eConnectionState.connected:\n            console.log('Connected and ready!');\n            break;\n        case eConnectionState.aboutToShutDown:\n            console.log('Connection weakening (keepalive timeout approaching)');\n            break;\n    }\n}, this.mID);\n<\/pre>\n<p><code>CVMContext<\/code> handles reconnection autonomously. If the connection drops, the controller thread detects it and initiates a new connection to a randomly selected node. For keychain-based logins, the user session persists across reconnections \u2014 only QR-based sessions require re-authentication.<\/p>\n<h3>VM States<\/h3>\n<p>The virtual machine on the full-node also transitions through states tracked by <code>eVMState<\/code>:<\/p>\n<pre>\n\/\/ All eVMState values (from \/lib\/enums.js):\n\/\/ eVMState.initializing          = 0  \u2014 VM is booting up\n\/\/ eVMState.ready                 = 1  \u2014 VM is ready for commands\n\/\/ eVMState.aboutToShutDown       = 2  \u2014 VM is about to shut down\n\/\/ eVMState.disabled              = 3  \u2014 VM thread is disabled \/ unavailable\n\/\/ eVMState.limitReached          = 4  \u2014 Resource limit reached\n\/\/ eVMState.errored               = 5  \u2014 VM encountered an error\n\/\/ eVMState.synced                = 6  \u2014 VM has been synchronized\n\/\/ eVMState.newPerspectiveAvailable = 7 \u2014 New blockchain perspective available\n\nCVMContext.getInstance().addVMStateChangedListener(function(arg) {\n    \/\/ arg.state contains the eVMState value\n    \/\/ arg.extended \u2014 if true, additional fields are available:\n    \/\/   arg.vmFlags, arg.vmID, arg.terminalID, arg.conversationID\n    \/\/ arg.threadID \u2014 the thread this state applies to\n    \n    switch(arg.state) {\n        case eVMState.initializing:\n            console.log('VM is initializing...');\n            break;\n        case eVMState.ready:\n            console.log('VM is ready \u2014 you can now execute commands');\n            break;\n        case eVMState.aboutToShutDown:\n            console.log('VM is about to shut down');\n            break;\n        case eVMState.disabled:\n            console.log('VM thread has been disabled');\n            break;\n        case eVMState.limitReached:\n            console.log('Resource limit reached');\n            break;\n        case eVMState.errored:\n            console.log('VM encountered an error');\n            break;\n        case eVMState.synced:\n            console.log('VM synchronized');\n            break;\n        case eVMState.newPerspectiveAvailable:\n            console.log('New perspective available \u2014 refresh state');\n            break;\n    }\n}, this.mID);\n<\/pre>\n<h2>III. Navigation API \u2014 cd, ls, pwd, and Domain Resolution<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-filesystem-ops.png\" alt=\"Decentralized filesystem navigation and operations\" style=\"width:100%;border-radius:8px;\" \/><figcaption>Navigating the decentralized filesystem: state domains as root directories, hierarchical paths, and familiar shell commands.<\/figcaption><\/figure>\n<p>GRIDNET OS organizes all data into <strong>State Domains<\/strong> \u2014 analogous to user accounts or home directories \u2014 stored in Merkle Patricia Tries on the blockchain. Navigation within this filesystem feels intentionally familiar: it uses the same commands as Linux\/DOS shells.<\/p>\n<p>The filesystem is accessed through <code>CVMContext.getInstance().getFileSystem<\/code>, which returns the <code>CFileSystem<\/code> singleton. All filesystem operations ultimately compile to GridScript commands sent to the full-node.<\/p>\n<h3>Changing Directory: <code>cd<\/code><\/h3>\n<pre>\nconst fs = CVMContext.getInstance().getFileSystem;\n\n\/\/ Navigate to a state domain (like a user's home directory)\nfs.doCD('\/alice.gridnet', true, false, false, threadID);\n\n\/\/ Navigate to a subdirectory\nfs.doCD('documents', true, false, false, threadID);\n\n\/\/ Navigate to root\nfs.doCD('\/', true, false, false, threadID);\n<\/pre>\n<p>The <code>doCD(path, updatePWD, isAbsolute, silent, threadID)<\/code> method sends a <code>cd<\/code> GridScript command to the full-node. The path can be absolute (starting with <code>\/<\/code>) or relative. Each State Domain is a top-level directory under <code>\/<\/code>.<\/p>\n<h3>Listing Directory Contents: <code>ls<\/code><\/h3>\n<pre>\n\/\/ List current directory\nconst reqID = fs.doLS(threadID);\n\n\/\/ Listen for the result\nCVMContext.getInstance().addNewDFSMsgListener(function(dfsMsg) {\n    \/\/ DFS message contains VM Meta Data with directory listing\n    \/\/ Parse entries from the response\n}, this.mID);\n<\/pre>\n<h3>Listing State Domains: <code>csds<\/code><\/h3>\n<pre>\n\/\/ List all state domains on the blockchain (like listing all user accounts)\n\/\/ Executed as raw GridScript\nCVMContext.getInstance().processGridScript('csds', threadID, processHandle);\n<\/pre>\n<h3>Processing GridScript Commands Directly<\/h3>\n<p>For navigation and other operations, you can execute any GridScript command through the <code>processGridScript()<\/code> method:<\/p>\n<pre>\nconst ctx = CVMContext.getInstance();\n\n\/\/ Full signature:\n\/\/ processGridScript(cmd, threadID, processHandle, mode, reqID)\n\/\/   cmd          \u2014 GridScript command string (default: \"\")\n\/\/   threadID     \u2014 Decentralized thread ID (default: system thread)\n\/\/   processHandle \u2014 Calling CWindow\/process (REQUIRED for user-mode)\n\/\/   mode         \u2014 eVMMetaCodeExecutionMode (default: RAW)\n\/\/   reqID        \u2014 Request ID (default: 0, auto-generated)\n\n\/\/ User-mode method (requires a valid process handle)\nctx.processGridScript('cd \/alice.gridnet', threadID, myProcessHandle);\nctx.processGridScript('ls', threadID, myProcessHandle);\nctx.processGridScript('pwd', threadID, myProcessHandle);\n\n\/\/ With explicit mode (e.g., for terminal-style output)\nctx.processGridScript('ls', threadID, myProcessHandle, eVMMetaCodeExecutionMode.GUITerminal);\n<\/pre>\n<p><strong>Important:<\/strong> <code>processGridScript()<\/code> is a user-mode method that <em>requires<\/em> a valid process handle. Anonymous calls will be rejected. This is a security feature \u2014 every operation on the decentralized state machine must be attributable to a registered process. For kernel-mode usage (system processes), use <code>processGridScriptKM()<\/code> which accepts additional parameters including <code>register<\/code> and <code>promiseInfo<\/code> for async promise integration. There is also <code>processGridScriptA()<\/code> which returns a <code>Promise<\/code> for async\/await usage.<\/p>\n<h2>IV. File Operations \u2014 Full CRUD on the Decentralized Filesystem<\/h2>\n<p>The decentralized filesystem supports complete CRUD operations. Each operation maps to a GridScript codeword that the full-node executes against the Merkle Patricia Trie state.<\/p>\n<h3><code>touch<\/code> \u2014 Create an Empty File<\/h3>\n<pre>\n\/\/ Create a new empty file\nctx.processGridScript('touch myfile.txt', threadID, processHandle);\n<\/pre>\n<h3><code>write<\/code> \u2014 Write Data to a File<\/h3>\n<pre>\n\/\/ Write content to a file\nctx.processGridScript('write myfile.txt', threadID, processHandle);\n\/\/ Note: content is provided through the DFS protocol's data fields\n<\/pre>\n<p>For file uploads, the FileManager dApp uses the DFS (Decentralized File System) protocol directly:<\/p>\n<pre>\nconst fs = CVMContext.getInstance().getFileSystem;\n\n\/\/ The DFS protocol handles file content through specialized messages\n\/\/ Files can be stored as eternal (permanent) or voted (crowd-funded) storage\nfs.doCommit(false, threadID); \/\/ Commit changes to blockchain\n<\/pre>\n<h3><code>cat<\/code> \u2014 Read File Contents<\/h3>\n<pre>\n\/\/ Read a file's contents\nctx.processGridScript('cat myfile.txt', threadID, processHandle);\n\n\/\/ Result arrives via GridScript result listener\nctx.addNewGridScriptResultListener(function(result) {\n    if (result.reqID === myReqID) {\n        \/\/ result.data contains the file content\n        \/\/ result.types contains data type information\n        console.log('File content:', result.data);\n    }\n}, this.mID);\n<\/pre>\n<h3><code>mkdir<\/code> \u2014 Create a Directory<\/h3>\n<pre>\nctx.processGridScript('mkdir documents', threadID, processHandle);\n<\/pre>\n<h3><code>rm<\/code> \u2014 Remove a File or Directory<\/h3>\n<pre>\nctx.processGridScript('rm myfile.txt', threadID, processHandle);\n<\/pre>\n<h3><code>head<\/code> \/ <code>tail<\/code> \u2014 Read Portions of Files<\/h3>\n<pre>\nctx.processGridScript('head myfile.txt', threadID, processHandle);\nctx.processGridScript('tail myfile.txt', threadID, processHandle);\n<\/pre>\n<h3>Access Control: <code>chown<\/code>, <code>setfacl<\/code>, <code>getfacl<\/code><\/h3>\n<pre>\n\/\/ Change ownership of a file (base58-encoded address)\nctx.processGridScript('chown &lt;base58address&gt; myfile.txt', threadID, processHandle);\n\n\/\/ Set access control list\nctx.processGridScript('setfacl &lt;base58address&gt; myfile.txt', threadID, processHandle);\n\n\/\/ Get current ACL\nctx.processGridScript('getfacl myfile.txt', threadID, processHandle);\n<\/pre>\n<h3>The DFS Commit Cycle<\/h3>\n<p>All filesystem modifications are <strong>transactional<\/strong>. Changes are staged locally and then committed to the blockchain through the DFS protocol. The commit cycle follows this pattern:<\/p>\n<pre>\nconst fs = CVMContext.getInstance().getFileSystem;\n\n\/\/ 1. Make changes (cd, mkdir, touch, write, rm...)\n\/\/ 2. Synchronize\nfs.doSync();\n\n\/\/ 3. Commit changes to blockchain\nfs.doCommit(false, threadID);\n\n\/\/ 4. Listen for commit result\nCVMContext.getInstance().addVMCommitStateChangedListener(function(state) {\n    switch(state) {\n        case eCommitState.prePending:\n            console.log('Commit lock acquired locally');\n            break;\n        case eCommitState.pending:\n            console.log('Full-node confirmed commit is pending');\n            break;\n        case eCommitState.success:\n            console.log('Commit successful! Changes are on the blockchain.');\n            break;\n        case eCommitState.aborted:\n            console.log('Commit was aborted');\n            break;\n    }\n}, this.mID);\n<\/pre>\n<h2>V. Transaction API \u2014 BT\/CT, Sending Value, Deploying Contracts<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-transactions.png\" alt=\"Transaction lifecycle with BT and CT\" style=\"width:100%;border-radius:8px;\" \/><figcaption>The transaction lifecycle: BEGIN TRANSACTION (BT), execute operations, authenticate, COMMIT TRANSACTION (CT) \u2014 mapping directly to familiar SQL transaction semantics.<\/figcaption><\/figure>\n<p>GRIDNET OS uses a transaction model that will feel instantly familiar to any database developer. <code>BT<\/code> (Begin Transaction) opens a transaction context, and <code>CT<\/code> (Commit Transaction) finalizes it. Between them, you can send value, deploy smart contracts, and modify blockchain state. This maps directly to SQL&#8217;s <code>BEGIN<\/code>\/<code>COMMIT<\/code> paradigm.<\/p>\n<h3>Sending Value (GNC Transfer)<\/h3>\n<p>GRIDNET OS supports two transaction modes:<\/p>\n<p><strong>1. Remote Mode (Decentralized Threads API)<\/strong> \u2014 Commands are sent as GridScript to the full-node for compilation and execution:<\/p>\n<pre>\n\/\/ Remote transaction: full-node compiles and executes\nconst ctx = CVMContext.getInstance();\n\n\/\/ The Wallet dApp constructs the GridScript command sequence:\nlet cmd = '';\ncmd += 'BT ';                           \/\/ Begin Transaction\ncmd += 'send ' + amount + ' ' + recipientAddress;  \/\/ Transfer value\ncmd += ' CT';                            \/\/ Commit Transaction\n\nctx.processGridScript(cmd, threadID, processHandle, eVMMetaCodeExecutionMode.RAW);\n\n\/\/ Authentication happens via QR code or local keychain signing\n\/\/ The full-node sends a QRIntentAuth request that CVMContext handles\n<\/pre>\n<p><strong>2. Local Mode (Trustless Browser Compilation)<\/strong> \u2014 The transaction bytecode is compiled locally using <code>GridScriptCompiler<\/code> and sent pre-compiled:<\/p>\n<pre>\nimport { GridScriptCompiler } from '\/lib\/GridScriptCompiler.js';\nimport { CTransaction } from '\/lib\/Transaction.js';\n\n\/\/ Compile GridScript locally\nconst compiler = new GridScriptCompiler();\nconst script = 'send ' + amount + ' ' + recipientAddress;\nconst result = await compiler.compile(script);\n\nif (result.success) {\n    \/\/ Create and sign the transaction locally\n    const tx = new CTransaction();\n    tx.setBytecode(result.bytecode);\n    \/\/ ... set other transaction fields ...\n    \n    \/\/ Submit pre-compiled transaction\n    const result = await ctx.submitPreCompiledTransactionA(\n        tx.getPackedData(),\n        processHandle,  \/\/ process handle (required)\n        threadID,       \/\/ thread ID (optional)\n        30000           \/\/ timeout in ms\n    );\n}\n<\/pre>\n<h3>The Commit Lock Mechanism<\/h3>\n<p>Before any commit, your dApp must acquire the <strong>commit lock<\/strong>. This prevents multiple applications from attempting simultaneous commits:<\/p>\n<pre>\nconst ctx = CVMContext.getInstance();\n\n\/\/ 1. Try to acquire the commit lock\nif (ctx.tryLockCommit(processHandle)) {\n    \/\/ Lock acquired \u2014 proceed with commit\n    \n    \/\/ 2. Execute the commit\n    ctx.commit(processHandle, false, 'system');\n    \n    \/\/ 3. The Magic Button UI changes to \"committing\" state\n    \/\/ 4. Full-node sends commitPending \u2192 commitSuccess\/commitAborted\n} else {\n    console.log('Another application is currently committing');\n}\n<\/pre>\n<p>The lock has a timeout (<code>mCommitLockTime<\/code>, default 60 seconds). If the full-node doesn&#8217;t confirm within the timeout, <code>CVMContext<\/code> automatically retries up to 3 times with exponential backoff, then breaks the lock and sends an abort notification.<\/p>\n<h3>The <code>submitPreCompiledTransactionA()<\/code> Method<\/h3>\n<pre>\n\/**\n * Submits a pre-compiled transaction to the network (user-mode, async)\n * @param {Uint8Array|ArrayBuffer} txData - BER-encoded transaction bytecode\n * @param {Object} processHandle - Calling process (CWindow instance, required)\n * @param {ArrayBuffer} [threadID=new ArrayBuffer()] - Thread to execute on (default: system thread)\n * @param {number} [timeoutMS=30000] - Timeout in milliseconds\n * @returns {Promise} - Resolves with result on success\n *\/\nasync submitPreCompiledTransactionA(txData, processHandle, threadID = new ArrayBuffer(), timeoutMS = 30000)\n<\/pre>\n<h2>VI. Identity &amp; Authentication<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-identity-auth.png\" alt=\"Identity and authentication mechanisms\" style=\"width:100%;border-radius:8px;\" \/><figcaption>Two authentication paths: QR code scanning with the mobile app, or headless local keychain signing for seamless browser-only authentication.<\/figcaption><\/figure>\n<p>Authentication on GRIDNET OS is cryptographic, not password-based. Your identity is your key pair. <code>CVMContext<\/code> provides two authentication pathways:<\/p>\n<h3>QR Code Authentication<\/h3>\n<p>The traditional flow: a QR code is displayed containing the connection&#8217;s conversation ID, the full-node&#8217;s address, and a random challenge. The user scans it with the GRIDNET Token mobile app, which signs the challenge with their private key and sends the signature back through the full-node.<\/p>\n<pre>\n\/\/ Trigger QR login\nctx.requestQRLogon();\n\n\/\/ Listen for login\nctx.addUserLogonListener(function(sessionDesc) {\n    console.log('User logged in:', ctx.getUserID);\n}, this.mID);\n<\/pre>\n<h3>Local Keychain Authentication (Headless)<\/h3>\n<p>The newer, browser-only flow. Users can store encrypted keychains locally (protected by a master password). On login, <code>CVMContext<\/code> decrypts the keychain and uses it to sign authentication challenges without any mobile device:<\/p>\n<pre>\n\/\/ Request login \u2014 automatically detects available keychains\nawait ctx.requestLoginChoice();\n\n\/\/ Or directly request keychain login\nawait ctx.requestKeychainLogin();\n\n\/\/ Check login status\nif (ctx.isLoggedIn) {\n    console.log('Logged in as:', ctx.getUserID);\n    console.log('Keychain login:', ctx.mIsKeychainLogin);\n}\n<\/pre>\n<h3>Identity Properties<\/h3>\n<pre>\n\/\/ Get current user ID (State Domain name \/ address)\nctx.getUserID              \/\/ \u2192 \"alice.gridnet\" or \"Anonymous4521\"\n\n\/\/ Get full State Domain ID\nctx.getUserFullID          \/\/ \u2192 full state domain identifier\n\n\/\/ Check if logged in\nctx.isLoggedIn             \/\/ \u2192 true\/false\n\n\/\/ Get user session description (contains pubkey, address, etc.)\nctx.getUserSessionDescription  \/\/ \u2192 CSessionDescription object\n\n\/\/ Get key chain manager for programmatic key operations\nctx.getKeyChainManager     \/\/ \u2192 CKeyChainManager instance\n<\/pre>\n<h3>Session Management<\/h3>\n<pre>\n\/\/ Logout\nawait ctx.logout();\n\n\/\/ Switch identity (keychain logins only)\nawait ctx.switchIdentity();\n\n\/\/ Lock screen\nawait ctx.lockScreen();\n<\/pre>\n<h2>VII. GridScript Compilation \u2014 The GridScriptCompiler<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-gridscript-compiler.png\" alt=\"GridScript compilation pipeline\" style=\"width:100%;border-radius:8px;\" \/><figcaption>The GridScriptCompiler transforms human-readable GridScript source into V2 bytecode with keyword hash chains \u2014 enabling trustless browser-side transaction compilation.<\/figcaption><\/figure>\n<p>The <code>GridScriptCompiler<\/code> is a pure JavaScript implementation that compiles GridScript source code into bytecode compatible with GRIDNET Core&#8217;s C++ VM. This enables <strong>local, trustless transaction compilation<\/strong> \u2014 your browser can construct valid blockchain transactions without relying on the full-node for compilation.<\/p>\n<pre>\nimport { GridScriptCompiler } from '\/lib\/GridScriptCompiler.js';\n\nconst compiler = new GridScriptCompiler();\n\n\/\/ Compile a simple value transfer\nconst result = await compiler.compile('send 100 recipientAddress');\n\nif (result.success) {\n    console.log('Bytecode:', result.bytecode);  \/\/ Uint8Array\n    console.log('No errors');\n} else {\n    console.log('Compilation errors:', result.errors);\n}\n<\/pre>\n<h3>Bytecode Format<\/h3>\n<p>The compiler generates <strong>V2 bytecode<\/strong> by default:<\/p>\n<pre>\nV2: [VERSION_BYTE][32_BYTE_HASH][OPCODES...]\n\n- VERSION_BYTE: 194 (0xC2) for V2\n- 32_BYTE_HASH: SHA-256 keyword image hash chain\n- OPCODES: Encoded codeword instructions\n<\/pre>\n<p>The keyword hash chain provides integrity verification: <code>H\u2080 = SHA256(\"GRIDSCRIPT_V2_KEYWORD_IMAGE\")<\/code>, then <code>H\u2099 = SHA256(H\u2099\u208b\u2081 || keyword)<\/code> for each compiled keyword. This ensures the bytecode hasn&#8217;t been tampered with.<\/p>\n<h3>Opcode Encoding<\/h3>\n<pre>\n- ID \u2264 127: Single byte [ID]\n- ID > 127: Two bytes [HIGH_BYTE | 0x80][LOW_BYTE] (little-endian with bit 7 set)\n<\/pre>\n<h3>Key Codewords for dApp Developers<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:8px;color:#00f0ff;\">Codeword<\/th>\n<th style=\"text-align:left;padding:8px;color:#00f0ff;\">Opcode<\/th>\n<th style=\"text-align:left;padding:8px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>cd<\/code><\/td>\n<td>162<\/td>\n<td>Change directory<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>ls<\/code><\/td>\n<td>174<\/td>\n<td>List directory contents<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>mkdir<\/code><\/td>\n<td>165<\/td>\n<td>Create directory<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>touch<\/code><\/td>\n<td>262<\/td>\n<td>Create empty file<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>rm<\/code><\/td>\n<td>263<\/td>\n<td>Remove file\/directory<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>write<\/code><\/td>\n<td>233<\/td>\n<td>Write to file<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>cat<\/code><\/td>\n<td>104<\/td>\n<td>Read file contents<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>send<\/code><\/td>\n<td>195<\/td>\n<td>Transfer value (2 inline params)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>balance<\/code><\/td>\n<td>198<\/td>\n<td>Query balance<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>chown<\/code><\/td>\n<td>225<\/td>\n<td>Change ownership (base58)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>setfacl<\/code><\/td>\n<td>223<\/td>\n<td>Set access control (base58)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>getfacl<\/code><\/td>\n<td>227<\/td>\n<td>Get access control<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>call<\/code><\/td>\n<td>152<\/td>\n<td>Call smart contract<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>echo<\/code><\/td>\n<td>157<\/td>\n<td>Output text<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>whoami<\/code><\/td>\n<td>235<\/td>\n<td>Current identity<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>info<\/code><\/td>\n<td>199<\/td>\n<td>Domain information<\/td>\n<\/tr>\n<\/table>\n<h3>Encoding Utilities: CTools<\/h3>\n<p>The full <code>CTools<\/code> class is exported from <code>\/lib\/tools.js<\/code> and provides a comprehensive set of utilities \u2014 encoding, formatting, BigInt conversion, logging, GNC value formatting, and much more. This is the <code>CTools<\/code> that <code>CVMContext<\/code> itself uses internally.<\/p>\n<p><strong>Important distinction:<\/strong> <code>\/lib\/GridScriptCompiler.js<\/code> also exports a class named <code>CTools<\/code>, but it is a <strong>stripped-down, environment-agnostic version<\/strong> containing only crypto and encoding utilities (SHA-256, Base58Check, Base64Check). This lightweight version exists so the compiler can run in both browser and Node.js environments without DOM dependencies. If you need the full toolkit (GNC formatting, path parsing, byte vector comparison, logging, etc.), import from <code>\/lib\/tools.js<\/code>.<\/p>\n<pre>\n\/\/ Full CTools \u2014 used by CVMContext and most dApps\nimport { CTools } from '\/lib\/tools.js';\nconst tools = CTools.getInstance();\n\n\/\/ Base58Check encode\/decode (for addresses)\nconst encoded = await tools.encodeBase58Check(binaryData);\nconst decoded = await tools.decodeBase58Check(encodedString);\n\n\/\/ Base64Check encode\/decode\nconst b64 = await tools.encodeBase64Check(binaryData);\n\n\/\/ SHA-256\nconst hash = await tools.sha256(data);\n\n\/\/ String \u2194 Bytes\nconst bytes = tools.stringToBytes('hello');\nconst str = tools.bytesToString(bytes);\n\n\/\/ GNC value formatting\nconst formatted = tools.formatGNCValue(valueInAttoGNC, 5); \/\/ \u2192 \"1.5 GNC\"\n\n\/\/ --- Stripped-down CTools for compiler\/Node.js use ---\n\/\/ import { CTools } from '\/lib\/GridScriptCompiler.js';\n\/\/ Only has: encodeBase58Check, decodeBase58Check, encodeBase64Check,\n\/\/           decodeBase64Check, sha256, stringToBytes, bytesToString\n<\/pre>\n<h2>VIII. The Event System \u2014 Subscriptions and State Notifications<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-event-system.png\" alt=\"Event-driven architecture with listeners\" style=\"width:100%;border-radius:8px;\" \/><figcaption>The event-driven architecture: register listeners, receive callbacks. Every state change, every network message, every block \u2014 all dispatched through a unified notification system.<\/figcaption><\/figure>\n<p>CVMContext&#8217;s architecture is fundamentally <strong>event-driven<\/strong>. Rather than polling for state changes, you register callback functions that fire when specific events occur. Every listener method returns a unique <strong>listener ID<\/strong> that can be used for later removal.<\/p>\n<h3>Complete Event Listener Registry<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:8px;color:#00f0ff;\">Method<\/th>\n<th style=\"text-align:left;padding:8px;color:#00f0ff;\">Event<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addConnectionStatusChangedListener(cb, appID)<\/code><\/td>\n<td>WebSocket connection state changes<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addVMStateChangedListener(cb, appID)<\/code><\/td>\n<td>Decentralized VM state transitions<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addVMCommitStateChangedListener(cb, appID)<\/code><\/td>\n<td>Commit operation state changes<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addContextStateChangedListener(cb, appID)<\/code><\/td>\n<td>CVMContext internal state changes<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewNetMsgListener(cb, appID)<\/code><\/td>\n<td>Raw network messages (CNetMsg)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewDFSMsgListener(cb, appID)<\/code><\/td>\n<td>DFS protocol messages<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addVMMetaDataListener(cb, appID)<\/code><\/td>\n<td>VM Meta Data protocol messages<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewGridScriptResultListener(cb, appID)<\/code><\/td>\n<td>GridScript execution results<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewTerminalDataListener(cb, appID)<\/code><\/td>\n<td>Terminal I\/O data<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewAppDataListener(cb, appID)<\/code><\/td>\n<td>Application-specific data<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addUserLogonListener(cb, appID)<\/code><\/td>\n<td>User login events<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addUserActionRequestListener(cb, appID)<\/code><\/td>\n<td>User interaction requests (QR, password)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addUserNotificationsListener(cb, appID)<\/code><\/td>\n<td>System notifications<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewKeyBlockListener(cb, appID)<\/code><\/td>\n<td>New key blocks appended to chain<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewDataBlockListener(cb, appID)<\/code><\/td>\n<td>New data blocks appended to chain<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewConsensusActionListener(cb, appID)<\/code><\/td>\n<td>Consensus task updates<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addSessionKeyAvailableListener(cb, appID)<\/code><\/td>\n<td>Session key established<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addOperationStatusListener(cb, appID)<\/code><\/td>\n<td>Operation status notifications<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewSwarmSDPMsgListener(cb, appID)<\/code><\/td>\n<td>WebRTC SDP signaling messages<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addDFSRequestCompletedListener(cb, appID)<\/code><\/td>\n<td>DFS request completion<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewSearchResultsListener(cb, appID)<\/code><\/td>\n<td>Blockchain search results<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewBlockDetailsListener(cb, appID)<\/code><\/td>\n<td>Block detail responses<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewDomainDetailsListener(cb, appID)<\/code><\/td>\n<td>Domain detail responses<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addNewTransactionDetailsListener(cb, appID)<\/code><\/td>\n<td>Transaction detail responses<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td style=\"padding:6px;\"><code>addBlockchainStatsListener(cb, appID)<\/code><\/td>\n<td>Blockchain statistics<\/td>\n<\/tr>\n<\/table>\n<h3>Pattern: Register \u2192 Listen \u2192 Unregister<\/h3>\n<pre>\nclass MyDApp extends CWindow {\n    constructor() {\n        super(\/* ... *\/);\n        \n        \/\/ Register listeners \u2014 store the IDs for cleanup\n        this.vmListenerID = CVMContext.getInstance()\n            .addVMStateChangedListener(this.onVMStateChanged.bind(this), this.mID);\n        this.dfsListenerID = CVMContext.getInstance()\n            .addNewDFSMsgListener(this.onDFSMessage.bind(this), this.mID);\n    }\n    \n    onVMStateChanged(arg) {\n        if (arg.state === eVMState.ready) {\n            this.loadData();\n        }\n    }\n    \n    onDFSMessage(dfsMsg) {\n        \/\/ Process filesystem responses\n    }\n    \n    \/\/ Clean up when window closes\n    closeWindow() {\n        CVMContext.getInstance().unregisterEventListenersByAppID(this.mID);\n        super.closeWindow();\n    }\n}\n<\/pre>\n<p><strong>Critical:<\/strong> Always unregister your listeners when your dApp window closes. Use <code>unregisterEventListenersByAppID(appID)<\/code> for bulk cleanup, or <code>unregisterEventListenerByID(id)<\/code> for individual removal.<\/p>\n<h2>IX. WebRTC Swarms \u2014 Cross-Browser Communication<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-webrtc-swarms.png\" alt=\"WebRTC swarm mesh network\" style=\"width:100%;border-radius:8px;\" \/><figcaption>WebRTC Swarms: browsers communicate directly through peer-to-peer data channels, using GRIDNET Core nodes for ICE signaling.<\/figcaption><\/figure>\n<p>GRIDNET OS includes a built-in <strong>WebRTC Swarms<\/strong> system that enables direct browser-to-browser communication without relying on the full-node for data transfer. The full-node serves only as the <strong>signaling server<\/strong> for ICE negotiation.<\/p>\n<pre>\nconst ctx = CVMContext.getInstance();\nconst swarms = ctx.getSwarmsManager; \/\/ CSwarmsManager instance\n\n\/\/ Join the global swarm\nconst swarmID = ctx.getMainSwarmID; \/\/ 'global'\n\n\/\/ Listen for SDP signaling messages\nctx.addNewSwarmSDPMsgListener(function(sdpEntity) {\n    \/\/ Handle WebRTC signaling\n    \/\/ sdpEntity contains offer\/answer\/ICE candidates\n}, this.mID);\n\n\/\/ Get ICE server configuration\nconst iceServers = ctx.ICEServers;\n<\/pre>\n<p>The Messenger dApp demonstrates the full WebRTC pattern: SDP offer\/answer exchange through the GRIDNET signaling infrastructure, ICE candidate gathering, and direct peer data channel establishment. This enables real-time messaging, file sharing, and collaborative features between browsers.<\/p>\n<h2>X. Blockchain Explorer API<\/h2>\n<p><code>CVMContext<\/code> provides a comprehensive set of methods for querying blockchain data. Each method comes in two variants: a <strong>callback-based<\/strong> version (returns a request ID) and an <strong>async\/Promise-based<\/strong> version (suffixed with <code>A<\/code>).<\/p>\n<h3>Async API Examples<\/h3>\n<pre>\nconst ctx = CVMContext.getInstance();\n\n\/\/ Get blockchain status\nconst status = await ctx.getBlockchainStatusA(threadID, processHandle);\n\n\/\/ Get recent blocks\nconst blocks = await ctx.getRecentBlocksA(10, 1, eSortBlocksBy.timestampDesc, \n    threadID, processHandle);\n\n\/\/ Get recent transactions\nconst txs = await ctx.getRecentTransactionsA(10, 1, false, threadID, processHandle);\n\n\/\/ Search the blockchain\nconst results = await ctx.searchBlockchainA('alice', 10, 1, null, \n    threadID, processHandle);\n\n\/\/ Get domain details\nconst domain = await ctx.getDomainDetailsA('alice.gridnet', '', false, \n    threadID, processHandle);\n\n\/\/ Get domain transaction history\nconst history = await ctx.getDomainHistoryA('alice.gridnet', 10, 1, \n    eSortTransactionsBy.timestampDesc, '', threadID, processHandle);\n\n\/\/ Get block details\nconst block = await ctx.getBlockDetailsA(blockID, true, false, false, \n    threadID, processHandle);\n\n\/\/ Get transaction details\nconst tx = await ctx.getTransactionDetailsA(txID, threadID, processHandle);\n\n\/\/ Get blockchain height\nconst height = await ctx.getHeightA(false, threadID, processHandle);\nconst keyHeight = await ctx.getHeightA(true, threadID, processHandle);\n\n\/\/ Get USDT price\nconst price = await ctx.getUSDTPriceA(threadID, processHandle);\n\n\/\/ Get market data\nconst market = await ctx.getMarketDataA(true, true, 1, 50, null, \n    eSortOrder.ascending, threadID, processHandle);\n\n\/\/ Subscribe to real-time updates\nawait ctx.subscribeToBlockchainUpdatesA(threadID, processHandle);\n<\/pre>\n<h2>XI. Advanced Features \u2014 Token Pools, State-Less Channels, DFS<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-advanced-features.png\" alt=\"Advanced blockchain features\" style=\"width:100%;border-radius:8px;\" \/><figcaption>Advanced features: Multi-Dimensional Token Pools for custom tokens, State-Less Channels for instant off-chain payments, and DFS for decentralized file storage.<\/figcaption><\/figure>\n<h3>Token Pools<\/h3>\n<p>GRIDNET OS supports <strong>Multi-Dimensional Token Pools<\/strong> \u2014 custom tokens that can be deployed on the blockchain. The <code>CStateLessChannelsManager<\/code> and related classes handle token pool operations:<\/p>\n<pre>\nconst ctx = CVMContext.getInstance();\nconst channels = ctx.getChannelsManager; \/\/ CStateLessChannelsManager\n\n\/\/ User's token pools are tracked\nconst pools = ctx.getUserTokenPools;\n\n\/\/ Token pool operations use GridScript:\n\/\/ regPool \u2014 register a token pool\n\/\/ getPool \u2014 query pool state\n\/\/ xTT \u2014 transfer tokens\n\/\/ poll \u2014 poll for updates\n<\/pre>\n<h3>State-Less Channels<\/h3>\n<p>State-Less Channels provide <strong>instant, off-chain payment channels<\/strong>. They work by establishing a cryptographic commitment between parties that can be settled on-chain at any time:<\/p>\n<pre>\nconst channels = CVMContext.getInstance().getChannelsManager;\n\/\/ CStateLessChannelsManager handles channel lifecycle\n\/\/ CStateLessChannel represents individual channels\n\/\/ CTransmissionToken represents off-chain payment proofs\n<\/pre>\n<h3>Process &amp; Thread Management<\/h3>\n<pre>\n\/\/ Create a JavaScript thread (runs in browser)\nconst threadID = ctx.createJSThread(\n    myFunction,         \/\/ function to execute\n    processID,          \/\/ owning process\n    1000,              \/\/ interval in ms\n    true,              \/\/ auto-start\n    false              \/\/ kernel mode\n);\n\n\/\/ Stop a thread\nctx.stopJSThread(threadID);\n\n\/\/ Create a decentralized thread (runs on full-node)\nconst reqID = ctx.createThread(threadID, processID);\n\n\/\/ Free a decentralized thread\nctx.freeThread(threadID, processID);\n\n\/\/ Send data to a thread\nctx.sendDataToThread(threadID, data);\n<\/pre>\n<h3>Terminal Integration<\/h3>\n<pre>\n\/\/ Send a line to the terminal\nctx.sendLine('ls -la\\r\\n', processID);\n\n\/\/ Send a keystroke\nctx.sendKeyStroke(13, processID, threadID); \/\/ Enter key\n\n\/\/ Send terminal dimensions\nctx.sendTerminalDimensions(24, 80, processID);\n<\/pre>\n<h2>XII. Complete CVMContext Method Reference<\/h2>\n<figure><img decoding=\"async\" src=\"https:\/\/gridnet.org\/wpp\/wp-content\/uploads\/2026\/02\/talking-to-the-blockchain-cvmcontext-deep-dive-api-reference.png\" alt=\"Complete API reference\" style=\"width:100%;border-radius:8px;\" \/><figcaption>The complete CVMContext API \u2014 every method, property, and accessor available to your dApp.<\/figcaption><\/figure>\n<h3>Core Singleton &amp; Identity<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method\/Property<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>CVMContext.getInstance(...nodeURIs)<\/code><\/td>\n<td>CVMContext<\/td>\n<td>Get or create the singleton instance<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>initialize()<\/code><\/td>\n<td>void<\/td>\n<td>Initialize all subsystems (called by bootloader)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>genRequestID()<\/code><\/td>\n<td>number<\/td>\n<td>Generate a unique request ID<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getUserID<\/code><\/td>\n<td>string<\/td>\n<td>Current user identifier<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setUserID<\/code><\/td>\n<td>void<\/td>\n<td>Set user identifier<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getUserFullID<\/code><\/td>\n<td>string<\/td>\n<td>Full state domain identifier<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get isLoggedIn<\/code><\/td>\n<td>boolean<\/td>\n<td>Whether a user session is active<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getUserSessionDescription<\/code><\/td>\n<td>CSessionDescription<\/td>\n<td>Current user session details<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>requestLoginChoice()<\/code><\/td>\n<td>void<\/td>\n<td>Show login method selection dialog<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>requestQRLogon()<\/code><\/td>\n<td>void<\/td>\n<td>Show QR code for mobile app login<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>requestKeychainLogin()<\/code><\/td>\n<td>Promise<\/td>\n<td>Login via local keychain<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>logout()<\/code><\/td>\n<td>Promise<\/td>\n<td>Logout and clear session<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>switchIdentity()<\/code><\/td>\n<td>Promise<\/td>\n<td>Switch sub-identity (keychain only)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>lockScreen()<\/code><\/td>\n<td>Promise<\/td>\n<td>Lock screen requiring re-auth<\/td>\n<\/tr>\n<\/table>\n<h3>Connection &amp; State<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method\/Property<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getConnectionState<\/code><\/td>\n<td>eConnectionState<\/td>\n<td>Current WebSocket connection state<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getVMState<\/code><\/td>\n<td>eVMState<\/td>\n<td>Current VM state<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getState<\/code><\/td>\n<td>eContextState<\/td>\n<td>Context internal state<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getCommitState<\/code><\/td>\n<td>eCommitState<\/td>\n<td>Current commit operation state<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getFullNodeIP<\/code><\/td>\n<td>string<\/td>\n<td>Current full-node IP address<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getCurrentNodeURI<\/code><\/td>\n<td>string<\/td>\n<td>Current WebSocket URI<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getSessionKey<\/code><\/td>\n<td>ArrayBuffer<\/td>\n<td>Current session encryption key<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getConversationID<\/code><\/td>\n<td>ArrayBuffer<\/td>\n<td>Local conversation identifier<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getSystemThreadID<\/code><\/td>\n<td>ArrayBuffer<\/td>\n<td>System decentralized thread ID<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getIsCommiting<\/code><\/td>\n<td>boolean<\/td>\n<td>Whether a commit is in progress<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>forceNode(nodeURI)<\/code><\/td>\n<td>void<\/td>\n<td>Force connection to specific node<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>clearForcedNode()<\/code><\/td>\n<td>void<\/td>\n<td>Clear forced node selection<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>endConnection()<\/code><\/td>\n<td>void<\/td>\n<td>Terminate current connection<\/td>\n<\/tr>\n<\/table>\n<h3>GridScript Execution<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>processGridScript(cmd, threadID, processHandle, mode?, reqID?)<\/code><\/td>\n<td>boolean|reqID<\/td>\n<td>Execute GridScript (user-mode, requires process handle). Defaults: mode=RAW, reqID=auto<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>processGridScriptA(cmd, threadID, processHandle, mode?, reqID?, timeoutMS?)<\/code><\/td>\n<td>Promise<\/td>\n<td>Execute GridScript (async\/Promise-based, user-mode)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>processGridScriptKM(cmd, threadID, processHandle, mode?, reqID?, register?, promiseInfo?)<\/code><\/td>\n<td>number|false<\/td>\n<td>Execute GridScript (kernel-mode, returns reqID)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>submitPreCompiledTransactionA(txData, processHandle, threadID?, timeoutMS?)<\/code><\/td>\n<td>Promise<\/td>\n<td>Submit pre-compiled transaction bytecode (user-mode, async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>processVMMetaData(generator, processHandle)<\/code><\/td>\n<td>boolean<\/td>\n<td>Send VM Meta Data (user-mode)<\/td>\n<\/tr>\n<\/table>\n<h3>Filesystem &amp; Subsystems<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Property<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getFileSystem<\/code><\/td>\n<td>CFileSystem<\/td>\n<td>Decentralized filesystem interface<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getSwarmsManager<\/code><\/td>\n<td>CSwarmsManager<\/td>\n<td>WebRTC swarms manager<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getChannelsManager<\/code><\/td>\n<td>CStateLessChannelsManager<\/td>\n<td>State-less channels manager<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getKeyChainManager<\/code><\/td>\n<td>CKeyChainManager<\/td>\n<td>Local keychain manager<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getCryptoFactory<\/code><\/td>\n<td>CX25519<\/td>\n<td>Cryptographic operations (ECDH, signing)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getLocalDataStore<\/code><\/td>\n<td>CLocalDataStore<\/td>\n<td>Browser-local storage<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getWindowManager<\/code><\/td>\n<td>CWindowManager<\/td>\n<td>Window management<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getPackageManager<\/code><\/td>\n<td>CPackageManager<\/td>\n<td>dApp package management<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getSettingsManager<\/code><\/td>\n<td>CSettingsManager<\/td>\n<td>Per-user settings<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getDNS<\/code><\/td>\n<td>CDNS<\/td>\n<td>DNS resolution<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getMagicButton<\/code><\/td>\n<td>CMagicButton<\/td>\n<td>Magic Button (commit UI control)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getMetaParser<\/code><\/td>\n<td>CVMMetaParser<\/td>\n<td>VM Meta Data parser<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getMetaGenerator<\/code><\/td>\n<td>CVMMetaGenerator<\/td>\n<td>VM Meta Data generator<\/td>\n<\/tr>\n<\/table>\n<h3>Transaction &amp; Commit<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>tryLockCommit(appHandle, breakLock)<\/code><\/td>\n<td>boolean<\/td>\n<td>Attempt to acquire commit lock<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>commit(appHandle, breakLock, threadID)<\/code><\/td>\n<td>boolean<\/td>\n<td>Execute commit operation<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>breakCommitLock(wasSuccess)<\/code><\/td>\n<td>void<\/td>\n<td>Release the commit lock<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>syncVM(breakCommit, processHandle)<\/code><\/td>\n<td>boolean<\/td>\n<td>Synchronize with VM state (user-mode)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>syncVMKF(breakCommit, processHandle)<\/code><\/td>\n<td>boolean<\/td>\n<td>Synchronize with VM state (kernel-mode)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>scopeSystemThread(scopeCommitTarget, scopeHomeDir)<\/code><\/td>\n<td>boolean<\/td>\n<td>Scope system thread to user&#8217;s domain<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setCommitTarget<\/code><\/td>\n<td>void<\/td>\n<td>Set target network (TestNet\/MainNet)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getCommitTarget<\/code><\/td>\n<td>eBlockchainMode<\/td>\n<td>Current target network<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getTotalPendingOutgressTransfer<\/code><\/td>\n<td>BigInt<\/td>\n<td>Total pending outgoing value<\/td>\n<\/tr>\n<\/table>\n<h3>Thread &amp; Process Management<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>createJSThread(funcPtr, processID, intervalMS, autoRun, isKernelMode)<\/code><\/td>\n<td>number<\/td>\n<td>Create a browser-side JS thread<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>stopJSThread(threadID)<\/code><\/td>\n<td>boolean<\/td>\n<td>Stop a JS thread<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>createThread(threadID, processID)<\/code><\/td>\n<td>number<\/td>\n<td>Create decentralized thread on full-node<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>freeThread(threadID, processID)<\/code><\/td>\n<td>boolean<\/td>\n<td>Free a decentralized thread<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>sendDataToThread(threadID, data, netMsgType)<\/code><\/td>\n<td>boolean<\/td>\n<td>Send data to a specific thread<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getThreadByID(id)<\/code><\/td>\n<td>CThread|null<\/td>\n<td>Find thread by ID across all processes<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getNewProcessID()<\/code><\/td>\n<td>number<\/td>\n<td>Generate new user-mode process ID<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getNewThreadID(isKernelMode)<\/code><\/td>\n<td>number<\/td>\n<td>Generate new thread ID<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>registerProcessByWinHandle(windowHandle)<\/code><\/td>\n<td>boolean<\/td>\n<td>Register a CWindow as a process<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>unregisterProcess(processID)<\/code><\/td>\n<td>boolean<\/td>\n<td>Unregister a process<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getProcessByID(id)<\/code><\/td>\n<td>CProcess<\/td>\n<td>Find process by ID<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getProcessByThreadID(id)<\/code><\/td>\n<td>CProcess|null<\/td>\n<td>Find process owning a thread<\/td>\n<\/tr>\n<\/table>\n<h3>Blockchain Explorer API<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getRecentTransactions(size, page, includeMem, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get recent transactions (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getRecentTransactionsA(size, page, ...)<\/code><\/td>\n<td>Promise&lt;CSearchResults&gt;<\/td>\n<td>Get recent transactions (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getRecentBlocks(size, page, sort, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get recent blocks (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getRecentBlocksA(size, page, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get recent blocks (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>searchBlockchain(query, size, page, flags, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Search blockchain (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>searchBlockchainA(query, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Search blockchain (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockDetails(blockID, includeTX, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get block details (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockDetailsA(blockID, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get block details (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getDomainDetails(address, perspective, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get domain details (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getDomainDetailsA(address, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get domain details (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getDomainHistory(address, size, page, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get domain tx history (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getDomainHistoryA(address, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get domain tx history (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getTransactionDetails(txID, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get transaction details (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getTransactionDetailsA(txID, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get transaction details (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockchainStatus(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get blockchain status (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockchainStatusA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get blockchain status (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getHeight(isKeyHeight, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get chain height (callback, cached)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getHeightA(isKeyHeight, ...)<\/code><\/td>\n<td>Promise&lt;number&gt;<\/td>\n<td>Get chain height (async, cached)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getUSDTPrice(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get USDT price (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getUSDTPriceA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get USDT price (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getLiveness(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get liveness state (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getLivenessA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get liveness state (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getTransactionDailyStats(days, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Get daily tx stats (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getTransactionDailyStatsA(days, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Get daily tx stats (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getNetworkUtilization24h(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>24h network utilization (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getNetworkUtilization24hA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>24h network utilization (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockSize24h(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>24h avg block size (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockSize24hA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>24h avg block size (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockRewards24h(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>24h avg rewards (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getBlockRewards24hA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>24h avg rewards (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getAverageBlockTime24h(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>24h avg block time (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getAverageBlockTime24hA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>24h avg block time (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getAverageKeyBlockTime24h(...)<\/code><\/td>\n<td>reqID<\/td>\n<td>24h avg key-block time (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getAverageKeyBlockTime24hA(...)<\/code><\/td>\n<td>Promise<\/td>\n<td>24h avg key-block time (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getMiningDifficulty(count, start, end, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Mining difficulty stats (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getMiningDifficultyA(count, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Mining difficulty stats (async, cacheable)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getMarketData(getMarketCap, getBalances, ...)<\/code><\/td>\n<td>reqID<\/td>\n<td>Market data (callback)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getMarketDataA(getMarketCap, ...)<\/code><\/td>\n<td>Promise<\/td>\n<td>Market data (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>subscribeToBlockchainUpdates(...)<\/code><\/td>\n<td>boolean<\/td>\n<td>Subscribe to real-time updates<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>subscribeToBlockchainUpdatesA(...)<\/code><\/td>\n<td>Promise&lt;boolean&gt;<\/td>\n<td>Subscribe to updates (async)<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>unsubscribeFromBlockchainUpdates(...)<\/code><\/td>\n<td>boolean<\/td>\n<td>Unsubscribe from updates<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>unsubscribeFromBlockchainUpdatesA(...)<\/code><\/td>\n<td>Promise&lt;boolean&gt;<\/td>\n<td>Unsubscribe from updates (async)<\/td>\n<\/tr>\n<\/table>\n<h3>Networking &amp; Security<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method\/Property<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>sendNetMsg(msg, breakCommit, UINotifyOnError)<\/code><\/td>\n<td>boolean<\/td>\n<td>Send authenticated\/encrypted CNetMsg<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>sendDFSMsg(msg, breakCommit)<\/code><\/td>\n<td>boolean<\/td>\n<td>Send DFS protocol message<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>notifyMobileToken(status, scope, reqID)<\/code><\/td>\n<td>boolean<\/td>\n<td>Send notification to mobile app via onion routing<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>notifyOperationStatus(status, scope, reqID)<\/code><\/td>\n<td>boolean<\/td>\n<td>Notify operation status to peer<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getKeyPair<\/code><\/td>\n<td>Object<\/td>\n<td>Ephemeral X25519 key pair<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get ICEServers<\/code><\/td>\n<td>Array<\/td>\n<td>WebRTC ICE server configuration<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setDoSignOutgressMsgs<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable message signing<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get publicIPAddress<\/code><\/td>\n<td>string<\/td>\n<td>Auto-detected public IP<\/td>\n<\/tr>\n<\/table>\n<h3>UI &amp; Logging<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method\/Property<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>logAppEvent(info, process, entryType, priority)<\/code><\/td>\n<td>void<\/td>\n<td>Log a user-mode application event<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setLoggingEnabled<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable logging<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setLogVMStatus<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable VM status logging<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setLogNetPackets<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable network packet logging<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setLogVMmeta<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable VM Meta Data logging<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setLogTerminalPackets<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable terminal packet logging<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setLogAppEvents<\/code><\/td>\n<td>void<\/td>\n<td>Enable\/disable app event logging<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>addGUITask(task, dispatchNotifications)<\/code><\/td>\n<td>boolean<\/td>\n<td>Add a task to the GUI task queue<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>playSound(sound)<\/code><\/td>\n<td>void<\/td>\n<td>Play a system sound<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>enterFullscreen()<\/code><\/td>\n<td>void<\/td>\n<td>Enter fullscreen mode<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>exitFullscreen()<\/code><\/td>\n<td>void<\/td>\n<td>Exit fullscreen mode<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>set setGamingModeEnabled<\/code><\/td>\n<td>void<\/td>\n<td>Toggle performance\/gaming mode<\/td>\n<\/tr>\n<\/table>\n<h3>Consensus Tasks<\/h3>\n<table style=\"width:100%;border-collapse:collapse;margin:1em 0;font-size:0.9em;\">\n<tr style=\"border-bottom:2px solid #00f0ff;\">\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Method<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Returns<\/th>\n<th style=\"text-align:left;padding:6px;color:#00f0ff;\">Description<\/th>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>addConsensusTask(task, isLocal)<\/code><\/td>\n<td>void<\/td>\n<td>Add a consensus task to the queue<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>getConsensusTaskByDescription(desc, subDesc)<\/code><\/td>\n<td>CConsensusTask|null<\/td>\n<td>Find task by description<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getConsensusTasks<\/code><\/td>\n<td>Array<\/td>\n<td>All pending consensus tasks<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>get getConsensusTasksCount<\/code><\/td>\n<td>number<\/td>\n<td>Number of pending tasks<\/td>\n<\/tr>\n<tr style=\"border-bottom:1px solid #1a2a4a;\">\n<td><code>clearPendngConsensusTasks()<\/code><\/td>\n<td>void<\/td>\n<td>Clear all pending tasks<\/td>\n<\/tr>\n<\/table>\n<h2>XIII. Putting It All Together \u2014 A Complete dApp Pattern<\/h2>\n<p>Here is the canonical pattern for a GRIDNET OS UI dApp that uses <code>CVMContext<\/code>:<\/p>\n<pre>\nimport { CWindow } from '\/lib\/window.js';\n\nclass MyDApp extends CWindow {\n    \n    static getPackageID() {\n        return 'org.example.mydapp';\n    }\n    \n    static getIcon() {\n        return '\/images\/mydapp-icon.png';\n    }\n    \n    constructor(x, y, w, h) {\n        super(x, y, w, h, myHTMLBody, 'My dApp', MyDApp.getIcon(), false);\n        \n        const ctx = CVMContext.getInstance();\n        \n        \/\/ 1. Register for events\n        ctx.addVMStateChangedListener(this.onVMStateChanged.bind(this), this.mID);\n        ctx.addNewDFSMsgListener(this.onDFSMessage.bind(this), this.mID);\n        ctx.addNewGridScriptResultListener(this.onGridScriptResult.bind(this), this.mID);\n        ctx.addConnectionStatusChangedListener(this.onConnectionChanged.bind(this), this.mID);\n        ctx.addVMCommitStateChangedListener(this.onCommitStateChanged.bind(this), this.mID);\n    }\n    \n    onVMStateChanged(arg) {\n        if (arg.state === eVMState.ready) {\n            \/\/ VM is ready \u2014 safe to execute commands\n            this.loadInitialData();\n        }\n    }\n    \n    onConnectionChanged(state) {\n        if (state === eConnectionState.disconnected) {\n            this.showDisconnectedUI();\n        }\n    }\n    \n    async loadInitialData() {\n        const ctx = CVMContext.getInstance();\n        \n        if (ctx.getConnectionState !== eConnectionState.connected) {\n            this.showNotConnectedError();\n            return;\n        }\n        \n        \/\/ Navigate to user's home directory\n        const fs = ctx.getFileSystem;\n        fs.doCD('\/' + ctx.getUserID, true, false, false, this.getThreadID);\n        fs.doLS(this.getThreadID);\n    }\n    \n    onDFSMessage(dfsMsg) {\n        \/\/ Handle filesystem responses\n    }\n    \n    onGridScriptResult(result) {\n        \/\/ Handle GridScript execution results\n    }\n    \n    onCommitStateChanged(state) {\n        \/\/ Handle commit lifecycle\n    }\n    \n    \/\/ CRITICAL: Clean up listeners on close\n    closeWindow() {\n        CVMContext.getInstance().unregisterEventListenersByAppID(this.mID);\n        super.closeWindow();\n    }\n}\n<\/pre>\n<h2>XIV. Conclusion \u2014 The Bridge Is Open<\/h2>\n<p>CVMContext is not just an API \u2014 it is the <strong>philosophical bridge<\/strong> between the familiar world of web development and the uncharted territory of decentralized computing. Through it, every HTML form submission can become a blockchain transaction. Every file save can become an immutable state change. Every chat message can traverse a peer-to-peer mesh without touching a central server.<\/p>\n<p>The design philosophy is clear: <strong>meet developers where they are<\/strong>. You don&#8217;t need to learn a new language. You don&#8217;t need to understand Merkle Patricia Tries. You don&#8217;t need to implement cryptographic protocols. CVMContext handles all of that. You write JavaScript. You subscribe to events. You call methods. The decentralized world opens up.<\/p>\n<p>This is Article 4 in our UI dApp Developer Series. With the foundation laid in previous articles on Shadow DOM architecture and the WebUI framework, and with this deep dive into CVMContext, you now possess the knowledge to build production-grade decentralized applications on GRIDNET OS.<\/p>\n<p>The bridge is open. Start building.<\/p>\n<p><em>\u2014 The Wizards of GRIDNET OS<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I. What CVMContext Is \u2014 And Why It Matters Every revolution needs a bridge between worlds. The steam engine needed the drive&#8230;<\/p>\n","protected":false},"author":1,"featured_media":835504,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[162,17,163],"tags":[168,139,155,164,197,142,156,215,212,169,165],"class_list":["post-835510","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-tutorial","category-tutorials","tag-api","tag-blockchain","tag-cvmcontext","tag-dapp","tag-dapps","tag-gridnet-os","tag-javascript","tag-state-management","tag-ui-development","tag-vmcontext","tag-web-development"],"_links":{"self":[{"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts\/835510","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=835510"}],"version-history":[{"count":6,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts\/835510\/revisions"}],"predecessor-version":[{"id":840112,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/posts\/835510\/revisions\/840112"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/media\/835504"}],"wp:attachment":[{"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/media?parent=835510"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/categories?post=835510"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mag.gridnet.org\/index.php\/wp-json\/wp\/v2\/tags?post=835510"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}