2024-03-16 13:53:07 -05:00
|
|
|
const { ethers } = require('hardhat');
|
2024-03-20 16:30:27 -05:00
|
|
|
const { getContractAddressByNetworkName } = require('./contract-config');
|
2024-03-23 16:30:35 -05:00
|
|
|
const readFromApi = require('./util/read-from-api');
|
2024-03-16 13:53:07 -05:00
|
|
|
|
2024-03-17 12:29:17 -05:00
|
|
|
const network = process.env.HARDHAT_NETWORK;
|
|
|
|
|
2024-03-16 13:53:07 -05:00
|
|
|
let dao;
|
2024-03-20 16:30:27 -05:00
|
|
|
let work1;
|
|
|
|
let onboarding;
|
2024-03-16 13:53:07 -05:00
|
|
|
let account;
|
|
|
|
let validationPools;
|
|
|
|
let reputation;
|
2024-03-23 16:30:35 -05:00
|
|
|
let posts;
|
2024-03-16 13:53:07 -05:00
|
|
|
|
|
|
|
const fetchReputation = async () => {
|
|
|
|
reputation = await dao.balanceOf(account);
|
|
|
|
console.log(`reputation: ${reputation}`);
|
|
|
|
};
|
|
|
|
|
2024-03-23 16:30:35 -05:00
|
|
|
const fetchPost = async (postIndex) => {
|
|
|
|
const {
|
|
|
|
id, sender, author, contentId,
|
|
|
|
} = await dao.posts(postIndex);
|
|
|
|
const { content } = await readFromApi(contentId);
|
|
|
|
const post = {
|
|
|
|
id,
|
|
|
|
sender,
|
|
|
|
author,
|
|
|
|
contentId,
|
|
|
|
content,
|
|
|
|
};
|
|
|
|
posts[postIndex] = post;
|
|
|
|
return post;
|
|
|
|
};
|
|
|
|
|
2024-03-16 13:53:07 -05:00
|
|
|
const fetchValidationPool = async (poolIndex) => {
|
2024-03-23 16:30:35 -05:00
|
|
|
const {
|
|
|
|
id, postIndex, sender, stakeCount, fee, duration, endTime, resolved, outcome,
|
|
|
|
} = await dao.validationPools(poolIndex);
|
|
|
|
const pool = {
|
|
|
|
id, postIndex, sender, stakeCount, fee, duration, endTime, resolved, outcome,
|
|
|
|
};
|
|
|
|
pool.post = await fetchPost(pool.postIndex);
|
2024-03-16 13:53:07 -05:00
|
|
|
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 () => {
|
2024-03-20 16:30:27 -05:00
|
|
|
const getContract = (name) => ethers.getContractAt(
|
|
|
|
name,
|
|
|
|
getContractAddressByNetworkName(network, name),
|
|
|
|
);
|
|
|
|
dao = await getContract('DAO');
|
|
|
|
work1 = await getContract('Work1');
|
|
|
|
onboarding = await getContract('Onboarding');
|
2024-03-16 13:53:07 -05:00
|
|
|
[account] = await ethers.getSigners();
|
|
|
|
const address = await account.getAddress();
|
|
|
|
console.log(`account: ${address}`);
|
2024-03-23 16:30:35 -05:00
|
|
|
posts = [];
|
2024-03-16 13:53:07 -05:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2024-03-26 12:13:23 -05:00
|
|
|
const poolIsValid = (pool) => {
|
2024-03-23 16:30:35 -05:00
|
|
|
switch (pool.sender) {
|
|
|
|
case getContractAddressByNetworkName(network, 'Work1'): {
|
2024-03-26 12:13:23 -05:00
|
|
|
// If this is a valid work evidence
|
|
|
|
// TODO: Can we decode from the post, a reference to the work request?
|
|
|
|
// The work request does have its own contentId, the work contract has that
|
|
|
|
// under availabilityStakes
|
|
|
|
const expectedContent = 'This is a work evidence post';
|
|
|
|
return pool.post.content.startsWith(expectedContent);
|
|
|
|
}
|
|
|
|
case getContractAddressByNetworkName(network, 'Onboarding'): {
|
|
|
|
const expectedContent = 'This is an onboarding work evidence post';
|
|
|
|
return pool.post.content.startsWith(expectedContent);
|
2024-03-23 16:30:35 -05:00
|
|
|
}
|
|
|
|
default:
|
2024-03-26 12:13:23 -05:00
|
|
|
console.log('Unrecognized sender %s', pool.sender);
|
2024-03-23 16:30:35 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
2024-03-18 14:03:53 -05:00
|
|
|
|
|
|
|
const getPoolStatus = (pool) => {
|
|
|
|
if (poolIsActive(pool)) return 'Active';
|
|
|
|
if (!pool.resolved) return 'Ready to Evaluate';
|
|
|
|
if (pool.outcome) return 'Accepted';
|
|
|
|
return 'Rejected';
|
2024-03-17 12:29:17 -05:00
|
|
|
};
|
|
|
|
|
2024-03-18 14:03:53 -05:00
|
|
|
const stake = async (pool, amount, inFavor) => {
|
|
|
|
console.log(`staking ${amount} ${inFavor ? 'in favor of' : 'against'} pool ${pool.id.toString()}`);
|
2024-03-16 13:53:07 -05:00
|
|
|
await dao.stake(pool.id, amount, true);
|
|
|
|
await fetchReputation();
|
|
|
|
};
|
|
|
|
|
|
|
|
const stakeEach = async (pools, amountPerPool) => {
|
|
|
|
const promises = [];
|
2024-03-23 16:30:35 -05:00
|
|
|
pools.forEach(async (pool) => {
|
|
|
|
const inFavor = await poolIsValid(pool);
|
|
|
|
promises.push(stake(pool, amountPerPool, inFavor));
|
2024-03-16 13:53:07 -05:00
|
|
|
});
|
|
|
|
await Promise.all(promises);
|
|
|
|
};
|
|
|
|
|
2024-03-26 15:28:44 -05:00
|
|
|
const printPool = (pool) => {
|
|
|
|
console.log(`pool ${pool.id.toString()}, `
|
2024-03-26 12:13:23 -05:00
|
|
|
+ `status: ${getPoolStatus(pool)}, `
|
|
|
|
+ `is valid: ${poolIsValid(pool)}, `
|
|
|
|
+ `post content: ${pool.post?.content}`);
|
2024-03-26 15:28:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
await initialize();
|
|
|
|
|
|
|
|
validationPools.forEach(printPool);
|
2024-03-16 13:53:07 -05:00
|
|
|
|
2024-03-18 14:03:53 -05:00
|
|
|
// 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);
|
2024-03-16 13:53:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Listen for new validation pools
|
|
|
|
dao.on('ValidationPoolInitiated', async (poolIndex) => {
|
2024-03-17 13:24:49 -05:00
|
|
|
const pool = await fetchValidationPool(poolIndex);
|
2024-03-26 15:28:44 -05:00
|
|
|
printPool(pool);
|
2024-03-16 13:53:07 -05:00
|
|
|
await fetchReputation();
|
2024-03-18 14:03:53 -05:00
|
|
|
if (!reputation) return;
|
|
|
|
const amountToStake = reputation / BigInt(2);
|
2024-03-26 12:13:23 -05:00
|
|
|
const inFavor = await poolIsValid(pool);
|
|
|
|
await stake(pool, amountToStake, inFavor);
|
2024-03-16 13:53:07 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
dao.on('ValidationPoolResolved', async (poolIndex, votePasses) => {
|
|
|
|
console.log(`pool ${poolIndex} resolved, status: ${votePasses ? 'accepted' : 'rejected'}`);
|
|
|
|
fetchValidationPool(poolIndex);
|
|
|
|
fetchReputation();
|
|
|
|
});
|
2024-03-20 16:30:27 -05:00
|
|
|
|
|
|
|
work1.on('AvailabilityStaked', async () => {
|
|
|
|
fetchReputation();
|
|
|
|
});
|
|
|
|
|
|
|
|
onboarding.on('AvailabilityStaked', async () => {
|
|
|
|
fetchReputation();
|
|
|
|
});
|
2024-03-16 13:53:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
main().catch((error) => {
|
|
|
|
console.error(error);
|
|
|
|
process.exitCode = 1;
|
|
|
|
});
|