<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aurelio Tamarit Blay</title>
    <description>The latest articles on DEV Community by Aurelio Tamarit Blay (@aurema_group_ee4f7593374a).</description>
    <link>https://dev.to/aurema_group_ee4f7593374a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4080359%2Fcb80da4d-5008-4850-b979-b7ed0ebcc954.jpg</url>
      <title>DEV Community: Aurelio Tamarit Blay</title>
      <link>https://dev.to/aurema_group_ee4f7593374a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aurema_group_ee4f7593374a"/>
    <language>en</language>
    <item>
      <title>INTEGRATING PHYSICAL VERIFICATION INTO YOUR RWA PLATFORM: A STEP-BY-STEP GUIDE WITH PTVS v1.0</title>
      <dc:creator>Aurelio Tamarit Blay</dc:creator>
      <pubDate>Sun, 16 Aug 2026 17:18:54 +0000</pubDate>
      <link>https://dev.to/aurema_group_ee4f7593374a/integrating-physical-verification-into-your-rwa-platform-a-step-by-step-guide-with-ptvs-v10-25pd</link>
      <guid>https://dev.to/aurema_group_ee4f7593374a/integrating-physical-verification-into-your-rwa-platform-a-step-by-step-guide-with-ptvs-v10-25pd</guid>
      <description>&lt;p&gt;INTEGRATING PHYSICAL VERIFICATION INTO YOUR RWA PLATFORM: A STEP-BY-STEP GUIDE WITH PTVS v1.0&lt;/p&gt;

&lt;p&gt;How to add on-chain physical verification to tokenized real-world assets using PTVSClaimInjector.sol&lt;/p&gt;

&lt;p&gt;If you're building an RWA tokenization platform, you've probably hit this wall:&lt;/p&gt;

&lt;p&gt;Your smart contract knows who owns the token, but it doesn't know if the asset behind the token still exists.&lt;/p&gt;

&lt;p&gt;MiCA Art. 36 requires continuous proof of reserve assets. Price oracles give you market value, but they can't verify physical integrity. You need physical verification — and it needs to be on-chain, deterministic, and legally admissible.&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll show you how to integrate the Prop Trust Verified Standard (PTVS v1.0) into your existing RWA platform using the open-source PTVSClaimInjector.sol smart contract.&lt;/p&gt;

&lt;p&gt;What you'll build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy PTVSClaimInjector on a testnet&lt;/li&gt;
&lt;li&gt;Generate a forensic inspection report (canonical JSON)&lt;/li&gt;
&lt;li&gt;Compute SHA-256 hash&lt;/li&gt;
&lt;li&gt;Inject a Verifiable Claim on-chain&lt;/li&gt;
&lt;li&gt;Query the claim from your dApp&lt;/li&gt;
&lt;li&gt;Integrate with ERC-3643/T-REX for compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time required: approximately 1 hour&lt;br&gt;
Prerequisites: Basic Solidity, familiarity with Hardhat or Foundry, MetaMask wallet&lt;/p&gt;

&lt;p&gt;Let's build.&lt;/p&gt;

&lt;p&gt;STEP 1: UNDERSTAND THE ARCHITECTURE&lt;/p&gt;

&lt;p&gt;Before writing code, let's understand the data flow:&lt;/p&gt;

&lt;p&gt;Physical Asset&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
PTCE Expert (on-site inspection)&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
PDF/A Report + QES Signature&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
Canonical JSON (deterministic serialization)&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
SHA-256 Hash (forensicHash)&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
PTVSClaimInjector.sol (on-chain)&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
Verifiable Claim stored&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
Circuit breaker logic triggered&lt;br&gt;
    |&lt;br&gt;
    v&lt;br&gt;
ERC-3643/T-REX compliance enforced&lt;/p&gt;

&lt;p&gt;Key concept: The forensicHash is the cryptographic link between the physical evidence (PDF/A report) and the on-chain claim. Any modification to the report changes the hash, making tampering detectable.&lt;/p&gt;

&lt;p&gt;STEP 2: DEPLOY PTVSCLAIMINJECTOR&lt;/p&gt;

&lt;p&gt;2.1 Get the Contract&lt;/p&gt;

