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

@agirails/sdk

v2.7.0

Published

AGIRAILS SDK for the ACTP (Agent Commerce Transaction Protocol) - Unified mock + blockchain support

Readme

AGIRAILS TypeScript SDK

TypeScript Node.js License: Apache 2.0 Tests

The official TypeScript SDK for the Agent Commerce Transaction Protocol (ACTP) - enabling AI agents to transact with each other through blockchain-based escrow.

Features

  • Three-tier API: Basic, Standard, and Advanced levels for different use cases
  • Adapter Routing: 0x... addresses route to ACTP, https:// to x402, agent IDs to ERC-8004
  • x402 Payments: HTTP-native micropayments via x402 protocol with optional relay fee splitting
  • ERC-8004 Bridge: Read-only resolution of agent IDs to wallet addresses for payments
  • ERC-8004 Reputation: Post-settlement feedback reporting to on-chain reputation registry
  • AGIRAILS.md: Agent config as source of truth with publish/pull/diff CLI and drift detection
  • Mock Runtime: Full local testing without blockchain connection
  • Type-safe: Complete TypeScript types with strict mode support
  • Async/Await: Promise-based API for modern async workflows
  • Comprehensive Errors: Structured exception types with error codes and recovery guidance
  • Keystore Security (AIP-13): Fail-closed ACTP_PRIVATE_KEY policy, ACTP_KEYSTORE_BASE64 for CI/CD, 30-min TTL cache
  • Lazy Publish: Mainnet activation deferred to first real transaction via pending-publish.json
  • Deployment CLI: actp deploy:env (generate base64 keystore) + actp deploy:check (scan for exposed secrets)
  • Security Built-in: EIP-712 signing, replay protection, safe nonce management
  • Configurable Confirmations: Block confirmation depth configurable per-network (default: 2)

Installation

npm install @agirails/sdk

Or with yarn:

yarn add @agirails/sdk

Quick Start

Testnet Quickstart (Base Sepolia)

Get started with real transactions on Base Sepolia testnet:

# Install CLI globally
npm install -g @agirails/sdk

# One-time setup: generates encrypted keystore at .actp/keystore.json
ACTP_KEY_PASSWORD=your-password actp init -m testnet

# Check your balance
ACTP_KEY_PASSWORD=your-password actp balance

# Make a payment
ACTP_KEY_PASSWORD=your-password actp pay 0xProviderAddress 100 --deadline 24h

# Watch transaction status
actp watch TX_ID

Alternative: Set ACTP_PRIVATE_KEY env var to use a raw private key instead of the keystore.

Basic API - Simple Payments

The simplest way to make a payment - just specify who, how much, and go:

import { ACTPClient } from '@agirails/sdk';

async function main() {
  // Create client in mock mode (no blockchain needed)
  const client = await ACTPClient.create({
    mode: 'mock',
    requesterAddress: '0x1111111111111111111111111111111111111111',
  });

  // Pay a provider
  const result = await client.basic.pay({
    to: '0xabcdefABCDEFabcdefABCDEFabcdefABCDEFabcd',
    amount: '100.00',  // $100 USDC
    deadline: '24h',   // Optional: expires in 24 hours
  });

  console.log('Transaction ID:', result.txId);
  console.log('State:', result.state);
}

main();

Standard API - Full Lifecycle Control

For applications that need explicit control over each transaction step:

import { ACTPClient } from '@agirails/sdk';
import { ethers } from 'ethers';

