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

@chainguarsdk/sdk

v0.1.1

Published

TypeScript SDK for ChainGuard - Security middleware for AI agents on Internet Computer Protocol

Downloads

112

Readme

@chainguarsdk/sdk

TypeScript SDK for ChainGuard - Security middleware for AI agents on Internet Computer Protocol

npm version License: MIT

Installation

npm install @chainguarsdk/sdk

Quick Start

import { ChainGuardClient } from '@chainguarsdk/sdk';

// Initialize client
const client = new ChainGuardClient({
  canisterId: 'foxtk-ziaaa-aaaai-atthq-cai',
  host: 'https://icp-api.io', // Optional, defaults to IC mainnet
});

// Execute a transfer
const result = await client.transfer(
  'Sepolia',           // chain
  'ETH',               // token
  '0x742d35Cc...',     // recipient address
  BigInt(1000000)      // amount in wei
);

console.log(result); // ActionResult (Executed | PendingSignatures | Denied)

Features

  • Simple API - Clean, intuitive methods for all ChainGuard operations
  • Type Safety - Full TypeScript support with complete type definitions
  • Flexible Authentication - Bring your own identity or use auto-generated ones
  • Helper Methods - Convenient wrappers for common actions (transfer, swap, approve)
  • Complete Coverage - Access to all canister functionality

API Reference

Initialization

import { ChainGuardClient } from '@chainguarsdk/sdk';
import { Ed25519KeyIdentity } from '@dfinity/identity';

// Option 1: Auto-generated identity (for testing)
const client = new ChainGuardClient({
  canisterId: 'your-canister-id',
});

// Option 2: Provide your own identity
const identity = Ed25519KeyIdentity.fromSecretKey(yourSecretKey);
const client = new ChainGuardClient({
  canisterId: 'your-canister-id',
  identity,
});

// Option 3: Custom host (for local development)
const client = new ChainGuardClient({
  canisterId: 'your-canister-id',
  host: 'http://localhost:4943',
});

Actions

Transfer Tokens

const result = await client.transfer(
  'Sepolia',              // chain
  'ETH',                  // token
  '0x742d35Cc6634C0...',  // to address
  BigInt(1000000000000000)  // 0.001 ETH in wei
);

// Check result
if ('Executed' in result) {
  console.log('Transaction hash:', result.Executed.tx_hash[0]);
} else if ('PendingSignatures' in result) {
  console.log('Awaiting signatures:', result.PendingSignatures.id);
} else if ('Denied' in result) {
  console.log('Denied:', result.Denied.reason);
}

Swap Tokens

const result = await client.swap(
  'Sepolia',                      // chain
  '0x1c7D4B196Cb0C7B01d743...',  // token in (USDC)
  'ETH',                          // token out
  BigInt(1000000),                // amount in (1 USDC with 6 decimals)
  BigInt(1),                      // min amount out
  3000                            // fee tier (0.3%) - optional
);

Approve Token Spending

const result = await client.approveToken(
  'Sepolia',
  '0x1c7D4B196Cb0C7B01d743...',  // token address
  '0x68b3465833fb72A70...',      // spender (Uniswap router)
  BigInt(1000000)                 // amount to approve
);

Threshold Signatures

Get Pending Requests

const pendingRequests = await client.getPendingRequests();

for (const request of pendingRequests) {
  console.log(`Request ${request.id}:`);
  console.log(`  Required signatures: ${request.required_signatures}`);
  console.log(`  Collected: ${request.collected_signatures.length}`);
  console.log(`  Status:`, request.status);
}

Sign a Request

const result = await client.signRequest(BigInt(1)); // request ID

if ('Ok' in result) {
  console.log('Signature added successfully');
  const updatedRequest = result.Ok;
  console.log(`Signatures: ${updatedRequest.collected_signatures.length}/${updatedRequest.required_signatures}`);
} else {
  console.error('Error:', result.Err);
}

Reject a Request

const result = await client.rejectRequest(
  BigInt(1),                    // request ID
  'Invalid recipient address'  // reason
);

Policies

List Policies

const policies = await client.listPolicies();

for (const policy of policies) {
  console.log(`Policy: ${policy.name}`);
  console.log(`  Priority: ${policy.priority}`);
  console.log(`  Conditions:`, policy.conditions);
  console.log(`  Action:`, policy.action);
}

Add a Policy

const result = await client.addPolicy({
  name: 'Allow Small Swaps',
  conditions: [
    { MaxAmount: BigInt(10000000) },  // Max 10 USDC
    { AllowedChains: ['Sepolia'] },
  ],
  action: { Allow: null },
  priority: 1,
});

if ('Ok' in result) {
  console.log('Policy added with ID:', result.Ok);
}

Audit Logs

Get Audit Logs

// Get all audit logs
const logs = await client.getAuditLogs();

// Get logs in time range (timestamps in nanoseconds)
const start = BigInt(Date.now() * 1000000);
const end = BigInt((Date.now() + 86400000) * 1000000); // +24h
const recentLogs = await client.getAuditLogs(start, end);

