Skip to content

feat: x402 micropayment gate for voice sessions#1

Merged
SwarnimWalavalkar merged 1 commit intodevfolioco:mainfrom
Ataxia123:feat/x402-voice-session-gate
Mar 19, 2026
Merged

feat: x402 micropayment gate for voice sessions#1
SwarnimWalavalkar merged 1 commit intodevfolioco:mainfrom
Ataxia123:feat/x402-voice-session-gate

Conversation

@Ataxia123
Copy link
Copy Markdown
Collaborator

Summary

  • Gate voice sessions behind x402 micropayments so each session costs a configurable USDC amount (default $1.00)
  • Payment is verified and settled on-chain via Delve's existing payment infrastructure (OnchainFi)
  • A signed, single-use JWT bridges the two services: Delve issues it after payment, AustinGPT validates it before granting LiveKit access
  • When the payment gate is not configured (no env vars), everything works exactly as before — free access preserved

Architecture

Browser → PaymentGate component (wallet + EIP-712 sign)
       → Delve POST /paid/voice/session (verify + settle on-chain)
       ← signed JWT (HS256, 10min TTL, single-use jti)
Browser → AustinGPT /api/connection-details?session_token=JWT
       → JWT verified, jti consumed
       ← LiveKit tokens
Browser → LiveKit Cloud ↔ AustinGPT Python Agent

What changed

API (client/app/api/connection-details/route.ts)

  • When VOICE_SESSION_JWT_SECRET is set, requires a valid session JWT via ?session_token= query param or Authorization: Bearer header
  • Validates signature (HS256), session_type === "voice", expiration, and single-use jti
  • Single-use enforcement via in-memory Set<string> cleared every 15 minutes
  • Returns 402 (no token), 401 (invalid/expired), 409 (already used)
  • Without the env var, free access is preserved (dev mode)

Frontend (client/app/talk/page.tsx + new components)

  • PaymentGate component renders before voice session when NEXT_PUBLIC_DELVE_API_URL is set
  • State machine: DISCONNECTED → WALLET_CONNECTED → SIGNING → PAYMENT_PENDING → SESSION_READY → voice begins
  • Mood-aware styling (yellow accent for Excited, blue for Critical) matching existing AustinGPT aesthetic
  • useVoiceSession hook manages the full wallet → sign → pay → token flow
  • Ported x402 payment header builder (lib/payment/) from unified-webapp (ERC-3009 TransferWithAuthorization)

Wallet config (config/wagmi.ts, context/AppKitContext.tsx)

  • wagmi adapter and AppKit modal now initialize when either Zora minting or payment gate is enabled
  • No change when neither is configured

Dependencies

  • Added jose for JWT verification in the API route

Setup

Environment Variables (client/.env.local)

# === Required for payment gate ===
VOICE_SESSION_JWT_SECRET=<32+ char hex string>   # Same secret as Delve backend
NEXT_PUBLIC_DELVE_API_URL=https://api.delve.bonfires.xyz  # Delve API base URL
NEXT_PUBLIC_PAYMENT_AGENT_ID=<agent-objectid>     # Agent to bill against

# === Required for wallet (also needed for Zora minting) ===
NEXT_PUBLIC_PROJECT_ID=<reown-project-id>         # https://cloud.reown.com

# === Optional overrides (sensible defaults) ===
NEXT_PUBLIC_PAYMENT_NETWORK=base                  # Default: base
NEXT_PUBLIC_PAYMENT_TOKEN_ADDRESS=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913  # USDC on Base
NEXT_PUBLIC_CHAIN_ID=8453                         # Base mainnet
NEXT_PUBLIC_PAYMENT_DEFAULT_AMOUNT=1.00           # Session price in USD

To enable the payment gate:

  1. Set the env vars above in client/.env.local
  2. Ensure the Delve backend has the same VOICE_SESSION_JWT_SECRET and exposes POST /paid/voice/session
  3. pnpm install && pnpm dev

To keep free access (dev/testing):

  • Don't set NEXT_PUBLIC_DELVE_API_URL — the payment gate is bypassed entirely
  • Don't set VOICE_SESSION_JWT_SECRET — the API route skips JWT validation

Test plan

  • Without any payment env vars: voice sessions work exactly as before (no regression)
  • With VOICE_SESSION_JWT_SECRET set but no token: /api/connection-details returns 402
  • With valid JWT: LiveKit tokens returned normally
  • Replay same JWT: returns 409 (single-use)
  • Expired JWT (>10 min): returns 401
  • Full E2E: connect wallet → pay → session token → voice conversation starts
  • Mobile: PaymentGate renders correctly on small screens

🤖 Generated with Claude Code

Gate voice sessions behind Delve's x402 payment infrastructure.
Users connect a wallet, sign an ERC-3009 USDC authorization, and
receive a single-use JWT that unlocks LiveKit access.

API changes:
- connection-details route validates JWT (jose) when VOICE_SESSION_JWT_SECRET is set
- Single-use enforcement via in-memory jti Set (cleared every 15 min)
- Without the secret, free access is preserved (dev mode)

Frontend changes:
- PaymentGate component shown before voice session when NEXT_PUBLIC_DELVE_API_URL is set
- useVoiceSession hook manages wallet → sign → pay → session flow
- Ported x402 payment header builder from unified-webapp (lib/payment/)
- wagmi/AppKit init updated to support payment gate independent of Zora minting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​jose@​6.2.210010010093100

View full report

@SwarnimWalavalkar SwarnimWalavalkar merged commit aecb3a9 into devfolioco:main Mar 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants