Operational guide for Vesper daily batch transaction automation via GitHub Actions.
Automated Schedule: 2:00 AM UTC daily
Manual Trigger: GitHub Actions UI or CLI
Network Support: Testnet (2 AM UTC) + Mainnet (manual)
Estimated Duration: 25-35 minutes per run
Log Retention: 30 days
GitHub Actions (2 AM UTC)
↓
Daily Batch Workflow (.github/workflows/daily-batch.yml)
├→ Setup Node.js 22 + npm cache
├→ Install dependencies
├→ Validate batch script (dry-run)
├→ Execute batch transactions (14 txs)
│ ├─ Phase 1: Create 4 streams
│ ├─ Phase 2: Withdraw from streams
│ ├─ Phase 3: Top-up streams
│ ├─ Phase 4: Cancel & read data
├→ Execute sweep-back recovery
└→ Upload logs to artifacts
↓
Batch Monitoring Workflow (.github/workflows/batch-monitoring.yml)
├→ Parse execution logs
├→ Generate summary report
└→ Post results to GitHub Workflow Summary
When: Every day at 2:00 AM UTC
Network: Testnet
Trigger: GitHub Actions cron schedule
Confirmation: Check GitHub Actions tab after 2:20 AM UTC
- Go to Actions tab in GitHub
- Select Daily Batch Automation workflow
- Find the most recent run (should be from today, 2 AM UTC)
- Click run name to view execution log
- Verify all 4 phases completed successfully
✓ Daily batch execution completed successfully in 28.5s
Total wallets: 5
Successful transactions: 14/14
Total µSTX spent on gas: 700 (14 txs × 50 fee)
Total STX recovered: 4.2 (from sweep-back)
Net daily cost: 3.5 STX (non-recoverable)
For testing or out-of-schedule runs:
- Go to Actions tab
- Select Daily Batch Automation workflow
- Click Run workflow button
- Choose network: mainnet or testnet
- Click Run workflow to start
# Testnet
gh workflow run daily-batch.yml -f network=testnet
# Mainnet
gh workflow run daily-batch.yml -f network=mainnetcurl -X POST \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/[owner]/[repo]/actions/workflows/daily-batch.yml/dispatches \
-d '{"ref":"main","inputs":{"network":"testnet"}}'Real-time monitoring:
- Open workflow run in Actions tab
- Expand each step to see console output
- Watch for phase completion messages:
[Phase 1/4] Creating streams...[Phase 2/4] Withdrawing from streams...[Phase 3/4] Adding top-ups...[Phase 4/4] Canceling and reading...
After completion:
- View Batch Execution Summary in workflow summary
- Download batch logs from Artifacts
- Check detailed JSON log:
scripts/logs/batch-YYYY-MM-DD.json
Batch logs location: scripts/logs/batch-YYYY-MM-DD.json
Structure:
{
"date": "2024-12-20",
"network": "testnet",
"transactions": [
{
"txHash": "0x...",
"function": "create-stream",
"walletFrom": "ST...",
"walletTo": "ST...",
"amount": 5000,
"status": "confirmed",
"timestamp": "2024-12-20T02:05:12.000Z"
},
...
],
"sweepSummary": {
"totalRecovered": 4200000,
"totalGasSpent": 700,
"netCost": 3500000
},
"durationMs": 28500
}Problem: Scheduled workflow didn't run
Checklist:
- Check GitHub Actions is enabled in Settings > Actions
- Verify workflow file syntax in
.github/workflows/daily-batch.yml - Confirm branch is
main(workflows only trigger on default branch) - Check cron time:
0 2 * * *= 2:00 AM UTC - Try manual dispatch to verify workflow works
Solution:
# Verify workflow syntax
act -l
# Manual test
gh workflow run daily-batch.yml -f network=testnetProblem: "Connection refused" or API timeout
Likely Cause: Network instability or API rate limiting
Recovery:
- Wait 5 minutes for transient issues to resolve
- Manually re-run workflow via GitHub UI
- If persistent, check Hiro API status at https://status.hiro.so
Manual Re-run:
gh workflow run daily-batch.yml -f network=testnetProblem: "Secrets not found" or "Invalid key format"
Steps:
- Check secrets exist: Settings > Secrets and variables > Actions
- Verify secret names match workflow exactly:
- Testnet:
DEPLOYER_PRIVATE_KEY_TESTNET - Mainnet:
DEPLOYER_PRIVATE_KEY
- Testnet:
- Verify private key format (64-char hex, no
0x) - Regenerate deployer wallet if corrupted
Reference: SECRETS_SETUP.md
Problem: "Balance too low" during batch or sweep
Cause: Deployer wallet depleted
Solution:
- Check deployer balance on testnet
- Request coins from faucet or top-up manually
- Retry batch execution
Manual Top-Up (testnet):
curl -X POST https://api.testnet.hiro.so/extended/v1/faucets/stx \
-H "Content-Type: application/json" \
-d '{"address":"ST..."}'Problem: "Timed out waiting for confirmation"
Cause: Stacks network congestion (rare)
Solution:
- Wait 10 minutes for network to clear
- Check Stacks network status at https://www.stacks.co/
- Manually re-run workflow if needed
Monitoring:
- Each transaction waits up to 200 seconds for confirmation
- 10-second polling interval between checks
- 20 retries total before timeout
Problem: Workflow shows success but no batch logs in artifacts
Cause: Batch script didn't save logs to scripts/logs/
Solution:
- Check script output for errors
- Verify
scripts/logs/directory exists - Ensure batch script has write permissions
Manual Log Check:
# After running batch locally
ls -la scripts/logs/
cat scripts/logs/batch-$(date +%Y-%m-%d).json | jq| Metric | Expected | Warning | Critical |
|---|---|---|---|
| Batch Duration | 25-35s | >45s | >60s |
| Successful TXs | 14/14 | <13 | <10 |
| Gas Spent | 700 µSTX | >1000 | >1500 |
| Funds Recovered | >3 STX | <2 STX | <1 STX |
| Loop Availability | >99% | >95% | <90% |
Track historical metrics:
- Download batch log from artifacts
- Extract key metrics from JSON
- Chart over time (spreadsheet or custom dashboard)
Sample metrics script:
#!/bin/bash
# Extract metrics from all batch logs
for logfile in scripts/logs/batch-*.json; do
date=$(jq -r '.date' "$logfile")
txs=$(jq '.transactions | length' "$logfile")
success=$(jq '[.transactions[] | select(.status == "confirmed")] | length' "$logfile")
gas=$(jq '.sweepSummary.totalGasSpent' "$logfile")
recovered=$(jq '.sweepSummary.totalRecovered' "$logfile")
echo "$date,$txs,$success,$gas,$recovered"
done- Testnet batch runs successfully for 7 consecutive days
- Secrets configured correctly in GitHub (see SECRETS_SETUP.md)
- Monitoring workflow captures and reports results correctly
- Logs parsed correctly and display in workflow summary
- Team has accessed and reviewed sample logs
- Mainnet contract deployed and address updated in secrets
- Mainnet deployer wallet funded and backed up
- Monitor workflow runs daily for first week after deployment
- Review batch logs weekly for anomalies (failed txs, high gas, etc.)
- Test manual dispatch monthly to verify workflow stability
- Rotate deployer keys annually or as needed
- Keep documentation updated with current addresses/contracts
- Archive logs for compliance and auditing (stored 30 days in artifacts)
- Workflow Failed: Check logs immediately, manual re-run if network issue
- All Transactions Failed: Check secrets and network connectivity
- Sweep-back Failed: Funds remain in stream wallets, safe (recoverable later)
- Out of Sync: Manually run batch, check block height differences
- Key Compromised: Rotate deployer key immediately, deploy new contract
- Setup: SECRETS_SETUP.md
- Batch Script: scripts/batch-transactions.ts
- CI/CD Pipeline: .github/workflows/ci.yml
- Stacks Docs: https://docs.stacks.co/
- Hiro API: https://docs.hiro.so/
Primary Workflows:
.github/workflows/daily-batch.yml— Main batch execution.github/workflows/batch-monitoring.yml— Results monitoring.github/workflows/ci.yml— Contract tests + frontend build
Support Files:
scripts/batch-transactions.ts— Batch execution logicscripts/logs/— Daily batch logs (JSON)docs/SECRETS_SETUP.md— Secret configuration guide
- Questions: See linked documentation above
- Issues: Report in GitHub Issues with workflow logs
- Escalation: Contact infrastructure team (mainnet issues)