@bolyra/payment-protocols
v0.7.0
Published
ZKP privacy layer for Visa TAP and Google AP2 — Bolyra as the identity backbone for agentic commerce
Maintainers
Readme
@bolyra/payment-protocols
ZKP privacy layer for agentic commerce payment protocols. Open-source protocol research — not production software.
What This Does
When AI agents make purchases on behalf of humans, payment networks need to verify:
- Is this agent authorized? (identity)
- What can it spend? (policy)
- Did the human consent? (authorization)
Today, Visa's Trusted Agent Protocol (TAP) and Google's Agent Payments Protocol (AP2) answer these questions with centralized registries and plain-text mandates. The merchant sees everything — the user's identity, their exact budget, their full policy.
Bolyra replaces that with zero-knowledge proofs. The merchant learns only:
- "This agent is authorized" (yes/no)
- "The spend policy is sufficient for this transaction" (yes/no)
- A trust score (0–100)
The merchant never sees: the human's identity, the exact spend limit, the full vendor allowlist, or the delegation chain structure.
Architecture
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Human │────▸│ Bolyra SDK │────▸│ ZKP Proof │
│ (identity) │ │ (handshake + │ │ (public │
│ │ │ spend policy) │ │ signals │
└──────────────┘ └──────────────────┘ │ only) │
└──────┬───────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌─────────────────┐
│ Visa TAP │ │ Google AP2 │ │ Spend Policy │
│ Adapter │ │ Adapter │ │ Encoder │
│ │ │ │ │ │
│ TAP payment │ │ AP2 mandate │ │ Bitmask │
│ signal + │ │ proof + │ │ encoding + │
│ trust score │ │ delegation │ │ verification │
└────────────────┘ └────────────────┘ └─────────────────┘Protocol Mapping
Visa TAP
| TAP Concept | Bolyra Equivalent | |---|---| | Agent registry lookup | ZKP proof of human authorization | | HTTP Message Signature (RFC 9421) | ZKP proof + scope commitment | | Payment Instructions API | Spend policy encoded in permission bitmask | | Payment Signals API | Scope commitment + agent nullifier | | Trust tier | Score-based grading (A/B/C/D/F) |
Google AP2
| AP2 Concept | Bolyra Equivalent | |---|---| | Intent Mandate | Bolyra handshake proof (human → agent) | | Cart Mandate | Spend policy ZKP (covers specific transaction) | | Payment Mandate | Off-chain verified proof (batch mode) | | Agent-to-agent delegation | Bolyra delegation chain with hop tracking | | Mandate signature | ZKP proof (Groth16 for human, PLONK for agent) |
Stripe Agent Commerce Protocol (ACP)
| Stripe ACP Concept | Bolyra Equivalent |
|---|---|
| Acting agent | Leaf delegatee in the v=2 bundle's delegationChain |
| Originating agent | Root credential the human authorized at handshake |
| Delegation depth | chainDepth from the verified context |
| Spending cap | Collapsed from cumulative FINANCIAL_* bits (2/3/4) on the leaf scope |
| sign_on_behalf flag | Bit 5 of the leaf scope (for pi.confirm flows) |
The narrowing wedge: a root agent with FINANCIAL_UNLIMITED can delegate down to a sub-agent with FINANCIAL_SMALL ($100 cap). Stripe ACP sees only the leaf's $100 cap, even though the root could have spent more.
Usage
Visa TAP Verification
import { createVisaTAPVerification } from '@bolyra/payment-protocols';
const result = await createVisaTAPVerification(
humanIdentity,
agentCredential,
{
maxTransactionAmount: 50_000, // $500
maxCumulativeAmount: 100_000, // $1,000
currency: 'USD',
timeWindow: { start: now, end: now + 86400 },
},
{
agentDid: 'did:bolyra:base-sepolia:...',
merchantId: 'visa-merchant-123',
amount: 5_000,
currency: 'USD',
transactionId: 'txn-abc-123',
},
);
// result.verified: boolean
// result.score: 0-100
// result.grade: 'A' | 'B' | 'C' | 'D' | 'F'
// result.paymentSignal: opaque token for TAP Payment Signals APIGoogle AP2 Agent Credential
import { createAP2AgentCredential, verifyAP2AgentCredential } from '@bolyra/payment-protocols';
// Agent side: create credential
const credential = await createAP2AgentCredential(
humanIdentity,
agentCredential,
[
{ name: 'purchase', maxAmount: 50_000, currency: 'USD' },
{ name: 'price_compare', maxAmount: 0, currency: 'USD' },
],
);
// Merchant side: verify credential
const verification = await verifyAP2AgentCredential(credential);
// verification.verified: boolean
// verification.score: 0-100Stripe ACP — narrowing wedge
import {
authContextToStripeACPContext,
verifyStripeACPSpend,
} from '@bolyra/payment-protocols';
import { verifyBundle } from '@bolyra/mcp';
// 1. Verify the v=2 bundle once (handshake + delegation chain).
const ctx = await verifyBundle(bundle, mcpConfig);
// 2. Reshape into a Stripe ACP context. The leaf delegatee becomes the
// acting agent; the root credential the human authorized stays as the
// originating agent for audit.
// rootAgentDid comes from ctx.did (set by verifyBundle from the verified
// credential commitment) — no caller-supplied root, no chain rebinding.
const acp = authContextToStripeACPContext(
ctx,
'base-sepolia', // DID network for actingAgentDid (must match ctx.did's network)
'usd', // ISO 4217 currency; lowercase per Stripe convention
);
// 3. Gate each PaymentIntent against the leaf-narrowed cap.
const decision = verifyStripeACPSpend(acp, 5_000, 'USD'); // $50
if (!decision.allowed) {
throw new Error(`Stripe ACP denied: ${decision.reason}`);
}
// Example: root had FINANCIAL_UNLIMITED, but the chain narrowed the leaf
// to FINANCIAL_SMALL. Stripe sees a $100 cap, not the root's authority.
// decision.tier === 'small'
// decision.capChecked === 10_000 // $100 in centsSpend Policy Encoding
import { encodeSpendPolicy, verifySpendPolicyProof } from '@bolyra/payment-protocols';
// Encode for ZKP circuit
const bitmask = encodeSpendPolicy({
maxTransactionAmount: 50_000,
maxCumulativeAmount: 100_000,
currency: 'USD',
timeWindow: { start: now, end: now + 86400 },
categoryRestriction: { allowedMCCs: ['5411', '5812'] },
});
// Merchant-side verification (from ZKP public signals)
const { satisfied, reasons } = verifySpendPolicyProof(bitmask, {
minTransactionAmount: 10_000,
requiredMCCs: ['5411'],
});Design Principles
- Thin glue — all cryptographic work delegates to
@bolyra/sdk - Lazy SDK import — heavy crypto deps load only when needed
- Score-based results — consistent with the OpenClaw adapter pattern
- Off-chain by default — batch verification for high-throughput commerce
- Privacy-preserving — merchant never learns more than necessary
- Protocol-agnostic core — spend policy encoding works with any payment protocol
License
Apache-2.0 — open-source protocol research.
