const { ethers } = require('hardhat'); const { getContractAddressByNetworkName } = require('./contract-config'); const network = process.env.HARDHAT_NETWORK; let dao; let work1; let onboarding; let account; let validationPools; let reputation; const fetchReputation = async () => { reputation = await dao.balanceOf(account); console.log(`reputation: ${reputation}`); }; const fetchValidationPool = async (poolIndex) => { const pool = await dao.validationPools(poolIndex); validationPools[poolIndex] = pool; return pool; }; const fetchValidationPools = async () => { const count = await dao.validationPoolCount(); console.log(`validation pool count: ${count}`); const promises = []; validationPools = []; for (let i = 0; i < count; i += 1) { promises.push(fetchValidationPool(i)); } await Promise.all(promises); }; const initialize = async () => { const getContract = (name) => ethers.getContractAt( name, getContractAddressByNetworkName(network, name), ); dao = await getContract('DAO'); work1 = await getContract('Work1'); onboarding = await getContract('Onboarding'); [account] = await ethers.getSigners(); const address = await account.getAddress(); console.log(`account: ${address}`); await fetchReputation(); await fetchValidationPools(); }; const poolIsActive = (pool) => { if (new Date() >= new Date(Number(pool.endTime) * 1000)) return false; if (pool.resolved) return false; return true; }; const poolIsValid = (pool) => [ getContractAddressByNetworkName(network, 'Work1'), getContractAddressByNetworkName(network, 'Onboarding'), ].includes(pool.sender); const getPoolStatus = (pool) => { if (poolIsActive(pool)) return 'Active'; if (!pool.resolved) return 'Ready to Evaluate'; if (pool.outcome) return 'Accepted'; return 'Rejected'; }; const stake = async (pool, amount, inFavor) => { console.log(`staking ${amount} ${inFavor ? 'in favor of' : 'against'} pool ${pool.id.toString()}`); await dao.stake(pool.id, amount, true); await fetchReputation(); }; const stakeEach = async (pools, amountPerPool) => { const promises = []; pools.forEach((pool) => { promises.push(stake(pool, amountPerPool, poolIsValid(pool))); }); await Promise.all(promises); }; async function main() { await initialize(); validationPools.forEach((pool) => { console.log(`pool ${pool.id.toString()}, status: ${getPoolStatus(pool)}`); }); // Stake half of available reputation on any active pools const activePools = validationPools.filter(poolIsActive); if (activePools.length && reputation > 0) { const amountPerPool = reputation / BigInt(2) / BigInt(activePools.length); await stakeEach(activePools, amountPerPool); } // Listen for new validation pools dao.on('ValidationPoolInitiated', async (poolIndex) => { console.log(`pool ${poolIndex} started`); const pool = await fetchValidationPool(poolIndex); await fetchReputation(); if (!reputation) return; const amountToStake = reputation / BigInt(2); if (poolIsValid(pool)) { // Stake half of available reputation on this validation pool await stake(pool, amountToStake, true); } else { console.log(`pool sender ${pool.sender} is not recognized`); await stake(pool, amountToStake, false); } }); dao.on('ValidationPoolResolved', async (poolIndex, votePasses) => { console.log(`pool ${poolIndex} resolved, status: ${votePasses ? 'accepted' : 'rejected'}`); fetchValidationPool(poolIndex); fetchReputation(); }); work1.on('AvailabilityStaked', async () => { fetchReputation(); }); onboarding.on('AvailabilityStaked', async () => { fetchReputation(); }); } main().catch((error) => { console.error(error); process.exitCode = 1; });