<?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: Mehran Mazhar</title>
    <description>The latest articles on DEV Community by Mehran Mazhar (@mehran_mazhar).</description>
    <link>https://dev.to/mehran_mazhar</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%2F1664250%2Fbf586a06-bea6-4f9f-bbc1-bfb533e5f408.jpg</url>
      <title>DEV Community: Mehran Mazhar</title>
      <link>https://dev.to/mehran_mazhar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mehran_mazhar"/>
    <language>en</language>
    <item>
      <title>Making MetaMask and TronLink sign transactions for a custom Rust blockchain</title>
      <dc:creator>Mehran Mazhar</dc:creator>
      <pubDate>Thu, 29 Oct 2026 16:41:21 +0000</pubDate>
      <link>https://dev.to/mehran_mazhar/making-metamask-and-tronlink-sign-transactions-for-a-custom-rust-blockchain-eli</link>
      <guid>https://dev.to/mehran_mazhar/making-metamask-and-tronlink-sign-transactions-for-a-custom-rust-blockchain-eli</guid>
      <description>&lt;p&gt;A few months ago I wrote &lt;a href="https://dev.to/mehran_mazhar/how-i-built-a-custom-rust-blockchain-for-on-chain-ride-lifecycle-594i"&gt;How I Built a Custom Rust Blockchain for On-Chain Ride Lifecycle&lt;/a&gt;. Clutch is a ride-sharing protocol where the rider pays the driver directly, and every step of a ride (request, offer, accept, pay, cancel) is a native transaction type on a small Proof-of-Authority chain written in Rust.&lt;/p&gt;

&lt;p&gt;Since then it went from "testnet with a faucet" to a mainnet that holds real money. This post is about the parts I did not expect to be hard: getting normal wallets to sign for a chain they have never heard of, and keeping the token honest once it is backed by real USDT.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you read part 1: block rewards are gone. The block author is now paid by a flat fee on each transaction.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: wallets refuse to sign a bare hash
&lt;/h2&gt;

&lt;p&gt;In part 1, the SDK held a local key and signed the transaction hash directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hash = keccak256(rlp([from, nonce, chain_id, data]))
signature = secp256k1_sign(keccak256(hash_as_hex_string))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works for an SDK. It does not work for MetaMask or TronLink. A wallet will not sign 32 opaque bytes for you, and it is right not to: a bare hash could be an Ethereum transaction on another chain.&lt;/p&gt;

&lt;p&gt;So the node now accepts three schemes, each checked against its own digest:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scheme&lt;/th&gt;
&lt;th&gt;Who signs&lt;/th&gt;
&lt;th&gt;What is signed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;SDK key, treasury, faucet&lt;/td&gt;
&lt;td&gt;&lt;code&gt;keccak256(hash)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;MetaMask, Trust Wallet (&lt;code&gt;personal_sign&lt;/code&gt;, EIP-191)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"\x19Ethereum Signed Message:\n" + len + "clutch-tx:{chain_id}:{hash}"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;TronLink (&lt;code&gt;signMessageV2&lt;/code&gt;, TIP-191)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"\x19TRON Signed Message:\n" + len + "clutch-tx:{chain_id}:{hash}"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The text the user sees in the wallet popup is &lt;code&gt;clutch-tx:{chain_id}:{hash}&lt;/code&gt;. The chain id is in it so a signature for the testnet can never be replayed on the mainnet.&lt;/p&gt;

&lt;p&gt;The nice surprise was TRON. A TRON account is the same kind of key as an Ethereum account: same curve, same Keccak-256, same 20 address bytes. TRON just writes them in base58 with a &lt;code&gt;0x41&lt;/code&gt; prefix. So supporting TronLink was one more prefix, not a new crypto stack. A user signed in with TronLink has a Clutch address that is literally their TRON address in hex.&lt;/p&gt;

