The Cycles Plugin provides comprehensive cycles management for ICP canisters, including balance monitoring, top-up operations, forecasting, and automated management.

Overview

The Cycles Plugin supports:
  • Balance Management: Check canister cycles balance and status
  • Top-Up Operations: Add cycles to canisters via management canister
  • ICP to Cycles Conversion: Convert ICP tokens to cycles using current XDR rates
  • Monitoring & Analytics: Track usage, forecasting, and automated alerts
  • Batch Operations: Bulk cycles operations for multiple canisters

Core Operations

getBalance(canisterId)

Get cycles balance and status for a canister. Parameters:
  • canisterId: Principal | string - Canister to query
Returns: Promise<ICyclesBalance>
  • canisterId: Principal - Canister ID
  • balance: bigint - Current cycles balance
  • status: string - Canister status
  • freezingThreshold: bigint - Freezing threshold in seconds
  • memorySize: bigint - Memory usage
  • idle_cycles_burned_per_day: bigint - Daily cycles burn rate
Example:
const balance = await agent.cyclesPlugin.getBalance('canister-id');

console.log('Canister:', balance.canisterId.toText());
console.log('Balance:', agent.cyclesPlugin.formatCycles(balance.balance));
console.log('Status:', balance.status);
console.log('Daily burn:', agent.cyclesPlugin.formatCycles(balance.idle_cycles_burned_per_day));

topUp(canisterId, amount?, options?)

Add cycles to a canister. Parameters:
  • canisterId: Principal | string - Canister to top up
  • amount (optional): bigint | string - Cycles amount (default: 2T)
  • options (optional): ICyclesTopUpOptions
    • priority: boolean - Priority transaction
    • memo: Uint8Array - Transaction memo
Returns: Promise<void> Example:
// Top up with default amount (2T cycles)
await agent.cyclesPlugin.topUp('canister-id');

// Top up with specific amount
await agent.cyclesPlugin.topUp('canister-id', '5T');

// Top up with bigint amount
await agent.cyclesPlugin.topUp('canister-id', BigInt('3000000000000'));

// Top up with options
await agent.cyclesPlugin.topUp('canister-id', '2T', {
  priority: true,
  memo: new Uint8Array([1, 2, 3, 4])
});

transfer(options)

Transfer cycles between canisters. Parameters:
  • options: ICyclesTransferOptions
    • from: Principal - Source canister
    • to: Principal - Destination canister
    • amount: bigint - Cycles amount to transfer
Returns: Promise<void> Example:
await agent.cyclesPlugin.transfer({
  from: Principal.fromText('source-canister'),
  to: Principal.fromText('destination-canister'),
  amount: BigInt('1000000000000') // 1T cycles
});

ICP to Cycles Conversion

convertIcpToCycles(icpAmount, options?)

Convert ICP tokens to cycles. Parameters:
  • icpAmount: bigint | string - ICP amount in e8s
  • options (optional): IICPToCyclesOptions
    • targetCanister: Principal - Canister to send cycles to
    • autoTopUp: boolean - Automatically top up target canister
Returns: Promise<ICyclesConversionResult>
  • icpAmount: bigint - ICP amount converted
  • cyclesAmount: bigint - Cycles received
  • xdrRate: bigint - XDR exchange rate used
  • fee: bigint - Conversion fee
Example:
// Convert 1 ICP to cycles
const result = await agent.cyclesPlugin.convertIcpToCycles(
  BigInt('100000000'), // 1 ICP in e8s
  { targetCanister: Principal.fromText('canister-id') }
);

console.log('Converted:', agent.cyclesPlugin.formatCycles(result.cyclesAmount), 'cycles');
console.log('XDR Rate:', result.xdrRate);
console.log('Fee:', result.fee);

getPricing()

Get current cycles pricing information. Returns: Promise<ICyclesPricing>
  • xdrRate: bigint - Current XDR to cycles rate
  • cyclesPerXdr: bigint - Cycles per XDR
  • icpToXdr: number - ICP to XDR exchange rate
  • lastUpdated: number - Last update timestamp
