<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[0x Agency]]></title><description><![CDATA[0x Agency]]></description><link>https://oxagency.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>0x Agency</title><link>https://oxagency.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 14 Oct 2026 16:52:32 GMT</lastBuildDate><atom:link href="https://oxagency.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Robust On-Chain Contact System for Web3 Projects]]></title><description><![CDATA[Building a Robust On-Chain Contact System for Web3 Projects
Introduction
In the rapidly evolving Web3 space, effective communication with a project's community and stakeholders is paramount. Tradition]]></description><link>https://oxagency.hashnode.dev/building-a-robust-on-chain-contact-system-for-web3-projects</link><guid isPermaLink="true">https://oxagency.hashnode.dev/building-a-robust-on-chain-contact-system-for-web3-projects</guid><category><![CDATA[0x]]></category><category><![CDATA[agency]]></category><category><![CDATA[contact]]></category><dc:creator><![CDATA[Jason B]]></dc:creator><pubDate>Sun, 11 Oct 2026 05:24:59 GMT</pubDate><content:encoded><![CDATA[<h1>Building a Robust On-Chain Contact System for Web3 Projects</h1>
<h2>Introduction</h2>
<p>In the rapidly evolving Web3 space, effective communication with a project's community and stakeholders is paramount. Traditional contact forms often fall short, lacking the transparency, immutability, and decentralized nature that define the blockchain ethos. As developers working on various decentralized applications, we frequently encounter the challenge of creating a reliable, verifiable, and censorship-resistant method for users to reach out. This isn't just about a simple feedback form; it's about establishing a trustless channel for feedback, support, and critical alerts within a decentralized ecosystem. This article explores how I approached building such a system, leveraging smart contracts and off-chain indexing to create a robust solution for managing project inquiries.</p>
<h2>The Problem</h2>
<p>Many Web3 projects, especially early-stage DAOs or dApps, rely on Discord, Telegram, or simple email forms for user contact. While these are accessible, they introduce centralization risks, can be prone to spam, and lack a verifiable audit trail. For critical inquiries, such as reporting vulnerabilities, proposing partnerships, or seeking support for high-value transactions, a more secure and transparent mechanism is needed. The core problem is bridging the gap between a user's desire to communicate securely and a project's need to receive and manage these communications efficiently, all while adhering to Web3 principles. We need a system that ensures messages are recorded immutably, can be verified on-chain, and are accessible to authorized parties without relying on a single point of failure.</p>
<h2>Our Approach</h2>
<p>To address this, I designed a hybrid system that combines an on-chain smart contract for immutable message storage with an off-chain indexing service for efficient retrieval and management. This architecture allows us to leverage the security and transparency of the blockchain for message submission while providing the scalability and query capabilities of traditional databases for operational use. The smart contract acts as the single source of truth for all contact requests, while the off-chain component provides the necessary interface for project administrators to view and respond to these requests.</p>
<pre><code>┌─────────────────┐     ┌───────────────────┐     ┌─────────────────┐
│ User DApp/Wallet│────▶│  Contact Smart Contract │────▶│  Blockchain Network │
└─────────────────┘     └───────────────────┘     └─────────────────┘
        │                                                 │
        │                                                 │
        ▼                                                 ▼
┌─────────────────┐                               ┌─────────────────┐
│  Off-Chain Indexer│◀──────────────────────────────│  Event Listener   │
└─────────────────┘                               └─────────────────┘
        │                                                 │
        ▼                                                 ▼
