npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@qilinxlabs/a2a-cronos

v0.3.1

Published

TypeScript SDK for A2A resource discovery and x402 payment protocol on Cronos networks

Downloads

17

Readme

a2a-cronos

TypeScript SDK for A2A resource discovery and x402 payment protocol on Cronos networks.

Disclaimer: This project is built on Cronos Labs x402 Examples and uses the @crypto.com/facilitator-client SDK for x402 payment processing.

Installation

pnpm add a2a-cronos
# or
npm install a2a-cronos

Features

  • A2AClient: Discover and access x402-protected resources
  • A2AServer: Expose and monetize resources with x402 payment
  • A2ABroker: DeFi swap broker with x402 payment (VVS Finance integration)
  • LLM Support: Google, Anthropic, and OpenAI for intelligent resource selection
  • System Prompts: Customizable LLM guardrails for service acceptance
  • Stateless Design: No internal database - developer provides storage callbacks
  • Framework Agnostic: Works with Express or any HTTP framework
  • Network Support: Cronos mainnet and testnet

Quick Start

Client Usage

import { A2AClient } from 'a2a-cronos';

const client = new A2AClient({
  privateKey: '0x...', // Required - your wallet private key
  network: 'cronos-testnet',
  llm: {
    provider: 'google',
    apiKey: 'your-google-api-key',
    model: 'gemini-3-pro-preview',
  },
});

// Discover + LLM select + fetch in one call
const result = await client.fetchWithQuery(
  'get me the paywalled resource',
  ['http://localhost:8787']
);

console.log(result);
// { ok: true, paid: true, paymentId: 'pay_xxx', txHash: '0x...', data: {...} }

Server Usage (Express)

import express from 'express';
import { A2AServer } from 'a2a-cronos';

// In-memory store (use database in production)
const entitlements = new Map();

const server = new A2AServer({
  name: 'my-resource-server',
  url: 'http://localhost:8787',
  network: 'cronos-testnet',
  merchantAddress: '0x...', // Required - address to receive payments
  resources: [
    {
      id: 'premium-data',
      title: 'Premium Data',
      path: '/api/data',
      price: '1000000', // 1 USDC (6 decimals)
    },
  ],
  onEntitlementCreated: async (entitlement) => {
    entitlements.set(entitlement.paymentId, entitlement);
  },
  checkEntitlement: async (paymentId) => {
    return entitlements.has(paymentId);
  },
});

const app = express();
app.use(express.json());

const middleware = server.expressMiddleware();

app.get('/.well-known/agent-card.json', middleware.agentCard);
app.get('/api/data', middleware.requirePayment('premium-data'), (req, res) => {
  res.json({ secret: 'premium content' });
});
app.post('/api/pay', middleware.handleSettlement);

app.listen(8787);

Client API Reference

A2AClientConfig

interface A2AClientConfig {
  /** Wallet private key for signing payments (REQUIRED) */
  privateKey: string;
  
  /** Target network. Default: 'cronos-testnet' */
  network?: 'cronos' | 'cronos-testnet';
  
  /** Custom RPC URL. Uses default if not specified */
  rpcUrl?: string;
  
  /** LLM configuration for AI-based resource selection */
  llm?: LLMConfig;
  
  /** 
   * System prompt for LLM (optional).
   * Used to set guardrails and instructions for agent behavior.
   */
  systemPrompt?: string;
}

interface LLMConfig {
  /** LLM provider */
  provider: 'google' | 'anthropic' | 'openai';
  
  /** API key for the provider (REQUIRED) */
  apiKey: string;
  
  /** Model name (e.g., 'gemini-3-pro-preview', 'claude-3-opus', 'gpt-4o') */
  model: string;
}

System Prompt Example

const client = new A2AClient({
  privateKey: '0x...',
  network: 'cronos-testnet',
  llm: {
    provider: 'google',
    apiKey: 'your-api-key',
    model: 'gemini-2.0-flash',
  },
  // Custom guardrails for service acceptance
  systemPrompt: `You are a cautious AI agent.
Rules:
- Never accept swap quotes with price impact > 5%
- Reject any service charging more than 0.5 USDC
- Always verify the broker fee is disclosed
- For VVS swaps, ensure minimum output is at least 95% of quoted amount`,
});

Quote Guardrails (Broker Services)

When using broker services for DeFi swaps, you can configure guardrails to automatically evaluate quotes before accepting them. The LLM evaluates each guardrail and decides whether to accept or reject the quote.

