dgf-prototype/ethereum/scripts/automatic-staking.js

131 lines
3.7 KiB
JavaScript

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;
});