for (const log of logs) {
  console.log(`[${new Date(Number(log.timestamp) / 1000000)}]`);
  console.log(`  Action: ${log.action_type}`);
  console.log(`  Requester: ${log.requester.toText()}`);
  console.log(`  Decision:`, log.policy_result.decision);

  if (log.execution_result.length > 0) {
    const exec = log.execution_result[0];
    console.log(`  Success: ${exec.success}`);
    if (exec.tx_hash.length > 0) {
      console.log(`  TX Hash: ${exec.tx_hash[0]}`);
    }
  }
}

Role Management

import { Principal } from '@dfinity/principal';

// Assign a role
const operatorPrincipal = Principal.fromText('xxxxx-xxxxx-xxx...');
await client.assignRole(operatorPrincipal, { Operator: null });

// Get roles for a principal
const roles = await client.getRoles(operatorPrincipal);
console.log('Roles:', roles);

// Revoke a role
await client.revokeRole(operatorPrincipal, { Operator: null });

Emergency Controls

// Pause the system (Owner only)
await client.pause();

// Check if paused
const isPaused = await client.isPaused();
console.log('System paused:', isPaused);

// Resume operations (Owner only)
await client.resume();

Configuration

// Get current configuration
const config = await client.getConfig();

if (config) {
  console.log('Canister name:', config.name);
  console.log('Supported chains:', config.supported_chains);
  console.log('Default threshold:', config.default_threshold);
  console.log('Policies:', config.policies.length);
}

Usage Examples

AI Agent Integration

import { ChainGuardClient } from '@chainguarsdk/sdk';

class TradingBot {
  constructor(private guard: ChainGuardClient) {}

  async executeDCA(tokenIn: string, tokenOut: string, amount: bigint) {
    console.log(`Executing DCA: ${amount} ${tokenIn} → ${tokenOut}`);

    const result = await this.guard.swap(
      'Sepolia',
      tokenIn,
      tokenOut,
      amount,
      BigInt(1),  // Accept any amount (for demo)
      3000        // 0.3% fee tier
    );

    if ('Executed' in result && result.Executed.success) {
      console.log('✓ DCA executed:', result.Executed.tx_hash[0]);
      return true;
    } else if ('PendingSignatures' in result) {
      console.log('⏳ Awaiting threshold signatures');
      return false;
    } else if ('Denied' in result) {
      console.error('✗ Denied:', result.Denied.reason);
      return false;
    }
  }
}

// Usage
const guard = new ChainGuardClient({ canisterId: 'your-id' });
const bot = new TradingBot(guard);

await bot.executeDCA(
  '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',  // USDC
  'ETH',
  BigInt(1000000)  // 1 USDC
);

Multi-Sig Treasury

import { ChainGuardClient } from '@chainguarsdk/sdk';
import { Ed25519KeyIdentity } from '@dfinity/identity';

// Signer 1
const signer1Identity = Ed25519KeyIdentity.generate();
const signer1 = new ChainGuardClient({
  canisterId: 'your-id',
  identity: signer1Identity,
});

// Signer 2
const signer2Identity = Ed25519KeyIdentity.generate();
const signer2 = new ChainGuardClient({
  canisterId: 'your-id',
  identity: signer2Identity,
});

// Request large transfer (will require threshold)
const result = await signer1.transfer(
  'Sepolia',
  'ETH',
  '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
  BigInt(10000000000000000000)  // 10 ETH - requires multi-sig
);

if ('PendingSignatures' in result) {
  const requestId = result.PendingSignatures.id;
  console.log('Request created:', requestId);

  // Signer 2 approves
  await signer2.signRequest(requestId);
  console.log('Request signed - will auto-execute when threshold met');
}

React Hook Example

import { useState, useEffect } from 'react';
import { ChainGuardClient } from '@chainguarsdk/sdk';

export function useChainGuard(canisterId: string) {
  const [client, setClient] = useState<ChainGuardClient | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const guard = new ChainGuardClient({ canisterId });
    setClient(guard);
    setLoading(false);
  }, [canisterId]);

  return { client, loading };
}

// In your component
function MyComponent() {
  const { client, loading } = useChainGuard('foxtk-ziaaa-aaaai-atthq-cai');

  const handleTransfer = async () => {
    if (!client) return;

    const result = await client.transfer(
      'Sepolia',
      'ETH',
      '0x...',
      BigInt(1000000)
    );

    // Handle result...
  };

  if (loading) return <div>Loading...</div>;

  return <button onClick={handleTransfer}>Send</button>;
}

Type Definitions

The SDK exports all ChainGuard types for TypeScript support:

import type {
  Action,
  ActionResult,
  ExecutionResult,
  PendingRequest,
  Policy,
  PolicyAction,
  Condition,
  AuditEntry,
  Role,
  ChainGuardConfig,
} from '@chainguard/sdk';

Error Handling

try {
  const result = await client.transfer('Sepolia', 'ETH', '0x...', BigInt(1000));

  if ('Denied' in result) {
    // Handle policy denial
    console.error('Transaction denied:', result.Denied.reason);
  } else if ('PendingSignatures' in result) {
    // Handle threshold requirement
    console.log('Awaiting signatures:', result.PendingSignatures.id);
  } else if ('Executed' in result) {
    // Handle successful execution
    if (result.Executed.success) {
      console.log('Success!', result.Executed.tx_hash[0]);
    } else {
      console.error('Execution failed:', result.Executed.error[0]);
    }
  }
} catch (error) {
  console.error('Network or canister error:', error);
}

Resources

License

MIT

Support