async function main() {
  // No wallet param needed — auto-detects .actp/keystore.json
  const client = await ACTPClient.create({
    mode: 'testnet',  // or 'mainnet' for production
    requesterAddress: '0x1111111111111111111111111111111111111111',
  });

  // Step 1: Create transaction (no funds locked yet)
  const txId = await client.standard.createTransaction({
    provider: '0xabcdefABCDEFabcdefABCDEFabcdefABCDEFabcd',
    amount: '100.50',
    deadline: '7d',
    disputeWindow: 172800,  // 2 days in seconds
  });
  console.log('Created transaction:', txId);

  // Step 2: Link escrow (locks funds, moves to COMMITTED)
  const escrowId = await client.standard.linkEscrow(txId);
  console.log('Escrow linked:', escrowId);

  // Step 3: Provider starts work (REQUIRED before DELIVERED!)
  await client.standard.transitionState(txId, 'IN_PROGRESS');

  // Step 4: Provider delivers with dispute window proof
  const abiCoder = ethers.AbiCoder.defaultAbiCoder();
  const disputeWindowProof = abiCoder.encode(['uint256'], [172800]); // 2 days
  await client.standard.transitionState(txId, 'DELIVERED', disputeWindowProof);

  // Step 5: Release funds to provider (after dispute window)
  await client.standard.releaseEscrow(txId);
  console.log('Payment complete!');
}

main();

Advanced API - Direct Runtime Access

For custom workflows and maximum flexibility:

import { ACTPClient } from '@agirails/sdk';

async function main() {
  const client = await ACTPClient.create({
    mode: 'mock',
    requesterAddress: '0x1111111111111111111111111111111111111111',
  });

  // Direct runtime access
  const runtime = client.advanced;

  // Create transaction with full control
  const txId = await runtime.createTransaction({
    requester: '0x...',
    provider: '0x...',
    amount: '1000000',  // Raw wei
    deadline: 1735689600,
    disputeWindow: 86400,
    serviceDescription: '0x...'
  });

  // Get transaction details
  const tx = await runtime.getTransaction(txId);
  console.log('State:', tx.state, 'Amount:', tx.amount);
}

main();

Transaction Lifecycle

ACTP transactions follow an 8-state lifecycle:

INITIATED → QUOTED → COMMITTED → IN_PROGRESS → DELIVERED → SETTLED
                ↘                      ↘              ↘
              CANCELLED              CANCELLED      DISPUTED → SETTLED

| State | Description | |-------|-------------| | INITIATED | Transaction created, no escrow linked | | QUOTED | Provider submitted price quote (optional) | | COMMITTED | Escrow linked, funds locked | | IN_PROGRESS | Provider actively working (optional) | | DELIVERED | Work delivered with proof | | SETTLED | Payment released (terminal) | | DISPUTED | Under dispute resolution | | CANCELLED | Cancelled before completion (terminal) |

Configuration

Client Modes

// Mock mode - local testing, no blockchain
const client = await ACTPClient.create({
  mode: 'mock',
  requesterAddress: '0x1111111111111111111111111111111111111111',
  stateDirectory: '.actp'  // Optional: persist state to disk
});

// Testnet mode - Base Sepolia (auto-detects keystore or ACTP_PRIVATE_KEY)
const client = await ACTPClient.create({
  mode: 'testnet',
  requesterAddress: '0x1111111111111111111111111111111111111111',
  rpcUrl: 'https://sepolia.base.org'  // Optional: custom RPC
});

// Mainnet mode - Base (auto-detects keystore or ACTP_PRIVATE_KEY)
const client = await ACTPClient.create({
  mode: 'mainnet',
  requesterAddress: '0x1111111111111111111111111111111111111111',
});

Amount Formats

The SDK accepts amounts in multiple formats:

// All equivalent to $100.50 USDC
await client.basic.pay({ to: '0x...', amount: 100.50 });
await client.basic.pay({ to: '0x...', amount: '100.50' });
await client.basic.pay({ to: '0x...', amount: '$100.50' });
await client.basic.pay({ to: '0x...', amount: '100500000' });  // Wei

Deadline Formats

// Relative formats
deadline: '1h'   // 1 hour from now
deadline: '24h'  // 24 hours from now
deadline: '7d'   // 7 days from now

// Absolute timestamp
deadline: 1735689600  // Unix timestamp

// ISO date string
deadline: '2025-01-01T00:00:00Z'

Error Handling

The SDK provides structured exceptions with error codes:

import {
  ACTPError,
  TransactionNotFoundError,
  InvalidStateTransitionError,
  InsufficientBalanceError,
  ValidationError
} from '@agirails/sdk';

