Skip to main content

Installation

npm install @cred-protocol/hono @cred-protocol/sdk

Quick Start

import { Hono } from 'hono'
import { credGates } from '@cred-protocol/hono'

const app = new Hono()

app.use('/api/*', credGates({
  apiKey: process.env.CRED_API_KEY,
  policy: 'standard',
}))

app.get('/api/resource', (c) => {
  const trust = c.get('credTrust')
  return c.json({ data: '...', trustTier: trust.trustTier })
})
Every request to /api/* is evaluated. Wallets that fail the standard policy get a 402 challenge response. Wallets that pass get the trust result on c.get('credTrust').

Configuration

credGates({
  // Required
  apiKey: process.env.CRED_API_KEY,

  // Policy (pick one)
  policy: 'standard',              // Named template
  // gates: ['human', 'verified'], // Or custom gates
  // operator: 'AND',

  // Dynamic pricing
  pricing: {
    enabled: true,
    curve: 'step',                 // 'linear', 'exponential', 'step'
    basePriceUsdc: 0.01,
  },

  // Failure handling
  on402: 'challenge',              // 'challenge' (402), 'deny' (403), 'pass' (allow)
  onBlocked: 'deny',              // 'deny' (403), 'challenge' (402), 'pass'

  // Response headers
  headers: true,                   // Set X-Cred-Trust-Score, X-Cred-Trust-Tier

  // Custom wallet extraction
  extractWallet: (c) => c.req.header('X-Agent-Wallet'),

  // Callback for logging/analytics
  onEvaluation: (result, c) => {
    console.log(`${result.walletAddress}: ${result.trustTier} (${result.trustScore})`)
  },
})

Wallet Address Extraction

By default the middleware checks (in order):
  1. X-Wallet-Address request header
  2. ?wallet= query parameter
If neither is present, it returns a 400. Override with extractWallet:
credGates({
  apiKey: process.env.CRED_API_KEY,
  policy: 'standard',
  extractWallet: (c) => {
    // Extract from JWT, session, or custom header
    return c.req.header('X-Agent-Wallet') || c.req.query('address')
  },
})

Response Headers

When headers: true (default), every response includes:
HeaderExampleDescription
X-Cred-Trust-Score750–100 composite score
X-Cred-Trust-TierverifiedTrust tier classification
X-Cred-Request-Ida1b2c3d4-...Request ID for debugging
X-Cred-Price-Multiplier0.25Dynamic price multiplier (if pricing enabled)

Failure Modes

on402: ‘challenge’ (default)

When gates fail, returns a 402 with a machine-readable challenge body:
{
  "type": "trust_challenge",
  "trust_score": 25,
  "trust_tier": "untrusted",
  "failed_gates": [
    { "gate_id": "verified", "gate_name": "Identity Verification", "passed": false }
  ],
  "message": "Wallet did not pass required trust checks"
}

on402: ‘deny’

Returns a simple 403:
{
  "error": "Trust requirements not met",
  "trustTier": "untrusted",
  "trustScore": 25,
  "failedGates": ["verified"]
}

on402: ‘pass’

Allows the request through with trust headers set. Use this for logging/monitoring without blocking.

Dynamic Pricing Example

Gate your API with trust-based pricing — trusted wallets pay less:
app.use('/api/*', credGates({
  apiKey: process.env.CRED_API_KEY,
  policy: 'reputation',
  pricing: { enabled: true, curve: 'step', basePriceUsdc: 0.01 },
  on402: 'challenge',
  headers: true,
}))

app.post('/api/generate', (c) => {
  const trust = c.get('credTrust')

  // trust.priceMultiplier:
  //   trusted (80+)  → 0.0  (free)
  //   verified (60-79) → 0.25 ($0.0025)
  //   limited (30-59)  → 0.5  ($0.005)
  //   untrusted (1-29) → 1.0  ($0.01)

  return c.json({
    result: '...',
    price: trust.suggestedPriceUsdc,
  })
})

Accessing Trust Data in Handlers

The trust result is stored via c.set('credTrust', result) and accessible in any downstream handler:
app.get('/api/profile', (c) => {
  const trust = c.get('credTrust')

  return c.json({
    wallet: trust.walletAddress,
    score: trust.trustScore,
    tier: trust.trustTier,
    gates: trust.gateResults.map(g => ({
      gate: g.gateId,
      passed: g.passed,
      score: g.score,
    })),
  })
})