PEP/402Documentation
USDC / Arc Testnet
Browse documentation
Docs / introduction

Research markets over an HTTP payment rail.

PEP/402 indexes source-linked public peptide listings, rechecks those sources at runtime, and exposes an x402-protected handoff on Arc Testnet. It separates market observation, payment settlement, and supplier fulfillment instead of presenting them as one magical button.

Start here

Overview

Every chart is calculated from the offer records returned by the markets API. Product photographs are fetched from allowlisted official distributor listings, dated, and visibly attributed; none are generated or taken from an unrelated stock library.

  • Marketplace: search and filter indexed compounds.
  • Market detail: compare supplier listings and normalized USD-per-milligram values.
  • Source check: fetch linked public pages and report reachability, product-text, and exact-price matches.
  • Source imagery: proxy each product's official listing photograph through a slug-bound, content-type-checked endpoint.
  • Story: a playable explanation of HTTP 402, Circle Gateway, and the product boundary.

Boundaries

A successful x402 settlement unlocks a source handoff and one non-transferable receipt claim. The receipt proves that payment event; it is not title to a peptide, a medical credential, or evidence that a supplier accepted an order. The supplier remains responsible for inventory, eligibility, shipping, order acceptance, and fulfillment.

Quick start

pnpm install
cp .env.example .env.local
pnpm dev

Without valid merchant and receipt-minter configuration, the markets and sources work normally while checkout stays locked. This is intentional: development mode does not manufacture a successful payment or mint.

Market data

Snapshot + source check

Price records are dated observations captured from ten public supplier catalogs on 2026-09-15. “Ten indexed distributors” describes coverage, not a quality ranking. At runtime, the server fetches each linked catalog and offer page, records reachability, and looks for matching product and price text.

The API reports live-source-check when at least one source responds and snapshot-fallback if every source is unavailable. A text match verifies visible source evidence; it does not certify inventory or quality.

Markets API

GET /api/markets returns distributors, products, dated offers, computed market rows, Arc configuration, per-offer verification state, and per-source probe results.

curl http://localhost:3000/api/markets

# Response header
X-Data-Provenance: live-source-check

The public response can be shared-cached for fifteen minutes while individual source fetches revalidate hourly. A failed source never turns a cached observation into a live quote.

Normalization

USD-per-milligram is calculated only when the listing is priced in USD and a numerical vial strength is available:

normalized price = USD listing price / vial strength in mg

GBP listings remain GBP. Listings whose strength is only visible after choosing a variant remain unnormalized. No foreign-exchange rate or hidden strength is inferred.

Payments

Wallet + Gateway

The global wallet control does not pretend Arc has a finite wallet allowlist. It requests EIP-6963 announcements and renders every installed EVM provider. A legacy window.ethereum provider remains a fallback. Reown AppKit adds WalletConnect QR/mobile access to its 600+ wallet ecosystem when NEXT_PUBLIC_REOWN_PROJECT_ID is configured. Coinbase Wallet, MetaMask, Rabby, and Rainbow are separated visually because Arc publishes explicit setup instructions for them.

After connection, the app requests Arc Testnet through EIP-3085/EIP-3326 and reads two distinct 6-decimal ERC-20 balances: USDC in the wallet and USDC available inside Circle Gateway. If Gateway is short, the user approves and deposits only the difference. That one-time onchain deposit enables later gas-free x402 authorizations.

DISCOVER      → EIP-6963 installed providers / WalletConnect QR
CONNECT       → eth_requestAccounts
SWITCH        → wallet_switchEthereumChain
FUND ONCE     → USDC.approve + GatewayWallet.deposit
PAY REPEATEDLY → EIP-712 authorization; no per-payment gas

x402 checkout

Each USD offer maps to a protected GET route at /api/checkout/[offerId]. The client deliberately requests the machine-readable HTTP 402 challenge, selects the Arc Gateway batching requirement, asks the connected wallet to sign it, and retries with the encoded signature.

PAYMENT-REQUIRED   → challenge
PAYMENT-SIGNATURE  → signed authorization
PAYMENT-RESPONSE   → settlement receipt

Settlement uses Circle Gateway’s batching facilitator and Gateway-aware exact EVM scheme. The client caps the authorization at the selected listing amount. The server route rejects unknown and non-USD offers and never computes an exchange rate.

Receipt mint

One OpenZeppelin ERC-1155 contract represents the whole registry. Each peptide has a stable, append-only token ID; each settled purchase can mint one unit of that type. This avoids deploying a speculative fungible token for every catalog item.

x402 payment succeeds
  → server signs EIP-712 Claim(buyer, tokenId, paymentId, deadline)
  → buyer calls claim(...) on Arc Testnet
  → contract consumes paymentId and mints one soulbound receipt

The voucher expires after 24 hours, is bound to the deployed contract and chain, and cannot be replayed. Transfers between non-zero addresses revert. Contract metadata comes from /api/tokens/[tokenId] and makes the receipt boundary explicit.

Backend boundary

The implemented testnet backend is stateless: the x402 payment signature is hashed with the offer ID to produce an idempotent payment ID, and the receipt contract prevents replay. This is enough to prove payment, unlock the source, and mint a receipt. Catalog prices remain the sourced market evidence; the test rail charges 0.01 USDC by default so a faucet-funded wallet can exercise the full flow. That charge is not represented as a physical purchase.

Arc configuration

NetworkArc Testnet
CAIP-2eip155:5042002
Chain ID5042002
RPChttps://rpc.testnet.arc.network
Testnet USDC0x3600000000000000000000000000000000000000
Gateway wallet0x0077777d7EBA4688BDeF3E311b846F25870A19B9
ARC_MERCHANT_ADDRESS=0xYOUR_NON_ZERO_EVM_ADDRESS
ARC_TESTNET_CHECKOUT_USDC=0.01
ARC_RECEIPT_CONTRACT_ADDRESS=0xYOUR_DEPLOYED_CONTRACT
ARC_MINT_AUTHORITY_PRIVATE_KEY=0xSERVER_ONLY_SIGNER
CIRCLE_X402_FACILITATOR_URL=https://gateway-api-testnet.circle.com

Payment states

503Not configuredNo valid merchant address; no 402 challenge is issued.
402Payment requiredChallenge is valid but authorization is absent or settlement failed.
2xxPaid handoffSettlement succeeded; source manifest, supplier URL, and buyer-bound mint voucher are returned.
4xxInvalid offerThe requested offer is unknown or not priced in USD.