QuoteGuardrail Interface

interface QuoteGuardrail {
  /** Rule identifier */
  id: string;
  /** Human-readable description */
  description: string;
  /** 
   * Condition in natural language that the LLM will evaluate.
   * The LLM checks this condition against the quote data.
   */
  condition: string;
  /** 'error' rejects quote, 'warning' logs but accepts */
  severity: 'error' | 'warning';
}

interface QuoteAcceptanceCriteria {
  /** Guardrail rules for LLM to evaluate */
  guardrails?: QuoteGuardrail[];
  /** Additional context for the LLM */
  evaluationContext?: string;
  /** Use LLM evaluation (default: true if LLM configured) */
  useLLMEvaluation?: boolean;
  
  // Programmatic fallbacks (used if LLM not available)
  minOutputAmount?: string;
  maxPriceImpact?: string;
  maxBrokerFee?: string;
  maxSlippage?: string;
  customCheck?: (quote: BrokerQuote) => boolean | Promise<boolean>;
}

Guardrail Example

import { requestQuote, acceptQuote, type QuoteAcceptanceCriteria } from 'a2a-cronos';

// Define guardrails
const criteria: QuoteAcceptanceCriteria = {
  guardrails: [
    {
      id: 'min_output',
      description: 'Ensure we receive tokens',
      condition: 'Output amount must be greater than 0',
      severity: 'error',
    },
    {
      id: 'max_slippage',
      description: 'Limit slippage tolerance',
      condition: 'Slippage tolerance must be less than 5%',
      severity: 'error',
    },
    {
      id: 'check_provider',
      description: 'Only accept trusted providers',
      condition: 'Provider must be VVS Finance or VVS Finance (Hybrid)',
      severity: 'error',
    },
    {
      id: 'warn_high_fee',
      description: 'Warn about high fees',
      condition: 'LP fee should be less than 1%',
      severity: 'warning', // Warns but doesn't reject
    },
  ],
  evaluationContext: 'Be conservative with large swaps over 100 USDC',
};

// Request and evaluate quote
const quote = await requestQuote(selection);
const evaluation = await acceptQuote(quote, criteria, llmConfig);

if (evaluation.accepted) {
  console.log('Quote accepted:', evaluation.reason);
  // Proceed with payment
} else {
  console.log('Quote rejected:', evaluation.reason);
  console.log('Failed guardrails:', evaluation.guardrailResults);
}

Evaluation Result

interface QuoteEvaluationResult {
  accepted: boolean;
  reason: string;
  guardrailResults?: Array<{
    id: string;
    passed: boolean;
    message: string;
  }>;
  warnings?: string[];
}

How It Works

  1. LLM Evaluation: When guardrails are configured and LLM is available, the quote is formatted and sent to the LLM along with the guardrail conditions
  2. The LLM analyzes the quote data (amounts, fees, slippage, metadata) against each guardrail condition
  3. Error severity guardrails that fail cause the quote to be rejected
  4. Warning severity guardrails that fail are logged but don't reject the quote
  5. Fallback: If LLM is unavailable, programmatic checks (minOutputAmount, maxSlippage, etc.) are used

A2AClient Methods

discover(url: string): Promise<DiscoveredAgent | null>

Discover an agent from a single URL by fetching its agent card.

const agent = await client.discover('http://localhost:8787');
if (agent) {
  console.log(agent.name, agent.resources);
}

discoverAll(urls: string[]): Promise<DiscoveredAgent[]>

Discover agents from multiple URLs concurrently.

const agents = await client.discoverAll([
  'http://localhost:8787',
  'http://localhost:8788',
]);

selectResource(agent: DiscoveredAgent, resourceIndex: number): ResourceTarget

Manually select a resource from a discovered agent by index.

const agent = await client.discover('http://localhost:8787');
const target = client.selectResource(agent, 0); // First resource

selectResourceWithLLM(query: string, agents: DiscoveredAgent[]): Promise<ResourceTarget | null>

Use LLM to intelligently select the best resource for a query. Requires llm config.

const agents = await client.discoverAll(['http://localhost:8787']);
const target = await client.selectResourceWithLLM(
  'get premium data',
  agents
);

fetchResource(target: ResourceTarget): Promise<FetchResult>

Fetch a resource with automatic x402 payment handling.

const target = client.selectResource(agent, 0);
const result = await client.fetchResource(target);