Example:
const pricing = await agent.cyclesPlugin.getPricing();
console.log('XDR Rate:', pricing.xdrRate);
console.log('ICP to XDR:', pricing.icpToXdr);
console.log('Last updated:', new Date(pricing.lastUpdated));

Monitoring & Analytics

getUsageMetrics(canisterId, period?)

Get cycles usage metrics for a canister. Parameters:
  • canisterId: Principal | string - Canister to analyze
  • period (optional): 'hour' | 'day' | 'week' | 'month' - Metrics period (default: ‘day’)
Returns: Promise<ICyclesUsageMetrics[]>
  • canisterId: Principal - Canister ID
  • period: string - Time period
  • totalConsumed: bigint - Total cycles consumed
  • avgConsumptionRate: bigint - Average consumption rate
  • timestamp: number - Metric timestamp
Example:
const metrics = await agent.cyclesPlugin.getUsageMetrics('canister-id', 'day');

for (const metric of metrics) {
  console.log(`${new Date(metric.timestamp).toDateString()}: ${agent.cyclesPlugin.formatCycles(metric.totalConsumed)} consumed`);
}

getForecast(canisterId)

Get cycles depletion forecast for a canister. Parameters:
  • canisterId: Principal | string - Canister to forecast
Returns: Promise<ICyclesForecast>
  • canisterId: Principal - Canister ID
  • currentBalance: bigint - Current balance
  • avgDailyConsumption: bigint - Average daily consumption
  • daysUntilDepletion: number - Estimated days until depletion
  • forecastDate: Date - Estimated depletion date
  • recommendedTopUp: bigint - Recommended top-up amount
  • confidence: number - Forecast confidence (0-100)
Example:
const forecast = await agent.cyclesPlugin.getForecast('canister-id');

console.log('Current balance:', agent.cyclesPlugin.formatCycles(forecast.currentBalance));
console.log('Days until depletion:', forecast.daysUntilDepletion);
console.log('Recommended top-up:', agent.cyclesPlugin.formatCycles(forecast.recommendedTopUp));
console.log('Confidence:', forecast.confidence + '%');

startMonitoring(config)

Start automated cycles monitoring. Parameters:
  • config: ICyclesMonitoringConfig
    • canisterIds: Principal[] - Canisters to monitor
    • lowBalanceThreshold: bigint - Low balance alert threshold
    • checkInterval: number - Check interval in seconds
    • autoTopUp (optional): Auto top-up configuration
      • enabled: boolean - Enable auto top-up
      • topUpAmount: bigint - Amount to top up
Returns: Promise<void> Example:
await agent.cyclesPlugin.startMonitoring({
  canisterIds: [
    Principal.fromText('canister-1'),
    Principal.fromText('canister-2')
  ],
  lowBalanceThreshold: BigInt('1000000000000'), // 1T cycles
  checkInterval: 300, // 5 minutes
  autoTopUp: {
    enabled: true,
    topUpAmount: BigInt('2000000000000') // 2T cycles
  }
});

console.log('Monitoring started');

stopMonitoring()

Stop automated monitoring. Returns: void Example:
agent.cyclesPlugin.stopMonitoring();
console.log('Monitoring stopped');

getAlerts()

Get current cycles alerts. Returns: ICyclesAlert[]
  • id: string - Alert ID
  • type: string - Alert type
  • severity: 'info' | 'warning' | 'critical' - Severity level
  • canisterId: Principal - Related canister
  • message: string - Alert message
  • currentBalance: bigint - Current balance when alert was created
  • threshold: bigint - Threshold that triggered alert
  • timestamp: Date - Alert timestamp
  • acknowledged: boolean - Whether alert was acknowledged
Example:
const alerts = agent.cyclesPlugin.getAlerts();

for (const alert of alerts) {
  console.log(`[${alert.severity.toUpperCase()}] ${alert.message}`);
  console.log(`Canister: ${alert.canisterId.toText()}`);
  console.log(`Balance: ${agent.cyclesPlugin.formatCycles(alert.currentBalance)}`);
}