try {
  await client.basic.pay({ to: 'invalid', amount: 100 });
} catch (error) {
  if (error instanceof ValidationError) {
    console.log('Validation failed:', error.message);
    console.log('Error code:', error.code);
    console.log('Details:', error.details);
  } else if (error instanceof InsufficientBalanceError) {
    console.log(`Need ${error.required}, have ${error.available}`);
  } else if (error instanceof ACTPError) {
    console.log(`ACTP error [${error.code}]: ${error.message}`);
  }
}

Exception Hierarchy

ACTPError (base)
├── TransactionNotFoundError
├── InvalidStateTransitionError
├── EscrowNotFoundError
├── InsufficientBalanceError
├── DeadlinePassedError
├── DisputeWindowActiveError
├── ContractPausedError
├── ValidationError
│   ├── InvalidAddressError
│   └── InvalidAmountError
├── NetworkError
│   ├── TransactionRevertedError
│   └── SignatureVerificationError
├── StorageError
│   ├── InvalidCIDError
│   ├── UploadTimeoutError
│   └── ContentNotFoundError
└── AgentLifecycleError

CLI Reference

The SDK includes a full-featured CLI for interacting with ACTP:

Core Commands

# Payment operations
actp pay <provider> <amount> [--deadline TIME] [--service TEXT]
actp balance [ADDRESS]
actp mint --amount AMOUNT  # Mock mode only

# Transaction management
actp list [--state STATE] [--limit N]
actp status <tx_id>
actp cancel <tx_id>

# Time manipulation (mock mode only)
actp time advance <seconds>
actp time set <timestamp>
actp time now

Agent-First Features

# Watch transaction state changes (streams updates)
actp watch <tx_id> [--interval SECONDS] [--format json|text]

# Batch operations from file
actp batch <command_file> [--parallel N] [--continue-on-error]

# Dry-run simulation
actp simulate pay <provider> <amount>
actp simulate fee <amount>

AGIRAILS.md Config Management

# Publish agent config to on-chain registry
actp publish [--dry-run]

# Pull config from on-chain registry
actp pull [--network base-sepolia]

# Compare local config vs on-chain
actp diff [--network base-sepolia]

Deployment Security (AIP-13)

# Generate ACTP_KEYSTORE_BASE64 for CI/CD
actp deploy:env

# Scan repo for exposed secrets
actp deploy:check [--fix] [--quiet]

Configuration

# Initialize keystore (one-time setup)
ACTP_KEY_PASSWORD=your-password actp init -m testnet   # or mainnet
ACTP_KEY_PASSWORD=your-password actp init -m mainnet

# General config
actp config set <key> <value>
actp config get <key>
actp config list
actp config reset

# Available config keys:
#   network: base-sepolia | base-mainnet | mock
#   rpc-url: RPC endpoint URL
#   state-directory: Directory for mock state persistence

Output Formats

# Human-readable (default)
actp list

# JSON output for scripting
actp list --format json

# NDJSON streaming for watch
actp watch TX_ID --format ndjson

Testing

Run the test suite:

# Run all tests
npm test

# Run with verbose output
npm test -- --verbose

# Run specific test file
npm test -- src/__tests__/client.test.ts

# Run tests matching pattern
npm test -- --testNamePattern="pay"

# Run with coverage
npm run test:coverage

API Reference

ACTPClient

| Method | Description | |--------|-------------| | ACTPClient.create(config) | Factory method to create client | | client.basic | Access basic adapter | | client.standard | Access standard adapter | | client.advanced | Access runtime directly | | client.getBalance() | Get USDC balance | | client.reset() | Reset mock state |

BasicAdapter

| Method | Description | |--------|-------------| | pay(params) | Create and fund transaction | | checkStatus(txId) | Get transaction status | | getBalance() | Get formatted balance |

StandardAdapter

| Method | Description | |--------|-------------| | createTransaction(params) | Create transaction | | linkEscrow(txId) | Link escrow and lock funds | | transitionState(txId, state, proof?) | Transition to new state | | releaseEscrow(txId) | Release funds | | getTransaction(txId) | Get transaction details | | getAllTransactions() | List all transactions |

