Automated Trigger Service for Decentralized Estate Planning
The off-chain automation layer that monitors StellarGhost contracts and triggers inheritance release when inactivity thresholds expire. Deploy as a serverless function, containerized service, or traditional server.
The StellarGhost Keeper is a critical infrastructure component that automates the inheritance release process. Since smart contracts cannot execute themselves, the keeper network monitors all active contracts and calls trigger_release() when the inactivity threshold is exceeded.
Key responsibilities:
- Monitor contract state periodically
- Detect expired inactivity thresholds
- Trigger inheritance release automatically
- Report transaction status to monitoring systems
- Maintain high availability and redundancy
┌─────────────────┐
│ Schedule/Cron │
│ (Daily Check) │
└────────┬────────┘
│
▼
┌──────────────────────┐
│ Keeper Service │
│ - Poll contracts │
│ - Check thresholds │
│ - Trigger release │
└────────┬─────────────┘
│
▼
┌──────────────────────┐
│ Stellar Blockchain │
│ (Trigger Txs) │
└──────────────────────┘
┌─────────────────────────────────────┐
│ Multiple Independent Keepers │
│ (AWS Lambda, Heroku, Self-Hosted) │
└─────────────────────────────────────┘
│ │ │
┌──────┘ │ └──────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│Keeper 1│ │Keeper 2│ │Keeper 3│
└────────┘ └────────┘ └────────┘
│ │ │
└─────────────┼─────────────┘
│
(Coordinate via Redis/DB)
│
▼
Stellar Network
(Single Trigger Call)
- Automated Monitoring - Continuous tracking of all active contracts
- Threshold Detection - Identifies contracts where inheritance should trigger
- Efficient Batching - Combines multiple triggers into single transaction (future)
- Error Handling - Graceful recovery from network failures
- Logging & Monitoring - Comprehensive audit trail via logs and events
- Multiple Deployment Options - Serverless, Docker, or traditional hosting
- Duplicate Prevention - Prevents multiple keepers from triggering same contract
- Fallback Mechanisms - Manual trigger capability for beneficiaries if keepers fail
Continuously polls the Stellar network for contract state changes.
interface ContractMonitor {
// Fetch active contracts
getActiveContracts(): Promise<ContractInfo[]>;
// Get contract state
getContractState(contractId: string): Promise<LockboxState>;
// Check if threshold exceeded
isThresholdExceeded(state: LockboxState): boolean;
// Calculate time remaining
getTimeRemaining(state: LockboxState): number;
}Executes trigger transactions on the Stellar network.
interface TriggerEngine {
// Trigger inheritance release
triggerRelease(contractId: string): Promise<TransactionHash>;
// Get transaction status
getTransactionStatus(txHash: string): Promise<TxStatus>;
// Estimate fees
estimateFees(contractId: string): Promise<number>;
}Prevents duplicate triggers in keeper network.
interface StateCoordinator {
// Register trigger attempt
registerTrigger(contractId: string, keeperId: string): Promise<boolean>;
// Get trigger history
getTriggerHistory(contractId: string): Promise<TriggerRecord[]>;
// Lock contract to prevent concurrent triggers
acquireLock(contractId: string, ttl: number): Promise<boolean>;
}- Node.js 18+
- npm or yarn
- Stellar testnet/public account with XLM
- Redis (for distributed keeper coordination)
- Keeper secret key (derived from master account)
-
Clone the repository:
git clone https://github.com/stellar-ghost/stellar-ghost-keeper.git cd stellar-ghost-keeper -
Install dependencies:
npm install
-
Configure environment variables:
cp .env.example .env
Update
.env:# Stellar Network STELLAR_NETWORK=testnet KEEPER_SECRET_KEY=SXX... CONTRACT_ID=CXXXX... # Monitoring CHECK_INTERVAL_MS=86400000 # 24 hours STALE_THRESHOLD_SECONDS=604800 # 7 days # Redis Coordination (for distributed keeper) REDIS_URL=redis://localhost:6379 KEEPER_ID=keeper-1 # Logging LOG_LEVEL=info SLACK_WEBHOOK_URL=https://hooks.slack.com/... # Database (for persistent trigger history) DATABASE_URL=postgresql://... -
Start the keeper:
npm start
# Stellar Configuration
STELLAR_NETWORK=testnet # testnet or public
KEEPER_SECRET_KEY=SXX... # Keeper account secret key
HORIZON_URL=https://horizon-testnet.stellar.org
# Contract Monitoring
CHECK_INTERVAL_MS=86400000 # Poll interval (ms)
BATCH_SIZE=100 # Contracts per poll
STALE_THRESHOLD_SECONDS=604800 # Consider contract stale after 7 days
# Keeper Coordination (distributed setup)
REDIS_URL=redis://localhost:6379
KEEPER_ID=keeper-1 # Unique identifier for this keeper
LOCK_TTL_SECONDS=3600 # Lock expiry time
# Logging & Monitoring
LOG_LEVEL=info # debug, info, warn, error
LOG_FORMAT=json # json or text
SLACK_WEBHOOK_URL=https://... # Slack notifications
DATADOG_API_KEY=xxx # Datadog monitoring
SENTRY_DSN=https://... # Error tracking
# Database
DATABASE_URL=postgresql://user:pass@host/db
DB_POOL_SIZE=10
# Performance
MAX_RETRIES=3
RETRY_DELAY_MS=5000
TIMEOUT_MS=30000npm run dev# Build image
docker build -t stellar-ghost-keeper .
# Run container
docker run --env-file .env stellar-ghost-keeper
# Docker Compose
docker-compose up-
Build for Lambda:
npm run build:lambda
-
Deploy:
serverless deploy
-
Configure CloudWatch Events:
- Trigger Lambda once daily
- Set timeout to 5 minutes
- Configure dead-letter queue for failures
# Create app
heroku create stellar-ghost-keeper
# Set environment variables
heroku config:set STELLAR_NETWORK=testnet KEEPER_SECRET_KEY=SXX...
# Deploy
git push heroku main
# View logs
heroku logs --tail# Create namespace
kubectl create namespace stellar-ghost
# Create secret
kubectl create secret generic keeper-config \
--from-literal=KEEPER_SECRET_KEY=SXX... \
-n stellar-ghost
# Deploy
kubectl apply -f k8s/deployment.yaml -n stellar-ghost
# Check status
kubectl get pods -n stellar-ghostnpm startnpm run dry-runnpm run trigger -- --contract-id CXXXX...npm run statusAll keeper activity is logged with structured JSON output:
{
"timestamp": "2026-07-14T15:00:00Z",
"level": "info",
"keeper_id": "keeper-1",
"action": "trigger_released",
"contract_id": "CXXXX...",
"tx_hash": "abcd1234...",
"gas_used": 1000,
"duration_ms": 2500
}Track key performance indicators:
- Contracts monitored
- Successful triggers per hour/day
- Average trigger latency
- Failed triggers and retry counts
- Keeper uptime percentage
Configure alerts for:
- Keeper process crashes
- Network connectivity issues
- Trigger transaction failures
- Suspicious activity (multiple triggers on same contract)
- Redis connection failures
If running as a service:
# Health check
GET /health
# Keeper status
GET /status
# Trigger contract manually
POST /trigger
Body: { "contract_id": "CXXXX..." }
# Get metrics
GET /metrics
# Get trigger history
GET /history?contract_id=CXXXX...- Never hardcode secret key in code
- Use environment variables for all sensitive data
- Rotate keys regularly
- Limit permissions - keeper account should only trigger contracts, not withdraw
- HTTPS only for all external requests
- IP whitelisting if possible
- Rate limiting to prevent abuse
- DDoS protection for public endpoints
- Verify threshold before triggering
- Check double-trigger prevention
- Validate contract state immutability
- Log all triggers for audit trail
# Run all tests
npm test
# Run specific test
npm test -- --testNamePattern="trigger"
# Test coverage
npm run test:coverage
# Integration tests (requires testnet setup)
npm run test:integration
# Load testing
npm run test:load- Check logs for error messages
- Verify keeper account has XLM for fees
- Test contract manually via CLI
- Check network connectivity
- Verify contract ID is correct
- Batch multiple triggers (future optimization)
- Adjust check frequency to reduce retries
- Use cheaper network operations
- Monitor fee trends on Stellar
- Enable Redis coordination for keeper network
- Implement locking mechanism (see state-coordinator)
- Add duplicate detection in database
- Verify keeper IDs are unique
# Reduce polling frequency
CHECK_INTERVAL_MS=604800000 # Weekly instead of daily
# Increase batch size
BATCH_SIZE=1000 # Process more contracts per poll
# Parallel processing
MAX_CONCURRENT_TRIGGERS=10
# Connection pooling
DB_POOL_SIZE=20stellar-ghost-keeper/
├── src/
│ ├── index.ts # Entry point
│ ├── keeper.ts # Main keeper logic
│ ├── monitor.ts # Contract monitor
│ ├── trigger-engine.ts # Trigger executor
│ ├── coordinator.ts # Distributed coordination
│ ├── config.ts # Configuration loader
│ ├── logger.ts # Logging setup
│ ├── stellar-utils.ts # Stellar SDK wrappers
│ ├── db/
│ │ ├── client.ts # Database connection
│ │ ├── triggers.ts # Trigger history queries
│ │ └── migrations/ # Database migrations
│ ├── handlers/
│ │ ├── api.ts # API endpoints
│ │ ├── lambda.ts # AWS Lambda handler
│ │ └── cron.ts # Cron task handler
│ └── tests/
│ ├── keeper.test.ts
│ ├── monitor.test.ts
│ └── trigger-engine.test.ts
├── Dockerfile
├── docker-compose.yml
├── serverless.yml # Serverless config
├── k8s/ # Kubernetes manifests
├── .env.example
├── package.json
└── README.md
We welcome contributions! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/improvement) - Write tests for new functionality
- Ensure all tests pass (
npm test) - Commit with clear messages
- Push and create a Pull Request
npm run dev # Start with hot reload
npm run build # Build TypeScript
npm test # Run tests
npm run lint # Run ESLint
npm run format # Format codeMIT License - see LICENSE file for details.
- Issues: Report bugs on GitHub
- Discussions: GitHub Discussions
- Discord: Stellar Developer Community
- Security: security@stellarghost.dev
Part of the 👻 StellarGhost ecosystem
For more information, visit the main monorepo.