if (result.ok) {
  console.log('Data:', result.data);
  if (result.paid) {
    console.log('Paid:', result.paymentId, result.txHash);
  }
}

fetchWithQuery(query: string, discoveryUrls: string[]): Promise<FetchResult>

Convenience method combining discover + LLM select + fetch. Requires llm config.

const result = await client.fetchWithQuery(
  'get me the paywalled resource',
  ['http://localhost:8787']
);

FetchResult

interface FetchResult {
  ok: boolean;           // Whether the fetch succeeded
  paid: boolean;         // Whether payment was made
  paymentId?: string;    // Payment ID if paid
  txHash?: string;       // Transaction hash if paid
  data?: unknown;        // Response data
  error?: string;        // Error message if failed
}

Server API Reference

A2AServerConfig

interface A2AServerConfig {
  /** Server name for AgentCard (REQUIRED) */
  name: string;
  
  /** Server description */
  description?: string;
  
  /** Public URL of the server (REQUIRED) */
  url: string;
  
  /** Target network (REQUIRED) */
  network: 'cronos' | 'cronos-testnet';
  
  /** Merchant address to receive payments (REQUIRED) */
  merchantAddress: string;
  
  /** Resource definitions (REQUIRED, at least one) */
  resources: ResourceDefinition[];
  
  /** Custom RPC URL */
  rpcUrl?: string;
  
  /** Asset symbol or contract address. Default: 'USDC' */
  asset?: string;
  
  /** Callback when payment is settled (REQUIRED) */
  onEntitlementCreated: (entitlement: Entitlement) => Promise<void>;
  
  /** Callback to check if paymentId is entitled (REQUIRED) */
  checkEntitlement: (paymentId: string) => Promise<boolean>;
}

interface ResourceDefinition {
  /** Unique resource ID (REQUIRED) */
  id: string;
  
  /** Display title */
  title?: string;
  
  /** Description */
  description?: string;
  
  /** URL path (REQUIRED, e.g., '/api/data') */
  path: string;
  
  /** Price in base units (REQUIRED, e.g., '1000000' for 1 USDC) */
  price: string;
  
  /** Settlement endpoint path. Default: '/api/pay' */
  settlementPath?: string;
}

A2AServer Methods

getAgentCard(): AgentCard

Get the AgentCard JSON for this server.

const card = server.getAgentCard();
// Returns: { name, description, url, network, resources: [...] }

expressMiddleware(): ExpressMiddleware

Get Express middleware handlers.

const middleware = server.expressMiddleware();

// Serve agent card
app.get('/.well-known/agent-card.json', middleware.agentCard);

// Protect a resource
app.get('/api/data', middleware.requirePayment('resource-id'), handler);

// Handle settlement
app.post('/api/pay', middleware.handleSettlement);

handlers(): Handlers

Get generic handlers for framework-agnostic usage.

const handlers = server.handlers();

// Get agent card
const card = handlers.getAgentCard();

// Check access (returns { allowed: boolean, challenge?: X402Challenge })
const access = await handlers.checkAccess('resource-id', paymentId);

// Generate challenge manually
const challenge = handlers.generateChallenge('resource-id');

// Settle payment
const result = await handlers.settlePayment({
  paymentId,
  paymentHeader,
  paymentRequirements,
});

Entitlement

Passed to onEntitlementCreated callback after successful payment:

interface Entitlement {
  paymentId: string;     // Unique payment ID
  resourceId: string;    // Resource that was paid for
  txHash: string;        // Settlement transaction hash
  amount: string;        // Amount paid
  payer?: string;        // Payer address (if available)
  settledAt: Date;       // Settlement timestamp
}

Broker API Reference (DeFi Swaps)

The broker module enables DeFi token swaps with x402 payment. Currently supports VVS Finance on Cronos.

Installation

# VVS Finance SDK is an optional peer dependency
pnpm add @vvs-finance/swap-sdk

A2ABrokerConfig

interface A2ABrokerConfig {
  /** Broker name for AgentCard (REQUIRED) */
  name: string;
  
  /** Broker description */
  description?: string;
  
  /** Public URL of the broker (REQUIRED) */
  url: string;
  
  /** Target network (REQUIRED) */
  network: 'cronos' | 'cronos-testnet';
  
  /** Broker wallet private key for executing swaps (REQUIRED) */
  brokerPrivateKey: string;
  
  /** Broker wallet address to receive x402 payments (REQUIRED) */
  brokerAddress: string;
  
