Stablecoin-Native Commerce Advertising Infrastructure
AdGrid is a programmable advertising platform where every ad is an executable commerce intent. Companies purchase QR-code placements (AdSlots) at physical and digital locations. Consumers scan codes to instantly purchase products, settling in USDC/USDT via the StateSet payment rails. StateSet collects a 3% protocol fee on every settled transaction.
No impressions. No clicks. No chargebacks. Just scan, settle, done.
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ ┌────────────────┐
│ Merchant │ │ AdGrid │ │ Consumer │ │ Settlement │
│ creates │────▶│ generates │────▶│ scans QR │────▶│ Engine splits │
│ campaign │ │ signed QR │ │ one-tap buy │ │ 97% / 3% │
└─────────────┘ └──────────────┘ └─────────────────┘ └────────────────┘
- Merchant creates a campaign with commerce offers and bids on ad slots
- AdGrid runs a Generalized Second-Price auction and generates Ed25519-signed QR codes
- Consumer scans a QR code and authorizes a stablecoin purchase
- Settlement Engine atomically splits payment: 97% to merchant, 3% to protocol treasury
AdGrid is built as a Rust workspace with seven crates:
| Crate | Purpose |
|---|---|
stateset-adgrid-core |
Domain types — AdSlot, AdCampaign, CommerceOffer, SettlementSplit, QrPayload |
stateset-adgrid-qr |
Ed25519-signed QR payloads, PNG/base64 encoding, nonce replay protection |
stateset-adgrid-auction |
GSP auction engine — highest bid wins, pays second price + $0.01 |
stateset-adgrid-settlement |
Multi-party USDC/USDT settlement, escrow, refunds |
stateset-adgrid-analytics |
Deterministic on-chain attribution, scan-to-settle funnel, ROAS |
stateset-adgrid-api |
Axum REST API with 14 endpoints |
stateset-adgrid-agent |
AI agent interface with NSR primitives for autonomous ad management |
# Build
cargo build
# Run tests
cargo test
# Start the API server
cargo run --bin adgrid-server
# Server binds to 0.0.0.0:8080 by default
# Override with ADGRID_BIND=127.0.0.1:3000The operator dashboard lives in dashboard/ and targets Node 22.12.0 via .nvmrc.
cd dashboard
npm ci
npm run lint
npm run buildSet VITE_ENABLE_DEMO_DATA=true only when you intentionally want seeded demo records in the UI.
The first dashboard screen now bootstraps a merchant session directly from the API:
- Create a new merchant with a browser-generated Ed25519 keypair
- Import an existing merchant ID and private key to restore access
- Export the active merchant session from the top bar for secret backup
All endpoints are under /v1. Authentication is via Ed25519 signature headers.
POST /v1/campaigns Create a campaign with escrowed USDC budget
GET /v1/campaigns/{id} Get campaign details and real-time analytics
POST /v1/campaigns/{id}/offers Add a commerce offer to a campaign
POST /v1/slots Create an ad slot (physical or digital)
GET /v1/slots Query available slots by location and time
POST /v1/slots/{id}/bid Submit or update a bid for an ad slot
POST /v1/qr/generate Generate a signed QR code for a commerce offer
POST /v1/qr/verify Verify and decode a scanned QR payload
POST /v1/settle Execute a stablecoin settlement for a purchase
POST /v1/refunds Initiate a refund through escrow release
GET /v1/analytics/campaign/{id} Campaign performance: scans, conversions, revenue, ROAS
GET /v1/analytics/platform Platform-wide metrics: GMV, protocol revenue, utilization
GET /v1/agent/capabilities Machine-readable tool catalog for external AI agents
GET /.well-known/agent.json Public discovery manifest for agent runtimes
POST /v1/agent/recommendations Generate preview-safe next actions for a merchant or campaign
POST /v1/agent/preview Dry-run one primitive and inspect the derived outcome without mutating state
POST /v1/agent/execute Execute one NSR primitive with Ed25519-authenticated merchant context
GET /v1/agent/actions List recent agent actions executed for the authenticated merchant
GET /v1/agent/context Load merchant balance, campaigns, offers, auctions, and recent actions in one response
POST /v1/merchants Onboard a new merchant
GET /v1/merchants/{id}/balance Merchant stablecoin balance and pending settlements
| Fee | Rate | Payer | When |
|---|---|---|---|
| Protocol Transaction Fee | 3.00% | Consumer (included in price) | On every QR-initiated purchase |
| Slot Auction Fee | 5.00% of clearing price | Winning Merchant | On auction settlement |
| Merchant Onboarding | Free | — | Account creation |
| Refund Processing | 0.50% | Merchant | On refund execution |
Every QR code is a cryptographically signed commerce intent, not a simple URL:
- Ed25519 signatures — payload is signed with the merchant's private key and verified before any settlement
- Nonce-based replay protection — each QR code contains a unique 32-byte nonce, consumed on settlement
- Time-bounded expiry — payloads expire after a configurable window (default 60 minutes)
- Atomic settlement — all-or-nothing execution prevents partial state
pub struct QrPayload {
pub version: u8,
pub offer_id: OfferId,
pub merchant_id: MerchantId,
pub price_usdc: Decimal,
pub slot_id: AdSlotId,
pub nonce: [u8; 32],
pub expiry: DateTime<Utc>,
pub signature: Ed25519Signature,
}Slots are allocated via continuous Generalized Second-Price (GSP) auctions:
- Bid currency: USDC, escrowed on submission
- Time granularity: 1-hour minimum slots
- Reserve price: Set per-slot by location owner
- Winner determination: Highest bid wins, pays second price + $0.01
- Auction fee: 5% of clearing price to protocol treasury
AdGrid exposes operations as Neuro-Symbolic Reasoning (NSR) primitives for autonomous campaign management:
CreateCampaign(merchant, products, budget) — Analyze catalog, generate offers, set budgets
AdjustBid(campaign, slot, target_roas) — Monitor auctions, optimize bids for ROI targets
OptimizeOffer(offer, metric, constraint) — A/B test pricing, adjust discounts
DetectAnomaly(campaign, window, threshold) — Flag unusual scan patterns, potential fraud
ReallocateBudget(campaign, performance_data) — Shift budget to high-converting slots
GenerateReport(campaign, period, format) — Human-readable performance reports
External agent runtimes can discover and call these primitives without scraping docs:
curl http://127.0.0.1:8080/.well-known/agent.jsonEach signed execution request wraps exactly one primitive:
{
"merchant_id": "merchant-uuid",
"primitive": {
"AdjustBid": {
"campaign_id": "campaign-uuid",
"slot_id": "slot-uuid",
"target_roas": "3.00",
"auto_apply": false
}
}
}The merchant_id in the body must match the X-Merchant-Id header used for Ed25519 request signing.
For retry safety, agents should also send X-Idempotency-Key on POST /v1/agent/execute; AdGrid will replay the cached action response for 24 hours instead of applying the primitive twice.
Agents can call POST /v1/agent/preview with the same request body before execution; preview forces auto_apply and auto_pause off, and execution now re-checks campaign and offer ownership against the authenticated merchant instead of trusting embedded IDs inside the primitive.
When the next step is unclear, agents can ask AdGrid for a plan first:
{
"merchant_id": "merchant-uuid",
"strategy": "Balanced",
"limit": 4
}The planner returns executable requests for preview-safe primitives such as AdjustBid, OptimizeOffer, DetectAnomaly, and GenerateReport. Executed actions are then available through GET /v1/agent/actions.
Agents that need working state before planning or execution can hydrate a merchant-scoped context snapshot first:
curl -H "X-Merchant-Id: merchant-uuid" \
-H "X-Timestamp: 1710000000" \
-H "X-Signature: <hex>" \
"http://127.0.0.1:8080/v1/agent/context?campaign_limit=6&offer_limit_per_campaign=3&auction_limit=8&action_limit=6"The context response includes the authenticated merchant's balance, recent campaigns with offer snapshots, open-auction summaries, and recent agent actions so external runtimes can decide on the next primitive without making a half-dozen separate API calls.
Agent-created offers now start from a category-based baseline price instead of 0, so downstream optimization primitives can refine real price points immediately.
Auction bid history is merchant-scoped: GET /v1/slots/{id}/bids returns the authenticated merchant's bids plus market-level summary fields, rather than exposing every bidder on the slot.
| Metric | Definition |
|---|---|
| Scan Rate | QR scans per impression-hour per slot |
| Scan-to-Settle Rate | % of scans that result in completed purchases |
| Gross Merchandise Volume | Total USDC settled through AdGrid |
| Protocol Revenue | 3% of GMV collected by StateSet |
| ROAS | (merchant revenue − slot cost) / slot cost |
| Time-to-Settle | Median time from QR scan to settlement finality |
| Slot Utilization | % of available slot-hours occupied by campaigns |
| Dimension | Legacy Ad Platforms | AdGrid |
|---|---|---|
| Revenue Model | CPM / CPC (impression-based) | 3% on settled commerce only |
| Settlement Speed | Net-30/60 advertiser billing | Sub-second stablecoin finality |
| Attribution | Probabilistic multi-touch | Deterministic on-chain proof |
| Physical Commerce | Limited | Native QR-to-settle |
| AI Integration | Black-box automated bidding | Full NSR Engine autonomy |
| Fee Transparency | Opaque interchange + processing | Flat 3%, fully auditable |
Apache-2.0
StateSet Inc. — San Francisco, CA