&lt;p&gt;The catch: &lt;strong&gt;this is a consensus change.&lt;/strong&gt; A validator without scheme 2 rejects any block containing a scheme-2 transaction. On a testnet you just upgrade. On our young mainnet it meant starting a new chain, which we only allowed because a script first proved that no token had ever been minted on the old one. The day real balances exist, the same change needs a planned rolling upgrade of every validator from the same block height.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending from MetaMask: pretending to be just enough of an EVM
&lt;/h2&gt;

&lt;p&gt;Signing ride transactions in the app was solved. But people also wanted to open MetaMask, see their CLT balance, and press Send.&lt;/p&gt;

&lt;p&gt;MetaMask can only send by signing a legacy Ethereum transaction (EIP-155). So the Hub API exposes a small JSON-RPC endpoint at &lt;code&gt;/rpc&lt;/code&gt; that answers the calls a wallet makes (&lt;code&gt;eth_chainId&lt;/code&gt;, &lt;code&gt;eth_getBalance&lt;/code&gt;, &lt;code&gt;eth_sendRawTransaction&lt;/code&gt; and friends), and the node gained one new transaction type, &lt;code&gt;WalletTransfer&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The node decodes the raw Ethereum transaction and recovers &lt;code&gt;from&lt;/code&gt; from its signature.&lt;/li&gt;
&lt;li&gt;It refuses anything that is not a plain value transfer: data, typed transactions, no chain id, a high &lt;code&gt;s&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Wallet values are in wei (18 decimals); CLT has 6. So &lt;code&gt;value = CLT units × 10^12&lt;/code&gt;, and &lt;strong&gt;any value with more than 6 decimals is refused, never rounded.&lt;/strong&gt; Rounding money silently is how you end up with balances nobody can explain.&lt;/li&gt;
&lt;li&gt;The transaction's hash is the real Ethereum hash, rebuilt from the fields and signature, so MetaMask, the explorer and the node all show the same hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also a consensus change, so it is switched on per chain by config: a &lt;code&gt;wallet_chain_id&lt;/code&gt; and a &lt;code&gt;wallet_transfers_from_block&lt;/code&gt; height that every validator must carry. Below that height the type is refused everywhere. The wallet chain ids (20770 mainnet, 20771 testnet) are registered on chainlist, so "Add network" works with one click.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real money: CLT backed 1:1 by USDT
&lt;/h2&gt;