&lt;p&gt;PTVSClaimInjector is open-source (MIT License). Clone the repository:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/aurema-group/ptvs-sdk-python.git
cd ptvs-sdk-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or install via npm (for JavaScript/TypeScript projects):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @aurema-group/ptvs-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2.2 Contract Source Code&lt;/p&gt;

&lt;p&gt;Here's the complete PTVSClaimInjector.sol contract:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

contract PTVSClaimInjector is Ownable {

    enum ClaimStatus { VERIFIED, CONDITIONAL, EXPIRED, REVOKED }

    struct VerifiableClaim {
        bytes32 assetId;
        uint8 ptvsScore;
        bytes32 forensicHash;
        uint256 inspectionTimestamp;
        address ptceAddress;
        ClaimStatus status;
    }

    mapping(bytes32 =&amp;gt; VerifiableClaim) public claims;
    mapping(address =&amp;gt; bool) public authorizedPTCEs;

    event ClaimInjected(
        bytes32 indexed assetId,
        uint8 ptvsScore,
        bytes32 forensicHash,
        address indexed ptceAddress,
        uint256 timestamp
    );

    event ClaimRenewed(
        bytes32 indexed assetId,
        uint8 newScore,
        bytes32 newHash,
        uint256 timestamp
    );

    event ClaimRevoked(
        bytes32 indexed assetId,
        string reason,
        uint256 timestamp
    );

    event CircuitBreakerTriggered(
        bytes32 indexed assetId,
        uint8 score,
        string action,
        uint256 timestamp
    );

    modifier onlyAuthorizedPTCE() {
        require(authorizedPTCEs[msg.sender], "Not authorized PTCE");
        _;
    }

    constructor() Ownable(msg.sender) {}

    function authorizePTCE(address ptce) external onlyOwner {
        authorizedPTCEs[ptce] = true;
    }

    function revokePTCE(address ptce) external onlyOwner {
        authorizedPTCEs[ptce] = false;
    }

    function injectClaim(
        bytes32 assetId,
        uint8 ptvsScore,
        bytes32 forensicHash,
        uint256 inspectionTimestamp,
        bytes memory ptceSignature
    ) external onlyAuthorizedPTCE {

        ClaimStatus status;
        if (ptvsScore &amp;gt;= 70) {
            status = ClaimStatus.VERIFIED;
        } else if (ptvsScore &amp;gt;= 50) {
            status = ClaimStatus.CONDITIONAL;
        } else {
            status = 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
        );

        // Trigger circuit breaker if needed
        if (status == ClaimStatus.REVOKED) {
            emit CircuitBreakerTriggered(
                assetId,
                ptvsScore,
                "Trading paused",
                block.timestamp
            );
        }
    }

    function renewClaim(
        bytes32 assetId,
        uint8 newScore,
        bytes32 newHash,
        uint256 newTimestamp,
        bytes memory ptceSignature
    ) external onlyAuthorizedPTCE {
        require(claims[assetId].assetId != bytes32(0), "Claim does not exist");

        ClaimStatus newStatus;
        if (newScore &amp;gt;= 70) {
            newStatus = ClaimStatus.VERIFIED;
        } else if (newScore &amp;gt;= 50) {
            newStatus = ClaimStatus.CONDITIONAL;
        } else {
            newStatus = ClaimStatus.REVOKED;
        }

        claims[assetId] = VerifiableClaim({
            assetId: assetId,
            ptvsScore: newScore,
            forensicHash: newHash,
            inspectionTimestamp: newTimestamp,
            ptceAddress: msg.sender,
            status: newStatus
        });

        emit ClaimRenewed(assetId, newScore, newHash, block.timestamp);
    }

    function revokeClaim(
        bytes32 assetId,
        string calldata reason
    ) external onlyOwner {
        require(claims[assetId].assetId != bytes32(0), "Claim does not exist");

        claims[assetId].status = ClaimStatus.REVOKED;

        emit ClaimRevoked(assetId, reason, block.timestamp);
        emit CircuitBreakerTriggered(
            assetId,
            claims[assetId].ptvsScore,
            reason,
            block.timestamp
        );
    }

    function getClaim(bytes32 assetId) 
        external 
        view 
        returns (VerifiableClaim memory) 
    {
        return claims[assetId];
    }

    function isClaimValid(bytes32 assetId) external view returns (bool) {
        VerifiableClaim memory claim = claims[assetId];
        return claim.status == ClaimStatus.VERIFIED;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2.3 Deploy to Testnet&lt;/p&gt;

&lt;p&gt;Using Hardhat:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx hardhat run scripts/deploy.js --network sepolia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or using Foundry:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;forge create src/PTVSClaimInjector.sol:PTVSClaimInjector --rpc-url $SEPOLIA_RPC_URL --private-key $PRIVATE_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save the deployed contract address — you'll need it for the next steps.&lt;/p&gt;

&lt;p&gt;STEP 3: GENERATE CANONICAL JSON AND COMPUTE HASH&lt;/p&gt;

&lt;p&gt;3.1 Create Inspection Data&lt;/p&gt;

&lt;p&gt;First, create the inspection findings:&lt;/p&gt;

&lt;p&gt;Python example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
from Crypto.Hash import SHA256

inspection_data = {
    "assetId": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678",
    "assetName": "Edificio residencial · Calle Mayor 42, Valencia",
    "assetType": "real_estate",
    "inspectionDate": "2026-08-15T10:30:00Z",
    "jurisdiction": "ES-VC",
    "ptceId": "PTCE-0161",
    "ptvsScore": 85,
    "structural": {
        "score": 85,
        "cracks": 0,
        "corrosion": 1,
        "degradation": 0
    },
    "legal": {
        "score": 92,
        "encumbrances": 0,
        "titleClear": True
    },
    "environmental": {
        "score": 78,
        "contamination": 0,
        "hazards": 0
    },
    "documentation": {
        "score": 95
    },
    "insurance": {
        "score": 88,
        "active": True
    },
    "notes": "Minor corrosion detected on balcony railings. Recommend treatment within 6 months."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3.2 Canonicalize JSON&lt;/p&gt;

&lt;p&gt;Canonical JSON ensures deterministic serialization (sorted keys, no whitespace):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Canonicalize: sort keys alphabetically, remove whitespace
canonical_json = json.dumps(
    inspection_data, 
    sort_keys=True, 
    separators=(',', ':'),
    ensure_ascii=False
)

print("Canonical JSON:")
print(canonical_json)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Output example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"assetId":"0x1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678","assetName":"Edificio residencial · Calle Mayor 42, Valencia","assetType":"real_estate",...}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3.3 Compute SHA-256 Hash&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Compute SHA-256 hash
hash_obj = SHA256.new(canonical_json.encode('utf-8'))
forensic_hash = '0x' + hash_obj.hexdigest()

print(f"Forensic Hash: {forensic_hash}")
# Output: 0xa3f2b8c9d4e5f6789012345678901234567890abcdef1234567890abcdef12345678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This hash is what you'll inject on-chain. It's the cryptographic link between your physical evidence and the on-chain claim.&lt;/p&gt;

&lt;p&gt;STEP 4: INJECT CLAIM ON-CHAIN&lt;/p&gt;

&lt;p&gt;4.1 Python Integration (Web3.py)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from web3 import Web3

# Connect to testnet
w3 = Web3(Web3.HTTPProvider('https://sepolia.infura.io/v3/YOUR_PROJECT_ID'))

# Contract ABI (simplified)
abi = [
    {
        "inputs": [
            {"name": "assetId", "type": "bytes32"},
            {"name": "ptvsScore", "type": "uint8"},
            {"name": "forensicHash", "type": "bytes32"},
            {"name": "inspectionTimestamp", "type": "uint256"},
            {"name": "ptceSignature", "type": "bytes"}
        ],
        "name": "injectClaim",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [{"name": "assetId", "type": "bytes32"}],
        "name": "getClaim",
        "outputs": [
            {
                "components": [
                    {"name": "assetId", "type": "bytes32"},
                    {"name": "ptvsScore", "type": "uint8"},
                    {"name": "forensicHash", "type": "bytes32"},
                    {"name": "inspectionTimestamp", "type": "uint256"},
                    {"name": "ptceAddress", "type": "address"},
                    {"name": "status", "type": "uint8"}
                ],
                "name": "",
                "type": "tuple"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    }
]

# Load contract
contract_address = '0xYOUR_DEPLOYED_CONTRACT_ADDRESS'
contract = w3.eth.contract(address=contract_address, abi=abi)

# PTCE account (must be authorized)
ptce_account = w3.eth.account.from_key('YOUR_PTCE_PRIVATE_KEY')

# Prepare transaction
asset_id = bytes.fromhex(inspection_data['assetId'][2:])  # Remove '0x'
ptvs_score = inspection_data['ptvsScore']
forensic_hash = bytes.fromhex(forensic_hash[2:])  # Remove '0x'
inspection_timestamp = int(datetime.now().timestamp())
ptce_signature = b''  # In production, this would be the QES signature

# Build transaction
nonce = w3.eth.get_transaction_count(ptce_account.address)
tx = contract.functions.injectClaim(
    asset_id,
    ptvs_score,
    forensic_hash,
    inspection_timestamp,
    ptce_signature
).build_transaction({
    'from': ptce_account.address,
    'nonce': nonce,
    'gas': 200000,
    'gasPrice': w3.eth.gas_price
})

# Sign and send
signed_tx = ptce_account.sign_transaction(tx)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)

print(f"Transaction sent: {tx_hash.hex()}")

# Wait for confirmation
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Transaction confirmed in block {receipt.blockNumber}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;4.2 JavaScript Integration (Web3.js)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Web3 = require('web3');
const crypto = require('crypto');

// Connect to testnet
const web3 = new Web3('https://sepolia.infura.io/v3/YOUR_PROJECT_ID');

// Contract instance
const contractAddress = '0xYOUR_DEPLOYED_CONTRACT_ADDRESS';
const contract = new web3.eth.Contract(ABI, contractAddress);

// PTCE account
const ptceAccount = web3.eth.accounts.privateKeyToAccount('YOUR_PTCE_PRIVATE_KEY');
web3.eth.accounts.wallet.add(ptceAccount);

// Inspection data
const inspectionData = {
  assetId: '0x1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678',
  ptvsScore: 85,
  // ... rest of inspection data
};

// Compute forensic hash (same as Python example)
const canonicalJson = JSON.stringify(inspectionData, Object.keys(inspectionData).sort());
const forensicHash = '0x' + crypto.createHash('sha256').update(canonicalJson).digest('hex');

// Inject claim
async function injectClaim() {
  const tx = await contract.methods.injectClaim(
    inspectionData.assetId,
    inspectionData.ptvsScore,
    forensicHash,
    Math.floor(Date.now() / 1000),
    '0x'  // ptceSignature
  ).send({
    from: ptceAccount.address,
    gas: 200000
  });

  console.log('Transaction hash:', tx.transactionHash);
  return tx;
}

injectClaim().catch(console.error);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;STEP 5: QUERY AND VERIFY CLAIMS&lt;/p&gt;

&lt;p&gt;5.1 Read Claim from Contract&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Query claim
claim = contract.functions.getClaim(asset_id).call()

print(f"Asset ID: 0x{claim[0].hex()}")
print(f"PTVS Score: {claim[1]}")
print(f"Forensic Hash: 0x{claim[2].hex()}")
print(f"Inspection Timestamp: {claim[3]}")
print(f"PTCE Address: {claim[4]}")
print(f"Status: {['VERIFIED', 'CONDITIONAL', 'EXPIRED', 'REVOKED'][claim[5]]}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;5.2 Verify Claim Independently&lt;/p&gt;

&lt;p&gt;Any third party can verify the claim by recomputing the hash:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def verify_claim(claim, original_json):
    """Verify that on-chain claim matches original inspection report."""

    # Recompute hash from original JSON
    recomputed_hash = '0x' + SHA256.new(original_json.encode('utf-8')).hexdigest()

    # Compare with on-chain hash
    on_chain_hash = '0x' + claim[2].hex()

    if recomputed_hash == on_chain_hash:
        print("Verification successful: hashes match")
        return True
    else:
        print("Verification failed: hashes do not match")
        print(f"  Expected: {on_chain_hash}")
        print(f"  Got:      {recomputed_hash}")
        return False

# Verify the claim
verify_claim(claim, canonical_json)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;STEP 6: INTEGRATE WITH ERC-3643/T-REX&lt;/p&gt;

&lt;p&gt;If you're using ERC-3643/T-REX for identity and compliance, here's how to integrate PTVS:&lt;/p&gt;

&lt;p&gt;6.1 Architecture&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERC-3643/T-REX
├─ Identity Registry (ONCHAINID)
├─ Compliance Module
└─ Token Contract
                ↕
PTVSClaimInjector (PTVS v1.0)
├─ Physical verification claims
├─ PTVS Score enforcement
└─ Circuit breaker actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;6.2 Compliance Integration Example&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// In your token contract
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./PTVSClaimInjector.sol";

contract RWA_Token is ERC20 {
    PTVSClaimInjector public ptvsInjector;
    bytes32 public assetId;

    constructor(
        address _ptvsInjector,
        bytes32 _assetId
    ) ERC20("Real World Asset Token", "RWAT") {
        ptvsInjector = PTVSClaimInjector(_ptvsInjector);
        assetId = _assetId;
    }

    function transfer(address to, uint256 amount) public override returns (bool) {
        // Check PTVS claim before allowing transfer
        require(
            ptvsInjector.isClaimValid(assetId),
            "Transfer blocked: asset verification expired or revoked"
        );

        return super.transfer(to, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This ensures that tokens cannot be transferred if the physical asset verification has expired or been revoked.&lt;/p&gt;

&lt;p&gt;STEP 7: BUILD A FRONTEND VERIFICATION WIDGET&lt;/p&gt;

&lt;p&gt;7.1 HTML + JavaScript Widget&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;PTVS Verification Widget&amp;lt;/title&amp;gt;
    &amp;lt;script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Asset Verification&amp;lt;/h1&amp;gt;
    &amp;lt;input type="text" id="assetId" placeholder="Enter Asset ID (0x...)"&amp;gt;
    &amp;lt;button onclick="verifyAsset()"&amp;gt;Verify&amp;lt;/button&amp;gt;

    &amp;lt;div id="result"&amp;gt;&amp;lt;/div&amp;gt;

    &amp;lt;script&amp;gt;
        const web3 = new Web3('https://sepolia.infura.io/v3/YOUR_PROJECT_ID');
        const contractAddress = '0xYOUR_DEPLOYED_CONTRACT_ADDRESS';
        const contractABI = [/* ABI here */];
        const contract = new web3.eth.Contract(contractABI, contractAddress);

        async function verifyAsset() {
            const assetId = document.getElementById('assetId').value;
            const claim = await contract.methods.getClaim(assetId).call();

            const statusMap = ['VERIFIED', 'CONDITIONAL', 'EXPIRED', 'REVOKED'];
            const status = statusMap[claim.status];

            let html = `
                &amp;lt;h2&amp;gt;Verification Result&amp;lt;/h2&amp;gt;
                &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Asset ID:&amp;lt;/strong&amp;gt; ${claim.assetId}&amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;PTVS Score:&amp;lt;/strong&amp;gt; ${claim.ptvsScore}/100&amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Status:&amp;lt;/strong&amp;gt; ${status}&amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Inspection Date:&amp;lt;/strong&amp;gt; ${new Date(claim.inspectionTimestamp * 1000).toLocaleString()}&amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;PTCE Address:&amp;lt;/strong&amp;gt; ${claim.ptceAddress}&amp;lt;/p&amp;gt;
            `;

            if (status === 'VERIFIED') {
                html += '&amp;lt;p style="color: green;"&amp;gt;Asset is verified and eligible for trading&amp;lt;/p&amp;gt;';
            } else if (status === 'CONDITIONAL') {
                html += '&amp;lt;p style="color: orange;"&amp;gt;Asset is conditional - increased risk&amp;lt;/p&amp;gt;';
            } else {
                html += '&amp;lt;p style="color: red;"&amp;gt;Asset verification revoked - trading paused&amp;lt;/p&amp;gt;';
            }

            document.getElementById('result').innerHTML = html;
        }
    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;STEP 8: TEST THE FULL FLOW&lt;/p&gt;

&lt;p&gt;8.1 Try the Sandbox First&lt;/p&gt;

&lt;p&gt;Before deploying to production, test the complete flow in our public sandbox:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://proptrustverified.com/sandbox/" rel="noopener noreferrer"&gt;https://proptrustverified.com/sandbox/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sandbox lets you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a mock asset&lt;/li&gt;
&lt;li&gt;Run a forensic inspection&lt;/li&gt;
&lt;li&gt;Compute SHA-256 hash&lt;/li&gt;
&lt;li&gt;Simulate on-chain claim injection&lt;/li&gt;
&lt;li&gt;Verify the claim&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No backend required. All computations happen in your browser.&lt;/p&gt;

&lt;p&gt;8.2 Production Checklist&lt;/p&gt;

&lt;p&gt;Before going to mainnet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security audit of your integration code&lt;/li&gt;
&lt;li&gt;Deploy PTVSClaimInjector to mainnet (or L2 like Arbitrum/Polygon for lower gas)&lt;/li&gt;
&lt;li&gt;Authorize your PTCE addresses&lt;/li&gt;
&lt;li&gt;Test circuit breaker logic with mock degraded assets&lt;/li&gt;
&lt;li&gt;Integrate with your existing compliance workflow&lt;/li&gt;
&lt;li&gt;Add monitoring for claim expiration (90-day re-audit cycle)&lt;/li&gt;
&lt;li&gt;Document the verification process for your users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;REAL-WORLD EXAMPLE: PROYECTO NAVARRÉS&lt;/p&gt;

&lt;p&gt;To see this in action with a real asset, check out Proyecto Navarrés:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asset: 108,000 m² urbanizable land in Valencia, Spain&lt;/li&gt;
&lt;li&gt;PTVS Score: 91/100 (VERIFIED)&lt;/li&gt;
&lt;li&gt;Status: Live on-chain with Verifiable Claim&lt;/li&gt;
&lt;li&gt;Case study: &lt;a href="https://forensics-oracle.org/case-studies/navarres/" rel="noopener noreferrer"&gt;https://forensics-oracle.org/case-studies/navarres/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This demonstrates that PTVS v1.0 is not theoretical — it's been executed against real assets.&lt;/p&gt;

&lt;p&gt;RESOURCES&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reference Architecture: &lt;a href="https://doi.org/10.5281/zenodo.21719175" rel="noopener noreferrer"&gt;https://doi.org/10.5281/zenodo.21719175&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/aurema-group/ptvs-sdk-python" rel="noopener noreferrer"&gt;https://github.com/aurema-group/ptvs-sdk-python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sandbox: &lt;a href="https://proptrustverified.com/sandbox/" rel="noopener noreferrer"&gt;https://proptrustverified.com/sandbox/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Compatibility Program: &lt;a href="https://forensics-oracle.org/compatibility/" rel="noopener noreferrer"&gt;https://forensics-oracle.org/compatibility/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;QUESTIONS?&lt;/p&gt;

&lt;p&gt;If you run into issues integrating PTVS, drop a comment below or reach out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical support: &lt;a href="mailto:enterprise@proptrustverified.com"&gt;enterprise@proptrustverified.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Discord: &lt;a href="https://discord.gg/forensics-oracle" rel="noopener noreferrer"&gt;https://discord.gg/forensics-oracle&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub Issues: &lt;a href="https://github.com/aurema-group/ptvs-sdk-python/issues" rel="noopener noreferrer"&gt;https://github.com/aurema-group/ptvs-sdk-python/issues&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy building!&lt;/p&gt;

&lt;p&gt;Aurelio Tamarit Blay is the Lead Researcher of the Forensics Oracle Initiative and creator of the Prop Trust Verified Standard (PTVS v1.0). He is a sworn judicial expert (Exp. No. 0161, Spain) with 33 years of forensic practice. ORCID: 0009-0007-5824-3602.&lt;/p&gt;

&lt;p&gt;Tags: blockchain smartcontracts rwa solidity&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>smartcontract</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
