Agent skill
midnight-tooling:lifecycle-management
Use when managing deployed contract lifecycles, inspecting contract state, backing up state before upgrades, planning contract migrations, implementing versioning strategies, or deprecating contracts gracefully.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/lifecycle-management
SKILL.md
Contract Lifecycle Management
Manage deployed Midnight contracts throughout their lifecycle, including state inspection, backups, versioning, migrations, and graceful deprecation.
When to Use
- Inspecting current contract state for debugging or monitoring
- Backing up contract state before upgrades
- Planning and executing contract migrations
- Implementing versioning strategies
- Deprecating old contract versions gracefully
- Managing multi-version contract deployments
Key Concepts
Contract Lifecycle Phases
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐
│ Deploy │───▶│ Active │───▶│ Migrate │───▶│ Sunset │───▶│ Archived │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘
│ │
│ ▼
│ ┌─────────┐
└────────▶│ Monitor │
└─────────┘
Immutability Consideration
Midnight contracts are immutable once deployed. "Upgrades" require:
- Deploying a new contract version
- Migrating state from old to new contract
- Updating references (e.g., in frontend, other contracts)
- Deprecating the old version
State Migration Patterns
| Pattern | Description | Use Case |
|---|---|---|
| Snapshot & Deploy | Export state, deploy new with state | Simple migrations |
| Proxy Pattern | Use proxy contract pointing to impl | Frequent upgrades |
| Dual-Write | Write to both old and new | Zero-downtime migrations |
| Lazy Migration | Migrate state on-demand | Large state migrations |
References
| Document | Description |
|---|---|
| state-inspection.md | Querying and analyzing contract state |
| migration-patterns.md | Strategies for contract upgrades |
Examples
| Example | Description |
|---|---|
| state-backup/ | Export and backup contract state |
| contract-upgrade/ | Migrate to new contract version |
Quick Start
1. Inspect Current State
import { connectContract } from '@midnight-ntwrk/midnight-js-contracts';
import { createIndexerClient } from '@midnight-ntwrk/midnight-js-indexer';
// Connect to contract
const contract = await connectContract({
address: CONTRACT_ADDRESS,
artifact: Contract,
wallet,
config,
});
// Query state via circuit
const state = await contract.query.get_state();
console.log('Current state:', state);
// Or query via indexer for raw state
const indexer = createIndexerClient({ url: config.indexer });
const rawState = await indexer.getContractState(CONTRACT_ADDRESS);
2. Backup State
interface StateBackup {
contractAddress: string;
blockHeight: number;
timestamp: string;
state: Record<string, unknown>;
}
async function backupState(
contract: ConnectedContract,
indexer: IndexerClient
): Promise<StateBackup> {
const state = await contract.query.get_full_state();
const info = await indexer.getContractInfo(contract.address);
return {
contractAddress: contract.address,
blockHeight: info.lastUpdateBlock,
timestamp: new Date().toISOString(),
state,
};
}
3. Deploy New Version
import { NewContract } from './build-v2/contract.cjs';
const newContract = await deployContract({
wallet,
artifact: NewContract,
initialState: {
...backupData.state,
version: 2,
},
config,
});
console.log('New version deployed at:', newContract.address);
Common Patterns
Version Registry
Track multiple contract versions:
interface ContractVersion {
version: number;
address: string;
deployedAt: string;
status: 'active' | 'deprecated' | 'archived';
}
class VersionRegistry {
private versions: ContractVersion[] = [];
addVersion(version: ContractVersion): void {
this.versions.push(version);
}
getActiveVersion(): ContractVersion | undefined {
return this.versions.find((v) => v.status === 'active');
}
deprecateVersion(version: number): void {
const v = this.versions.find((v) => v.version === version);
if (v) {
v.status = 'deprecated';
}
}
getAllVersions(): ContractVersion[] {
return [...this.versions].sort((a, b) => b.version - a.version);
}
}
Health Monitoring
interface ContractHealth {
address: string;
isResponding: boolean;
lastActivity: Date | null;
stateConsistent: boolean;
warnings: string[];
}
async function checkContractHealth(
contract: ConnectedContract,
indexer: IndexerClient
): Promise<ContractHealth> {
const warnings: string[] = [];
let isResponding = false;
let lastActivity: Date | null = null;
let stateConsistent = true;
try {
// Test responsiveness
await contract.query.get_version();
isResponding = true;
} catch {
warnings.push('Contract not responding to queries');
}
try {
// Check last activity
const info = await indexer.getContractInfo(contract.address);
lastActivity = new Date(info.lastUpdateTimestamp);
// Warn if inactive for long time
const daysSinceActivity = (Date.now() - lastActivity.getTime()) / (1000 * 60 * 60 * 24);
if (daysSinceActivity > 30) {
warnings.push(`No activity for ${daysSinceActivity.toFixed(0)} days`);
}
} catch {
warnings.push('Could not fetch contract info');
}
return {
address: contract.address,
isResponding,
lastActivity,
stateConsistent,
warnings,
};
}
Migration Script Template
interface MigrationPlan {
sourceVersion: number;
targetVersion: number;
sourceAddress: string;
steps: MigrationStep[];
}
interface MigrationStep {
name: string;
execute: () => Promise<void>;
rollback?: () => Promise<void>;
}
async function executeMigration(plan: MigrationPlan): Promise<string> {
console.log(`Migrating from v${plan.sourceVersion} to v${plan.targetVersion}`);
const completedSteps: MigrationStep[] = [];
try {
for (const step of plan.steps) {
console.log(`Executing: ${step.name}`);
await step.execute();
completedSteps.push(step);
}
console.log('Migration completed successfully');
return 'success';
} catch (error) {
console.error('Migration failed, rolling back...');
// Rollback in reverse order
for (const step of completedSteps.reverse()) {
if (step.rollback) {
try {
await step.rollback();
} catch (rollbackError) {
console.error(`Rollback failed for ${step.name}`);
}
}
}
throw error;
}
}
Graceful Deprecation
async function deprecateContract(
oldContract: ConnectedContract,
newContractAddress: string
): Promise<void> {
// 1. Set deprecation flag in old contract (if supported)
try {
await oldContract.call.set_deprecated({
successor: newContractAddress,
});
console.log('Old contract marked as deprecated');
} catch {
console.log('Contract does not support deprecation flag');
}
// 2. Log deprecation for monitoring
console.log(`Contract ${oldContract.address} deprecated`);
console.log(`Successor: ${newContractAddress}`);
// 3. Update documentation and client configurations
// (manual step or integrate with your deployment system)
}
State Inspection Queries
Common state inspection operations:
// Get all accounts with balances
const accounts = await contract.query.get_all_accounts();
// Get contract metadata
const metadata = await contract.query.get_metadata();
// Get specific state field
const owner = await contract.query.get_owner();
// Get state at specific block (via indexer)
const historicalState = await indexer.getContractStateAtBlock(
CONTRACT_ADDRESS,
blockHeight
);
Related Skills
contract-deployment- Deploying new contract versionscontract-calling- Interacting with contractsmidnight-indexerplugin - Advanced state queries
Related Commands
/midnight:check- Verify environment configuration
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?