UNPKG

@celo/contractkit

Version:

Celo's ContractKit to interact with Celo network

497 lines 27 kB
"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