vtimestamp_verify
Verify file or text timestamps on the Verus blockchain using SHA-256 hashes. Check if content has been recorded on-chain and retrieve proof details for verification.
Instructions
Verify whether a file or text has been timestamped on a VerusID. Provide either a file_path or text — the server computes the SHA-256 hash and checks it against the on-chain record. Returns blockchain proof details if found.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| identity | Yes | VerusID name (e.g., "alice@") | |
| file_path | No | Path to a file to verify. Mutually exclusive with text. | |
| text | No | Text string to verify. Mutually exclusive with file_path. |
Implementation Reference
- src/tools.ts:24-159 (handler)Registration and handler implementation for the vtimestamp_verify tool.
server.tool( 'vtimestamp_verify', 'Verify whether a file or text has been timestamped on a VerusID. Provide either a file_path or text — the server computes the SHA-256 hash and checks it against the on-chain record. Returns blockchain proof details if found.', { identity: z.string().describe('VerusID name (e.g., "alice@")'), file_path: z.string().optional().describe('Path to a file to verify. Mutually exclusive with text.'), text: z.string().optional().describe('Text string to verify. Mutually exclusive with file_path.'), }, async ({ identity, file_path, text }) => { if (!isValidIdentity(identity)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid identity format — must be a VerusID name ending with @ (e.g., "alice@")' ); } // Validate exactly one input mode if (!file_path && !text) { throw new McpError( ErrorCode.InvalidParams, 'Must provide either file_path or text' ); } if (file_path && text) { throw new McpError( ErrorCode.InvalidParams, 'Only one of file_path or text may be provided — they are mutually exclusive' ); } // Resolve hash from the provided input let hash: string; if (file_path) { try { const fileBuffer = await readFile(file_path); hash = sha256(fileBuffer); } catch (err) { throw new McpError( ErrorCode.InvalidParams, `Failed to read file: ${err instanceof Error ? err.message : 'Unknown error'}` ); } } else { hash = sha256(text!); } try { const keys = getVdxfKeys(); const historyResponse = await getIdentityHistory(identity); const timestamp = findTimestampByHash(historyResponse.history, hash, keys); if (!timestamp) { return { content: [ { type: 'text' as const, text: JSON.stringify( { verified: false, identity: historyResponse.fullyqualifiedname, hash, message: `No timestamp matching this hash was found on identity ${historyResponse.fullyqualifiedname}`, }, null, 2 ), }, ], }; } let blocktime: number | undefined; try { const block = await getBlock(timestamp.blockhash); blocktime = block.time; } catch { // Block time is optional } return { content: [ { type: 'text' as const, text: JSON.stringify( { verified: true, identity: historyResponse.fullyqualifiedname, hash: timestamp.data.sha256, title: timestamp.data.title, description: timestamp.data.description ?? null, filename: timestamp.data.filename ?? null, filesize: timestamp.data.filesize ?? null, block_height: timestamp.blockheight, block_time: blocktime ? new Date(blocktime * 1000).toISOString() : null, block_hash: timestamp.blockhash, transaction_id: timestamp.txid, }, null, 2 ), }, ], }; } catch (err) { if (err instanceof VerusRpcError && err.code === RPC_ERROR_CODES.IDENTITY_NOT_FOUND) { return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Identity '${identity}' not found`, }), }, ], isError: true, }; } if (err instanceof McpError) throw err; return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Failed to verify timestamp: ${err instanceof Error ? err.message : 'Unknown error'}`, }), }, ], isError: true, }; } } );