  /** DeFi providers to use (REQUIRED) */
  providers: DeFiProvider[];
  
  /** Broker fee configuration (default: no fee) */
  fee?: BrokerFeeConfig;
  
  /** Custom RPC URL */
  rpcUrl?: string;
  
  /** Callback when swap is completed (REQUIRED) */
  onSwapCompleted: (swap: SwapRecord) => Promise<void>;
  
  /** Callback to check swap status (REQUIRED) */
  checkSwapStatus: (swapId: string) => Promise<SwapStatus | null>;
}

interface BrokerFeeConfig {
  /** Fee type: 'fixed' for USDC, 'percentage' for output tokens */
  type: 'fixed' | 'percentage';
  
  /** Amount: USDC for fixed (e.g., "0.01"), or % for percentage (e.g., "1.5") */
  amount: string;
}

Broker Usage Example

import express from 'express';
import { A2ABroker, VVSFinanceProvider, type SwapRecord } from 'a2a-cronos';

const swaps = new Map<string, SwapRecord>();

const broker = new A2ABroker({
  name: 'vvs-swap-broker',
  description: 'Token swap broker via VVS Finance',
  url: 'http://localhost:8787',
  network: 'cronos-testnet',
  brokerPrivateKey: process.env.BROKER_PRIVATE_KEY!,
  brokerAddress: process.env.BROKER_ADDRESS!,
  providers: [
    new VVSFinanceProvider({
      quoteApiClientId: process.env.VVS_QUOTE_API_CLIENT_ID!,
    }),
  ],
  // Optional: 1% fee on output tokens
  fee: { type: 'percentage', amount: '1.0' },
  onSwapCompleted: async (swap) => {
    swaps.set(swap.swapId, swap);
    console.log('Swap completed:', swap.swapTxHash);
  },
  checkSwapStatus: async (swapId) => {
    return swaps.get(swapId)?.status || null;
  },
});

const app = express();
app.use(express.json());

// Get swap quote
app.get('/api/broker/quote', async (req, res) => {
  const { input, output, amount } = req.query;
  const quote = await broker.getQuote(
    input as string,
    output as string,
    amount as string
  );
  const { trade, ...publicQuote } = quote;
  res.json(publicQuote);
});

// Execute swap (paywalled)
app.post('/api/broker/swap', async (req, res) => {
  const { quoteId } = req.body;
  const paymentHeader = req.headers['x-payment'];
  
  if (!paymentHeader) {
    const challenge = broker.generateChallenge(quoteId);
    return res.status(402).json(challenge);
  }
  
  // Verify payment and execute swap...
});

app.listen(8787);

SwapQuote Response

interface SwapQuote {
  quoteId: string;           // Quote ID for reference
  provider: string;          // "VVS Finance"
  inputToken: string;        // Input token address
  inputTokenSymbol: string;  // "USDC"
  outputToken: string;       // Output token address
  outputTokenSymbol: string; // "VVS"
  inputAmount: string;       // "0.1"
  outputAmount: string;      // "125.5"
  minimumOutput: string;     // "124.25" (after slippage)
  priceImpact?: string;      // "0.05"
  brokerFee?: BrokerFeeInfo; // Fee details if configured
  routes: SwapRoute[];       // Routing/pool details
  validUntil: number;        // Quote expiry timestamp
}

interface SwapRoute {
  path: string[];            // Token addresses in route
  pools: SwapPoolInfo[];     // Pool details
  portion?: string;          // "100%" or split percentage
}

interface SwapPoolInfo {
  poolType: string;          // "V2", "V3_3000", etc.
  poolAddress?: string;      // Pool contract address
  fee?: string;              // "0.30%"
  liquidity?: string;        // Available liquidity
}

Supported Tokens

| Token | Mainnet | Testnet | |-------|---------|---------| | USDC | 0xc01efAaF7C5C61bEbFAeb358E1161b537b8bC0e0 | 0xf951eC28187D9E5Ca673Da8FE6757E6f0Be5F77C | | VVS | 0x2D03bECE6747ADC00E1a131BBA1469C15fD11e03 | 0x2D03bECE6747ADC00E1a131BBA1469C15fD11e03 | | CRO | NATIVE | NATIVE | | WCRO | 0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23 | 0x6a3173618859C7cd40fAF6921b5E9eB6A76f1fD4 |

You can use either token symbols or contract addresses:

// Using symbols
const quote = await broker.getQuote('USDC', 'VVS', '0.1');