┌─────────────────┐                               ┌─────────────────┐
│  Admin Dashboard │◀──────────────────────────────│  Database (e.g., Pg)│
└─────────────────┘                               └─────────────────┘
</code></pre>
<p>In this architecture:</p>
<ul>
<li><strong>User DApp/Wallet</strong> initiates a transaction to the smart contract.</li>
<li><strong>Contact Smart Contract</strong> records the message and emits an event.</li>
<li><strong>Blockchain Network</strong> ensures immutability and transparency.</li>
<li><strong>Event Listener</strong> monitors the blockchain for new contact events.</li>
<li><strong>Off-Chain Indexer</strong> processes events and stores data in a database.</li>
<li><strong>Database</strong> (e.g., PostgreSQL) provides queryable storage.</li>
<li><strong>Admin Dashboard</strong> allows authorized project members to view and manage requests.</li>
</ul>
<h2>Implementation</h2>
<p>The core of this system is a Solidity smart contract that allows users to submit messages. For simplicity, I'm focusing on a basic message submission, but it could be extended with message types, subject lines, and even encrypted content. The contract stores a hash of the message content on-chain, and the full content is typically stored off-chain (e.g., IPFS) with the hash serving as a pointer and integrity check. For this example, I'll show a simplified version where the message content itself is stored, assuming gas costs are acceptable for the use case or content is short.</p>
<pre><code class="language-solidity">// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ProjectContact {
    struct ContactMessage {
        address sender;
        uint256 timestamp;
        string messageHash; // Hash of the actual message content (e.g., IPFS CID)
        // For simplicity, we'll store a short message directly for this example
        string shortMessage;
    }

    ContactMessage[] public messages;

    event MessageSubmitted(address indexed sender, uint256 timestamp, string messageHash, string shortMessage, uint256 messageId);

    function submitContact(string memory _messageHash, string memory _shortMessage) public {
        require(bytes(_messageHash).length &gt; 0, "Message hash cannot be empty");
        require(bytes(_shortMessage).length &gt; 0, "Short message cannot be empty");

        uint256 messageId = messages.length;
        messages.push(ContactMessage({
            sender: msg.sender,
            timestamp: block.timestamp,
            messageHash: _messageHash,
            shortMessage: _shortMessage
        }));

        emit MessageSubmitted(msg.sender, block.timestamp, _messageHash, _shortMessage, messageId);
    }

    function getMessageCount() public view returns (uint256) {
        return messages.length;
    }

    // In a real scenario, we'd add access control for reading messages
    // and potentially more sophisticated storage for large content.
}
</code></pre>
<p>On the off-chain side, an event listener (e.g., a Node.js service using <code>ethers.js</code> or <code>web3.js</code>) would subscribe to <code>MessageSubmitted</code> events. When an event is detected, the listener would parse the event data and store it in a traditional database. This database then powers an admin dashboard where project teams can view and manage these contact requests. This dual approach ensures that even if the off-chain service goes down, the messages are still immutably recorded on the blockchain, preserving the integrity of the <a href="https://0x.agency/insights/0x-agency-contact">on-chain contact process</a>.</p>
<h2>Results &amp; Insights</h2>
<p>Implementing this system provided several key benefits. Firstly, it significantly increased the transparency and verifiability of contact submissions. Users could confirm their message was recorded on-chain, fostering greater trust. Secondly, by separating storage (on-chain) from retrieval and management (off-chain), we achieved a scalable solution. The gas costs for submitting a message were minimal, and querying historical messages from the database was fast and efficient, avoiding expensive on-chain reads. We observed a reduction in duplicate inquiries because users had a clear, verifiable submission process. However, a limitation is the need for robust off-chain infrastructure to ensure reliable event processing and database uptime. This approach also requires careful consideration of data privacy, as sensitive information should ideally be encrypted before being hashed and referenced on-chain, or stored entirely off-chain in a secure manner. This balance between transparency and privacy is a constant challenge in Web3, especially for aspects like <a href="https://0x.agency/insights/web3-community-management">web3 community management</a>.</p>
<h2>Conclusion</h2>
<p>Building an on-chain contact system, augmented by off-chain indexing, offers a powerful solution for Web3 projects seeking transparent and verifiable communication channels. While the smart contract provides the immutable backbone, the off-chain components are crucial for practical usability and efficient management. This hybrid model effectively addresses the shortcomings of traditional contact methods in a decentralized context, providing a robust framework for user engagement. Future improvements could include integrating decentralized identity solutions for sender verification, implementing more sophisticated encryption for message content, and exploring ZK-proofs for privacy-preserving submissions. The evolution of Web3 infrastructure will undoubtedly bring more sophisticated tools to enhance such systems, further blurring the lines between on-chain and off-chain capabilities.</p>
]]></content:encoded></item><item><title><![CDATA[How to Build a Simple Website Health Checker With Python]]></title><description><![CDATA[How to Build a Simple Website Health Checker With Python
When maintaining a website, it’s easy to overlook broken links, unexpected HTTP errors, and pages that stop responding correctly.
These issues ]]></description><link>https://oxagency.hashnode.dev/how-to-build-a-simple-website-health-checker-with-python</link><guid isPermaLink="true">https://oxagency.hashnode.dev/how-to-build-a-simple-website-health-checker-with-python</guid><dc:creator><![CDATA[Jason B]]></dc:creator><pubDate>Sun, 11 Oct 2026 04:38:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6acb0d1aa89ccf0fce914fbb/5f64b2ed-e341-4523-9c52-68ebab0bf32b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How to Build a Simple Website Health Checker With Python</p>
<p>When maintaining a website, it’s easy to overlook broken links, unexpected HTTP errors, and pages that stop responding correctly.</p>
<p>These issues can affect user experience, create maintenance headaches, and make technical audits more difficult.</p>
<p>In this tutorial, we’ll build a small website health checker using Python. It will request a list of URLs, record their HTTP status codes, measure response times, and export the results to a CSV file.</p>
<p>The goal is to create a practical starting point that developers can extend for their own projects.</p>
<p>What We’re Building</p>
<p>Our script will:</p>
<ul>
<li><p>Read URLs from a text file.</p>
</li>
<li><p>Send HTTP requests to each URL.</p>
</li>
<li><p>Record the status code and response time.</p>
</li>
<li><p>Handle common connection errors and timeouts.</p>
</li>
<li><p>Export the results to a CSV report.</p>
</li>
</ul>
<p>This example checks individual URLs rather than crawling an entire website. That keeps the implementation simple and makes it easier to control the requests being sent.</p>
<p>Step 1: Install the Dependency</p>
<p>You’ll need Python 3 and the requests package.</p>
<p>Install it with:</p>
<p>python -m pip install requests</p>
<p>Create a file named urls.txt with one URL per line:</p>
<p><a href="https://example.com">https://example.com</a> <a href="https://www.python.org">https://www.python.org</a> <a href="https://www.wikipedia.org">https://www.wikipedia.org</a></p>
<p>Use websites you’re authorized to test, and avoid sending unnecessary requests to third-party services.</p>
<p>Step 2: Create the Health Checker</p>
<p>Create a file named health_check.py:</p>
<p>import csv import time from pathlib import Path import requests INPUT_FILE = Path("urls.txt") OUTPUT_FILE = Path("health_report.csv") TIMEOUT_SECONDS = 10 def check_url(url): started = time.perf_counter() try: response = requests.get( url, timeout=TIMEOUT_SECONDS, allow_redirects=True, headers={ "User-Agent": "SimpleWebsiteHealthChecker/1.0" }, ) elapsed = round( (time.perf_counter() - started) * 1000, 2, ) return { "url": url, "status_code": response.status_code, "response_time_ms": elapsed, "final_url": response.url, "error": "", } except requests.RequestException as exc: elapsed = round( (time.perf_counter() - started) * 1000, 2, ) return { "url": url, "status_code": "", "response_time_ms": elapsed, "final_url": "", "error": str(exc), } def main(): if not INPUT_FILE.exists(): raise SystemExit( f"Input file not found: {INPUT_FILE}" ) urls = [ line.strip() for line in INPUT_FILE.read_text().splitlines() if line.strip() and not line.strip().startswith("#") ] results = [] for index, url in enumerate(urls): if not url.startswith(("http://", "https://")): print(f"Skipping invalid URL format: {url}") continue result = check_url(url) results.append(result) print( f"{result['url']} | " f"status={result['status_code'] or 'ERROR'} | " f"{result['response_time_ms']} ms" ) # Add a delay between requests. if index &lt; len(urls) - 1: time.sleep(1) columns = [ "url", "status_code", "response_time_ms", "final_url", "error", ] with OUTPUT_FILE.open( "w", newline="", encoding="utf-8", ) as file: writer = csv.DictWriter( file, fieldnames=columns, ) writer.writeheader() writer.writerows(results) print(f"\nReport saved to {OUTPUT_FILE}") if <strong>name</strong> == "<strong>main</strong>": main()</p>
<p>Step 3: Run the Script</p>
<p>From the directory containing both files, execute:</p>
<p>python health_check.py</p>
<p>The terminal will display the URLs being checked, their HTTP status codes, and the measured response times.</p>
<p>The script creates a file named health_report.csv, which you can open in a spreadsheet application or process with another script.</p>
<p>Example report structure:</p>
<p>URL Status code Response time <a href="https://example.com">https://example.com</a> 200 Measured at runtime <a href="https://www.python.org">https://www.python.org</a> 200 Measured at runtime</p>
<p>These are illustrative successful status codes, not results from a test run.</p>
<p>Step 4: Understand the Results</p>
<p>HTTP status codes provide a useful first indication of a page’s availability.</p>
<ul>
<li><p>2xx: The request was successful.</p>
</li>
<li><p>3xx: The server redirected the request.</p>
</li>
<li><p>4xx: The request encountered a client-side error, such as a missing page or an access restriction.</p>
</li>
<li><p>5xx: The server reported an error.</p>
</li>
<li><p>Request error: The request timed out, the connection failed, or another networking problem occurred.</p>
</li>
</ul>
<p>A successful HTTP response doesn’t necessarily mean that a page is functioning correctly. For example, a website may return status 200 while displaying an application error.</p>
<p>Likewise, a 403 response doesn’t automatically mean a page is broken. It may indicate that access is restricted.</p>
<p>Step 5: Ideas for Extending the Tool</p>
<p>Once the basic script is working, there are several useful improvements to explore.</p>
<p>Add HTML title extraction. Retrieve each page’s title and flag pages that have missing or empty title elements.</p>
<p>Track historical changes. Save reports with timestamps so you can compare results over time and identify recurring failures.</p>
<p>Introduce retry logic. Retry temporary connection failures carefully, with a maximum retry count and an appropriate delay.</p>
<p>Add structured logging. Record failures in a consistent format so they can be investigated later.</p>
<p>Integrate with a dashboard. Load the CSV data into a reporting tool to visualize response times and status-code distributions.</p>
<p>For production use, consider URL validation, private-network address blocking, redirect validation, rate limits, and additional safeguards before accepting URLs from untrusted users. These controls are particularly important if the script becomes a public service.</p>
<p>Conclusion</p>
<p>A small Python script can make routine website checks easier to repeat and document.</p>
<p>The broader lesson is that useful automation often starts with a narrowly defined problem, a simple implementation, and clear output. From there, developers can add validation, monitoring, and reporting as real requirements emerge.</p>
<p>Start small, verify the results, and expand the tool only when there’s a clear reason to do so.</p>
<p>⸻</p>
<p>Written by 0x Agency — technology, software development, and digital growth. Website: <a href="https://0x.agency">https://0x.agency</a></p>
]]></content:encoded></item></channel></rss>