@celo/contractkit
Version:
Celo's ContractKit to interact with Celo network
497 lines • 27 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.ReleaseGoldWrapper = void 0;
const base_1 = require("@celo/base");
const address_1 = require("@celo/base/lib/address");
const connect_1 = require("@celo/connect");
const signatureUtils_1 = require("@celo/utils/lib/signatureUtils");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const Array_1 = require("fp-ts/lib/Array");
const BaseWrapper_1 = require("./BaseWrapper");
const BaseWrapperForGoverning_1 = require("./BaseWrapperForGoverning");
/**
* Contract for handling an instance of a ReleaseGold contract.
*/
class ReleaseGoldWrapper extends BaseWrapperForGoverning_1.BaseWrapperForGoverning {
constructor() {
super(...arguments);
/**
* Returns the beneficiary of the ReleaseGold contract
* @return The address of the beneficiary.
*/
this.getBeneficiary = (0, BaseWrapper_1.proxyCall)(this.contract.methods.beneficiary);
/**
* Returns the releaseOwner address of the ReleaseGold contract
* @return The address of the releaseOwner.
*/
this.getReleaseOwner = (0, BaseWrapper_1.proxyCall)(this.contract.methods.releaseOwner);
/**
* Returns the refund address of the ReleaseGold contract
* @return The refundAddress.
*/
this.getRefundAddress = (0, BaseWrapper_1.proxyCall)(this.contract.methods.refundAddress);
/**
* Returns the owner's address of the ReleaseGold contract
* @return The owner's address.
*/
this.getOwner = (0, BaseWrapper_1.proxyCall)(this.contract.methods.owner);
/**
* Returns true if the liquidity provision has been met for this contract
* @return If the liquidity provision is met.
*/
this.getLiquidityProvisionMet = (0, BaseWrapper_1.proxyCall)(this.contract.methods.liquidityProvisionMet);
/**
* Returns true if the contract can validate
* @return If the contract can validate
*/
this.getCanValidate = (0, BaseWrapper_1.proxyCall)(this.contract.methods.canValidate);
/**
* Returns true if the contract can vote
* @return If the contract can vote
*/
this.getCanVote = (0, BaseWrapper_1.proxyCall)(this.contract.methods.canVote);
/**
* Returns the total withdrawn amount from the ReleaseGold contract
* @return The total withdrawn amount from the ReleaseGold contract
*/
this.getTotalWithdrawn = (0, BaseWrapper_1.proxyCall)(this.contract.methods.totalWithdrawn, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Returns the maximum amount of gold (regardless of release schedule)
* currently allowed for release.
* @return The max amount of gold currently withdrawable.
*/
this.getMaxDistribution = (0, BaseWrapper_1.proxyCall)(this.contract.methods.maxDistribution, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Indicates if the release grant is revoked or not
* @return A boolean indicating revoked releasing (true) or non-revoked(false).
*/
this.isRevoked = (0, BaseWrapper_1.proxyCall)(this.contract.methods.isRevoked);
/**
* Returns the total balance of the ReleaseGold instance
* @return The total ReleaseGold instance balance
*/
this.getTotalBalance = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getTotalBalance, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Returns the the sum of locked and unlocked gold in the ReleaseGold instance
* @return The remaining total ReleaseGold instance balance
*/
this.getRemainingTotalBalance = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getRemainingTotalBalance, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Returns the remaining unlocked gold balance in the ReleaseGold instance
* @return The available unlocked ReleaseGold instance gold balance
*/
this.getRemainingUnlockedBalance = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getRemainingUnlockedBalance, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Returns the remaining locked gold balance in the ReleaseGold instance
* @return The remaining locked ReleaseGold instance gold balance
*/
this.getRemainingLockedBalance = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getRemainingLockedBalance, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Returns the total amount that has already released up to now
* @return The already released gold amount up to the point of call
*/
this.getCurrentReleasedTotalAmount = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getCurrentReleasedTotalAmount, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Returns currently withdrawable amount
* @return The amount that can be yet withdrawn
*/
this.getWithdrawableAmount = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getWithdrawableAmount, undefined, BaseWrapper_1.valueToBigNumber);
/**
* Revoke a Release schedule
* @return A CeloTransactionObject
*/
this.revokeReleasing = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.revoke);
/**
* Revoke a vesting CELO schedule from the contract's beneficiary.
* @return A CeloTransactionObject
*/
this.revokeBeneficiary = this.revokeReleasing;
/**
* Refund `refundAddress` and `beneficiary` after the ReleaseGold schedule has been revoked.
* @return A CeloTransactionObject
*/
this.refundAndFinalize = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.refundAndFinalize);
/**
* Locks gold to be used for voting.
* @param value The amount of gold to lock
*/
this.lockGold = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.lockGold, (0, BaseWrapper_1.tupleParser)(BaseWrapper_1.valueToString));
this.transfer = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.transfer, (0, BaseWrapper_1.tupleParser)(BaseWrapper_1.stringIdentity, BaseWrapper_1.valueToString));
/**
* Unlocks gold that becomes withdrawable after the unlocking period.
* @param value The amount of gold to unlock
*/
this.unlockGold = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.unlockGold, (0, BaseWrapper_1.tupleParser)(BaseWrapper_1.valueToString));
/**
* Relocks gold that has been unlocked but not withdrawn.
* @param index The index of the pending withdrawal to relock from.
* @param value The value to relock from the specified pending withdrawal.
*/
this._relockGold = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.relockGold, (0, BaseWrapper_1.tupleParser)(BaseWrapper_1.valueToString, BaseWrapper_1.valueToString));
/**
* Withdraw gold in the ReleaseGold instance that has been unlocked but not withdrawn.
* @param index The index of the pending locked gold withdrawal
*/
this.withdrawLockedGold = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.withdrawLockedGold, (0, BaseWrapper_1.tupleParser)(BaseWrapper_1.valueToString));
/**
* Transfer released gold from the ReleaseGold instance back to beneficiary.
* @param value The requested gold amount
*/
this.withdraw = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.withdraw, (0, BaseWrapper_1.tupleParser)(BaseWrapper_1.valueToString));
/**
* Beneficiary creates an account on behalf of the ReleaseGold contract.
*/
this.createAccount = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.createAccount);
/**
* Beneficiary creates an account on behalf of the ReleaseGold contract.
* @param name The name to set
* @param dataEncryptionKey The key to set
* @param walletAddress The address to set
*/
this.setAccount = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setAccount);
/**
* Sets the name for the account
* @param name The name to set
*/
this.setAccountName = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setAccountName);
/**
* Sets the metadataURL for the account
* @param metadataURL The url to set
*/
this.setAccountMetadataURL = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setAccountMetadataURL);
/**
* Sets the wallet address for the account
* @param walletAddress The address to set
*/
this.setAccountWalletAddress = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setAccountWalletAddress);
/**
* Sets the data encryption of the account
* @param dataEncryptionKey The key to set
*/
this.setAccountDataEncryptionKey = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setAccountDataEncryptionKey);
/**
* Sets the contract's liquidity provision to true
*/
this.setLiquidityProvision = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setLiquidityProvision);
/**
* Sets the contract's `canExpire` field to `_canExpire`
* @param _canExpire If the contract can expire `EXPIRATION_TIME` after the release schedule finishes.
*/
this.setCanExpire = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setCanExpire);
/**
* Sets the contract's max distribution
*/
this.setMaxDistribution = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setMaxDistribution);
/**
* Sets the contract's beneficiary
*/
this.setBeneficiary = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.setBeneficiary);
/**
* Revokes pending votes
* @param validatorGroup The group to revoke the vote for.
* @param value The amount of gold to revoke.
*/
this.revokePendingVotes = (group, value) => this.revokePending(this.address, group, value);
/**
* Revokes active votes
* @param group The group to revoke the vote for.
* @param value The amount of gold to revoke.
*/
this.revokeActiveVotes = (group, value) => this.revokeActive(this.address, group, value);
/**
* Revokes value from pending/active aggregate
* @param group The group to revoke the vote for.
* @param value The amount of gold to revoke.
*/
this.revokeValueFromVotes = (group, value) => this.revoke(this.address, group, value);
this.revokeAllVotesForGroup = (group) => __awaiter(this, void 0, void 0, function* () {
const txos = [];
const electionContract = yield this.contracts.getElection();
const { pending, active } = yield electionContract.getVotesForGroupByAccount(this.address, group);
if (pending.isGreaterThan(0)) {
const revokePendingTx = yield this.revokePendingVotes(group, pending);
txos.push(revokePendingTx);
}
if (active.isGreaterThan(0)) {
const revokeActiveTx = yield this.revokeActiveVotes(group, active);
txos.push(revokeActiveTx);
}
return txos;
});
this.revokeAllVotesForAllGroups = () => __awaiter(this, void 0, void 0, function* () {
const electionContract = yield this.contracts.getElection();
const groups = yield electionContract.getGroupsVotedForByAccount(this.address);
const txoMatrix = yield (0, base_1.concurrentMap)(4, groups, (group) => this.revokeAllVotesForGroup(group));
return (0, Array_1.flatten)(txoMatrix);
});
}
/**
* Returns the underlying Release schedule of the ReleaseGold contract
* @return A ReleaseSchedule.
*/
getReleaseSchedule() {
return __awaiter(this, void 0, void 0, function* () {
const releaseSchedule = yield this.contract.methods.releaseSchedule().call();
return {
releaseStartTime: (0, BaseWrapper_1.valueToInt)(releaseSchedule.releaseStartTime),
releaseCliff: (0, BaseWrapper_1.valueToInt)(releaseSchedule.releaseCliff),
numReleasePeriods: (0, BaseWrapper_1.valueToInt)(releaseSchedule.numReleasePeriods),
releasePeriod: (0, BaseWrapper_1.valueToInt)(releaseSchedule.releasePeriod),
amountReleasedPerPeriod: (0, BaseWrapper_1.valueToBigNumber)(releaseSchedule.amountReleasedPerPeriod),
};
});
}
/**
* Returns the underlying Release schedule of the ReleaseGold contract
* @return A ReleaseSchedule.
*/
getHumanReadableReleaseSchedule() {
return __awaiter(this, void 0, void 0, function* () {
const releaseSchedule = yield this.getReleaseSchedule();
return Object.assign(Object.assign({}, releaseSchedule), { releaseCliff: (0, BaseWrapper_1.unixSecondsTimestampToDateString)(releaseSchedule.releaseCliff), releaseStartTime: (0, BaseWrapper_1.unixSecondsTimestampToDateString)(releaseSchedule.releaseStartTime), releasePeriod: (0, BaseWrapper_1.secondsToDurationString)(releaseSchedule.releasePeriod) });
});
}
/**
* Returns the underlying Revocation Info of the ReleaseGold contract
* @return A RevocationInfo struct.
*/
getRevocationInfo() {
return __awaiter(this, void 0, void 0, function* () {
try {
const revocationInfo = yield this.contract.methods.revocationInfo().call();
return {
revocable: revocationInfo.revocable,
canExpire: revocationInfo.canExpire,
releasedBalanceAtRevoke: (0, BaseWrapper_1.valueToBigNumber)(revocationInfo.releasedBalanceAtRevoke),
revokeTime: (0, BaseWrapper_1.valueToInt)(revocationInfo.revokeTime),
};
}
catch (_) {
// This error is caused by a mismatch between the deployed contract and the locally compiled version.
// Specifically, networks like baklava and rc0 were deployed before adding `canExpire`.
console.info('Some info could not be fetched, returning default for revocation info.');
return {
revocable: false,
canExpire: false,
releasedBalanceAtRevoke: new bignumber_js_1.default(0),
revokeTime: 0,
};
}
});
}
/**
* Indicates if the release grant is revocable or not
* @return A boolean indicating revocable releasing (true) or non-revocable(false).
*/
isRevocable() {
return __awaiter(this, void 0, void 0, function* () {
const revocationInfo = yield this.getRevocationInfo();
return revocationInfo.revocable;
});
}
/**
* Returns the time at which the release schedule was revoked
* @return The timestamp of the release schedule revocation
*/
getRevokeTime() {
return __awaiter(this, void 0, void 0, function* () {
const revocationInfo = yield this.getRevocationInfo();
return revocationInfo.revokeTime;
});
}
/**
* Returns the balance of released gold when the grant was revoked
* @return The balance at revocation time. 0 can also indicate not revoked.
*/
getReleasedBalanceAtRevoke() {
return __awaiter(this, void 0, void 0, function* () {
const revocationInfo = yield this.getRevocationInfo();
return revocationInfo.releasedBalanceAtRevoke.toString();
});
}
unlockAllGold() {
return __awaiter(this, void 0, void 0, function* () {
const lockedGold = yield this.contracts.getLockedGold();
const amount = yield lockedGold.getAccountTotalLockedGold(this.address);
return this.unlockGold(amount);
});
}
/**
* Relocks gold in the ReleaseGold instance that has been unlocked but not withdrawn.
* @param index The index of the pending withdrawal to relock from.
* @param value The value to relock from the specified pending withdrawal.
*/
relockGold(value) {
return __awaiter(this, void 0, void 0, function* () {
const lockedGold = yield this.contracts.getLockedGold();
const pendingWithdrawals = yield lockedGold.getPendingWithdrawals(this.address);
// Ensure there are enough pending withdrawals to relock.
const totalValue = yield lockedGold.getPendingWithdrawalsTotalValue(this.address);
if (totalValue.isLessThan(value)) {
throw new Error(`Not enough pending withdrawals to relock ${value}`);
}
// Assert pending withdrawals are sorted by time (increasing), so that we can re-lock starting
// with those furthest away from being available (at the end).
const throwIfNotSorted = (pw, i) => {
if (i > 0 && !pw.time.isGreaterThanOrEqualTo(pendingWithdrawals[i - 1].time)) {
throw new Error('Pending withdrawals not sorted by timestamp');
}
};
pendingWithdrawals.forEach(throwIfNotSorted);
let remainingToRelock = new bignumber_js_1.default(value);
const relockPw = (acc, pw, i) => {
const valueToRelock = bignumber_js_1.default.minimum(pw.value, remainingToRelock);
if (!valueToRelock.isZero()) {
remainingToRelock = remainingToRelock.minus(valueToRelock);
acc.push(this._relockGold(i, valueToRelock));
}
return acc;
};
return pendingWithdrawals.reduceRight(relockPw, []);
});
}
/**
* Authorizes an address to sign votes on behalf of the account.
* @param signer The address of the vote signing key to authorize.
* @param proofOfSigningKeyPossession The account address signed by the signer address.
* @return A CeloTransactionObject
*/
authorizeVoteSigner(signer, proofOfSigningKeyPossession) {
return __awaiter(this, void 0, void 0, function* () {
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.authorizeVoteSigner(signer, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s));
});
}
/**
* Authorizes an address to sign validation messages on behalf of the account.
* @param signer The address of the validator signing key to authorize.
* @param proofOfSigningKeyPossession The account address signed by the signer address.
* @return A CeloTransactionObject
*/
authorizeValidatorSigner(signer, proofOfSigningKeyPossession) {
return __awaiter(this, void 0, void 0, function* () {
const validators = yield this.contracts.getValidators();
const account = this.address;
if (yield validators.isValidator(account)) {
const message = this.connection.web3.utils.soliditySha3({
type: 'address',
value: account,
});
const prefixedMsg = (0, signatureUtils_1.hashMessageWithPrefix)(message);
const pubKey = (0, signatureUtils_1.signedMessageToPublicKey)(prefixedMsg, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s);
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.authorizeValidatorSignerWithPublicKey(signer, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s, (0, BaseWrapper_1.stringToSolidityBytes)(pubKey)));
}
else {
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.authorizeValidatorSigner(signer, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s));
}
});
}
/**
* @deprecated use `authorizeValidatorSignerWithPublicKey`
*/
authorizeValidatorSignerAndBls(signer, proofOfSigningKeyPossession) {
return __awaiter(this, void 0, void 0, function* () {
return this.authorizeValidatorSignerWithPublicKey(signer, proofOfSigningKeyPossession);
});
}
/**
* Authorizes an address to sign consensus messages on behalf of the contract's account. Also switch BLS key at the same time.
* @param signer The address of the signing key to authorize.
* @param proofOfSigningKeyPossession The contract's account address signed by the signer address.
* @return A CeloTransactionObject
*/
authorizeValidatorSignerWithPublicKey(signer, proofOfSigningKeyPossession) {
return __awaiter(this, void 0, void 0, function* () {
const account = this.address;
const message = this.connection.web3.utils.soliditySha3({
type: 'address',
value: account,
});
const prefixedMsg = (0, signatureUtils_1.hashMessageWithPrefix)(message);
const pubKey = (0, signatureUtils_1.signedMessageToPublicKey)(prefixedMsg, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s);
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.authorizeValidatorSignerWithPublicKey(signer, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s, (0, BaseWrapper_1.stringToSolidityBytes)(pubKey)));
});
}
/**
* Authorizes an address to sign attestation messages on behalf of the account.
* @param signer The address of the attestation signing key to authorize.
* @param proofOfSigningKeyPossession The account address signed by the signer address.
* @return A CeloTransactionObject
*/
authorizeAttestationSigner(signer, proofOfSigningKeyPossession) {
return __awaiter(this, void 0, void 0, function* () {
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.authorizeAttestationSigner(signer, proofOfSigningKeyPossession.v, proofOfSigningKeyPossession.r, proofOfSigningKeyPossession.s));
});
}
/**
* Revokes pending votes
* @deprecated prefer revokePendingVotes
* @param account The account to revoke from.
* @param validatorGroup The group to revoke the vote for.
* @param value The amount of gold to revoke.
*/
revokePending(account, group, value) {
return __awaiter(this, void 0, void 0, function* () {
const electionContract = yield this.contracts.getElection();
const groups = yield electionContract.getGroupsVotedForByAccount(account);
const index = (0, address_1.findAddressIndex)(group, groups);
const { lesser, greater } = yield electionContract.findLesserAndGreaterAfterVote(group, value.times(-1));
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.revokePending(group, value.toFixed(), lesser, greater, index));
});
}
/**
* Revokes active votes
* @deprecated Prefer revokeActiveVotes
* @param account The account to revoke from.
* @param group The group to revoke the vote for.
* @param value The amount of gold to revoke.
*/
revokeActive(account, group, value) {
return __awaiter(this, void 0, void 0, function* () {
const electionContract = yield this.contracts.getElection();
const groups = yield electionContract.getGroupsVotedForByAccount(account);
const index = (0, address_1.findAddressIndex)(group, groups);
const { lesser, greater } = yield electionContract.findLesserAndGreaterAfterVote(group, value.times(-1));
return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.revokeActive(group, value.toFixed(), lesser, greater, index));
});
}
/**
* Revokes value from pending/active aggregate
* @deprecated prefer revokeValueFromVotes
* @param account The account to revoke from.
* @param group The group to revoke the vote for.
* @param value The amount of gold to revoke.
*/
revoke(account, group, value) {
return __awaiter(this, void 0, void 0, function* () {
const electionContract = yield this.contracts.getElection();
const vote = yield electionContract.getVotesForGroupByAccount(account, group);
if (value.gt(vote.pending.plus(vote.active))) {
throw new Error(`can't revoke more votes for ${group} than have been made by ${account}`);
}
const txos = [];
const pendingValue = bignumber_js_1.default.minimum(vote.pending, value);
if (!pendingValue.isZero()) {
txos.push(yield this.revokePending(account, group, pendingValue));
}
if (pendingValue.lt(value)) {
const activeValue = value.minus(pendingValue);
txos.push(yield this.revokeActive(account, group, activeValue));
}
return txos;
});
}
}
exports.ReleaseGoldWrapper = ReleaseGoldWrapper;
//# sourceMappingURL=ReleaseGold.js.map