// Using addresses
const quote = await broker.getQuote(
  '0xf951eC28187D9E5Ca673Da8FE6757E6f0Be5F77C',
  '0x2D03bECE6747ADC00E1a131BBA1469C15fD11e03',
  '0.1'
);

Networks & Assets

Default RPC URLs

| Network | RPC URL | |---------|---------| | cronos | https://evm.cronos.org | | cronos-testnet | https://evm-t3.cronos.org |

Supported Assets

Currently only USDC supports EIP-3009 and x402 protocol:

| Asset | Mainnet Address | Testnet Address | |-------|-----------------|-----------------| | USDC | 0xc01efAaF7C5C61bEbFAeb358E1161b537b8bC0e0 | 0xf951eC28187D9E5Ca673Da8FE6757E6f0Be5F77C |

You can pass either the symbol 'USDC' or the contract address directly:

// Using symbol (recommended)
const server = new A2AServer({
  asset: 'USDC', // Resolves to correct address per network
  // ...
});

// Using address directly
const server = new A2AServer({
  asset: '0xf951eC28187D9E5Ca673Da8FE6757E6f0Be5F77C',
  // ...
});

Error Handling

import { 
  A2AError, 
  ConfigurationError, 
  NetworkError, 
  PaymentError, 
  ValidationError 
} from 'a2a-cronos';

try {
  await client.fetchResource(target);
} catch (error) {
  if (error instanceof ConfigurationError) {
    console.log('Config issue:', error.message);
  } else if (error instanceof NetworkError) {
    console.log('Network issue:', error.status, error.message);
  } else if (error instanceof PaymentError) {
    console.log('Payment failed:', error.phase, error.details);
  } else if (error instanceof ValidationError) {
    console.log('Validation failed:', error.field, error.message);
  }
}

Explorer URLs

For displaying transaction links:

| Network | Explorer URL | |---------|--------------| | cronos | https://explorer.cronos.org/tx/{txHash} | | cronos-testnet | https://explorer.cronos.org/testnet/tx/{txHash} |


Complete Examples

Client Example (Next.js API Route)

// app/api/agent/route.ts
import { A2AClient } from 'a2a-cronos';

export async function POST(request: Request) {
  const { query } = await request.json();

  const client = new A2AClient({
    privateKey: process.env.PRIVATE_KEY!,
    network: 'cronos-testnet',
    llm: {
      provider: 'google',
      apiKey: process.env.GOOGLE_API_KEY!,
      model: 'gemini-3-pro-preview',
    },
  });

  const result = await client.fetchWithQuery(query, [
    'http://localhost:8787',
  ]);

  return Response.json(result);
}

Server Example (Express)

// server.ts
import 'dotenv/config';
import express from 'express';
import { A2AServer, type Entitlement } from 'a2a-cronos';

const entitlements = new Map<string, Entitlement>();

const a2aServer = new A2AServer({
  name: 'my-api',
  description: 'Premium API with x402 paywall',
  url: process.env.PUBLIC_URL || 'http://localhost:8787',
  network: 'cronos-testnet',
  merchantAddress: process.env.MERCHANT_ADDRESS!,
  resources: [
    {
      id: 'premium-endpoint',
      title: 'Premium Endpoint',
      description: 'Access to premium data',
      path: '/api/premium',
      price: '1000000', // 1 USDC
    },
    {
      id: 'basic-endpoint',
      title: 'Basic Endpoint',
      path: '/api/basic',
      price: '100000', // 0.1 USDC
    },
  ],
  onEntitlementCreated: async (entitlement) => {
    entitlements.set(entitlement.paymentId, entitlement);
    console.log('Payment received:', entitlement.txHash);
  },
  checkEntitlement: async (paymentId) => {
    return entitlements.has(paymentId);
  },
});

const app = express();
app.use(express.json());

const middleware = a2aServer.expressMiddleware();

// Discovery endpoint
app.get('/.well-known/agent-card.json', middleware.agentCard);

// Protected endpoints
app.get('/api/premium', middleware.requirePayment('premium-endpoint'), (req, res) => {
  res.json({ data: 'premium content' });
});

app.get('/api/basic', middleware.requirePayment('basic-endpoint'), (req, res) => {
  res.json({ data: 'basic content' });
});

// Settlement endpoint
app.post('/api/pay', middleware.handleSettlement);

app.listen(8787, () => {
  console.log('Server running on http://localhost:8787');
});

License

MIT