clearAlerts()

Clear all alerts. Returns: void Example:
agent.cyclesPlugin.clearAlerts();
console.log('All alerts cleared');

Batch Operations

getBatchBalances(canisterIds)

Get balances for multiple canisters. Parameters:
  • canisterIds: (Principal | string)[] - Canisters to query
Returns: Promise<ICyclesBalance[]> - Array of balance information Example:
const balances = await agent.cyclesPlugin.getBatchBalances([
  'canister-1',
  'canister-2',
  'canister-3'
]);

for (const balance of balances) {
  console.log(`${balance.canisterId.toText()}: ${agent.cyclesPlugin.formatCycles(balance.balance)}`);
}

batchTopUp(operations)

Top up multiple canisters. Parameters:
  • operations: Array of top-up operations
    • canisterId: Principal | string - Target canister
    • amount: bigint | string - Cycles amount
    • options: ICyclesTopUpOptions (optional)
Returns: Promise<Array<{ canisterId: string; success: boolean; error?: string }>> Example:
const results = await agent.cyclesPlugin.batchTopUp([
  { canisterId: 'canister-1', amount: '2T' },
  { canisterId: 'canister-2', amount: '3T' },
  { canisterId: 'canister-3', amount: '1T', options: { priority: true } }
]);

for (const result of results) {
  if (result.success) {
    console.log(`✓ ${result.canisterId} topped up successfully`);
  } else {
    console.log(`✗ ${result.canisterId} failed: ${result.error}`);
  }
}

Utility Functions

formatCycles(cycles)

Format cycles amount for display. Parameters:
  • cycles: bigint - Cycles amount
Returns: string - Formatted cycles (e.g., “2.5T”, “1.2B”) Example:
const formatted = agent.cyclesPlugin.formatCycles(BigInt('2500000000000'));
console.log(formatted); // "2.5T"

parseCycles(cycles)

Parse cycles string to bigint. Parameters:
  • cycles: string - Cycles string (e.g., “2.5T”, “1B”)
Returns: bigint - Parsed cycles amount Example:
const amount = agent.cyclesPlugin.parseCycles('2.5T');
console.log(amount); // 2500000000000n

validateAmount(amount)

Validate and convert cycles amount. Parameters:
  • amount: bigint | string - Amount to validate
Returns: bigint - Validated amount Example:
const validated = agent.cyclesPlugin.validateAmount('5T');
console.log(validated); // 5000000000000n

canisterExists(canisterId)

Check if a canister exists. Parameters:
  • canisterId: Principal | string - Canister to check
Returns: Promise<boolean> - Whether canister exists Example:
const exists = await agent.cyclesPlugin.canisterExists('canister-id');
if (exists) {
  console.log('Canister exists');
}

getBalanceSummary(canisterId)

Get formatted balance summary. Parameters:
  • canisterId: Principal | string - Canister to summarize
Returns: Promise<string> - Balance summary Example:
const summary = await agent.cyclesPlugin.getBalanceSummary('canister-id');
console.log(summary); // "Balance: 2.5T cycles (healthy)"

estimateConsumption(canisterId, days?)

Estimate cycles consumption over time. Parameters:
  • canisterId: Principal | string - Canister to analyze
  • days (optional): number - Number of days to estimate (default: 30)
Returns: Promise<bigint> - Estimated consumption Example:
const consumption = await agent.cyclesPlugin.estimateConsumption('canister-id', 7);
console.log('Estimated 7-day consumption:', agent.cyclesPlugin.formatCycles(consumption));

Types

ICyclesBalance

Cycles balance information.
interface ICyclesBalance {
  canisterId: Principal;
  balance: bigint;
  status: string;
  freezingThreshold: bigint;
  memorySize: bigint;
  idle_cycles_burned_per_day: bigint;
}

ICyclesMonitoringConfig

