UNPKG

@mimicry/kaleidoscope

Version:

Kaleidoscope is an NPM package that conveniently aggregates responses from multiple NFT data providers.

1,305 lines (1,285 loc) 89.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var decimal_js = require('decimal.js'); var got = _interopDefault(require('got')); var candlestickConvert = require('candlestick-convert'); function _regeneratorRuntime() { _regeneratorRuntime = function () { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = "function" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || "@@iterator", asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator", toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, ""); } catch (err) { define = function (obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, "_invoke", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if ("throw" !== record.type) { var result = record.arg, value = result.value; return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, "_invoke", { value: function (method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = "suspendedStart"; return function (method, arg) { if ("executing" === state) throw new Error("Generator is already running"); if ("completed" === state) { if ("throw" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) { if ("suspendedStart" === state) throw state = "completed", context.arg; context.dispatchException(context.arg); } else "return" === context.method && context.abrupt("return", context.arg); state = "executing"; var record = tryCatch(innerFn, self, context); if ("normal" === record.type) { if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if ("function" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) { var ctor = "function" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, "toString", function () { return "[object Generator]"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) keys.push(key); return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function (skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); }, stop: function () { this.done = !0; var rootRecord = this.tryEntries[0].completion; if ("throw" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function (exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if ("root" === entry.tryLoc) return handle("end"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"), hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error("try statement without catch or finally"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function (type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function (record, afterLoc) { if ("throw" === record.type) throw record.arg; return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function (finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, catch: function (tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if ("throw" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function (iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, "next" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } (function (Chain) { Chain["ETHEREUM"] = "ethereum"; Chain["POLYGON"] = "polygon"; Chain["SOLANA"] = "solana"; Chain["BSC"] = "bsc"; Chain["ARBITRUM"] = "arbitrum"; Chain["OPTIMISM"] = "optimism"; Chain["KLAYTN"] = "klaytn"; Chain["AVALANCHE"] = "avalanche"; })(exports.Chain || (exports.Chain = {})); (function (CurrencySymbol) { CurrencySymbol["ETH"] = "ETH"; CurrencySymbol["USD"] = "USD"; CurrencySymbol["MATIC"] = "MATIC"; CurrencySymbol["SOL"] = "SOL"; CurrencySymbol["BNB"] = "BNB"; CurrencySymbol["KLAY"] = "KLAY"; CurrencySymbol["AVAX"] = "AVAX"; })(exports.CurrencySymbol || (exports.CurrencySymbol = {})); (function (ConsensusFilter) { ConsensusFilter["MAD"] = "mad"; ConsensusFilter["NONE"] = "none"; })(exports.ConsensusFilter || (exports.ConsensusFilter = {})); (function (ConsensusMethod) { ConsensusMethod["MEDIAN"] = "median"; ConsensusMethod["RANDOM"] = "random"; ConsensusMethod["MEAN"] = "mean"; })(exports.ConsensusMethod || (exports.ConsensusMethod = {})); (function (Timeframe) { Timeframe["FIVE_MIN"] = "5m"; Timeframe["FIFTEEN_MIN"] = "15m"; Timeframe["THIRTY_MIN"] = "30m"; Timeframe["ONE_HOUR"] = "1h"; Timeframe["ONE_DAY"] = "1d"; Timeframe["ONE_WEEK"] = "1w"; })(exports.Timeframe || (exports.Timeframe = {})); /** * Return all _values with no filtering * * @param _values A list of Values * @returns The original list of Values */ function none(_values) { return _values; } /** * Return all _values that fall within the Mean Absolute Deviation of the mean * * @param _values A list of Values * @returns A filtered list of Values */ function mad(_values) { if (_values.length === 0) return _values; var mean = _values.reduce(function (acc, val) { return acc.plus(val.amount.decimal); }, new decimal_js.Decimal(0)).dividedBy(_values.length); var deviations = _values.map(function (val) { return val.amount.decimal.minus(mean).absoluteValue(); }); var meanAbsoluteDeviation = deviations.reduce(function (acc, val) { return acc.plus(val); }, new decimal_js.Decimal(0)).dividedBy(deviations.length); // Calculate the lower and upper bounds of the filtered range var lowerBound = mean.minus(meanAbsoluteDeviation); var upperBound = mean.plus(meanAbsoluteDeviation); // Filter the _values that fall within the range var filteredValues = _values.filter(function (val) { return val.amount.decimal.greaterThanOrEqualTo(lowerBound) && val.amount.decimal.lessThanOrEqualTo(upperBound); }); return filteredValues; } /** * Return the median Value of the list of Values. * If the list has an even number of Values, return the mean of the two middle Values. */ function median(_values) { if (_values.length === 0) { throw new Error('Cannot calculate median of empty array'); } else if (_values.length === 1) { return _values[0]; } // Check if all currencies are the same var currency = _values[0].currencyInfo; for (var _iterator = _createForOfIteratorHelperLoose(_values), _step; !(_step = _iterator()).done;) { var value = _step.value; if (value.currencyInfo.symbol !== currency.symbol) { throw new Error('All Values must be in the same currency to calculate median.'); } } // sort _values by their decimal amount _values.sort(function (a, b) { return a.amount.decimal.comparedTo(b.amount.decimal); }); var midIndex = Math.floor(_values.length / 2); // if _values has an even length, calculate the average of the two middle amounts if (_values.length % 2 === 0) { var midVal1 = _values[midIndex - 1].amount.decimal; var midVal2 = _values[midIndex].amount.decimal; var average = decimal_js.Decimal.div(decimal_js.Decimal.add(midVal1, midVal2), 2); // create a new Value object with the calculated median return { currencyInfo: _values[midIndex].currencyInfo, amount: { atomic: BigInt(average.times(Math.pow(10, _values[midIndex].currencyInfo.decimals)).toFixed(0)), decimal: average } }; } else { // if _values has an odd length, return the middle Value return _values[midIndex]; } } /** * Return a random value from the list */ function random(_values) { if (_values.length === 0) { throw new Error('Cannot select a random Value from an empty array'); } var randomIndex = Math.floor(Math.random() * _values.length); return _values[randomIndex]; } /** * Return the mean Value of the list of Values. */ function mean(values) { if (values.length === 0) { throw new Error('Cannot calculate mean of empty array'); } else if (values.length === 1) { return values[0]; } // Check if all currencies are the same var currency = values[0].currencyInfo; for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) { var value = _step.value; if (value.currencyInfo.symbol !== currency.symbol) { throw new Error('All values must be in the same currency to calculate mean'); } } // Compute the sum of all decimal amounts var decimalSum = new decimal_js.Decimal(0); for (var _iterator2 = _createForOfIteratorHelperLoose(values), _step2; !(_step2 = _iterator2()).done;) { var _value = _step2.value; decimalSum = decimalSum.plus(_value.amount.decimal); } // Compute the mean (average) var meanDecimal = decimalSum.dividedBy(values.length); // Convert the mean decimal amount to atomic var meanAtomic = BigInt(meanDecimal.times(new decimal_js.Decimal(10).pow(currency.decimals)).toFixed(0)); return { currencyInfo: currency, amount: { atomic: meanAtomic, decimal: meanDecimal } }; } var RestfulFactory = /*#__PURE__*/function () { function RestfulFactory(_globalConfig) { this._verbose = false; { console.log(this.getName() + " Constructor"); } if (_globalConfig.verbose) { this._verbose = Boolean(_globalConfig.verbose); } if (!_globalConfig.dataProviders) { throw new Error('No providers specified.'); } } var _proto = RestfulFactory.prototype; _proto.getName = function getName() { return this.constructor.name; }; _proto.runFactory = /*#__PURE__*/function () { var _runFactory = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_dataProviders, _method, _params, _consensusMechanism) { var values, sources, key, _provider, value, finalValue, verboseOutput; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: values = []; sources = []; _context.t0 = _regeneratorRuntime().keys(_dataProviders); case 3: if ((_context.t1 = _context.t0()).done) { _context.next = 19; break; } key = _context.t1.value; _provider = _dataProviders[key]; _context.prev = 6; _context.next = 9; return _provider[_method].apply(_provider, _params); case 9: value = _context.sent; values.push(value); sources.push({ source: _provider.getName(), value: value.amount }); _context.next = 17; break; case 14: _context.prev = 14; _context.t2 = _context["catch"](6); // Skips Providers with methods not implemented. // Skips Providers who's apis are down, throttled, or returning invalid data. { console.error({ provider: _provider.getName(), method: _method, // @ts-ignore error: _context.t2.message }); } case 17: _context.next = 3; break; case 19: if (!(values.length === 0)) { _context.next = 21; break; } throw new Error('No valid values returned from providers.'); case 21: verboseOutput = { method: _method, timestamp: new Date().toISOString() }; if (values.length === 1) { finalValue = values[0]; verboseOutput['data'] = finalValue; verboseOutput['source'] = sources[0].source; } else { finalValue = this.applyConsensusMechanism(values, _consensusMechanism); verboseOutput['currencyInfo'] = finalValue.currencyInfo; verboseOutput['data'] = finalValue.amount; verboseOutput['sources'] = sources; } return _context.abrupt("return", this._verbose ? verboseOutput : finalValue); case 24: case "end": return _context.stop(); } }, _callee, this, [[6, 14]]); })); function runFactory(_x, _x2, _x3, _x4) { return _runFactory.apply(this, arguments); } return runFactory; }(); _proto.addDataProvider = function addDataProvider(_providerName, _apiKey) { throw new Error('Method not implemented: addDataProvider()'); }; _proto.applyConsensusMechanism = function applyConsensusMechanism(_data, _consensusMechanism) { if (_consensusMechanism === void 0) { _consensusMechanism = { filter: exports.ConsensusFilter.NONE, method: exports.ConsensusMethod.MEDIAN }; } var _filteredData = this._applyConsensusFilter(_data, _consensusMechanism.filter); var _consensusValue = this._applyConsensusMethod(_filteredData, _consensusMechanism.method); return _consensusValue; }; _proto.getBlockchain = function getBlockchain(_chain) { throw new Error('Method not implemented: addDataProvider()'); }; _proto.getCorrectProviders = function getCorrectProviders(_dataProviders, _providerName) { var dataProviders = _dataProviders; if (_providerName) { var _dataProviders2; dataProviders = (_dataProviders2 = {}, _dataProviders2[_providerName] = _dataProviders[_providerName], _dataProviders2); } return dataProviders; }; _proto.initProviders = function initProviders(_providers) { for (var _i = 0, _Object$entries = Object.entries(_providers); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _Object$entries[_i], _providerName = _Object$entries$_i[0], _apiKey = _Object$entries$_i[1]; this.addDataProvider(_providerName, String(_apiKey)); } }; _proto._applyConsensusFilter = function _applyConsensusFilter(_data, _consensusFilter) { switch (_consensusFilter) { case undefined: case exports.ConsensusFilter.NONE: return none(_data); case exports.ConsensusFilter.MAD: return mad(_data); default: throw new Error(_consensusFilter + " is not a valid consensus filter."); } }; _proto._applyConsensusMethod = function _applyConsensusMethod(_data, _consensusMethod) { switch (_consensusMethod) { case undefined: case exports.ConsensusMethod.MEDIAN: return median(_data); case exports.ConsensusMethod.MEAN: return mean(_data); case exports.ConsensusMethod.RANDOM: return random(_data); default: throw new Error(_consensusMethod + " is not a valid consensus method."); } }; return RestfulFactory; }(); var RestfulProvider = /*#__PURE__*/function () { function RestfulProvider(_providerConfig, _apiHost) { { console.log(this.getName() + " Constructor using " + _apiHost); } // Futureproofing for when providers have custom configs var apiKey = typeof _providerConfig === 'string' ? _providerConfig : _providerConfig.apiKey; this._config = { key: apiKey, host: _apiHost }; } var _proto = RestfulProvider.prototype; _proto.gotJson = /*#__PURE__*/function () { var _gotJson = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_uri, _options) { var timesToRetry, combinedOptions, json; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: timesToRetry = 5; combinedOptions = _extends({}, _options, { retry: { limit: timesToRetry, backoffLimit: 10000, calculateDelay: function calculateDelay(_ref) { var attemptCount = _ref.attemptCount, computedValue = _ref.computedValue, error = _ref.error; { console.log("Retrying " + _uri + " (" + attemptCount + " of " + timesToRetry + ") \n in " + computedValue / 4 / 1000 + " seconds \n due to " + error); } return computedValue / 4; } } }); _context.next = 4; return got(_uri, combinedOptions).json(); case 4: json = _context.sent; return _context.abrupt("return", json); case 6: case "end": return _context.stop(); } }, _callee); })); function gotJson(_x, _x2) { return _gotJson.apply(this, arguments); } return gotJson; }(); _proto.getApiHost = function getApiHost() { return this._config.host; }; _proto.getApiKey = function getApiKey() { return this._config.key; }; _proto.getBlockchain = function getBlockchain(_chain) { throw new Error('Method not implemented: getBlockchain()'); }; _proto.getCurrencyInfoFromChain = function getCurrencyInfoFromChain(_chain) { switch (_chain) { case undefined: case exports.Chain.ARBITRUM: case exports.Chain.OPTIMISM: case exports.Chain.ETHEREUM: return this.getCurrencyInfoFromSymbol(exports.CurrencySymbol.ETH); case exports.Chain.POLYGON: return this.getCurrencyInfoFromSymbol(exports.CurrencySymbol.MATIC); case exports.Chain.SOLANA: return this.getCurrencyInfoFromSymbol(exports.CurrencySymbol.SOL); case exports.Chain.BSC: return this.getCurrencyInfoFromSymbol(exports.CurrencySymbol.BNB); default: throw new Error(_chain + " is not a valid chain."); } }; _proto.getCurrencyInfoFromSymbol = function getCurrencyInfoFromSymbol(_symbol) { switch (_symbol) { case undefined: case exports.CurrencySymbol.ETH: return { symbol: exports.CurrencySymbol.ETH, name: 'Ethereum', decimals: 18 }; case exports.CurrencySymbol.MATIC: return { symbol: exports.CurrencySymbol.MATIC, name: 'Matic', decimals: 18 }; case exports.CurrencySymbol.BNB: return { symbol: exports.CurrencySymbol.BNB, name: 'Binance Coin', decimals: 18 }; case exports.CurrencySymbol.SOL: return { symbol: exports.CurrencySymbol.SOL, name: 'Solana', decimals: 9 }; case exports.CurrencySymbol.USD: return { symbol: exports.CurrencySymbol.USD, name: 'United States Dollar', decimals: 8 }; default: throw new Error(_symbol + " is not a valid CurrencySymbol."); } }; _proto.getName = function getName() { return this.constructor.name; }; return RestfulProvider; }(); /** * Given a bigint and CurrencyInfo, return an Value object. */ function bigIntToValue(_value, _currencyInfo) { var decimal = new decimal_js.Decimal(Number(_value) / Math.pow(10, _currencyInfo.decimals)); var atomic = _value; return { currencyInfo: _currencyInfo, amount: { atomic: atomic, decimal: decimal } }; } /** * Given a number and CurrencyInfo, return a bigint. */ function numberToBigInt(_value, _currencyInfo) { return BigInt(_value * Math.pow(10, _currencyInfo.decimals)); } /** * Given a number and CurrencyInfo, return a bigint. */ function numberToValue(_value, _currencyInfo) { var bigValue = numberToBigInt(_value, _currencyInfo); return bigIntToValue(bigValue, _currencyInfo); } /** * Given a chain, return the blockchain explorer's host URI. */ function chainToBlockchainExplorerHost(_chain) { switch (_chain) { case undefined: case exports.Chain.ETHEREUM: return 'https://etherscan.io'; case exports.Chain.POLYGON: return 'https://polygonscan.com'; case exports.Chain.SOLANA: return 'https://explorer.solana.com'; case exports.Chain.BSC: return 'https://bscscan.com'; case exports.Chain.ARBITRUM: return 'https://arbiscan.io'; case exports.Chain.OPTIMISM: return 'https://optimistic.etherscan.io'; default: throw new Error("Cannot find blockchain explorer using unknown chain: " + _chain); } } // Docs: https://www.coingecko.com/en/api/documentation var CoinGeckoNonFungible = /*#__PURE__*/function (_RestfulProvider) { _inheritsLoose(CoinGeckoNonFungible, _RestfulProvider); function CoinGeckoNonFungible(_config) { var apiHost = 'https://api.coingecko.com/api/v3/'; return _RestfulProvider.call(this, _config, apiHost) || this; } // https://api.coingecko.com/api/v3/nfts/{chain}/contract/{contract_address} var _proto = CoinGeckoNonFungible.prototype; _proto.getFloor = /*#__PURE__*/ function () { var _getFloor = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_contract) { var host, chain, uri, json, currencyInfo; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: host = this.getApiHost(); chain = this.getBlockchain(_contract.chain); uri = host + "nfts/" + chain + "/contract/" + _contract.address; _context.next = 5; return this.gotJson(uri); case 5: json = _context.sent; currencyInfo = this.getCurrencyInfoFromChain(_contract.chain); return _context.abrupt("return", numberToValue(Number(json.floor_price.native_currency), currencyInfo)); case 8: case "end": return _context.stop(); } }, _callee, this); })); function getFloor(_x) { return _getFloor.apply(this, arguments); } return getFloor; }(); _proto.getFloorChart = /*#__PURE__*/function () { var _getFloorChart = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_contract, _timeframe) { return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: throw new Error('Method not implemented.'); case 1: case "end": return _context2.stop(); } }, _callee2); })); function getFloorChart(_x2, _x3) { return _getFloorChart.apply(this, arguments); } return getFloorChart; }(); _proto.getHistoricSales = /*#__PURE__*/function () { var _getHistoricSales = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_contract) { return _regeneratorRuntime().wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: throw new Error('Method not implemented.'); case 1: case "end": return _context3.stop(); } }, _callee3); })); function getHistoricSales(_x4) { return _getHistoricSales.apply(this, arguments); } return getHistoricSales; }(); _proto.getMarketCap = /*#__PURE__*/function () { var _getMarketCap = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(_contract) { return _regeneratorRuntime().wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: throw new Error('Method not implemented.'); case 1: case "end": return _context4.stop(); } }, _callee4); })); function getMarketCap(_x5) { return _getMarketCap.apply(this, arguments); } return getMarketCap; }() // /nfts/{asset_platform_id}/contract/{contract_address} ; _proto.getMetadata = /*#__PURE__*/ function () { var _getMetadata = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(_contract) { var host, chain, uri, json, currencyInfo, metadata; return _regeneratorRuntime().wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: host = this.getApiHost(); chain = this.getBlockchain(_contract.chain); uri = host + "nfts/" + chain + "/contract/" + _contract.address; _context5.next = 5; return this.gotJson(uri); case 5: json = _context5.sent; currencyInfo = this.getCurrencyInfoFromChain(_contract.chain); metadata = { contract: _contract, symbol: json.symbol, name: json.name, description: json.description, collectionSize: Number(json.total_supply), ownerCount: Number(json.number_of_unique_addresses), images: { thumbnail: json.image.small }, urls: { explorer: chainToBlockchainExplorerHost(_contract.chain) + "/address/" + _contract.address, website: json.links.homepage, discord: json.links.discord, twitter: json.links.twitter }, stats: { currencyInfo: currencyInfo, floor: { h24: numberToValue(Number(json.floor_price.native_currency), currencyInfo).amount, h24Change: numberToValue(Number(json.floor_price_24h_percentage_change.native_currency), currencyInfo).amount.decimal }, volume: { h24: numberToValue(Number(json.volume_24h.native_currency), currencyInfo).amount, h24Change: numberToValue(Number(json.volume_24h_percentage_change.native_currency), currencyInfo).amount.decimal } } }; return _context5.abrupt("return", metadata); case 9: case "end": return _context5.stop(); } }, _callee5, this); })); function getMetadata(_x6) { return _getMetadata.apply(this, arguments); } return getMetadata; }(); _proto.getBlockchain = function getBlockchain(_chain) { switch (_chain) { case undefined: case exports.Chain.ETHEREUM: return 'ethereum'; case exports.Chain.BSC: return 'binance-smart-chain'; case exports.Chain.POLYGON: return 'polygon-pos'; case exports.Chain.ARBITRUM: return 'arbitrum-one'; case exports.Chain.SOLANA: throw new Error('Solana is supported by CoinGecko, but not yet implemented.'); // return 'solana'; case exports.Chain.OPTIMISM: return 'optimistic-ethereum'; case exports.Chain.AVALANCHE: return 'avalanche'; case exports.Chain.KLAYTN: return 'klay-token'; default: throw new Error(_chain + " is not supported by " + this.getName() + "."); } }; _proto.getName = function getName() { return 'CoinGecko'; }; return CoinGeckoNonFungible; }(RestfulProvider); function ticksToIOCHLV(_ticks) { if (_ticks.length === 0) { throw new Error('No ticks provided.'); } // Sort ticks by time in ascending order _ticks.sort(function (a, b) { return a[0] - b[0]; }); // Assume the first price as previous close for the first tick var previousClose = _ticks[0][1]; return _ticks.map(function (_ref) { var time = _ref[0], price = _ref[1]; var open = previousClose; var close = price; var high = Math.max(open, close); var low = Math.min(open, close); var ohlcv = { time: time, open: open, high: high, low: low, close: close, volume: 0 }; // Update previousClose for the next tick previousClose = close; return ohlcv; }); } // Docs: https://www.coingecko.com/en/api/documentation // Pro Docs: https://apiguide.coingecko.com/exclusive-endpoints/for-paid-plan-subscribers var CoinGeckoProNonFungible = /*#__PURE__*/function (_RestfulProvider) { _inheritsLoose(CoinGeckoProNonFungible, _RestfulProvider); function CoinGeckoProNonFungible(_config) { var apiHost = 'https://pro-api.coingecko.com/api/v3/'; return _RestfulProvider.call(this, _config, apiHost) || this; } // {host}/nfts/{asset_platform_id}/contract/{contract_address}/market_chart var _proto = CoinGeckoProNonFungible.prototype; _proto.getFloorChart = /*#__PURE__*/ function () { var _getFloorChart = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_contract, _timeframe) { var _this$_getTimeParams, _days, _newTimeframe, host, chain, uri, options, json, iochlv, baseTimeframe, currencyInfo, combinedResponse; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: _this$_getTimeParams = this._getTimeParams(_timeframe), _days = _this$_getTimeParams[0], _newTimeframe = _this$_getTimeParams[1]; host = this.getApiHost(); chain = this.getBlockchain(_contract.chain); uri = host + "nfts/" + chain + "/contract/" + _contract.address + "/market_chart"; options = { searchParams: { days: _days }, headers: { Accept: 'application/json', 'x-cg-pro-api-key': this.getApiKey() } }; // Get the ticks and convert them to candles _context.next = 7; return this.gotJson(uri, options); case 7: json = _context.sent; iochlv = ticksToIOCHLV(json.floor_price_native); // 5 minutes is the default timeframe for <=14 days of data baseTimeframe = 60 * 5; if (_days === 'max') { // 1d is the default timeframe for >14 days of data // We have 1d volume to match to 1d candles iochlv = this._injectVolumeIntoIOCHLV(iochlv, json.h24_volume_native); // add volume to 1d candles baseTimeframe = 60 * 60 * 24; } // Convert the candles to the requested timeframe iochlv = candlestickConvert.batchCandleJSON(iochlv, baseTimeframe, _newTimeframe); currencyInfo = this.getCurrencyInfoFromChain(_contract.chain); combinedResponse = { currencyInfo: currencyInfo, iochlv: iochlv }; return _context.abrupt("return", combinedResponse); case 15: case "end": return _context.stop(); } }, _callee, this); })); function getFloorChart(_x, _x2) { return _getFloorChart.apply(this, arguments); } return getFloorChart; }(); _proto._getTimeParams = function _getTimeParams(_timeframe) { switch (_timeframe) { case exports.Timeframe.FIVE_MIN: return [14, 60 * 5]; case exports.Timeframe.FIFTEEN_MIN: return [14, 60 * 15]; case exports.Timeframe.THIRTY_MIN: return [14, 60 * 15]; case exports.Timeframe.ONE_HOUR: return [14, 60 * 60]; case undefined: case exports.Timeframe.ONE_DAY: return ["max", 60 * 60 * 24]; case exports.Timeframe.ONE_WEEK: return ["max", 60 * 60 * 24 * 7]; default: throw new Error('Invalid timeframe.'); } }; _proto._injectVolumeIntoIOCHLV = function _injectVolumeIntoIOCHLV(_iochlv, _volume) { // Create a volume map for quick lookup var volumeMap = new Map(_volume.map(function (_ref) { var time = _ref[0], volume = _ref[1]; return [time, volume]; })); // Add volume to the matching IOHLCV data return _iochlv.map(function (ohlcv) { var volume = volumeMap.get(ohlcv.time) || 0; return _extends({}, ohlcv, { volume: volume }); }); } // {host}/nfts/{chain}/contract/{contract_address} ; _proto.getFloor = /*#__PURE__*/ function () { var _getFloor = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_contract) { var host, chain, uri, options, json, currencyInfo; return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: host = this.getApiHost(); chain = this.getBlockchain(_contract.chain); uri = host + "nfts/" + chain + "/contract/" + _contract.address; options = { headers: { Accept: 'application/json', 'x-cg-pro-api-key': this.getApiKey() } }; _context2.next = 6; return this.gotJson(uri, options); case 6: json = _context2.sent; currencyInfo = this.getCurrencyInfoFromChain(_contract.chain); return _context2.abrupt("return", numberToValue(Number(json.floor_price.native_currency), currencyInfo)); case 9: case "end": return _context2.stop(); } }, _callee2, this); })); function getFloor(_x3) { return _getFloor.apply(this, arguments); } return getFloor; }(); _proto.getHistoricSales = /*#__PURE__*/function () { var _getHistoricSales = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_contract) { return _regeneratorRuntime().wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: throw new Error('Method not implemented.'); case 1: case "end": return _context3.stop(); } }, _callee3); })); function getHistoricSales(_x4) { return _getHistoricSales.apply(this, arguments); } return getHistoricSales; }(); _proto.getMarketCap = /*#__PURE__*/function () { var _getMarketCap = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(_contract) { return _regeneratorRuntime().wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: throw new Error('Method not implemented.'); case 1: case "end": return _context4.stop(); } }, _callee4); })); function getMarketCap(_x5) { return _getMarketCap.apply(this, arguments); } return getMarketCap; }() // /nfts/{asset_platform_id}/contract/{contract_address} ; _proto.getMetadata = /*#__PURE__*/ function () { var _getMetadata = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(_contract) { var host, chain, uri, options, json, currencyInfo, metadata; return _regeneratorRuntime().wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: host = this.getApiHost(); chain = this.getBlockchain(_contract.chain); uri = host + "nfts/" + chain + "/contract/" + _contract.address; options = { headers: { Accept: 'application/json', 'x-cg-pro-api-key': this.getApiKey() } }; _context5.next = 6; return this.gotJson(uri, options); case 6: json = _context5.sent; currencyInfo = this.getCurrencyInfoFromChain(_contract.chain); metadata = { contract: _contract, symbol: json.symbol, name: json.name, description: json.description, collectionSize: Number(json.total_supply), ownerCount: Number(json.number_of_unique_addresses), images: { thumbnail: json.image.small }, urls: { explorer: chainToBlockchainExplorerHost(_contract.chain) + "/address/" + _contract.address, website: json.links.homepage, discord: json.links.discord, twitter: json.links.twitter }, stats: { currencyInfo: currencyInfo, floor: { h24: numberToValue(Number(json.floor_price.native_currency), currencyInfo).amount,