UNPKG

@celo/contractkit

Version:

Celo's ContractKit to interact with Celo network

273 lines 12.5 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SortedOraclesWrapper = exports.MedianRelation = void 0; const address_1 = require("@celo/base/lib/address"); const connect_1 = require("@celo/connect"); const address_2 = require("@celo/utils/lib/address"); const fixidity_1 = require("@celo/utils/lib/fixidity"); const base_1 = require("../base"); const celo_tokens_1 = require("../celo-tokens"); const BaseWrapper_1 = require("./BaseWrapper"); var MedianRelation; (function (MedianRelation) { MedianRelation[MedianRelation["Undefined"] = 0] = "Undefined"; MedianRelation[MedianRelation["Lesser"] = 1] = "Lesser"; MedianRelation[MedianRelation["Greater"] = 2] = "Greater"; MedianRelation[MedianRelation["Equal"] = 3] = "Equal"; })(MedianRelation || (exports.MedianRelation = MedianRelation = {})); /** * Currency price oracle contract. */ class SortedOraclesWrapper extends BaseWrapper_1.BaseWrapper { constructor(connection, contract, registry) { super(connection, contract); this.connection = connection; this.contract = contract; this.registry = registry; /** * Returns the report expiry parameter. * @returns Current report expiry. */ this.reportExpirySeconds = (0, BaseWrapper_1.proxyCall)(this.contract.methods.reportExpirySeconds, undefined, BaseWrapper_1.valueToBigNumber); /** * Helper function to get the rates for StableToken, by passing the address * of StableToken to `getRates`. */ this.getStableTokenRates = () => __awaiter(this, void 0, void 0, function* () { return this.getRates(base_1.CeloContract.StableToken); }); } /** * Gets the number of rates that have been reported for the given target * @param target The ReportTarget, either CeloToken or currency pair * @return The number of reported oracle rates for `token`. */ numRates(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const response = yield this.contract.methods.numRates(identifier).call(); return (0, BaseWrapper_1.valueToInt)(response); }); } /** * Returns the median rate for the given target * @param target The ReportTarget, either CeloToken or currency pair * @return The median exchange rate for `token`, expressed as: * amount of that token / equivalent amount in CELO */ medianRate(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const response = yield this.contract.methods.medianRate(identifier).call(); return { rate: (0, BaseWrapper_1.valueToFrac)(response[0], response[1]), }; }); } /** * Checks if the given address is whitelisted as an oracle for the target * @param target The ReportTarget, either CeloToken or currency pair * @param oracle The address that we're checking the oracle status of * @returns boolean describing whether this account is an oracle */ isOracle(target, oracle) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); return this.contract.methods.isOracle(identifier, oracle).call(); }); } /** * Returns the list of whitelisted oracles for a given target * @param target The ReportTarget, either CeloToken or currency pair * @returns The list of whitelisted oracles for a given token. */ getOracles(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); return this.contract.methods.getOracles(identifier).call(); }); } /** * Returns the expiry for the target if exists, if not the default. * @param target The ReportTarget, either CeloToken or currency pair * @return The report expiry in seconds. */ getTokenReportExpirySeconds(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const response = yield this.contract.methods.getTokenReportExpirySeconds(identifier).call(); return (0, BaseWrapper_1.valueToBigNumber)(response); }); } /** * Checks if the oldest report for a given target is expired * @param target The ReportTarget, either CeloToken or currency pair */ isOldestReportExpired(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const response = yield this.contract.methods.isOldestReportExpired(identifier).call(); // response is NOT an array, but a js object with two keys 0 and 1 return [response[0], response[1]]; }); } /** * Removes expired reports, if any exist * @param target The ReportTarget, either CeloToken or currency pair * @param numReports The upper-limit of reports to remove. For example, if there * are 2 expired reports, and this param is 5, it will only remove the 2 that * are expired. */ removeExpiredReports(target, numReports) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); if (!numReports) { numReports = (yield this.getReports(target)).length - 1; } return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.removeExpiredReports(identifier, numReports)); }); } /** * Updates an oracle value and the median. * @param target The ReportTarget, either CeloToken or currency pair * @param value The amount of `token` equal to one CELO. */ report(target, value, oracleAddress) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const fixedValue = (0, fixidity_1.toFixed)((0, BaseWrapper_1.valueToBigNumber)(value)); const { lesserKey, greaterKey } = yield this.findLesserAndGreaterKeys(target, (0, BaseWrapper_1.valueToBigNumber)(value), oracleAddress); return (0, connect_1.toTransactionObject)(this.connection, this.contract.methods.report(identifier, fixedValue.toFixed(), lesserKey, greaterKey), { from: oracleAddress }); }); } /** * Updates an oracle value and the median. * @param value The amount of US Dollars equal to one CELO. * @param oracleAddress The address to report as * @param token The token to report for */ reportStableToken(value, oracleAddress, token = celo_tokens_1.StableToken.cUSD) { return __awaiter(this, void 0, void 0, function* () { return this.report(celo_tokens_1.stableTokenInfos[token].contract, value, oracleAddress); }); } /** * Returns current configuration parameters. */ getConfig() { return __awaiter(this, void 0, void 0, function* () { return { reportExpirySeconds: yield this.reportExpirySeconds(), }; }); } /** * @dev Returns human readable configuration of the sortedoracles contract * @return SortedOraclesConfig object */ getHumanReadableConfig() { return __awaiter(this, void 0, void 0, function* () { const config = yield this.getConfig(); return { reportExpiry: (0, BaseWrapper_1.secondsToDurationString)(config.reportExpirySeconds), }; }); } /** * Gets all elements from the doubly linked list. * @param target The ReportTarget, either CeloToken or currency pair in question * @return An unpacked list of elements from largest to smallest. */ getRates(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const response = yield this.contract.methods.getRates(identifier).call(); const rates = []; for (let i = 0; i < response[0].length; i++) { const medRelIndex = parseInt(response[2][i], 10); rates.push({ address: response[0][i], rate: (0, fixidity_1.fromFixed)((0, BaseWrapper_1.valueToBigNumber)(response[1][i])), medianRelation: medRelIndex, }); } return rates; }); } /** * Gets all elements from the doubly linked list. * @param target The ReportTarget, either CeloToken or currency pair in question * @return An unpacked list of elements from largest to smallest. */ getTimestamps(target) { return __awaiter(this, void 0, void 0, function* () { const identifier = yield this.toCurrencyPairIdentifier(target); const response = yield this.contract.methods.getTimestamps(identifier).call(); const timestamps = []; for (let i = 0; i < response[0].length; i++) { const medRelIndex = parseInt(response[2][i], 10); timestamps.push({ address: response[0][i], timestamp: (0, BaseWrapper_1.valueToBigNumber)(response[1][i]), medianRelation: medRelIndex, }); } return timestamps; }); } getReports(target) { return __awaiter(this, void 0, void 0, function* () { const [rates, timestamps] = yield Promise.all([ this.getRates(target), this.getTimestamps(target), ]); const reports = []; for (const rate of rates) { const match = timestamps.filter((t) => (0, address_1.eqAddress)(t.address, rate.address)); reports.push({ address: rate.address, rate: rate.rate, timestamp: match[0].timestamp }); } return reports; }); } findLesserAndGreaterKeys(target, value, oracleAddress) { return __awaiter(this, void 0, void 0, function* () { const currentRates = yield this.getRates(target); let greaterKey = address_1.NULL_ADDRESS; let lesserKey = address_1.NULL_ADDRESS; // This leverages the fact that the currentRates are already sorted from // greatest to lowest value for (const rate of currentRates) { if (!(0, address_1.eqAddress)(rate.address, oracleAddress)) { if (rate.rate.isLessThanOrEqualTo(value)) { lesserKey = rate.address; break; } greaterKey = rate.address; } } return { lesserKey, greaterKey }; }); } toCurrencyPairIdentifier(target) { return __awaiter(this, void 0, void 0, function* () { if ((0, celo_tokens_1.isStableTokenContract)(target)) { return this.registry.addressFor(target); } else if ((0, address_2.isValidAddress)(target)) { return target; } else { throw new Error(`${target} is not StableTokenContract deployed or a valid Address`); } }); } } exports.SortedOraclesWrapper = SortedOraclesWrapper; //# sourceMappingURL=SortedOracles.js.map