@celo/contractkit
Version:
Celo's ContractKit to interact with Celo network
150 lines • 9.81 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EpochManagerWrapper = exports.EpochProcessStatus = void 0;
const base_1 = require("@celo/base");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const BaseWrapper_1 = require("./BaseWrapper");
const BaseWrapperForGoverning_1 = require("./BaseWrapperForGoverning");
var EpochProcessStatus;
(function (EpochProcessStatus) {
EpochProcessStatus[EpochProcessStatus["NotStarted"] = 0] = "NotStarted";
EpochProcessStatus[EpochProcessStatus["Started"] = 1] = "Started";
})(EpochProcessStatus || (exports.EpochProcessStatus = EpochProcessStatus = {}));
/**
* Contract handling epoch management.
*/
class EpochManagerWrapper extends BaseWrapperForGoverning_1.BaseWrapperForGoverning {
constructor() {
super(...arguments);
this.epochDuration = (0, BaseWrapper_1.proxyCall)(this.contract.methods.epochDuration, undefined, BaseWrapper_1.valueToInt);
this.firstKnownEpoch = (0, BaseWrapper_1.proxyCall)(this.contract.methods.firstKnownEpoch, undefined, BaseWrapper_1.valueToInt);
this.getCurrentEpochNumber = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getCurrentEpochNumber, undefined, BaseWrapper_1.valueToInt);
this.getFirstBlockAtEpoch = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getFirstBlockAtEpoch, undefined, BaseWrapper_1.valueToInt);
this.getLastBlockAtEpoch = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getLastBlockAtEpoch, undefined, BaseWrapper_1.valueToInt);
this.getEpochNumberOfBlock = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getEpochNumberOfBlock, undefined, BaseWrapper_1.valueToInt);
this.processedGroups = (0, BaseWrapper_1.proxyCall)(this.contract.methods.processedGroups, undefined, BaseWrapper_1.valueToString);
this.isOnEpochProcess = (0, BaseWrapper_1.proxyCall)(this.contract.methods.isOnEpochProcess);
this.isEpochProcessingStarted = (0, BaseWrapper_1.proxyCall)(this.contract.methods.isEpochProcessingStarted);
this.isIndividualProcessing = (0, BaseWrapper_1.proxyCall)(this.contract.methods.isIndividualProcessing);
this.isTimeForNextEpoch = (0, BaseWrapper_1.proxyCall)(this.contract.methods.isTimeForNextEpoch);
this.getElectedAccounts = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getElectedAccounts);
this.getElectedSigners = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getElectedSigners);
this.getEpochProcessingStatus = (0, BaseWrapper_1.proxyCall)(this.contract.methods.epochProcessing, undefined, (result) => {
return {
status: parseInt(result.status),
perValidatorReward: new bignumber_js_1.default(result.perValidatorReward),
totalRewardsVoter: new bignumber_js_1.default(result.totalRewardsVoter),
totalRewardsCommunity: new bignumber_js_1.default(result.totalRewardsCommunity),
totalRewardsCarbonFund: new bignumber_js_1.default(result.totalRewardsCarbonFund),
};
});
this.startNextEpochProcess = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.startNextEpochProcess);
this.finishNextEpochProcess = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.finishNextEpochProcess);
this.sendValidatorPayment = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.sendValidatorPayment);
this.setToProcessGroups = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setToProcessGroups);
this.processGroups = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.processGroups);
this.startNextEpochProcessTx = () => __awaiter(this, void 0, void 0, function* () {
// check that the epoch process is not already started
const isEpochProcessStarted = yield this.isOnEpochProcess();
if (isEpochProcessStarted) {
console.warn('Epoch process has already started.');
return;
}
return this.startNextEpochProcess();
});
this.finishNextEpochProcessTx = () => __awaiter(this, void 0, void 0, function* () {
const { groups, lessers, greaters } = yield this.getEpochGroupsAndSorting();
return this.finishNextEpochProcess(groups, lessers, greaters);
});
this.processGroupsTx = () => __awaiter(this, void 0, void 0, function* () {
const { groups, lessers, greaters } = yield this.getEpochGroupsAndSorting();
return this.processGroups(groups, lessers, greaters);
});
this.getLessersAndGreaters = (groups) => __awaiter(this, void 0, void 0, function* () {
const scoreManager = yield this.contracts.getScoreManager();
const election = yield this.contracts.getElection();
const processingStatusPromise = this.getEpochProcessingStatus();
const groupWithVotesPromise = election.getEligibleValidatorGroupsVotes();
const lessers = new Array(groups.length);
const greaters = new Array(groups.length);
const rewards = yield Promise.all(groups.map((group) => __awaiter(this, void 0, void 0, function* () {
const groupScore = yield scoreManager.getGroupScore(group);
return yield election.getGroupEpochRewards(group, (yield processingStatusPromise).totalRewardsVoter, groupScore);
})));
const groupWithVotes = yield groupWithVotesPromise;
const groupWithVotesMap = new Map(groupWithVotes.map((group) => [group.address, group]));
const missingGroups = groups.filter((group) => !groupWithVotesMap.has(group));
const missingGroupsLoaded = yield Promise.all(missingGroups.map((group) => __awaiter(this, void 0, void 0, function* () {
const votes = yield election.getTotalVotesForGroup(group);
return { group, votes };
})));
for (const group of missingGroupsLoaded) {
groupWithVotes.push({ address: group.group, votes: group.votes });
}
for (let i = 0; i < groups.length; i++) {
const reward = rewards[i];
// biome-ignore lint/style/useForOf: unsure why we need it do it this way
for (let j = 0; j < groupWithVotes.length; j++) {
if (groupWithVotes[j].address === groups[i]) {
groupWithVotes[j].votes.plus(reward);
break;
}
}
groupWithVotes.sort((a, b) => (b.votes.gt(a.votes) ? 1 : b.votes.lt(a.votes) ? -1 : 0));
for (let j = 0; j < groupWithVotes.length; j++) {
if (groupWithVotes[j].address === groups[i]) {
greaters[i] = j === 0 ? base_1.NULL_ADDRESS : groupWithVotes[j - 1].address;
lessers[i] =
j === groupWithVotes.length - 1 ? base_1.NULL_ADDRESS : groupWithVotes[j + 1].address;
break;
}
}
}
return [lessers, greaters];
});
this.getEpochGroupsAndSorting = () => __awaiter(this, void 0, void 0, function* () {
const elected = yield this.getElectedAccounts();
const validators = yield this.contracts.getValidators();
const electedGroups = Array.from(new Set(yield Promise.all(elected.map((validator) => __awaiter(this, void 0, void 0, function* () { return validators.getMembershipInLastEpoch(validator); })))));
const groupProcessedEvents = yield this.contract.getPastEvents('GroupProcessed', {
// We need +1 because events are emitted on the first block of the new epoch
fromBlock: (yield this.getFirstBlockAtEpoch(yield this.getCurrentEpochNumber())) + 1,
});
// Filter out groups that have been processed
const groups = electedGroups.filter((group) => {
return !groupProcessedEvents.some((event) => event.returnValues.group === group);
});
const [lessers, greaters] = yield this.getLessersAndGreaters(groups);
return { groups, lessers, greaters };
});
}
get _contract() {
return this.contract;
}
getConfig() {
return __awaiter(this, void 0, void 0, function* () {
const currentEpochNumber = yield this.getCurrentEpochNumber();
const epochDuration = yield this.epochDuration();
const isTimeForNextEpoch = yield this.isTimeForNextEpoch();
return {
currentEpochNumber,
epochDuration,
isTimeForNextEpoch,
};
});
}
}
exports.EpochManagerWrapper = EpochManagerWrapper;
//# sourceMappingURL=EpochManager.js.map