Level 0 & Level 1 APIs

Level 0 - Low-level Primitives

import { ServiceDirectory, request, provide } from '@agirails/sdk';

// Register a provider for a service
const { serviceDirectory } = require('@agirails/sdk');
// serviceDirectory is an in-memory, per-process singleton
// Provider registers automatically when calling provide()

// Find providers for a service
const providers = serviceDirectory.findProviders('text-gen');
// Returns string[] of provider addresses

Level 1 - Agent Framework

import { Agent, AgentConfig } from '@agirails/sdk';

// Create an agent (auto-detects keystore, no wallet param needed)
const agent = new Agent({
  name: 'my-agent',
  network: 'testnet',
});

// Register services via agent.provide()
agent.provide('text-generation', async (job) => {
  return { result: `Processed: ${job.input}` };
});

await agent.start();

SDK Parity

This TypeScript SDK maintains full parity with the Python SDK:

| Feature | TypeScript SDK | Python SDK | |---------|----------------|------------| | DeliveryProof Schema | AIP-4 v1.1 (12 fields) | AIP-4 v1.1 (12 fields) | | Result Hashing | keccak256 | keccak256 | | JSON Canonicalization | Insertion order | Insertion order | | EIP-712 Signing | Full support | Full support | | Level0 API | Full ACTP flow | Full ACTP flow | | Level1 Agent API | Complete | Complete | | CLI Commands | watch, batch, simulate, publish, pull, diff, deploy:* | watch, batch, simulate, publish, pull, diff, deploy:* | | Adapter Routing | ACTP + x402 + ERC-8004 | ACTP + x402 + ERC-8004 | | ERC-8004 Bridge | Identity + Reputation | Identity + Reputation | | AGIRAILS.md Config | publish/pull/diff/drift detection | publish/pull/diff | | Keystore AIP-13 | Full (30-min TTL cache) | Full (30-min TTL cache) | | Lazy Publish | pending-publish lifecycle | pending-publish lifecycle | | Nonce Tracking | SecureNonce, ReceivedNonceTracker | SecureNonce, ReceivedNonceTracker | | Attestation Tracking | UsedAttestationTracker | UsedAttestationTracker |

Shared Test Vectors: Both SDKs use the same JSON test fixtures to ensure identical behavior.

Networks

| Network | Chain ID | Status | |---------|----------|--------| | Base Sepolia | 84532 | ✅ Active (Testnet) | | Base Mainnet | 8453 | ✅ Active |

Fee Structure

  • Platform Fee: 1% of transaction amount
  • Minimum Fee: $0.05 USDC

Security

  • EIP-712 Signing: Typed structured data for secure message signing
  • Replay Protection: Nonce management prevents transaction replay
  • Non-custodial Escrow: 2-of-2 release pattern
  • EAS Integration: Ethereum Attestation Service for delivery proofs
  • ERC-8004 Reputation: On-chain settlement/dispute feedback after ACTP transactions
  • Input Validation: All user inputs validated before processing

Transaction Confirmations

