UNPKG

@celo/contractkit

Version:

Celo's ContractKit to interact with Celo network

243 lines 12.6 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.AttestationsWrapper = exports.AttestationState = void 0; const base_1 = require("@celo/base"); const address_1 = require("@celo/base/lib/address"); const connect_1 = require("@celo/connect"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const BaseWrapper_1 = require("./BaseWrapper"); /** * Contract for managing identities */ var AttestationState; (function (AttestationState) { AttestationState[AttestationState["None"] = 0] = "None"; AttestationState[AttestationState["Incomplete"] = 1] = "Incomplete"; AttestationState[AttestationState["Complete"] = 2] = "Complete"; })(AttestationState || (exports.AttestationState = AttestationState = {})); class AttestationsWrapper extends BaseWrapper_1.BaseWrapper { constructor(connection, contract, contracts) { super(connection, contract); this.connection = connection; this.contract = contract; this.contracts = contracts; /** * Returns the time an attestation can be completable before it is considered expired */ this.attestationExpiryBlocks = (0, BaseWrapper_1.proxyCall)(this.contract.methods.attestationExpiryBlocks, undefined, BaseWrapper_1.valueToInt); /** * Returns the attestation request fee in a given currency. * @param address Token address. * @returns The fee as big number. */ this.attestationRequestFees = (0, BaseWrapper_1.proxyCall)(this.contract.methods.attestationRequestFees, undefined, BaseWrapper_1.valueToBigNumber); this.selectIssuersWaitBlocks = (0, BaseWrapper_1.proxyCall)(this.contract.methods.selectIssuersWaitBlocks, undefined, BaseWrapper_1.valueToInt); /** * @notice Returns the unselected attestation request for an identifier/account pair, if any. * @param identifier Attestation identifier (e.g. phone hash) * @param account Address of the account */ this.getUnselectedRequest = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getUnselectedRequest, undefined, (res) => ({ blockNumber: (0, BaseWrapper_1.valueToInt)(res[0]), attestationsRequested: (0, BaseWrapper_1.valueToInt)(res[1]), attestationRequestFeeToken: res[2], })); /** * @notice Checks if attestation request is expired. * @param attestationRequestBlockNumber Attestation Request Block Number to be checked */ this.isAttestationExpired = (attestationRequestBlockNumber) => __awaiter(this, void 0, void 0, function* () { // We duplicate the implementation here, until Attestation.sol->isAttestationExpired is not external const attestationExpiryBlocks = yield this.attestationExpiryBlocks(); const blockNumber = yield this.connection.getBlockNumber(); return blockNumber >= attestationRequestBlockNumber + attestationExpiryBlocks; }); /** * Returns the issuers of attestations for a phoneNumber/account combo * @param identifier Attestation identifier (e.g. phone hash) * @param account Address of the account */ this.getAttestationIssuers = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getAttestationIssuers); /** * Returns the attestation state of a phone number/account/issuer tuple * @param identifier Attestation identifier (e.g. phone hash) * @param account Address of the account */ this.getAttestationState = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getAttestationState, undefined, (state) => ({ attestationState: (0, BaseWrapper_1.valueToInt)(state[0]) })); /** * Returns the attestation stats of a identifer/account pair * @param identifier Attestation identifier (e.g. phone hash) * @param account Address of the account */ this.getAttestationStat = (0, BaseWrapper_1.proxyCall)(this.contract.methods.getAttestationStats, undefined, (stat) => ({ completed: (0, BaseWrapper_1.valueToInt)(stat[0]), total: (0, BaseWrapper_1.valueToInt)(stat[1]), })); /** * Returns the attestation signer for the specified account. * @param account The address of token rewards are accumulated in. * @param account The address of the account. * @return The reward amount. */ this.getPendingWithdrawals = (0, BaseWrapper_1.proxyCall)(this.contract.methods.pendingWithdrawals, undefined, BaseWrapper_1.valueToBigNumber); /** * Allows issuers to withdraw accumulated attestation rewards * @param address The address of the token that will be withdrawn */ this.withdraw = (0, BaseWrapper_1.proxySend)(this.connection, this.contract.methods.withdraw); /** * Returns the list of accounts associated with an identifier. * @param identifier Attestation identifier (e.g. phone hash) */ this.lookupAccountsForIdentifier = (0, BaseWrapper_1.proxyCall)(this.contract.methods.lookupAccountsForIdentifier); } /** * Returns the verified status of an identifier/account pair indicating whether the attestation * stats for a given pair are completed beyond a certain threshold of confidence (aka "verified") * @param identifier Attestation identifier (e.g. phone hash) * @param account Address of the account * @param numAttestationsRequired Optional number of attestations required. Will default to * hardcoded value if absent. * @param attestationThreshold Optional threshold for fraction attestations completed. Will * default to hardcoded value if absent. */ getVerifiedStatus(identifier, account, numAttestationsRequired = 3, attestationThreshold = 0.25) { return __awaiter(this, void 0, void 0, function* () { const stats = yield this.getAttestationStat(identifier, account); if (!stats) { return { isVerified: false, numAttestationsRemaining: 0, total: 0, completed: 0, }; } const numAttestationsRemaining = numAttestationsRequired - stats.completed; const fractionAttestation = stats.total < 1 ? 0 : stats.completed / stats.total; // 'verified' is a term of convenience to mean that the attestation stats for a // given identifier are beyond a certain threshold of confidence const isVerified = numAttestationsRemaining <= 0 && fractionAttestation >= attestationThreshold; return { isVerified, numAttestationsRemaining, total: stats.total, completed: stats.completed, }; }); } /** * Calculates the amount of StableToken required to request Attestations * @param attestationsRequested The number of attestations to request */ getAttestationFeeRequired(attestationsRequested) { return __awaiter(this, void 0, void 0, function* () { const contract = yield this.contracts.getStableToken(base_1.StableToken.cUSD); const attestationFee = yield this.contract.methods .getAttestationRequestFee(contract.address) .call(); return new bignumber_js_1.default(attestationFee).times(attestationsRequested); }); } /** * Approves the necessary amount of StableToken to request Attestations * @param attestationsRequested The number of attestations to request */ approveAttestationFee(attestationsRequested) { return __awaiter(this, void 0, void 0, function* () { const tokenContract = yield this.contracts.getStableToken(base_1.StableToken.cUSD); const fee = yield this.getAttestationFeeRequired(attestationsRequested); return tokenContract.approve(this.address, fee.toFixed()); }); } /** * Returns the current configuration parameters for the contract. * @param tokens List of tokens used for attestation fees. use CeloTokens.getAddresses() to get * @return AttestationsConfig object */ getConfig(tokens) { return __awaiter(this, void 0, void 0, function* () { const feeTokens = tokens; const fees = yield Promise.all(feeTokens.map((token) => __awaiter(this, void 0, void 0, function* () { const fee = yield this.attestationRequestFees(token); return { fee, address: token }; }))); return { attestationExpiryBlocks: yield this.attestationExpiryBlocks(), attestationRequestFees: fees, }; }); } /** * @dev Returns human readable configuration of the attestations contract * @param tokens List of tokens used for attestation fees. use CeloTokens.getAddresses() to get * @return AttestationsConfig object */ getHumanReadableConfig(tokens) { return __awaiter(this, void 0, void 0, function* () { const config = yield this.getConfig(tokens); return { attestationRequestFees: config.attestationRequestFees, attestationExpiry: (0, BaseWrapper_1.blocksToDurationString)(config.attestationExpiryBlocks), }; }); } /** * Lookup mapped wallet addresses for a given list of identifiers * @param identifiers Attestation identifiers (e.g. phone hashes) */ lookupIdentifiers(identifiers) { return __awaiter(this, void 0, void 0, function* () { // Unfortunately can't be destructured const stats = yield this.contract.methods.batchGetAttestationStats(identifiers).call(); const matches = stats[0].map(BaseWrapper_1.valueToInt); const addresses = stats[1]; const completed = stats[2].map(BaseWrapper_1.valueToInt); const total = stats[3].map(BaseWrapper_1.valueToInt); // Map of identifier -> (Map of address -> AttestationStat) const result = {}; let rIndex = 0; for (let pIndex = 0; pIndex < identifiers.length; pIndex++) { const pHash = identifiers[pIndex]; const numberOfMatches = matches[pIndex]; if (numberOfMatches === 0) { continue; } const matchingAddresses = {}; for (let mIndex = 0; mIndex < numberOfMatches; mIndex++) { const matchingAddress = addresses[rIndex]; matchingAddresses[matchingAddress] = { completed: completed[rIndex], total: total[rIndex], }; rIndex++; } result[pHash] = matchingAddresses; } return result; }); } revoke(identifer, account) { return __awaiter(this, void 0, void 0, function* () { const accounts = yield this.lookupAccountsForIdentifier(identifer); const idx = accounts.findIndex((acc) => (0, address_1.eqAddress)(acc, account)); if (idx < 0) { throw new Error("Account not found in identifier's accounts"); } return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.revoke(identifer, idx)); }); } } exports.AttestationsWrapper = AttestationsWrapper; //# sourceMappingURL=Attestations.js.map