Monitoring configuration.
interface ICyclesMonitoringConfig {
  canisterIds: Principal[];
  lowBalanceThreshold: bigint;
  checkInterval: number;
  autoTopUp?: {
    enabled: boolean;
    topUpAmount: bigint;
  };
}

ICyclesForecast

Cycles depletion forecast.
interface ICyclesForecast {
  canisterId: Principal;
  currentBalance: bigint;
  avgDailyConsumption: bigint;
  daysUntilDepletion: number;
  forecastDate: Date;
  recommendedTopUp: bigint;
  confidence: number;
}

Usage Patterns

Automated Cycles Management

// Set up comprehensive monitoring
await agent.cyclesPlugin.startMonitoring({
  canisterIds: [
    Principal.fromText('app-canister'),
    Principal.fromText('storage-canister'),
    Principal.fromText('api-canister')
  ],
  lowBalanceThreshold: BigInt('500000000000'), // 500B cycles
  checkInterval: 600, // 10 minutes
  autoTopUp: {
    enabled: true,
    topUpAmount: BigInt('2000000000000') // 2T cycles
  }
});

// Check alerts periodically
setInterval(async () => {
  const alerts = agent.cyclesPlugin.getAlerts();
  if (alerts.length > 0) {
    console.log(`${alerts.length} cycles alerts active`);
    for (const alert of alerts) {
      console.log(`- ${alert.message}`);
    }
  }
}, 60000); // Check every minute

Bulk Canister Management

const canisters = [
  'canister-1',
  'canister-2', 
  'canister-3'
];

// Check all balances
const balances = await agent.cyclesPlugin.getBatchBalances(canisters);
const lowBalanceCanisters = balances.filter(b => 
  b.balance < BigInt('1000000000000') // Less than 1T cycles
);

if (lowBalanceCanisters.length > 0) {
  console.log(`${lowBalanceCanisters.length} canisters need top-up`);
  
  // Top up low balance canisters
  const topUpOperations = lowBalanceCanisters.map(canister => ({
    canisterId: canister.canisterId.toText(),
    amount: '3T' as const
  }));
  
  const results = await agent.cyclesPlugin.batchTopUp(topUpOperations);
  console.log('Top-up results:', results);
}

Cost Optimization Analysis

// Analyze cycles usage across multiple canisters
const canisters = ['app', 'storage', 'api', 'cdn'];
const analysis = [];

for (const canisterId of canisters) {
  const balance = await agent.cyclesPlugin.getBalance(canisterId);
  const forecast = await agent.cyclesPlugin.getForecast(canisterId);
  const metrics = await agent.cyclesPlugin.getUsageMetrics(canisterId, 'week');
  
  analysis.push({
    canisterId,
    currentBalance: balance.balance,
    dailyBurn: balance.idle_cycles_burned_per_day,
    daysRemaining: forecast.daysUntilDepletion,
    weeklyUsage: metrics.reduce((sum, m) => sum + m.totalConsumed, 0n)
  });
}

// Sort by efficiency (cycles per day)
analysis.sort((a, b) => Number(b.dailyBurn - a.dailyBurn));

console.log('Cycles Usage Analysis:');
for (const canister of analysis) {
  console.log(`${canister.canisterId}:`);
  console.log(`  Balance: ${agent.cyclesPlugin.formatCycles(canister.currentBalance)}`);
  console.log(`  Daily burn: ${agent.cyclesPlugin.formatCycles(canister.dailyBurn)}`);
  console.log(`  Days remaining: ${canister.daysRemaining}`);
}

Error Handling

import { ICPAgentError } from 'icp-agent-kit';

try {
  await agent.cyclesPlugin.topUp('invalid-canister', '1T');
} catch (error) {
  if (error instanceof ICPAgentError) {
    if (error.code === 'CANISTER_NOT_FOUND') {
      console.log('Canister does not exist');
    } else if (error.code === 'INSUFFICIENT_CYCLES') {
      console.log('Not enough cycles for operation');
    }
  }
}