&lt;p&gt;1 USD = 1,000,000 CLT base units. CLT only enters the chain through a &lt;code&gt;Mint&lt;/code&gt; transaction, and only one address can sign it: the &lt;code&gt;mint_authority&lt;/code&gt;, fixed in the genesis block. A separate treasury service watches for USDT deposits (TRC-20 on Tron, BEP-20 on BNB Chain), and mints the matching CLT to the depositor (minus the transfer relay's fee, for deposits that go through one). Withdrawals are the reverse: a &lt;code&gt;Burn&lt;/code&gt; on Clutch, then a USDT payout on Tron.&lt;/p&gt;

&lt;p&gt;Every mint and burn carries a reference, and the chain stores a &lt;code&gt;processed_ref_{ref}&lt;/code&gt; marker so the same deposit can never be credited twice, even if the treasury retries after a crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three bugs that could have created money
&lt;/h2&gt;

&lt;p&gt;These are the ones that scared me. All are fixed, all have tests, and I am writing them down because each one looked harmless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Two transfers in one block minted money.&lt;/strong&gt; Block state is validated first and applied as one deferred RocksDB batch at the end. So two transfers from the same account in one block were both validated against the &lt;em&gt;pre-block&lt;/em&gt; balance, and the second write to the balance key won. Send 10 to A and 10 to B from a balance of 10: both pass, both recipients get 10, the sender ends at 0. Fix: one transaction per account per block, enforced when authoring and when importing. The same staleness broke the exactly-once marker (two mints with one ref in one block), so a block also may not repeat a ref.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The block author's fee erased the author's own transaction.&lt;/strong&gt; The fee credit to the block author was appended after the per-transaction writes, so it became the last write to the author's balance key and silently discarded any transaction the author had sent in that block. The recipient kept the money, the author's debit vanished: unbacked CLT. Fix: fold the fee into the already-staged write instead of appending, and abort the import if that fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A debug flag deleted the chain on every deploy.&lt;/strong&gt; &lt;code&gt;developer_mode = true&lt;/code&gt; made the node delete its database on graceful shutdown. Our stage configs had it for a month. Whichever node stopped cleanly inside Docker's 30-second grace period lost its chain; the ones that got SIGKILLed kept theirs. So the data loss moved between nodes and looked like a volume problem, then a sync problem, then a deploy-script problem. The node now refuses to delete its database when a data path is mounted.&lt;/p&gt;

&lt;p&gt;The lesson I took from all three: with a deferred write batch, "last write wins" is a money bug waiting for a second writer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it is now, honestly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The mainnet has been live since October 2026 and holds real USDT.&lt;/li&gt;
&lt;li&gt;It is alpha: $100 per deposit, $200 per day, withdrawals of $25 to $50 on Tron.&lt;/li&gt;
&lt;li&gt;The mint and payout keys are on the server, not in a KMS yet. The three validators run on one host. There has been no security audit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of that, &lt;strong&gt;I am asking people to try the free testnet first&lt;/strong&gt;, where nothing costs real money: &lt;a href="https://app-stage.clutchprotocol.io" rel="noopener noreferrer"&gt;app-stage.clutchprotocol.io&lt;/a&gt;. Sign in with MetaMask or TronLink, and do one ride as passenger or driver (two browser windows work).&lt;/p&gt;

&lt;p&gt;I am looking for 10 people to finish one ride and tell me the first thing that confused them or broke. Comments here are perfect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code (node, hub, explorer, treasury, deploy): &lt;a href="https://github.com/clutchprotocol" rel="noopener noreferrer"&gt;github.com/clutchprotocol&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://docs.clutchprotocol.io" rel="noopener noreferrer"&gt;docs.clutchprotocol.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Site: &lt;a href="https://clutchprotocol.io" rel="noopener noreferrer"&gt;clutchprotocol.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 1: &lt;a href="https://dev.to/mehran_mazhar/how-i-built-a-custom-rust-blockchain-for-on-chain-ride-lifecycle-594i"&gt;How I Built a Custom Rust Blockchain for On-Chain Ride Lifecycle&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions I would love answers to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Would you have done wallet support differently, for example an EVM-compatible layer instead of a custom transfer type?&lt;/li&gt;
&lt;li&gt;How would you roll out a signature-scheme change on a chain that already holds balances?&lt;/li&gt;
&lt;li&gt;Would you use this as a rider or a driver, and what would stop you?&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>rust</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I Built a Custom Rust Blockchain for On-Chain Ride Lifecycle</title>
      <dc:creator>Mehran Mazhar</dc:creator>
      <pubDate>Fri, 26 Jun 2026 15:08:49 +0000</pubDate>
      <link>https://dev.to/mehran_mazhar/how-i-built-a-custom-rust-blockchain-for-on-chain-ride-lifecycle-594i</link>
      <guid>https://dev.to/mehran_mazhar/how-i-built-a-custom-rust-blockchain-for-on-chain-ride-lifecycle-594i</guid>
      <description>&lt;p&gt;Update: part 2 covers wallets, real USDT backing and three money bugs.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mehran_mazhar/making-metamask-and-tronlink-sign-transactions-for-a-custom-rust-blockchain-eli" class="crayons-story__hidden-navigation-link"&gt;Making MetaMask and TronLink sign transactions for a custom Rust blockchain&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mehran_mazhar" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1664250%2Fbf586a06-bea6-4f9f-bbc1-bfb533e5f408.jpg" alt="mehran_mazhar profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mehran_mazhar" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mehran Mazhar
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mehran Mazhar
                
                
              
              &lt;div id="story-author-preview-content-4942396" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mehran_mazhar" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1664250%2Fbf586a06-bea6-4f9f-bbc1-bfb533e5f408.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mehran Mazhar&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mehran_mazhar/making-metamask-and-tronlink-sign-transactions-for-a-custom-rust-blockchain-eli" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mehran_mazhar/making-metamask-and-tronlink-sign-transactions-for-a-custom-rust-blockchain-eli" id="article-link-4942396"&gt;
          Making MetaMask and TronLink sign transactions for a custom Rust blockchain
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/rust"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;rust&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/mehran_mazhar/making-metamask-and-tronlink-sign-transactions-for-a-custom-rust-blockchain-eli#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
I wanted ride-sharing operations — request, offer, accept, pay, cancel — to be &lt;strong&gt;first-class on-chain transactions&lt;/strong&gt;, not generic smart-contract calls wrapped in app logic. So I built &lt;strong&gt;Clutch Protocol&lt;/strong&gt;: a custom non-EVM blockchain in Rust, a GraphQL bridge for apps, a JavaScript SDK for client-side signing, and a public stage testnet you can try without installing anything.

&lt;p&gt;This post is the technical story: what I built, why I didn't use Ethereum, how a ride actually flows through the stack, and — just as importantly — what I &lt;em&gt;haven't&lt;/em&gt; solved yet.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem I was solving
&lt;/h2&gt;

&lt;p&gt;Traditional ride apps centralize trust: the platform owns matching, payments, and dispute resolution. Putting the &lt;strong&gt;ride state machine on-chain&lt;/strong&gt; changes the contract between riders, drivers, and app builders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every step is a signed, auditable transaction&lt;/li&gt;
&lt;li&gt;Private keys stay on the client (Bitcoin-style)&lt;/li&gt;
&lt;li&gt;App developers can earn on-chain referrer fees when users complete rides&lt;/li&gt;
&lt;li&gt;Drivers receive CLT directly via &lt;code&gt;RidePay&lt;/code&gt;, not through a platform ledger&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tradeoff is real: you lose EVM composability and must ship custom SDKs. For a domain-specific protocol, that tradeoff felt acceptable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture at a glance
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Demo App / Your dApp
        │
        ▼
  clutch-hub-sdk-js   (client-side signing, RLP, secp256k1)
        │
        ▼
  clutch-hub-api      (GraphQL + WebSocket + faucet)
        │
        ▼
  clutch-node         (Aura consensus, WebSocket JSON-RPC)
        │
        ▼
  clutch-explorer     (indexer → Postgres → REST UI)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/clutchprotocol/clutch-node" rel="noopener noreferrer"&gt;clutch-node&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Blockchain core&lt;/td&gt;
&lt;td&gt;Rust, Aura, libp2p&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/clutchprotocol/clutch-hub-api" rel="noopener noreferrer"&gt;clutch-hub-api&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;App bridge&lt;/td&gt;
&lt;td&gt;Rust, async-graphql&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/clutchprotocol/clutch-hub-sdk-js" rel="noopener noreferrer"&gt;clutch-hub-sdk-js&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Client SDK&lt;/td&gt;
&lt;td&gt;TypeScript, npm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/clutchprotocol/clutch-hub-demo-app" rel="noopener noreferrer"&gt;clutch-hub-demo-app&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Reference UI&lt;/td&gt;
&lt;td&gt;React, Vite, Leaflet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/clutchprotocol/clutch-deploy" rel="noopener noreferrer"&gt;clutch-deploy&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Full stack&lt;/td&gt;
&lt;td&gt;Docker Compose&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.clutchprotocol.io" rel="noopener noreferrer"&gt;https://docs.clutchprotocol.io&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why a custom chain (and not Ethereum)
&lt;/h2&gt;

&lt;p&gt;Clutch is &lt;strong&gt;non-EVM&lt;/strong&gt;. Ride operations are native transaction types with RLP encoding:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RideRequest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Passenger requests a ride&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RideOffer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Driver offers to fulfill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RideAcceptance&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Passenger accepts; fare debited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RidePay&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Payment installment to driver + referrers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RideCancel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cancel trip; refund unpaid fare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RideRequestCancel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cancel pending request&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(Tags 6–7 are intentionally unused — they held two arrival-confirmation types I removed while simplifying the state machine.)&lt;/p&gt;

&lt;p&gt;Apps don't deploy contracts. They call the Hub API for unsigned payloads, sign locally, and submit signed RLP hex. The node validates signatures, nonces, and applies the ride state machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you gain:&lt;/strong&gt; simpler app surface, predictable tx format, ride logic enforced in the node.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you lose:&lt;/strong&gt; DeFi composability, existing wallet/tooling, large validator ecosystem.&lt;/p&gt;
&lt;h2&gt;
  
  
  How a ride works (end to end)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RideRequest → RideOffer(s) → RideAcceptance → RidePay → completed
     ↓                              ↓
RideRequestCancel              RideCancel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  1. Build unsigned transaction (server)
&lt;/h3&gt;

&lt;p&gt;The Hub API constructs the payload and injects referrer addresses from config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUnsignedRideRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;pickupLatitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;35.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;pickupLongitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;51.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;dropoffLatitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;35.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;dropoffLongitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;51.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;fare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns JSON like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"function_call_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RideRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Sign client-side (never send private keys)
&lt;/h3&gt;

&lt;p&gt;The SDK holds your key locally and signs with secp256k1 — the key never touches the API. It's also what signs the auth challenge, so pass it when you construct the SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ClutchHubSdk&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clutch-hub-sdk-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// privateKey stays in the client; it signs both the auth challenge and txs.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ClutchHubSdk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api-stage.clutchprotocol.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ensureAuth signs a timestamped challenge with your key to get a short-lived JWT.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ensureAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsigned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUnsignedRideRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;35.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;51.4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;dropoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;35.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;51.5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;fare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsigned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Submit signed transaction
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submitTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rawTransaction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Hub forwards to the node over WebSocket JSON-RPC (&lt;code&gt;send_raw_transaction&lt;/code&gt;). Validators include the tx in a block; state updates atomically.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Read state (GraphQL or subscriptions)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listRideRequests&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeRideRequests&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Open requests:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Subscriptions multiplex over a shared WebSocket to &lt;code&gt;/graphql/ws&lt;/code&gt;. Under the hood the API polls the node (~0.5–1s) and pushes snapshots — an honest alpha limitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  CLT economics (driver-first)
&lt;/h2&gt;

&lt;p&gt;Ride payments and validator rewards are &lt;strong&gt;separate&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RidePay&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Referrer fees + driver remainder&lt;/td&gt;
&lt;td&gt;2% request + 2% offer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocks&lt;/td&gt;
&lt;td&gt;Fixed reward to block author&lt;/td&gt;
&lt;td&gt;50 CLT per block&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; 10 CLT fare, one full &lt;code&gt;RidePay&lt;/code&gt;, both referrers set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request referrer: 1 CLT&lt;/li&gt;
&lt;li&gt;Offer referrer: 1 CLT&lt;/li&gt;
&lt;li&gt;Driver: 8 CLT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;App builders:&lt;/strong&gt; run your own Hub API, set your wallet as &lt;code&gt;default_ride_request_referrer&lt;/code&gt; / &lt;code&gt;default_ride_offer_referrer&lt;/code&gt;, and earn CLT when users complete rides on your deployment. No separate grants program — rewards come from real ride activity.&lt;/p&gt;

&lt;p&gt;Details: &lt;a href="https://docs.clutchprotocol.io/getting-started/app-developer-incentives" rel="noopener noreferrer"&gt;https://docs.clutchprotocol.io/getting-started/app-developer-incentives&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Security model
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client-side signing only&lt;/strong&gt; — the API receives signed RLP hex, never private keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallet auth via a signed challenge&lt;/strong&gt; — you prove key ownership by signing a timestamped message (no passwords), which mints a short-lived JWT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce anti-replay&lt;/strong&gt; — per-account nonce enforced on-chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faucet&lt;/strong&gt; — server-side signer only, testnet &lt;code&gt;Transfer&lt;/code&gt; only; disabled in production&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it in 3 minutes (no install)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;&lt;a href="https://app-stage.clutchprotocol.io" rel="noopener noreferrer"&gt;https://app-stage.clutchprotocol.io&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose Passenger or Driver → generate wallet → &lt;strong&gt;Request CLT&lt;/strong&gt; (faucet)&lt;/li&gt;
&lt;li&gt;Passenger: request a ride on the map · Driver: submit an offer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full tutorial: &lt;a href="https://docs.clutchprotocol.io/getting-started/ride-lifecycle" rel="noopener noreferrer"&gt;https://docs.clutchprotocol.io/getting-started/ride-lifecycle&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the full stack locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/clutchprotocol/clutch-deploy.git
&lt;span class="nb"&gt;cd &lt;/span&gt;clutch-deploy
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Demo app&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:5173" rel="noopener noreferrer"&gt;http://localhost:5173&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hub API&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:3000/health" rel="noopener noreferrer"&gt;http://localhost:3000/health&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explorer&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:5174" rel="noopener noreferrer"&gt;http://localhost:5174&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;clutch-hub-sdk-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's Alpha
&lt;/h3&gt;

&lt;p&gt;This is an honest work-in-progress, not a finished product:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Testnet only&lt;/strong&gt; — CLT is free test currency; nothing real is charged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No reputation or ratings&lt;/strong&gt; — nothing scores drivers or riders yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No dispute resolution&lt;/strong&gt; — cancellations are on-chain, but there's no
arbitration when two parties disagree, and no no-show/fraud handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Matching is naive&lt;/strong&gt; — no surge pricing or geospatial optimization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriptions poll the node (~1s)&lt;/strong&gt; rather than true push.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DAO governance&lt;/strong&gt; is on the roadmap, not in the code.&lt;/li&gt;
&lt;li&gt;APIs may change without notice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;Eight public repos under &lt;a href="https://github.com/clutchprotocol" rel="noopener noreferrer"&gt;https://github.com/clutchprotocol&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Star the org if this is interesting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discussions:&lt;/strong&gt; &lt;a href="https://github.com/orgs/clutchprotocol/discussions" rel="noopener noreferrer"&gt;https://github.com/orgs/clutchprotocol/discussions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issues and PRs welcome&lt;/strong&gt; — conventional commits appreciated&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Questions I'd love feedback on
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dispute resolution &amp;amp; reputation&lt;/strong&gt; — this is the part I &lt;em&gt;haven't&lt;/em&gt; built and find hardest. With no central operator to force a refund, what actually works: escrow with a timeout, staked third-party arbitrators, something else? If you've shipped marketplace or payments infra, I'd genuinely value your take.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-specific chain vs. smart contracts&lt;/strong&gt; — worth it for ride-sharing, or would you always reach for an L2?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referrer-fee model for app builders&lt;/strong&gt; — sensible incentive, or weird?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What would you build&lt;/strong&gt; on this stack?&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://clutchprotocol.io" rel="noopener noreferrer"&gt;https://clutchprotocol.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://docs.clutchprotocol.io" rel="noopener noreferrer"&gt;https://docs.clutchprotocol.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stage demo: &lt;a href="https://app-stage.clutchprotocol.io" rel="noopener noreferrer"&gt;https://app-stage.clutchprotocol.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm SDK: &lt;a href="https://www.npmjs.com/package/clutch-hub-sdk-js" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/clutch-hub-sdk-js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/clutchprotocol" rel="noopener noreferrer"&gt;https://github.com/clutchprotocol&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://dev.to/mehran_mazhar"&gt;Mehran Mazhar&lt;/a&gt; (&lt;a href="https://github.com/MehranMazhar" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;). Alpha software — use at your own risk.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>blockchain</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
