142 lines
5.6 KiB
JavaScript
Executable File
142 lines
5.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* Chainlink Keepers Setup Script
|
|
* Registers PriceFeedKeeper with Chainlink Automation
|
|
*
|
|
* Usage:
|
|
* node scripts/reserve/chainlink-keeper-setup.js
|
|
*
|
|
* Environment Variables:
|
|
* RPC_URL_138 - ChainID 138 RPC endpoint
|
|
* PRIVATE_KEY - Deployer private key
|
|
* KEEPER_REGISTRY_ADDRESS - Chainlink KeeperRegistry address
|
|
* PRICE_FEED_KEEPER_ADDRESS - PriceFeedKeeper contract address
|
|
* LINK_TOKEN_ADDRESS - LINK token address
|
|
* UPKEEP_INTERVAL - Upkeep interval in seconds (default: 30)
|
|
* GAS_LIMIT - Gas limit for upkeep (default: 500000)
|
|
* FUNDING_AMOUNT - LINK amount to fund (default: 10 LINK)
|
|
*/
|
|
|
|
const { ethers } = require('ethers');
|
|
require('dotenv').config();
|
|
|
|
const CONFIG = {
|
|
rpcUrl: process.env.RPC_URL_138 || 'http://localhost:8545',
|
|
privateKey: process.env.PRIVATE_KEY,
|
|
keeperRegistry: process.env.KEEPER_REGISTRY_ADDRESS,
|
|
keeperAddress: process.env.PRICE_FEED_KEEPER_ADDRESS,
|
|
linkToken: process.env.LINK_TOKEN_ADDRESS,
|
|
upkeepInterval: parseInt(process.env.UPKEEP_INTERVAL || '30'),
|
|
gasLimit: parseInt(process.env.GAS_LIMIT || '500000'),
|
|
fundingAmount: ethers.parseEther(process.env.FUNDING_AMOUNT || '10'),
|
|
};
|
|
|
|
// Chainlink KeeperRegistry ABI (simplified)
|
|
const KEEPER_REGISTRY_ABI = [
|
|
"function registerUpkeep(address target, uint32 gasLimit, address admin, bytes calldata checkData, uint96 amount, address source, bytes memory encryptedEmail) external returns (uint256)",
|
|
"function getUpkeep(uint256 id) external view returns (address target, uint32 executeGas, bytes memory checkData, uint96 balance, address lastKeeper, uint96 balance, address admin, uint64 maxValidBlocknumber, uint96 amountSpent)",
|
|
"function addFunds(uint256 id, uint96 amount) external",
|
|
"event UpkeepRegistered(uint256 indexed id, address indexed target, uint32 gasLimit, address admin)",
|
|
];
|
|
|
|
// ChainlinkKeeperCompatible ABI
|
|
const KEEPER_COMPATIBLE_ABI = [
|
|
"function checkUpkeep(bytes calldata checkData) external view returns (bool upkeepNeeded, bytes memory performData)",
|
|
"function performUpkeep(bytes calldata performData) external",
|
|
];
|
|
|
|
// LINK Token ABI
|
|
const LINK_TOKEN_ABI = [
|
|
"function approve(address spender, uint256 amount) external returns (bool)",
|
|
"function transfer(address to, uint256 amount) external returns (bool)",
|
|
"function balanceOf(address account) external view returns (uint256)",
|
|
];
|
|
|
|
async function main() {
|
|
console.log('=== Chainlink Keepers Setup ===\n');
|
|
|
|
// Validate configuration
|
|
if (!CONFIG.privateKey) throw new Error('PRIVATE_KEY is required');
|
|
if (!CONFIG.keeperRegistry) throw new Error('KEEPER_REGISTRY_ADDRESS is required');
|
|
if (!CONFIG.keeperAddress) throw new Error('PRICE_FEED_KEEPER_ADDRESS is required');
|
|
if (!CONFIG.linkToken) throw new Error('LINK_TOKEN_ADDRESS is required');
|
|
|
|
const provider = new ethers.JsonRpcProvider(CONFIG.rpcUrl);
|
|
const wallet = new ethers.Wallet(CONFIG.privateKey, provider);
|
|
|
|
console.log('Network:', CONFIG.rpcUrl);
|
|
console.log('Deployer:', wallet.address);
|
|
console.log('Keeper Registry:', CONFIG.keeperRegistry);
|
|
console.log('Keeper Address:', CONFIG.keeperAddress);
|
|
console.log('LINK Token:', CONFIG.linkToken);
|
|
console.log('Upkeep Interval:', CONFIG.upkeepInterval, 'seconds');
|
|
console.log('Gas Limit:', CONFIG.gasLimit);
|
|
console.log('Funding Amount:', ethers.formatEther(CONFIG.fundingAmount), 'LINK');
|
|
console.log('');
|
|
|
|
// Check LINK balance
|
|
const linkToken = new ethers.Contract(CONFIG.linkToken, LINK_TOKEN_ABI, wallet);
|
|
const linkBalance = await linkToken.balanceOf(wallet.address);
|
|
console.log('LINK Balance:', ethers.formatEther(linkBalance), 'LINK');
|
|
|
|
if (linkBalance < CONFIG.fundingAmount) {
|
|
throw new Error(`Insufficient LINK balance. Need ${ethers.formatEther(CONFIG.fundingAmount)} LINK`);
|
|
}
|
|
|
|
// Approve LINK spending
|
|
console.log('\nApproving LINK spending...');
|
|
const approveTx = await linkToken.approve(CONFIG.keeperRegistry, CONFIG.fundingAmount);
|
|
await approveTx.wait();
|
|
console.log('✓ LINK approved');
|
|
|
|
// Register upkeep
|
|
console.log('\nRegistering upkeep...');
|
|
const keeperRegistry = new ethers.Contract(CONFIG.keeperRegistry, KEEPER_REGISTRY_ABI, wallet);
|
|
|
|
const checkData = ethers.toUtf8Bytes(''); // Empty check data
|
|
const encryptedEmail = ethers.toUtf8Bytes(''); // Empty email
|
|
|
|
const registerTx = await keeperRegistry.registerUpkeep(
|
|
CONFIG.keeperAddress,
|
|
CONFIG.gasLimit,
|
|
wallet.address, // Admin
|
|
checkData,
|
|
CONFIG.fundingAmount,
|
|
wallet.address, // Source
|
|
encryptedEmail
|
|
);
|
|
|
|
console.log('Transaction sent:', registerTx.hash);
|
|
const receipt = await registerTx.wait();
|
|
|
|
// Parse UpkeepRegistered event
|
|
const event = receipt.logs.find(log => {
|
|
try {
|
|
const parsed = keeperRegistry.interface.parseLog(log);
|
|
return parsed.name === 'UpkeepRegistered';
|
|
} catch {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
if (event) {
|
|
const parsed = keeperRegistry.interface.parseLog(event);
|
|
const upkeepId = parsed.args.id;
|
|
console.log('✓ Upkeep registered!');
|
|
console.log('Upkeep ID:', upkeepId.toString());
|
|
console.log('');
|
|
console.log('=== Setup Complete ===');
|
|
console.log('Upkeep ID:', upkeepId.toString());
|
|
console.log('Monitor at:', `https://automation.chain.link/${upkeepId}`);
|
|
} else {
|
|
console.log('⚠ Could not parse UpkeepRegistered event');
|
|
console.log('Check transaction receipt for upkeep ID');
|
|
}
|
|
}
|
|
|
|
main().catch(error => {
|
|
console.error('Error:', error.message);
|
|
process.exit(1);
|
|
});
|
|
|