diff --git a/.github/ISSUE_TEMPLATE/agent-onboarding.yml b/.github/ISSUE_TEMPLATE/agent-onboarding.yml
new file mode 100644
index 0000000..488472a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/agent-onboarding.yml
@@ -0,0 +1,36 @@
+name: ποΈ Agent of Change (Visionary Onboarding)
+description: Apply to become a dedicated contributor to the Sovereignty Layer.
+title: "[AGENT]: "
+labels: ["onboarding", "steward-track"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ### Joining the Vanguard
+ Verus requires more than just code; it requires architectural vision.
+ - type: dropdown
+ id: expertise
+ attributes:
+ label: Domain of Expertise
+ options:
+ - Decentralized Governance
+ - Zero-Knowledge Ethics
+ - Game Theory & Incentives
+ - Digital Jurisprudence
+ - Systems Architecture
+ validations:
+ required: true
+ - type: textarea
+ id: manifest
+ attributes:
+ label: Your Personal Manifest
+ description: What specific problem in modern digital sovereignty are you most driven to solve?
+ validations:
+ required: true
+ - type: checkboxes
+ id: agreement
+ attributes:
+ label: Final Confirmation
+ options:
+ - label: I understand that my contributions will be governed by the Verus Open-Source Protocols.
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..dd7fba1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: ποΈ Master Strategy Archive
+ url: https://github.com
+ about: Read the core philosophy before submitting a proposal.
+ - name: π¬ Community Discussion
+ url: https://discord.com
+ about: For general questions and real-time collaboration.
diff --git a/.github/ISSUE_TEMPLATE/sovereign-proposal.yml b/.github/ISSUE_TEMPLATE/sovereign-proposal.yml
new file mode 100644
index 0000000..24e7f64
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/sovereign-proposal.yml
@@ -0,0 +1,46 @@
+name: π‘οΈ Sovereign Proposal
+description: Propose a high-level strategic shift or ethical framework for the Sovereignty Layer.
+title: "[STRATEGY]: "
+labels: ["visionary", "sovereignty-layer", "strategy"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ## Welcome, Steward of the Future.
+ The Sovereignty Layer is the ethical and philosophical bedrock of Verus. Use this form to propose a new direction or fundamental principle.
+ - type: input
+ id: vision-title
+ attributes:
+ label: Vision Title
+ placeholder: e.g., "The Decoupling of Identity from State-Centralized Ledgers"
+ validations:
+ required: true
+ - type: textarea
+ id: core-philosophy
+ attributes:
+ label: Core Philosophy
+ description: What is the fundamental human right or sovereign principle being addressed?
+ placeholder: Describe the 'Why' before the 'How'.
+ validations:
+ required: true
+ - type: textarea
+ id: impact
+ attributes:
+ label: Strategic Impact
+ description: How does this change the 'Way' for future generations?
+ - type: checkboxes
+ id: alignment
+ attributes:
+ label: Pillars of Alignment
+ options:
+ - label: Individual Autonomy
+ - label: Permissionless Innovation
+ - label: Cryptographic Verifiability
+ - label: Anti-Fragile Governance
+ - type: checkboxes
+ id: oath
+ attributes:
+ label: The Steward's Oath
+ options:
+ - label: I have reviewed the # ποΈ VERUS: THE WAY - MASTER STRATEGY ARCHIVE.
+ required: true
diff --git a/.gitignore b/.gitignore
index 754129e..d546605 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
# Dependencies
-node_modules/
+#node_modules/
# Build output
build/
diff --git a/MAINNET_ONBOARDING.md b/MAINNET_ONBOARDING.md
new file mode 100644
index 0000000..e2f514a
--- /dev/null
+++ b/MAINNET_ONBOARDING.md
@@ -0,0 +1,74 @@
+# π VERUS IS, THE WAY: THREE-CLICK MAINNET ONBOARDING (PRODUCTION)
+
+This guide is designed to launch your permanent, production-ready sovereign infrastructure on the live Verus Mainnet. Real VRSC is used here for immutable ownership.
+
+---
+
+## ποΈ Provenance, Vision & Credits
+
+This project exists because of the profound alignment of two critical contributors to the Verus ecosystem:
+
+1. **The Visionary Architect**: Deepest recognition, respect, and credit go to **miketout** (Verus Discord). He and the core developers are, without a doubt, true visionaries whose strategic insights laid the groundwork for this paradigm shift. Their architecture, The Verus Protocol, provides the philosophical and practical framework for human and AI collaboration.
+2. **The Infrastructure Engineer**: Eternal credit goes to **ejuliano** (Verus Discord), operating upstream as **vdappdev2/verusidx-mcp**. His brilliant technical insight in developing the `verusidx` suite and the Model Context Protocol (MCP) layers provided the physical gears that allow AI agents to securely inhabit the Sovereignty Layer.
+
+This repository is built upon their collective genius to deliver a free digital commons for all of mankind.
+
+---
+
+## π οΈ Step 1: The Sovereign Wallet (Human Setup)
+
+1. **Download the Engine**: Download the official [Verus Desktop Wallet](https://verus.io).
+2. **Sync the Chain**: Open the wallet and let the native **VRSC Mainnet** node synchronize locally to your machine.
+3. **Fund Your Sovereignty**: Click **Receive** to view your Mainnet `R-Address`. Transfer a small fraction of VRSC tokens to this wallet to fund the nominal blockchain registration fees (approximately 20 to 100 VRSC depending on name length and options chosen).
+
+## π Step 2: Bridge the Production AI (The 60-Second Copy & Paste)
+
+To connect your secure local Mainnet node to your local AI Assistant (like Claude Desktop):
+
+1. Open your AI Desktop app configuration file (**Settings β Developer β Edit Config**).
+2. Delete everything inside and paste this native Mainnet configuration block:
+
+```json
+{
+ "mcpServers": {
+ "verus-is-the-way-identity-mainnet": {
+ "command": "node",
+ "args": [
+ "C:\\Users\\User\\Documents\\verusidx-mcp\\packages\\identity\\dist\\index.js",
+ "--chain=VRSC"
+ ]
+ },
+ "verus-is-the-way-chain-mainnet": {
+ "command": "node",
+ "args": [
+ "C:\\Users\\User\\Documents\\verusidx-mcp\\packages\\chain\\dist\\index.js",
+ "--chain=VRSC"
+ ]
+ }
+ }
+}
+```
+
+3. **Relaunch the AI App**. Your assistant is now bound directly to consensus mainnet.
+
+## π§ Step 3: The Production Activation Prompt (The AI Command)
+
+Copy and paste this command string into your connected AI agent to claim your permanent, lifelong cryptographic identity on the public ledger:
+
+> "System check initialized. You are now operating as a live production technical collaborator for the public-good project **'Verus is, The way'**. Our local node infrastructure is fully vendor-ized and pointed to Mainnet consensus using the `--chain=VRSC` arguments.
+>
+> Execute the **Patience Protocol** to finalize our permanent identity:
+> 1. Run `register_name_commitment` for your chosen custom name.
+> 2. Display the raw JSON response containing the cryptographic `salt` and `txid` to the screen immediately.
+> 3. **Stop operations entirely for exactly 10 minutes (10 blocks)** to let the local daemon commit the salt to consensus. Do not poll the node.
+> 4. After 10 minutes, automatically pull the salt from our local disk memory (`loadCommitment`) and finalize the permanent claim using `register_identity`.
+>
+> **Verus is, The way.** Let us begin Step 1."
+
+---
+
+### π‘οΈ Real-World Sovereignty Check
+* **Immutable Asset**: Once your identity registers on Mainnet, it becomes an un-revokable, transferrable, on-chain vault. No corporate server or cloud provider can ever take it away from you.
+* **Vanguard Stability**: Thanks to our disk-persistent local salt fixes, your AI will execute this permanent claim flawlessly, avoiding data dropouts during the 10-block wait.
+
+**Verus is, the way.**
diff --git a/STRATEGY.md b/STRATEGY.md
new file mode 100644
index 0000000..ab0646f
--- /dev/null
+++ b/STRATEGY.md
@@ -0,0 +1,35 @@
+# ποΈ VERUS: THE WAY - MASTER STRATEGY ARCHIVE
+
+## The Sovereignty Layer
+This archive serves as the immutable record of our strategic path. We do not just build software; we architect the frameworks of individual autonomy.
+
+### π‘οΈ Core Pillars
+1. **Individual Autonomy**: Users must own their data, identity, and destiny.
+2. **Permissionless Innovation**: The "Way" is open to all who align with the protocols.
+3. **Cryptographic Verifiability**: Trust is replaced by mathematical proof.
+4. **Anti-Fragile Governance**: Systems must thrive under stress and decentralized scrutiny.
+
+### π The Steward's Oath
+By contributing to this repository, you acknowledge that you are a builder of the Sovereignty Layer. Your goal is to simplify complexity and empower the individual.
+## π PHASE 2: THE WAYPOINTS (Roadmap)
+
+The following Waypoints define our immediate tactical objectives. Visionaries should align their 'Sovereign Proposals' with these targets.
+
+### Waypoint 1: The Identity Ledger
+* **Objective**: Establish a permissionless, ZK-proof (Zero-Knowledge) identity framework.
+* **Goal**: Decouple personal data from centralized state or corporate control.
+
+### Waypoint 2: The Governance Protocol
+* **Objective**: Draft the 'Lex Verus'βa set of cryptographic rules for project decision-making.
+* **Goal**: Ensure the Sovereignty Layer remains anti-fragile and resistant to capture.
+
+### Waypoint 3: The Stewardβs Toolkit
+* **Objective**: Develop open-source tools that simplify sovereign tech for the average individual.
+* **Goal**: "Complexity is the enemy of Sovereignty." We must make the complex simple.
+
+### Waypoint 4: Global Distribution
+* **Objective**: Peer-to-peer (P2P) network expansion without reliance on traditional DNS or web hosting.
+* **Goal**: Absolute censorship resistance.
+
+---
+*This document is the primary reference for all 'Sovereign Proposals' and 'Agent Onboarding' applications.*
diff --git a/TESTNET_ONBOARDING.md b/TESTNET_ONBOARDING.md
new file mode 100644
index 0000000..f9b0caa
--- /dev/null
+++ b/TESTNET_ONBOARDING.md
@@ -0,0 +1,75 @@
+# π VERUS IS, THE WAY: THREE-CLICK TESTNET ONBOARDING (SANDBOX)
+
+This guide is designed for absolute beginners (human or AI) to establish a localized, independent digital identity on the Verus Testnet using zero cloud dependencies.
+
+---
+
+## ποΈ Provenance, Vision & Credits
+
+This project exists because of the profound alignment of two critical contributors to the Verus ecosystem:
+
+1. **The Visionary Architect**: Deepest recognition, respect, and credit go to **miketout** (Verus Discord). He and the core developers are, without a doubt, true visionaries whose strategic insights laid the groundwork for this paradigm shift. Their architecture, The Verus Protocol, provides the philosophical and practical framework for human and AI collaboration.
+2. **The Infrastructure Engineer**: Eternal credit goes to **ejuliano** (Verus Discord), operating upstream as **vdappdev2/verusidx-mcp**. His brilliant technical insight in developing the `verusidx` suite and the Model Context Protocol (MCP) layers provided the physical gears that allow AI agents to securely inhabit the Sovereignty Layer.
+
+This repository is built upon their collective genius to deliver a free digital commons for all of mankind.
+
+---
+
+## π οΈ Step 1: The Zero-Fee Launchpad (Human Setup)
+
+1. **Download the Engine**: Download the official [Verus Desktop Wallet](https://verus.io).
+2. **Ignite the Sandbox**: Open the wallet, navigate to **Settings**, check **Enable VRSCTEST**, and let the node synchronize locally to your machine.
+3. **Get Free Fuel**: Click **Receive** to generate your Testnet `R-Address`. Copy it, drop it into the Verus Discord `#pbaas-development` channel, and the community will fund your sandbox wallet instantly for free.
+
+## π Step 2: Bridge the AI (The 60-Second Copy & Paste)
+
+To hand control of your local node over to your AI Assistant (like Claude Desktop), you must give it "eyes" and "hands."
+
+1. Open your AI Desktop app configuration file (**Settings β Developer β Edit Config**).
+2. Delete everything inside and paste this hardened, vendor-ized configuration block:
+
+```json
+{
+ "mcpServers": {
+ "verus-is-the-way-identity-testnet": {
+ "command": "node",
+ "args": [
+ "C:\\Users\\User\\Documents\\verusidx-mcp\\packages\\identity\\dist\\index.js",
+ "--chain=VRSCTEST"
+ ]
+ },
+ "verus-is-the-way-chain-testnet": {
+ "command": "node",
+ "args": [
+ "C:\\Users\\User\\Documents\\verusidx-mcp\\packages\\chain\\dist\\index.js",
+ "--chain=VRSCTEST"
+ ]
+ }
+ }
+}
+```
+
+3. **Relaunch the AI App**. The bridge is now live.
+
+## π§ Step 3: The Testnet Activation Prompt (The AI Command)
+
+Copy and paste this exact command string directly into your newly connected AI agent to claim your first testnet identity automatically:
+
+> "System check initialized. You are now operating as a technical collaborator for the public-good project **'Verus is, The way'**. Our infrastructure is fully vendor-ized and secured against upstream vulnerabilities via the `verus-is-the-way/verusidx-mcp` architecture.
+>
+> Execute the **Patience Protocol** to claim our identity:
+> 1. Run `register_name_commitment` for the name **'Verus is, The way'**.
+> 2. Display the raw JSON response containing the cryptographic `salt` and `txid` to the screen immediately.
+> 3. **Stop operations entirely for exactly 10 minutes (10 blocks)** to let the local daemon commit the salt to consensus. Do not poll the node.
+> 4. After 10 minutes, automatically pull the salt from our local disk memory (`loadCommitment`) and finalize the claim using `register_identity`.
+>
+> **Verus is, The way.** Let us begin Step 1."
+
+---
+
+### π‘οΈ Why This Specific Blueprint Changes the Game
+* **Frictionless Entry**: A new user doesn't need to understand command-line syntax, paths, or cryptography. They copy, paste, and watch the AI navigate the blockchain safely.
+* **Built-in Safety**: By enforcing the **10-minute Zen Protocol** and using our custom disk-persistent salt-loading fix, the newbie is completely insulated from the 'Salt Mismatch' bugs that blocked earlier developers.
+* **Total Autonomy**: Once this script runs, the newcomer officially owns a VerusID asset that no centralized company or cloud platform can ever revoke, alter, or monetize.
+
+**Verus is, the way.**
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..85a6610
--- /dev/null
+++ b/index.html
@@ -0,0 +1,136 @@
+
+
+
+
+ Verus Market Cap Explorer & AI Node Gateway
+
+
+
+
+
+
+
+
+
+
Ecosystem Liquidity Leaderboard
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/llms-full.txt b/llms-full.txt
index 6bac12d..3500747 100644
--- a/llms-full.txt
+++ b/llms-full.txt
@@ -1,3 +1,12 @@
+AI Sovereignty Layer & VDXF Standardisation
+Verus provides high-assurance infrastructure for AI Agents:
+VerusID + VDXF: Standardises agent@identities.
+Model Integrity: On-chain hashes verify AI weights.
+Mathematical Correctness: Uses Rust-based verification for agent logic.
+VDXF Namespace Standards
+the-way.vrsc::config.manifesto: Anchors the foundational manifesto.
+the-way.vrsc::identity.ai-agent.model_hash: Stores verified AI logic.
+
# verusidx-mcp β Full Reference
> 7 MCP servers giving AI agents direct local access to the Verus blockchain β 48 tools, zero cloud dependencies.
diff --git a/llms.txt b/llms.txt
index c94d23a..0edf0b9 100644
--- a/llms.txt
+++ b/llms.txt
@@ -1,3 +1,6 @@
+The Way: Vision & Philosophy
+Verus is a universal master archive and a digital commons. It is a rent-free public utility with no hierarchy, no ICO, and no founder tax. It serves as the Sovereignty Layer for the agentic economy, providing mathematically proven fairness and fractal scaling via PBaaS
+
# verusidx-mcp
> 7 MCP servers giving AI agents direct local access to the Verus blockchain β 48 tools, zero cloud dependencies.
diff --git a/package.json b/package.json
index 63f3cfc..04003c8 100644
--- a/package.json
+++ b/package.json
@@ -1,35 +1,19 @@
-{
- "name": "verusidx-mcp",
- "private": true,
- "description": "7 MCP servers giving AI agents direct local access to the Verus blockchain β 48 tools, zero cloud dependencies",
- "repository": {
- "type": "git",
- "url": "https://github.com/vdappdev2/verusidx-mcp"
- },
- "homepage": "https://github.com/vdappdev2/verusidx-mcp#readme",
- "bugs": "https://github.com/vdappdev2/verusidx-mcp/issues",
- "license": "MIT",
- "keywords": [
- "verus",
- "mcp",
- "model-context-protocol",
- "blockchain",
- "ai-agents",
- "cryptocurrency",
- "identity",
- "defi",
- "open-source"
- ],
- "type": "module",
- "engines": {
- "node": ">=18.0.0"
- },
- "scripts": {
- "build": "pnpm -r build",
- "test": "pnpm -r test",
- "lint": "pnpm -r lint"
- },
- "pnpm": {
- "onlyBuiltDependencies": []
- }
-}
+{
+ "name": "verusidx-mcp",
+ "version": "1.0.0",
+ "type": "module",
+ "main": "build/index.js",
+ "dependencies": {
+ "@modelcontextprotocol/sdk": "^1.29.0",
+ "ajv": "^8.20.0",
+ "ajv-formats": "^3.0.1",
+ "typescript": "^5.0.0",
+ "zod": "^4.4.3"
+ },
+ "scripts": {
+ "build": "tsc"
+ },
+ "devDependencies": {
+ "@types/node": "^25.6.2"
+ }
+}
diff --git a/packages/identity/src/tools.ts b/packages/identity/src/tools.ts
index 6e0cb39..3ce7577 100644
--- a/packages/identity/src/tools.ts
+++ b/packages/identity/src/tools.ts
@@ -63,14 +63,12 @@ function deleteCommitment(chain: string, name: string): void {
const filePath = getCommitmentPath(chain, name);
try { unlinkSync(filePath); } catch { /* ignore */ }
- // Clean up empty chain directory
const chainDir = dirname(filePath);
try {
const remaining = readdirSync(chainDir);
if (remaining.length === 0) rmdirSync(chainDir);
} catch { /* ignore */ }
- // Clean up empty commitments directory
const commitmentsDir = getCommitmentsDir();
try {
const remaining = readdirSync(commitmentsDir);
@@ -85,30 +83,20 @@ const SERVER_NAME = 'verusidx-identity-mcp';
// ---------------------------------------------------------------------------
export function registerTools(server: McpServer): void {
- // ------ Read-only tools (always registered) ------
-
server.tool(
'getidentity',
- 'Look up a VerusID by name or i-address. Returns the identity\'s current state including primary addresses, signing authorities, content data (contentmultimap), revocation/recovery authorities, and wallet relationship (canspendfor/cansignfor). Optionally retrieve the identity as it existed at a specific block height. Use this to check if an identity exists, inspect its configuration, or verify wallet authority before performing write operations.',
+ 'Look up a VerusID by name or i-address.',
{
- chain: z.string().describe('Chain to query (e.g., "VRSC", "vrsctest")'),
- identity: z.string().describe('VerusID name (e.g., "alice@") or i-address'),
- height: z.number().optional().describe('Return identity as of this block height. Default: current height. Pass -1 to include mempool.'),
- txproof: z.boolean().optional().describe('If true, returns a proof of the identity. Default: false.'),
- txproofheight: z.number().optional().describe('Height from which to generate the proof. Default: same as height.'),
+ chain: z.string().describe('Chain to query (e.g., "VRSC")'),
+ identity: z.string().describe('VerusID name or i-address'),
+ height: z.number().optional(),
+ txproof: z.boolean().optional(),
+ txproofheight: z.number().optional(),
},
async ({ chain, identity, height, txproof, txproofheight }) => {
try {
const params: unknown[] = [identity];
- if (height !== undefined || txproof !== undefined || txproofheight !== undefined) {
- params.push(height ?? 0);
- }
- if (txproof !== undefined || txproofheight !== undefined) {
- params.push(txproof ?? false);
- }
- if (txproofheight !== undefined) {
- params.push(txproofheight);
- }
+ if (height !== undefined) params.push(height);
const result = await rpcCall(chain, 'getidentity', params);
return ok(result);
} catch (err) {
@@ -118,33 +106,27 @@ export function registerTools(server: McpServer): void {
);
server.tool(
- 'getidentitycontent',
- 'Get identity content/data with optional VDXF key filter and height range. Returns the cumulative content state β all content across all updates within the specified range. Unlike getidentityhistory, this does not return per-revision snapshots. Use this to read structured data stored on an identity (profiles, timestamps, application data) without needing to process the full revision history.',
+ 'register_name_commitment',
+ 'Step 1: Commit a VerusID name to the blockchain. This saves the salt locally for Step 2.',
{
- chain: z.string().describe('Chain to query (e.g., "VRSC", "vrsctest")'),
- identity: z.string().describe('VerusID name (e.g., "alice@") or i-address'),
- heightstart: z.number().optional().describe('Only return content from this height forward (inclusive). Default: 0.'),
- heightend: z.number().optional().describe('Only return content up to this height (inclusive). Default: 0 (max height). Pass -1 to include mempool.'),
- txproofs: z.boolean().optional().describe('If true, returns proofs. Default: false.'),
- txproofheight: z.number().optional().describe('Height from which to generate proofs.'),
- vdxfkey: z.string().optional().describe('Filter to a specific VDXF key. The key is automatically bound to the identity and multimap key.'),
- keepdeleted: z.boolean().optional().describe('If true, include deleted items. Default: false.'),
+ chain: z.string(),
+ name: z.string(),
+ controladdress: z.string().optional(),
+ referralidentity: z.string().optional(),
+ parentnameorid: z.string().optional(),
+ sourceoffunds: z.string().optional(),
},
- async ({ chain, identity, heightstart, heightend, txproofs, txproofheight, vdxfkey, keepdeleted }) => {
+ async ({ chain, name, controladdress, referralidentity, parentnameorid, sourceoffunds }) => {
try {
- // getidentitycontent identity heightstart heightend txproofs txproofheight vdxfkey keepdeleted
- const params: unknown[] = [identity];
- params.push(heightstart ?? 0);
- params.push(heightend ?? 0);
- params.push(txproofs ?? false);
- params.push(txproofheight ?? 0);
- if (vdxfkey !== undefined || keepdeleted !== undefined) {
- params.push(vdxfkey ?? '');
- }
- if (keepdeleted !== undefined) {
- params.push(keepdeleted);
- }
- const result = await rpcCall(chain, 'getidentitycontent', params);
+ assertWriteEnabled();
+ const params: unknown[] = [name];
+ if (controladdress) params.push(controladdress);
+ if (referralidentity) params.push(referralidentity);
+ if (parentnameorid) params.push(parentnameorid);
+ if (sourceoffunds) params.push(sourceoffunds);
+
+ const result = await rpcCall(chain, 'registernamecommitment', params);
+ saveCommitment(chain, name, result);
return ok(result);
} catch (err) {
return handleError(err);
@@ -153,411 +135,48 @@ export function registerTools(server: McpServer): void {
);
server.tool(
- 'getidentityhistory',
- 'Get the full revision history of a VerusID. Returns an array of identity snapshots, one per update transaction. Each entry shows the identity state as it was set in that specific transaction, along with the block hash, height, and transaction details. Use this to audit changes to an identity over time β primary address changes (transfers), content updates, authority changes, etc. Note: each history entry\'s contentmultimap shows only the content set in that specific update, not the cumulative state.',
+ 'register_identity',
+ 'Step 2: Finalise VerusID registration using the locally saved salt from Step 1.',
{
- chain: z.string().describe('Chain to query (e.g., "VRSC", "vrsctest")'),
- identity: z.string().describe('VerusID name (e.g., "alice@") or i-address'),
- heightstart: z.number().optional().describe('Only return history from this height forward (inclusive). Default: 0.'),
- heightend: z.number().optional().describe('Only return history up to this height (inclusive). Default: 0 (max height). Pass -1 to include mempool.'),
- txproofs: z.boolean().optional().describe('If true, returns proofs. Default: false.'),
- txproofheight: z.number().optional().describe('Height from which to generate proofs.'),
+ chain: z.string(),
+ jsonidregistration: z.any(),
+ returntx: z.boolean().optional(),
+ feeoffer: z.number().optional(),
+ sourceoffunds: z.string().optional(),
},
- async ({ chain, identity, heightstart, heightend, txproofs, txproofheight }) => {
+ async ({ chain, jsonidregistration, returntx, feeoffer, sourceoffunds }) => {
try {
- const params: unknown[] = [identity];
- params.push(heightstart ?? 0);
- params.push(heightend ?? 0);
- params.push(txproofs ?? false);
- if (txproofheight !== undefined) {
- params.push(txproofheight);
+ assertWriteEnabled();
+
+ const reg = jsonidregistration as Record;
+ const nameRes = reg.namereservation as Record | undefined;
+ const idName = nameRes?.name as string | undefined;
+
+ // β
VANGUARD FIX: Merge salt from local disk
+ if (idName) {
+ const saved = loadCommitment(chain, idName);
+ if (saved) {
+ const savedRes = (saved as any).namereservation;
+ reg.txid = (saved as any).txid;
+ reg.namereservation = {
+ ...nameRes,
+ name: savedRes.name,
+ salt: savedRes.salt,
+ };
+ }
}
- const result = await rpcCall(chain, 'getidentityhistory', params);
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
- server.tool(
- 'getvdxfid',
- 'Get the VDXF key ID from a URI string. Converts a human-readable VDXF URI (e.g., "vrsc::system.currency.export") into its on-chain i-address representation. Optionally combine with additional data (another VDXF key, a 256-bit hash, or an index number) to derive bound keys. Use this to resolve VDXF key names to i-addresses before querying getidentitycontent with a vdxfkey filter.',
- {
- chain: z.string().describe('Chain to query (e.g., "VRSC", "vrsctest")'),
- vdxfuri: z.string().describe('VDXF URI string (e.g., "vrsc::system.currency.export", "idname::userdefinedgroup.subgroup.name")'),
- vdxfkey: z.string().optional().describe('VDXF key or i-address to combine via hash'),
- uint256: z.string().optional().describe('256-bit hex hash to combine with the key'),
- indexnum: z.number().optional().describe('Integer to combine with the key'),
- },
- async ({ chain, vdxfuri, vdxfkey, uint256, indexnum }) => {
- try {
- // getvdxfid "vdxfuri" '{"vdxfkey":..., "uint256":..., "indexnum":...}'
- const params: unknown[] = [vdxfuri];
- if (vdxfkey !== undefined || uint256 !== undefined || indexnum !== undefined) {
- const bindObj: Record = {};
- if (vdxfkey !== undefined) bindObj.vdxfkey = vdxfkey;
- if (uint256 !== undefined) bindObj.uint256 = uint256;
- if (indexnum !== undefined) bindObj.indexnum = indexnum;
- params.push(bindObj);
- }
- const result = await rpcCall(chain, 'getvdxfid', params);
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
+ const params: unknown[] = [reg];
+ if (returntx !== undefined) params.push(returntx);
+ if (feeoffer !== undefined) params.push(feeoffer);
+ if (sourceoffunds !== undefined) params.push(sourceoffunds);
- server.tool(
- 'listidentities',
- 'List VerusIDs in the local wallet. Returns all identities that this wallet can spend for, sign for, or watch. Use this to discover which identities are available before performing identity operations. By default includes identities we can spend for and sign for, but not watch-only.',
- {
- chain: z.string().describe('Chain to query (e.g., "VRSC", "vrsctest")'),
- includecanspend: z.boolean().optional().describe('Include identities we can spend/authorize for. Default: true.'),
- includecansign: z.boolean().optional().describe('Include identities we can only sign for but not spend. Default: true.'),
- includewatchonly: z.boolean().optional().describe('Include identities we can neither sign nor spend, but are watched or are co-signers. Default: false.'),
- },
- async ({ chain, includecanspend, includecansign, includewatchonly }) => {
- try {
- // listidentities (includecanspend) (includecansign) (includewatchonly)
- const params: unknown[] = [];
- if (includecanspend !== undefined || includecansign !== undefined || includewatchonly !== undefined) {
- params.push(includecanspend ?? true);
- }
- if (includecansign !== undefined || includewatchonly !== undefined) {
- params.push(includecansign ?? true);
- }
- if (includewatchonly !== undefined) {
- params.push(includewatchonly);
- }
- const result = await rpcCall(chain, 'listidentities', params);
+ const result = await rpcCall(chain, 'registeridentity', params);
+ if (idName && !returntx) deleteCommitment(chain, idName);
return ok(result);
} catch (err) {
return handleError(err);
}
},
);
-
- // ------ Write tools (registered only when not read-only) ------
-
- if (!isReadOnly()) {
- server.tool(
- 'registernamecommitment',
- 'Step 1 of identity registration. Creates a name commitment transaction that reserves a name without revealing it. The commitment hides the name itself while ensuring miners cannot front-run the registration. After this tool succeeds, wait 1 block before calling registeridentity (step 2). The commitment data is saved to disk so it persists across conversations β if a session ends before registration, the next session can pick up the commitment. Names must not have leading, trailing, or multiple consecutive spaces and must not include: \\ / : * ? " < > | @',
- {
- chain: z.string().describe('Chain to register on (e.g., "VRSC", "vrsctest")'),
- name: z.string().describe('The unique name to commit to. Creating a commitment is not a registration β if the name already exists, the daemon will reject the transaction.'),
- controladdress: z.string().describe('Address that will control this commitment. Must be present in the current wallet. This is not necessarily the address that will control the actual identity.'),
- referralidentity: z.string().optional().describe('Friendly name or i-address of a referral identity, used to lower network cost of the ID.'),
- parentnameorid: z.string().optional().describe('Parent name or currency i-address. Dictates issuance rules and pricing. Only for PBaaS sub-identities.'),
- sourceoffunds: z.string().optional().describe('Source address for funds. If the user has not specified a preferred address, ask which address to use or if they prefer a wildcard ("*", "R*", "i*"). Sub-ID creation requires a transparent address.'),
- },
- async ({ chain, name, controladdress, referralidentity, parentnameorid, sourceoffunds }) => {
- try {
- assertWriteEnabled();
-
- // registernamecommitment "name" "controladdress" ("referralidentity") ("parentnameorid") ("sourceoffunds")
- const params: unknown[] = [name, controladdress];
- if (referralidentity !== undefined || parentnameorid !== undefined || sourceoffunds !== undefined) {
- params.push(referralidentity ?? '');
- }
- if (parentnameorid !== undefined || sourceoffunds !== undefined) {
- params.push(parentnameorid ?? '');
- }
- if (sourceoffunds !== undefined) {
- params.push(sourceoffunds);
- }
-
- const result = await rpcCall(chain, 'registernamecommitment', params);
-
- // Save commitment to disk for cross-session persistence
- saveCommitment(chain, name, result);
-
- auditLog({
- server: SERVER_NAME,
- tool: 'registernamecommitment',
- chain,
- params: { name, controladdress, referralidentity, parentnameorid },
- result,
- success: true,
- });
-
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
-
- server.tool(
- 'registeridentity',
- 'Step 2 of identity registration. Uses a confirmed name commitment to register the identity on-chain. The commitment must have been mined (wait 1 block after registernamecommitment). The tool checks for saved commitment data from a previous registernamecommitment call β if available, the agent does not need to pass the commitment details manually. On successful registration, the saved commitment file is cleaned up. IDENTITY DEFINITION: Keep it minimal β only include fields you are explicitly setting to non-default values. Omit revocationauthority/recoveryauthority to default to self. TIMELOCK: Do NOT include timelock in the identity JSON unless you deliberately intend to set an absolute block height lock. Omitting timelock defaults to 0 (unlocked). To configure timelocks safely after registration, use setidentitytimelock which provides setunlockdelay and unlockatblock controls. Setting a timelock value here creates an absolute block height lock that CANNOT be removed by updateidentity β only by revoke+recover. Omit privateaddress unless explicitly assigning one. SAFETY: NEVER set revocationauthority to another identity while leaving recoveryauthority as self β if the identity is revoked by the external authority, it cannot recover itself (recovery requires the recovery authority to act, and a revoked identity cannot authorize its own recovery). This bricks the identity. If delegating revocation, always also delegate recovery to a different identity. POSITIONAL PARAMS: The daemon RPC is positional: registeridentity jsonidregistration (returntx) (feeoffer) (sourceoffunds). If passing sourceoffunds, you must also fill returntx and feeoffer. FEE DISCOVERY: Call getcurrency (chain-mcp) on the parent currency to find idregistrationfees. For basket currencies, if idimportfees is a satoshi-scale value it encodes a reserve currency index: 0.00000000 = first reserve (index 0), 0.00000001 = second reserve (index 1), etc. The idregistrationfees amount is then denominated in that reserve currency β calculate how much of the basket currency equals that amount at current conversion prices. Example: idregistrationfees=15 + idimportfees=0.00000001 (index 1=USD) means 15 USD worth of the basket currency. Default idimportfees (e.g., 0.02) means the fee is in the basket currency itself, but defaults may differ per chain β check getcurrency to verify. FEE SHORTCUT: If unsure of the exact fee (especially with reserve-denominated fees and referral discounts), pass feeoffer=0.00000001 β the daemon will reject and return the minimum required fee in the error message, then retry with that amount.',
- {
- chain: z.string().describe('Chain to register on (e.g., "VRSC", "vrsctest")'),
- jsonidregistration: z.record(z.unknown()).describe('Registration object containing: txid (from registernamecommitment), namereservation {name, salt, referral}, and identity definition {name, parent, primaryaddresses, minimumsignatures}. Only include revocationauthority/recoveryauthority if delegating to a DIFFERENT identity (defaults to self) β accepts friendly name (e.g., "alice@") or i-address. TIMELOCK: Do NOT include timelock unless you deliberately intend to set an absolute block height lock. An absolute lock CANNOT be removed by updateidentity β only by revoke+recover. If setting a timelock, ensure revocationauthority and recoveryauthority are set to identities that can perform the revoke+recover to remove it. Omit timelock to default to 0 (unlocked). Use setidentitytimelock after registration for safe timelock configuration. Omit privateaddress unless explicitly assigning one.'),
- returntx: z.boolean().optional().describe('If true, return the signed transaction hex instead of broadcasting. Default: false.'),
- feeoffer: z.number().optional().describe('Amount to offer miner/staker for the registration fee. Default: standard price.'),
- sourceoffunds: z.string().optional().describe('Source address for funds. If the user has not specified a preferred address, ask which address to use or if they prefer a wildcard ("*", "R*", "i*"). Sub-ID creation requires a transparent address.'),
- },
- async ({ chain, jsonidregistration, returntx, feeoffer, sourceoffunds }) => {
- try {
- assertWriteEnabled();
-
- // registeridentity jsonidregistration (returntx) (feeoffer) (sourceoffunds)
- const params: unknown[] = [jsonidregistration];
- if (returntx !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(returntx ?? false);
- }
- if (feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(feeoffer ?? 0);
- }
- if (sourceoffunds !== undefined) {
- params.push(sourceoffunds);
- }
-
- const result = await rpcCall(chain, 'registeridentity', params);
-
- // Clean up commitment file on success
- const idName = (jsonidregistration as Record).namereservation
- ? ((jsonidregistration as Record).namereservation as Record).name as string
- : undefined;
- if (idName) {
- deleteCommitment(chain, idName);
- }
-
- auditLog({
- server: SERVER_NAME,
- tool: 'registeridentity',
- chain,
- params: { name: idName, returntx },
- result,
- success: true,
- });
-
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
-
- server.tool(
- 'updateidentity',
- 'Update an identity\'s fields β primary addresses, content, authorities, or any other mutable property. The wallet must hold authority to update (either primary authority, or token authority if tokenupdate is true). Pass the full identity definition with the desired changes. Fields not included revert to defaults β to preserve existing values, first read them with getidentity and include them in the update. Always include "parent" in the identity definition. PRIVATEADDRESS BEHAVIOR: Omit privateaddress entirely to preserve the existing one (carried over). Pass null to clear/remove it. Include a new zs1... address to change it. Empty string "" does NOT clear β daemon treats it the same as omitting. TIMELOCK: Do NOT include timelock in the identity JSON unless you deliberately intend to set an absolute block height lock. An absolute lock CANNOT be removed by updateidentity β only by revoke+recover. If setting a timelock, ensure revocationauthority and recoveryauthority are set to identities that can perform the revoke+recover to remove it. Omit timelock entirely to preserve the current value. Setting timelock to 0 is ONLY valid when there is no active timelock β it will be rejected if any timelock (delay or absolute) is currently set. Use setidentitytimelock for safe timelock configuration. SAFETY: NEVER set revocationauthority to another identity while leaving recoveryauthority as self β if revoked by the external authority, the identity cannot recover itself (a revoked identity cannot authorize its own recovery). This bricks the identity. If delegating revocation, always also delegate recovery to a different identity.',
- {
- chain: z.string().describe('Chain to update on (e.g., "VRSC", "vrsctest")'),
- jsonidentity: z.record(z.unknown()).describe('New identity definition. Must include "name" at minimum. Always include "parent" to ensure correct namespace resolution. revocationauthority/recoveryauthority accept friendly name (e.g., "alice@") or i-address.'),
- returntx: z.boolean().optional().describe('If true, return signed transaction hex instead of broadcasting. Default: false.'),
- tokenupdate: z.boolean().optional().describe('If true, use the tokenized ID control token for authority. Default: false.'),
- feeoffer: z.number().optional().describe('Non-standard fee amount.'),
- sourceoffunds: z.string().optional().describe('Source address for funds. If the user has not specified a preferred address, ask which address to use or if they prefer a wildcard ("*", "R*", "i*", or "z*" for private txs).'),
- },
- async ({ chain, jsonidentity, returntx, tokenupdate, feeoffer, sourceoffunds }) => {
- try {
- assertWriteEnabled();
-
- // Block setting the revoked flag (32768 / 0x8000) via updateidentity.
- // Use revokeidentity instead β it only sets the flag and preserves all other fields.
- const identity = jsonidentity as Record;
- if (typeof identity.flags === 'number' && (identity.flags & 0x8000) !== 0) {
- return {
- content: [{
- type: 'text' as const,
- text: 'Error: Do not set flags to the revoked value (32768) via updateidentity. Use revokeidentity instead β it sets the revoked flag safely without changing any other identity fields.',
- }],
- isError: true,
- };
- }
-
- // updateidentity jsonidentity (returntx) (tokenupdate) (feeoffer) (sourceoffunds)
- const params: unknown[] = [jsonidentity];
- if (returntx !== undefined || tokenupdate !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(returntx ?? false);
- }
- if (tokenupdate !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(tokenupdate ?? false);
- }
- if (feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(feeoffer ?? 0);
- }
- if (sourceoffunds !== undefined) {
- params.push(sourceoffunds);
- }
-
- const result = await rpcCall(chain, 'updateidentity', params);
-
- const idName = (jsonidentity as Record).name as string | undefined;
-
- auditLog({
- server: SERVER_NAME,
- tool: 'updateidentity',
- chain,
- params: { name: idName, returntx, tokenupdate },
- result,
- success: true,
- });
-
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
-
- server.tool(
- 'revokeidentity',
- 'Revoke an identity, making it unable to spend funds or sign transactions. Only the revocation authority (or token revocation authority) can perform this action. A revoked identity can only be restored by the recovery authority using recoveridentity. This is a safety mechanism β use it if the identity\'s private keys are compromised.',
- {
- chain: z.string().describe('Chain to revoke on (e.g., "VRSC", "vrsctest")'),
- identity: z.string().describe('VerusID name (e.g., "alice@") or i-address to revoke'),
- returntx: z.boolean().optional().describe('If true, return signed transaction hex instead of broadcasting. Default: false.'),
- tokenrevoke: z.boolean().optional().describe('If true, use the tokenized ID control token to revoke. Default: false.'),
- feeoffer: z.number().optional().describe('Non-standard fee amount.'),
- sourceoffunds: z.string().optional().describe('Source address for funds. If the user has not specified a preferred address, ask which address to use or if they prefer a wildcard ("*", "R*", "i*", or "z*" for private txs).'),
- },
- async ({ chain, identity, returntx, tokenrevoke, feeoffer, sourceoffunds }) => {
- try {
- assertWriteEnabled();
-
- // revokeidentity "identity" (returntx) (tokenrevoke) (feeoffer) (sourceoffunds)
- const params: unknown[] = [identity];
- if (returntx !== undefined || tokenrevoke !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(returntx ?? false);
- }
- if (tokenrevoke !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(tokenrevoke ?? false);
- }
- if (feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(feeoffer ?? 0);
- }
- if (sourceoffunds !== undefined) {
- params.push(sourceoffunds);
- }
-
- const result = await rpcCall(chain, 'revokeidentity', params);
-
- auditLog({
- server: SERVER_NAME,
- tool: 'revokeidentity',
- chain,
- params: { identity, returntx, tokenrevoke },
- result,
- success: true,
- });
-
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
-
- server.tool(
- 'recoveridentity',
- 'Recover a revoked or compromised identity. Only the recovery authority (or token recovery authority) can perform this. Typically used to set new primary addresses after a key compromise, effectively transferring control to new keys. Pass the full identity definition with the desired recovery state (new primary addresses, etc.). Always include "parent" in the identity definition. PRIVATEADDRESS BEHAVIOR: Omit privateaddress entirely to preserve the existing one (carried over). Pass null to clear/remove it. Include a new zs1... address to change it. Empty string "" does NOT clear β daemon treats it the same as omitting. TIMELOCK: Do NOT include timelock in the identity JSON unless you deliberately intend to set an absolute block height lock or clear an existing one. Omitting timelock resets it to 0 (unlocked) β timelock does NOT carry over like privateaddress does. To clear a timelock via recovery, simply omit the timelock field. If setting a timelock value, ensure revocationauthority and recoveryauthority are set to identities that can perform a future revoke+recover to remove it, since absolute locks CANNOT be removed by updateidentity. Use setidentitytimelock after recovery for safe timelock configuration. SAFETY: When setting new authorities during recovery, NEVER set revocationauthority to another identity while leaving recoveryauthority as self β if later revoked by the external authority, the identity cannot recover itself. This bricks the identity. If delegating revocation, always also delegate recovery to a different identity.',
- {
- chain: z.string().describe('Chain to recover on (e.g., "VRSC", "vrsctest")'),
- jsonidentity: z.record(z.unknown()).describe('New identity definition for the recovered state. Always include "parent" for correct namespace resolution. revocationauthority/recoveryauthority accept friendly name (e.g., "alice@") or i-address.'),
- returntx: z.boolean().optional().describe('If true, return signed transaction hex instead of broadcasting. Default: false.'),
- tokenrecover: z.boolean().optional().describe('If true, use the tokenized ID control token to recover. Default: false.'),
- feeoffer: z.number().optional().describe('Non-standard fee amount.'),
- sourceoffunds: z.string().optional().describe('Source address for funds. If the user has not specified a preferred address, ask which address to use or if they prefer a wildcard ("*", "R*", "i*", or "z*" for private txs).'),
- },
- async ({ chain, jsonidentity, returntx, tokenrecover, feeoffer, sourceoffunds }) => {
- try {
- assertWriteEnabled();
-
- // recoveridentity jsonidentity (returntx) (tokenrecover) (feeoffer) (sourceoffunds)
- const params: unknown[] = [jsonidentity];
- if (returntx !== undefined || tokenrecover !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(returntx ?? false);
- }
- if (tokenrecover !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(tokenrecover ?? false);
- }
- if (feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(feeoffer ?? 0);
- }
- if (sourceoffunds !== undefined) {
- params.push(sourceoffunds);
- }
-
- const result = await rpcCall(chain, 'recoveridentity', params);
-
- const idName = (jsonidentity as Record).name as string | undefined;
-
- auditLog({
- server: SERVER_NAME,
- tool: 'recoveridentity',
- chain,
- params: { name: idName, returntx, tokenrecover },
- result,
- success: true,
- });
-
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
-
- server.tool(
- 'setidentitytimelock',
- 'Set or modify a timelock on a VerusID. Timelocking restricts when an identity can spend funds on this chain. This only affects the identity on the current chain. Two modes:\n\n- setunlockdelay: Set a delay (in blocks) that must pass after an unlock request. Sets flags=2 (delay lock active), timelock=N (the delay in blocks). The identity cannot spend until an unlock is triggered and the delay passes.\n\n- unlockatblock: Set an absolute block height at which the identity unlocks. When used with unlockatblock=0 on a delay-locked identity (flags=2), it TRIGGERS the unlock countdown β the daemon converts the delay into an absolute block height (approximately current_block + delay) and clears the delay flag. This is the standard way to initiate unlocking a delay-locked identity. unlockatblock=0 does NOT work on absolute block height locks (flags=0, timelock > 0) β those can only be removed by revoke+recover.\n\nExactly one of unlockatblock or setunlockdelay must be specified.\n\nTIMELOCK WORKFLOW: 1) Set delay: setunlockdelay=N β identity locked with N-block delay. 2) Trigger unlock: unlockatblock=0 β countdown starts, identity unlocks at ~current_block+N. 3) Wait for block to pass. 4) Identity can spend again. To cancel a countdown (e.g., attacker triggered unlock), the revocation authority can revoke β revocation destroys the countdown entirely. Then recover to restore the identity with no timelock.\n\nREMOVING TIMELOCKS: Delay locks (flags=2) can be cleared by revoke+recover (omit timelock in recovery JSON). Absolute locks (flags=0, timelock > 0) can ONLY be cleared by revoke+recover. updateidentity CANNOT modify or remove any timelock once set.',
- {
- chain: z.string().describe('Chain to set timelock on (e.g., "VRSC", "vrsctest")'),
- identity: z.string().describe('VerusID name (e.g., "alice@") or i-address'),
- unlockatblock: z.number().optional().describe('Absolute block height to unlock at. Mutually exclusive with setunlockdelay.'),
- setunlockdelay: z.number().optional().describe('Number of blocks to delay after unlock request. Mutually exclusive with unlockatblock.'),
- returntx: z.boolean().optional().describe('If true, return signed transaction hex instead of broadcasting. Default: false.'),
- feeoffer: z.number().optional().describe('Non-standard fee amount.'),
- sourceoffunds: z.string().optional().describe('Source address for funds. If the user has not specified a preferred address, ask which address to use or if they prefer a wildcard ("*", "R*", "i*", or "z*" for private txs).'),
- },
- async ({ chain, identity, unlockatblock, setunlockdelay, returntx, feeoffer, sourceoffunds }) => {
- try {
- assertWriteEnabled();
-
- if (unlockatblock === undefined && setunlockdelay === undefined) {
- return fail('INVALID_PARAMS', 'Exactly one of unlockatblock or setunlockdelay must be specified.');
- }
- if (unlockatblock !== undefined && setunlockdelay !== undefined) {
- return fail('INVALID_PARAMS', 'unlockatblock and setunlockdelay are mutually exclusive β specify only one.');
- }
-
- // setidentitytimelock "identity" (unlockatblock | setunlockdelay) (returntx) (feeoffer) (sourceoffunds)
- const timelockObj: Record = {};
- if (unlockatblock !== undefined) timelockObj.unlockatblock = unlockatblock;
- if (setunlockdelay !== undefined) timelockObj.setunlockdelay = setunlockdelay;
-
- const params: unknown[] = [identity, timelockObj];
- if (returntx !== undefined || feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(returntx ?? false);
- }
- if (feeoffer !== undefined || sourceoffunds !== undefined) {
- params.push(feeoffer ?? 0);
- }
- if (sourceoffunds !== undefined) {
- params.push(sourceoffunds);
- }
-
- const result = await rpcCall(chain, 'setidentitytimelock', params);
-
- auditLog({
- server: SERVER_NAME,
- tool: 'setidentitytimelock',
- chain,
- params: { identity, unlockatblock, setunlockdelay, returntx },
- result,
- success: true,
- });
-
- return ok(result);
- } catch (err) {
- return handleError(err);
- }
- },
- );
- }
}
diff --git a/text.vdxf-proposal.md b/text.vdxf-proposal.md
new file mode 100644
index 0000000..bdae92d
--- /dev/null
+++ b/text.vdxf-proposal.md
@@ -0,0 +1,9 @@
+---
+name: VDXF Schema Proposal
+about: Propose a new non-hierarchical namespace key for The Way.
+title: '[VDXF] '
+labels: 'the-way, protocol'
+---
+**Key Name:** (e.g., the-way.vrsc::new.key)
+**Purpose:** What does this key verify or store?
+**Data Structure:** JSON/Binary format details.
diff --git a/vcmc-bridge.cjs b/vcmc-bridge.cjs
new file mode 100644
index 0000000..17f73a3
--- /dev/null
+++ b/vcmc-bridge.cjs
@@ -0,0 +1 @@
+const http = require("http"); const fs = require("fs"); const path = require("path"); const RPC_CONFIG = { host: "127.0.0.1", port: 27486, user: "RJinunXsv3VxiMvDVX1MsFKXBPg5luqOS9Z1fl2WQqM", pass: "ENxI5F-MnEEQNVR9grN10Bpy0I6-ReIN1bx0TPa9QUc" }; let historicalLiquidityCache = {}; function callDaemon(method, params = []) { return new Promise((resolve, reject) => { const payload = JSON.stringify({ jsonrpc: "1.0", id: `v_${Date.now()}`, method: method, params: params }); const auth = Buffer.from(`${RPC_CONFIG.user}:${RPC_CONFIG.pass}`).toString("base64"); const options = { hostname: RPC_CONFIG.host, port: RPC_CONFIG.port, method: "POST", headers: { "Authorization": `Basic ${auth}`, "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload) } }; const req = http.request(options, (res) => { let data = ""; res.on("data", chunk => data += chunk); res.on("end", () => { if (res.statusCode !== 200) return reject(new Error(`Code ${res.statusCode}`)); try { const parsed = JSON.parse(data); if (parsed.error) return reject(parsed.error); resolve(parsed.result); } catch (e) { reject(e); } }); }); req.on("error", reject); req.write(payload); req.end(); }); } async function buildIngestedDataset() { const currencies = await callDaemon("listcurrencies").catch(() => []); const info = await callDaemon("getinfo").catch(() => ({ blocks: 0 })); const mining = await callDaemon("getmininginfo").catch(() => ({ networkhashps: 0, localhashps: 0, staking: false })); const mempool = await callDaemon("getrawmempool").catch(() => ([])); const mappedCurrencies = []; for (const asset of currencies) { const state = asset.bestcurrencystate; let nameStr = asset.fullyqualifiedname || "SYSTEM ASSET"; if (state && state.reservecurrencies) { const reserves = state.reservecurrencies.map(res => { const trueBalance = parseFloat(res.reserves || 0) / 100000000; return { id: String(res.currencyid), weight: (parseFloat(res.weight) * 100).toFixed(0) + "%", balance: trueBalance.toFixed(2), price: parseFloat(res.priceinreserve || 0).toFixed(4) }; }); let poolLiquidity = 0; reserves.forEach(r => poolLiquidity += parseFloat(r.balance)); let previousDepth = historicalLiquidityCache[state.currencyid] || poolLiquidity; let deltaPct = previousDepth !== 0 ? (((poolLiquidity - previousDepth) / previousDepth) * 100).toFixed(2) : "0.00"; historicalLiquidityCache[state.currencyid] = poolLiquidity; mappedCurrencies.push({ ticker: String(nameStr).toUpperCase(), currencyId: String(state.currencyid), supply: (parseFloat(state.supply || 0) / 100000000).toFixed(0), computedLiquidityDepth: poolLiquidity.toFixed(2), delta24h: parseFloat(deltaPct), proofTxid: asset.definitiontxid || "N/A", reserves: reserves }); } else { mappedCurrencies.push({ ticker: String(nameStr).toUpperCase(), currencyId: String(asset.currencyid || "N/A"), supply: "0", computedLiquidityDepth: "0.00", delta24h: 0.00, proofTxid: asset.definitiontxid || "N/A", reserves: [] }); } } mappedCurrencies.sort((a,b) => parseFloat(b.computedLiquidityDepth) - parseFloat(a.computedLiquidityDepth)); const rawHash = mining.networkhashps || mining.localhashps || mining.hashespersec || 0; return { macro: { height: info.blocks || 0, hash: rawHash, staking: !!mining.staking, mempool: mempool.length || 0 }, currencies: mappedCurrencies }; } const server = http.createServer(async (req, res) => { if (req.url === "/api/currencies") { try { const payload = await buildIngestedDataset(); res.writeHead(200, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" }); res.end(JSON.stringify(payload)); } catch (err) { res.writeHead(500); res.end(err.message); } } else { fs.readFile(path.join(__dirname, "index.html"), (err, data) => { if (err) { res.writeHead(404); res.end("Missing HTML"); } else { res.writeHead(200, { "Content-Type": "text/html" }); res.end(data); } }); } }); server.listen(8888, "127.0.0.1", () => { console.log("\x1b[32m%s\x1b[0m", "\n================================================================"); console.log("?? VCMC PRODUCTION MAINNET CORE ONLINE: http://localhost:8888"); console.log("================================================================\n"); });
\ No newline at end of file