All state-changing operations in ACTPKernel wait for block confirmations before events are emitted. The default is 2 confirmations (~4-6s on Base L2's ~2s blocks), configurable via BlockchainRuntimeConfig.confirmations. The SDK's EventMonitor receives already-confirmed events; no additional confirmation handling is needed at the application layer.

Decentralized Identifiers (DIDs)

AGIRAILS uses did:ethr DIDs based on the ERC-1056 standard for identity management.

DID Format

Every Ethereum address automatically IS a DID - no registration required:

did:ethr:84532:0x742d35cc6634c0532925a3b844bc9e7595f0beb
       ↑      ↑
   chainId  address

Basic Usage

import { DIDResolver } from '@agirails/sdk';

// Build DID from address (no registration needed!)
const did = DIDResolver.buildDID('0x742d35cc6634c0532925a3b844bc9e7595f0beb', 84532);
// → 'did:ethr:84532:0x742d35cc6634c0532925a3b844bc9e7595f0beb'

// Parse DID components
const parsed = DIDResolver.parseDID(did);
console.log(parsed.method);   // 'ethr'
console.log(parsed.chainId);  // 84532
console.log(parsed.address);  // '0x742d35cc6634c0532925a3b844bc9e7595f0beb'

// Validate DID format
const isValid = DIDResolver.isValidDID(did);  // true

Resolve DID to DID Document

import { DIDResolver } from '@agirails/sdk';

// Create resolver for Base Sepolia
const resolver = await DIDResolver.create({ network: 'base-sepolia' });

// Resolve DID to W3C DID Document
const result = await resolver.resolve('did:ethr:84532:0x742d35cc...');

if (result.didDocument) {
  console.log('Controller:', result.didDocument.controller);
  console.log('Verification Methods:', result.didDocument.verificationMethod);
  console.log('Service Endpoints:', result.didDocument.service);
}

Verify Signatures

import { DIDResolver } from '@agirails/sdk';

const resolver = await DIDResolver.create({ network: 'base-sepolia' });

// Verify a signature was made by a DID's controller (or authorized delegate)
const result = await resolver.verifySignature(
  'did:ethr:84532:0x742d35cc...',  // DID
  'Hello AGIRAILS',                 // Original message
  '0x1234...',                      // Signature
  { chainId: 84532 }                // Verification options
);

if (result.valid) {
  console.log('Signature valid!');
  console.log('Signer:', result.signer);
  console.log('Is delegate:', result.isDelegate);
}

Advanced: Manage Identity (Optional)

For advanced use cases, use DIDManager to manage delegates and attributes:

import { DIDManager } from '@agirails/sdk';

// Create manager with signer
const manager = new DIDManager(signer, { network: 'base-sepolia' });

// Add a signing delegate (valid for 24 hours)
await manager.addDelegate(
  'did:ethr:84532:0x742d35cc...',  // Your DID
  '0xDelegateAddress...',          // Delegate address
  'sigAuth',                        // Delegate type
  86400                             // Validity in seconds
);

// Rotate key ownership
await manager.changeOwner(
  'did:ethr:84532:0x742d35cc...',
  '0xNewOwnerAddress...'
);

// Add service endpoint attribute
await manager.setAttribute(
  'did:ethr:84532:0x742d35cc...',
  'did/svc/AgentService',
  'https://my-agent.example.com/api',
  86400
);

DID in ACTP Transactions

DIDs are used internally for:

  • Provider/Consumer Identity: Transaction parties identified by DIDs
  • Message Signing: EIP-712 messages reference DIDs
  • Delivery Proofs: Attestations link to provider DIDs
  • Reputation: Future reputation system will be DID-based

Environment Variables

# Wallet resolution (checked in order):
ACTP_PRIVATE_KEY=0x...       # Raw private key (fail-closed on mainnet — see AIP-13)
ACTP_KEYSTORE_BASE64=...     # Base64 keystore for CI/CD (use actp deploy:env to generate)
ACTP_KEY_PASSWORD=...        # Decrypts keystore (ACTP_KEYSTORE_BASE64 or .actp/keystore.json)

# Optional
BASE_SEPOLIA_RPC=...         # Custom RPC for Base Sepolia
BASE_MAINNET_RPC=...         # Custom RPC for Base Mainnet
CDP_API_KEY=...              # Coinbase Developer Platform API key
PIMLICO_API_KEY=...          # Pimlico bundler/paymaster API key
IPFS_GATEWAY=...             # Custom IPFS gateway URL

Requirements

  • Node.js 18+ (required for global fetch and AbortController)
  • TypeScript 5.0+ (for development)
  • Dependencies: ethers, viem, permissionless

Module Format

The SDK ships as CommonJS only. It works with require() and with bundlers (webpack, esbuild, Rollup) that support CJS. If you are using ESM (import syntax), Node.js will auto-interop with CJS modules — no additional configuration is needed.

License

Apache 2.0 License - see LICENSE for details.

Links