This sandbox demonstrates the complete PTVS v1.0 verification flow: from physical asset inspection to on-chain Verifiable Claim injection. All computations happen in your browser using the Web Crypto API. No data is sent to any server. When you’re ready to integrate PTVS into production, visit our documentation or contact our technical team.
Interactive Playground
PTVS v1.0 Verification Flow Simulator
Complete the 6 steps below to generate a mock Verifiable Claim
Step 1: Define the Asset
Integration Examples
Ready to integrate PTVS into your platform? Here are code examples in Python, JavaScript, and Solidity.
# Install: pip install pycryptodome web3 from Crypto.Hash import SHA256 import json from web3 import Web3 # 1. Create canonical JSON inspection_data = { "assetId": "0x1a2b3c4d5e6f", "inspectionDate": "2026-08-15T10:30:00Z", "ptceId": "PTCE-0161", "ptvsScore": 85, "findings": { "structural": {"cracks": 0, "corrosion": 1}, "legal": {"encumbrances": 0, "titleClear": True} } } # 2. Canonicalize (sorted keys, no whitespace) canonical_json = json.dumps(inspection_data, sort_keys=True, separators=(',', ':')) # 3. Compute SHA-256 hash hash_obj = SHA256.new(canonical_json.encode('utf-8')) forensic_hash = hash_obj.hexdigest() # 4. Inject claim on-chain w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/YOUR_KEY')) contract = w3.eth.contract(address='0x...', abi=PTVS_ABI) tx_hash = contract.functions.injectClaim( inspection_data['assetId'], inspection_data['ptvsScore'], bytes.fromhex(forensic_hash), 1692095400, b'' ).transact({'from': ptce_address})
// Install: npm install web3 const Web3 = require('web3'); const crypto = require('crypto'); // 1. Create canonical JSON const inspectionData = { assetId: '0x1a2b3c4d5e6f', inspectionDate: '2026-08-15T10:30:00Z', ptceId: 'PTCE-0161', ptvsScore: 85, findings: { structural: { cracks: 0, corrosion: 1 }, legal: { encumbrances: 0, titleClear: true } } }; // 2. Canonicalize (sorted keys, no whitespace) const canonicalJson = JSON.stringify(inspectionData, Object.keys(inspectionData).sort().reduce((obj, key) => { obj[key] = inspectionData[key]; return obj; }, {}), null, 0 ); // 3. Compute SHA-256 hash const forensicHash = crypto .createHash('sha256') .update(canonicalJson) .digest('hex'); // 4. Inject claim on-chain const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_KEY'); const contract = new web3.eth.Contract(PTVS_ABI, '0x...'); const tx = await contract.methods.injectClaim( inspectionData.assetId, inspectionData.ptvsScore, '0x' + forensicHash, Math.floor(Date.now() / 1000), '0x' ).send({ from: ptceAddress });
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/Ownable.sol"; contract PTVSClaimInjector is Ownable { struct VerifiableClaim { bytes32 assetId; uint8 ptvsScore; bytes32 forensicHash; uint256 inspectionTimestamp; address ptceAddress; ClaimStatus status; } enum ClaimStatus { VERIFIED, CONDITIONAL, EXPIRED, REVOKED } mapping(bytes32 => VerifiableClaim) public claims; mapping(address => bool) public authorizedPTCEs; event ClaimInjected( bytes32 indexed assetId, uint8 ptvsScore, bytes32 forensicHash, address indexed ptceAddress, uint256 timestamp ); modifier onlyAuthorizedPTCE() { require(authorizedPTCEs[msg.sender], "Not authorized"); _; } function injectClaim( bytes32 assetId, uint8 ptvsScore, bytes32 forensicHash, uint256 inspectionTimestamp, bytes memory ptceSignature ) external onlyAuthorizedPTCE { ClaimStatus status = ptvsScore >= 70 ? ClaimStatus.VERIFIED : ClaimStatus.REVOKED; claims[assetId] = VerifiableClaim({ assetId: assetId, ptvsScore: ptvsScore, forensicHash: forensicHash, inspectionTimestamp: inspectionTimestamp, ptceAddress: msg.sender, status: status }); emit ClaimInjected( assetId, ptvsScore, forensicHash, msg.sender, block.timestamp ); } function getClaim(bytes32 assetId) external view returns (VerifiableClaim memory) { return claims[assetId]; } }
