- Change file mode from 644 to 755 for all project files - Add chain_id parameter to get_balance RPC endpoint with default "ait-devnet" - Rename Miner.extra_meta_data to extra_metadata for consistency
259 lines
10 KiB
JavaScript
Executable File
259 lines
10 KiB
JavaScript
Executable File
const { ethers } = require("hardhat");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
async function main() {
|
|
console.log("🚀 Deploying OpenClaw Autonomous Economics Contracts");
|
|
console.log("==============================================");
|
|
|
|
const [deployer] = await ethers.getSigners();
|
|
const balance = await deployer.getBalance();
|
|
|
|
console.log(`Deployer: ${deployer.address}`);
|
|
console.log(`Balance: ${ethers.utils.formatEther(balance)} ETH`);
|
|
|
|
if (balance.lt(ethers.utils.parseEther("1"))) {
|
|
throw new Error("Insufficient ETH balance. Minimum 1 ETH recommended for deployment.");
|
|
}
|
|
|
|
console.log("");
|
|
console.log("Proceeding with contract deployment...");
|
|
|
|
// Deployment configuration
|
|
const deployedContracts = {
|
|
network: hre.network.name,
|
|
deployer: deployer.address,
|
|
timestamp: new Date().toISOString(),
|
|
contracts: {}
|
|
};
|
|
|
|
try {
|
|
// Get existing contracts
|
|
let aitbcTokenAddress, paymentProcessorAddress, aiPowerRentalAddress;
|
|
|
|
try {
|
|
const existingContractsFile = `deployed-contracts-${hre.network.name}.json`;
|
|
if (fs.existsSync(existingContractsFile)) {
|
|
const existingContracts = JSON.parse(fs.readFileSync(existingContractsFile, 'utf8'));
|
|
aitbcTokenAddress = existingContracts.contracts.AITBCToken?.address;
|
|
paymentProcessorAddress = existingContracts.contracts.AITBCPaymentProcessor?.address;
|
|
aiPowerRentalAddress = existingContracts.contracts.AIPowerRental?.address;
|
|
}
|
|
} catch (error) {
|
|
console.log("Could not load existing contracts, deploying mock ones...");
|
|
}
|
|
|
|
// Deploy Mock ERC20 if needed
|
|
if (!aitbcTokenAddress) {
|
|
console.log("📦 Deploying mock AITBC token...");
|
|
const MockERC20 = await ethers.getContractFactory("MockERC20");
|
|
const aitbcToken = await MockERC20.deploy(
|
|
"AITBC Token",
|
|
"AITBC",
|
|
ethers.utils.parseEther("1000000")
|
|
);
|
|
await aitbcToken.deployed();
|
|
aitbcTokenAddress = aitbcToken.address;
|
|
|
|
deployedContracts.contracts.AITBCToken = {
|
|
address: aitbcTokenAddress,
|
|
deploymentHash: aitbcToken.deployTransaction.hash,
|
|
gasUsed: (await aitbcToken.deployTransaction.wait()).gasUsed.toString()
|
|
};
|
|
|
|
console.log(`✅ AITBC Token: ${aitbcTokenAddress}`);
|
|
}
|
|
|
|
// Deploy Mock Payment Processor if needed
|
|
if (!paymentProcessorAddress) {
|
|
console.log("📦 Deploying mock AITBC Payment Processor...");
|
|
const MockPaymentProcessor = await ethers.getContractFactory("AITBCPaymentProcessor");
|
|
const paymentProcessor = await MockPaymentProcessor.deploy(aitbcTokenAddress);
|
|
await paymentProcessor.deployed();
|
|
paymentProcessorAddress = paymentProcessor.address;
|
|
|
|
deployedContracts.contracts.AITBCPaymentProcessor = {
|
|
address: paymentProcessorAddress,
|
|
deploymentHash: paymentProcessor.deployTransaction.hash,
|
|
gasUsed: (await paymentProcessor.deployTransaction.wait()).gasUsed.toString()
|
|
};
|
|
|
|
console.log(`✅ Payment Processor: ${paymentProcessorAddress}`);
|
|
}
|
|
|
|
// Deploy AgentWallet contract
|
|
console.log("📦 Deploying AgentWallet contract...");
|
|
const AgentWallet = await ethers.getContractFactory("AgentWallet");
|
|
const agentWallet = await AgentWallet.deploy(
|
|
aitbcTokenAddress,
|
|
paymentProcessorAddress
|
|
);
|
|
await agentWallet.deployed();
|
|
|
|
deployedContracts.contracts.AgentWallet = {
|
|
address: agentWallet.address,
|
|
deploymentHash: agentWallet.deployTransaction.hash,
|
|
gasUsed: (await agentWallet.deployTransaction.wait()).gasUsed.toString()
|
|
};
|
|
|
|
console.log(`✅ AgentWallet: ${agentWallet.address}`);
|
|
|
|
// Deploy AgentOrchestration contract
|
|
console.log("📦 Deploying AgentOrchestration contract...");
|
|
const AgentOrchestration = await ethers.getContractFactory("AgentOrchestration");
|
|
const agentOrchestration = await AgentOrchestration.deploy();
|
|
await agentOrchestration.deployed();
|
|
|
|
deployedContracts.contracts.AgentOrchestration = {
|
|
address: agentOrchestration.address,
|
|
deploymentHash: agentOrchestration.deployTransaction.hash,
|
|
gasUsed: (await agentOrchestration.deployTransaction.wait()).gasUsed.toString()
|
|
};
|
|
|
|
console.log(`✅ AgentOrchestration: ${agentOrchestration.address}`);
|
|
|
|
// Deploy or extend AIPowerRental contract
|
|
if (!aiPowerRentalAddress) {
|
|
console.log("📦 Deploying AIPowerRental contract...");
|
|
const AIPowerRental = await ethers.getContractFactory("AIPowerRental");
|
|
const aiPowerRental = await AIPowerRental.deploy(
|
|
aitbcTokenAddress
|
|
);
|
|
await aiPowerRental.deployed();
|
|
aiPowerRentalAddress = aiPowerRental.address;
|
|
|
|
deployedContracts.contracts.AIPowerRental = {
|
|
address: aiPowerRentalAddress,
|
|
deploymentHash: aiPowerRental.deployTransaction.hash,
|
|
gasUsed: (await aiPowerRental.deployTransaction.wait()).gasUsed.toString()
|
|
};
|
|
|
|
console.log(`✅ AIPowerRental: ${aiPowerRentalAddress}`);
|
|
} else {
|
|
console.log(`📦 Using existing AIPowerRental: ${aiPowerRentalAddress}`);
|
|
deployedContracts.contracts.AIPowerRental = {
|
|
address: aiPowerRentalAddress,
|
|
note: "Existing contract - agent features added"
|
|
};
|
|
}
|
|
|
|
// Initialize contracts
|
|
console.log("🔧 Initializing contracts...");
|
|
|
|
// Authorize deployer as agent
|
|
await agentWallet.authorizeAgent(deployer.address, deployer.address);
|
|
console.log("✅ Authorized deployer as agent");
|
|
|
|
// Authorize deployer as provider
|
|
await agentWallet.authorizeProvider(deployer.address);
|
|
console.log("✅ Authorized deployer as provider");
|
|
|
|
// Authorize agent for AIPowerRental
|
|
const aiPowerRentalContract = await ethers.getContractAt("AIPowerRental", aiPowerRentalAddress);
|
|
await aiPowerRentalContract.authorizeAgent(deployer.address, deployer.address);
|
|
console.log("✅ Authorized agent for AIPowerRental");
|
|
|
|
// Authorize provider for AIPowerRental
|
|
await aiPowerRentalContract.authorizeProvider(deployer.address);
|
|
console.log("✅ Authorized provider for AIPowerRental");
|
|
|
|
// Save deployment information
|
|
const deploymentFile = `deployed-contracts-${hre.network.name}.json`;
|
|
|
|
// Load existing contracts if file exists
|
|
let existingContracts = {};
|
|
if (fs.existsSync(deploymentFile)) {
|
|
existingContracts = JSON.parse(fs.readFileSync(deploymentFile, 'utf8'));
|
|
}
|
|
|
|
// Merge with existing contracts
|
|
const allContracts = {
|
|
...existingContracts,
|
|
...deployedContracts
|
|
};
|
|
|
|
fs.writeFileSync(
|
|
path.join(__dirname, "..", deploymentFile),
|
|
JSON.stringify(allContracts, null, 2)
|
|
);
|
|
|
|
// Generate environment variables for frontend
|
|
const envVars = `
|
|
# AITBC OpenClaw Autonomous Economics - ${hre.network.name.toUpperCase()}
|
|
# Generated on ${new Date().toISOString()}
|
|
|
|
# Contract Addresses
|
|
VITE_AGENT_WALLET_ADDRESS=${agentWallet.address}
|
|
VITE_AGENT_ORCHESTRATION_ADDRESS=${agentOrchestration.address}
|
|
VITE_AI_POWER_RENTAL_ADDRESS=${aiPowerRentalAddress}
|
|
VITE_AITBC_TOKEN_ADDRESS=${aitbcTokenAddress}
|
|
VITE_PAYMENT_PROCESSOR_ADDRESS=${paymentProcessorAddress}
|
|
|
|
# Network Configuration
|
|
VITE_NETWORK_NAME=${hre.network.name}
|
|
VITE_CHAIN_ID=${hre.network.config.chainId || 1}
|
|
VITE_RPC_URL=${hre.network.config.url || 'http://localhost:8545'}
|
|
|
|
# Agent Configuration
|
|
VITE_DEFAULT_SPENDING_LIMIT=1000
|
|
VITE_MICRO_TRANSACTION_THRESHOLD=0.001
|
|
VITE_MIN_ALLOWANCE=10
|
|
VITE_MAX_ALLOWANCE=100000
|
|
|
|
# Bid Strategy Configuration
|
|
VITE_MARKET_WINDOW=24
|
|
VITE_PRICE_HISTORY_DAYS=30
|
|
VITE_VOLATILITY_THRESHOLD=0.15
|
|
VITE_MAX_CONCURRENT_PLANS=10
|
|
VITE_ASSIGNMENT_TIMEOUT=300
|
|
VITE_MONITORING_INTERVAL=30
|
|
VITE_RETRY_LIMIT=3
|
|
`;
|
|
|
|
const envFile = path.join(__dirname, "..", "..", "apps", "marketplace-web", ".env.agent-economics");
|
|
fs.writeFileSync(envFile, envVars);
|
|
|
|
console.log("");
|
|
console.log("🎉 CONTRACT DEPLOYMENT COMPLETED");
|
|
console.log("===============================");
|
|
console.log(`Total gas used: ${calculateTotalGas(deployedContracts)}`);
|
|
console.log(`Deployment file: ${deploymentFile}`);
|
|
console.log(`Environment file: ${envFile}`);
|
|
console.log("");
|
|
console.log("📋 Contract Addresses:");
|
|
console.log(` AgentWallet: ${agentWallet.address}`);
|
|
console.log(` AgentOrchestration: ${agentOrchestration.address}`);
|
|
console.log(` AIPowerRental: ${aiPowerRentalAddress}`);
|
|
console.log(` AITBC Token: ${aitbcTokenAddress}`);
|
|
console.log(` Payment Processor: ${paymentProcessorAddress}`);
|
|
console.log("");
|
|
console.log("🔧 Next Steps:");
|
|
console.log(" 1. Verify contracts on Etherscan (if on testnet/mainnet)");
|
|
console.log(" 2. Update frontend with new contract addresses");
|
|
console.log(" 3. Test agent wallet functionality");
|
|
console.log(" 4. Initialize bid strategy engine");
|
|
console.log(" 5. Set up agent orchestrator");
|
|
|
|
} catch (error) {
|
|
console.error("❌ Deployment failed:", error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
function calculateTotalGas(deployedContracts) {
|
|
let totalGas = 0;
|
|
for (const contract of Object.values(deployedContracts.contracts)) {
|
|
if (contract.gasUsed) {
|
|
totalGas += parseInt(contract.gasUsed);
|
|
}
|
|
}
|
|
return totalGas.toLocaleString();
|
|
}
|
|
|
|
main()
|
|
.then(() => process.exit(0))
|
|
.catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|