diff --git a/dist/api/Address.js b/dist/api/Address.js index 8e2a3016..2b64aab9 100644 --- a/dist/api/Address.js +++ b/dist/api/Address.js @@ -34,6 +34,10 @@ class Address extends _DataCollector.DataCollectorItem { type: _types.addrTypes.CONTRACT, contractInterfaces: { $in: _types.tokensInterfaces } }, params); + }, + + getCirculatingSupply: params => { + return this.parent.getCirculatingSupply(); } }; }}exports.Address = Address;exports.default = diff --git a/dist/api/Blocks.js b/dist/api/Blocks.js index 8f8802f2..efc71fa8 100644 --- a/dist/api/Blocks.js +++ b/dist/api/Blocks.js @@ -6,9 +6,12 @@ var _Tx = require('./Tx'); var _Address = require('./Address'); var _Event = require('./Event'); var _TokenAccount = require('./TokenAccount'); -var _TxPending = require('./TxPending');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} +var _TxPending = require('./TxPending'); +var _getCirculatingSupply = require('./getCirculatingSupply');var _getCirculatingSupply2 = _interopRequireDefault(_getCirculatingSupply);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} + const lastLimit = _config2.default.api.lastBlocks || 10; const collections = _config2.default.blocks.collections; + class Blocks extends _DataCollector.DataCollector { constructor(db) { let collectionName = collections.Blocks; @@ -17,6 +20,7 @@ class Blocks extends _DataCollector.DataCollector { this.latest = 0; this.lastBlocks = []; this.lastTransactions = []; + this.circulatingSupply = null; this.addItem(collections.Blocks, 'Block', _Block.Block); this.addItem(collections.PendingTxs, 'TxPending', _TxPending.TxPending); this.addItem(collections.Txs, 'Tx', _Tx.Tx); @@ -26,31 +30,39 @@ class Blocks extends _DataCollector.DataCollector { } tick() { this.setLastBlocks(); + this.setCirculatingSupply(); } run(module, action, params) { return this.itemPublicAction(module, action, params); } - setLastBlocks() { - this.collection. - find(). - sort({ number: -1 }). - limit(this.lastLimit). - toArray((err, blocks) => { - if (err) console.log(err);else - { - this.Tx.db. - find({ txType: { $in: [_types.txTypes.default, _types.txTypes.contract] } }). - sort({ blockNumber: -1, transactionIndex: -1 }). - limit(this.lastLimit). - toArray((err, txs) => { - if (err) console.log(err);else - { - this.updateLastBlocks(blocks, txs); - } - }); - } - }); + + async setLastBlocks() { + try { + let { collection, lastLimit, Tx } = this; + let blocks = await collection.find().sort({ number: -1 }).limit(lastLimit).toArray(); + let txs = await Tx.db.find({ txType: { $in: [_types.txTypes.default, _types.txTypes.contract] } }). + sort({ blockNumber: -1, transactionIndex: -1 }). + limit(this.lastLimit). + toArray(); + + this.updateLastBlocks(blocks, txs); + } catch (err) { + console.log(err); + } + } + + async setCirculatingSupply() { + try { + const collection = this.db.collection(collections.Addrs); + let circulating = await (0, _getCirculatingSupply2.default)(collection); + this.circulatingSupply = Object.assign({}, circulating); + } catch (err) { + console.log(err); + } + } + getCirculatingSupply() { + return this.formatData(this.circulatingSupply); } getLastBlocks() { @@ -58,9 +70,11 @@ class Blocks extends _DataCollector.DataCollector { let transactions = this.lastTransactions; return this.formatData({ blocks, transactions }); } + getLastBlock() { return this.lastBlocks[0] || null; } + updateLastBlocks(blocks, transactions) { this.lastBlocks = blocks; this.lastTransactions = transactions; @@ -71,6 +85,7 @@ class Blocks extends _DataCollector.DataCollector { this.events.emit('newBlocks', this.formatData({ blocks, transactions })); } } + async getAddress(address) { return this.Address.run('getAddress', { address }); } diff --git a/dist/api/HttpServer.js b/dist/api/HttpServer.js new file mode 100644 index 00000000..df6e16a3 --- /dev/null +++ b/dist/api/HttpServer.js @@ -0,0 +1,25 @@ +'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.HttpServer = undefined;var _http = require('http');var _http2 = _interopRequireDefault(_http); +var _express = require('express');var _express2 = _interopRequireDefault(_express);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} + +const HttpServer = exports.HttpServer = ({ blocks, status }) => { + const app = (0, _express2.default)(); + const httpServer = _http2.default.Server(app); + app.set('etag', false); + app.set('x-powered-by', false); + + app.use('/status', (req, res) => { + const data = status.getState().data; + res.send(data); + }); + + app.use('/circulating', (req, res) => { + const data = blocks.getCirculatingSupply().data; + res.send(data); + }); + + // 404 + app.use((req, res, next) => res.status(404).send()); + return httpServer; +};exports.default = + +HttpServer; \ No newline at end of file diff --git a/dist/api/TokenAccount.js b/dist/api/TokenAccount.js index 69ed582e..dbbe69c3 100644 --- a/dist/api/TokenAccount.js +++ b/dist/api/TokenAccount.js @@ -41,21 +41,35 @@ class TokenAccount extends _DataCollector.DataCollectorItem { }, getTokenBalance: async params => { - const { contract } = params; + const { contract, addresses } = params; + if (!contract) return; + + let query = {}; + + if (addresses) query = this.fieldFilterParse('address', addresses); + let contractData = await this.parent.getAddress(contract); + contractData = contractData.data; if (!contractData) return; - let { totalSupply } = contractData; + + let { totalSupply, decimals } = contractData; if (!totalSupply) return; - let accounts = await this.find({ contract }); + + query.contract = contract; + let accounts = await this.find(query, null, null, { _id: 0, address: 1, balance: 1 }); if (accounts) accounts = accounts.data; if (!accounts) return; let accountsBalance = (0, _utils.bigNumberSum)(accounts.map(account => account.balance)); totalSupply = new _bignumber.BigNumber(totalSupply); let balance = accountsBalance ? totalSupply.minus(accountsBalance) : totalSupply; + let data = { balance, accountsBalance, totalSupply, decimals + + // send accounts + };if (addresses) data.accounts = accounts; - const data = this.serialize({ balance, accountsBalance, totalSupply }); + data = this.serialize(data); return { data }; } }; diff --git a/dist/api/UserEventsApi.js b/dist/api/UserEventsApi.js index 6f616d0c..76fd5d23 100644 --- a/dist/api/UserEventsApi.js +++ b/dist/api/UserEventsApi.js @@ -4,7 +4,7 @@ var _config = require('../lib/config');var _config2 = _interopRequireDefault(_co var _apiLib = require('./apiLib');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} function UserEventsSocket() { - return (0, _child_process.fork)(_path2.default.resolve(__dirname, '../services/userEvents.js')); + return (0, _child_process.fork)(_path2.default.resolve(__dirname, '../services/userEvents/userEventsService.js')); } const UserEventsApi = exports.UserEventsApi = (io, Blocks, log) => { diff --git a/dist/api/getCirculatingSupply.js b/dist/api/getCirculatingSupply.js new file mode 100644 index 00000000..c17dd50c --- /dev/null +++ b/dist/api/getCirculatingSupply.js @@ -0,0 +1,16 @@ +'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _config = require('../lib/config');var _config2 = _interopRequireDefault(_config); +var _types = require('../lib/types'); +var _utils = require('../lib/utils');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} +const { bridgeAddress } = _config2.default;exports.default = + +async function (collection) { + try { + let { balance, decimals } = await collection.findOne({ address: bridgeAddress }); + decimals = decimals || 18; + const bridgeBalance = (0, _utils.applyDecimals)(balance, decimals).toString(10); + let circulatingSupply = (0, _utils.bigNumberDifference)(_types.TOTAL_SUPPLY, bridgeBalance).toString(10); + return { circulatingSupply, totalSupply: _types.TOTAL_SUPPLY, bridgeBalance }; + } catch (err) { + return Promise.reject(err); + } +}; \ No newline at end of file diff --git a/dist/api/index.js b/dist/api/index.js index e73d4bdf..9d2760e9 100644 --- a/dist/api/index.js +++ b/dist/api/index.js @@ -4,9 +4,10 @@ var _Blocks = require('./Blocks');var _Blocks2 = _interopRequireDefault(_Blocks) var _Status = require('./Status');var _Status2 = _interopRequireDefault(_Status); var _TxPool = require('./TxPool');var _TxPool2 = _interopRequireDefault(_TxPool); var _Logger = require('../lib/Logger');var _Logger2 = _interopRequireDefault(_Logger); -var _http = require('http');var _http2 = _interopRequireDefault(_http); var _UserEventsApi = require('./UserEventsApi');var _UserEventsApi2 = _interopRequireDefault(_UserEventsApi); var _config = require('../lib/config');var _config2 = _interopRequireDefault(_config); +var _HttpServer = require('./HttpServer'); + var _apiLib = require('./apiLib');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} @@ -32,16 +33,8 @@ _dataSource2.default.then(db => { status.start(); txPool.start(); - const httpServer = _http2.default.createServer((req, res) => { - const url = req.url || null; - if (url && url === '/status') { - res.writeHead(200, { 'Content-type': 'application/json' }); - res.write(JSON.stringify(status.state)); - } else { - res.writeHead(404, 'Not Found'); - } - res.end(); - }); + // http server + const httpServer = (0, _HttpServer.HttpServer)({ blocks, status }); httpServer.listen(port, address); const io = new _socket2.default(httpServer); diff --git a/dist/lib/DataCollector/DataCollectorItem.js b/dist/lib/DataCollector/DataCollectorItem.js index bb1d9fa2..c0b4f108 100644 --- a/dist/lib/DataCollector/DataCollectorItem.js +++ b/dist/lib/DataCollector/DataCollectorItem.js @@ -156,7 +156,8 @@ filterSort = filterSort;exports. fieldFilterParse = fieldFilterParse;var _mongodb = require('mongodb');var _pagination = require('./pagination');var _types = require('../../lib/types');class DataCollectorItem {constructor(collection, key, parent, { cursorField = '_id', sortDir = -1, sortable = { _id: -1 } } = {}) {if (!(collection instanceof _mongodb.Collection)) {throw new Error('Collection is not mongodb Collection');}this.db = collection;this.key = key;this.parent = parent;this.fieldsTypes = null;this.cursorField = cursorField;this.cursorData = null;this.sortDir = sortDir;sortable[cursorField] = sortDir;this.sortableFields = sortable;this.sort = { [cursorField]: sortDir };this.publicActions = {};this.fields = {};}getDefaultsFields() {return Object.assign({}, this.fields);}async run(action, params) {try {const f = this.publicActions[action];if (f && typeof f === 'function') return f(params);else throw new Error(`Unknown action: ${action}`);} catch (err) {return Promise.reject(err);}}async find(query, sort, limit, project) {let collection = this.db;project = project || this.getDefaultsFields();let data = await (0, _pagination.find)(collection, query, sort, limit, project);return { data };}async getOne(query, project) {project = project || this.getDefaultsFields();let data = await this.db.findOne(query, { project });return { data };}async setFieldsTypes() {let types = await getFieldsTypes(this.db);this.fieldsTypes = types;return types;}async getFieldsTypes() {let types = this.fieldsTypes;return types || this.setFieldsTypes();}responseParams(params) {let sort = params.sort || this.sort || {};let sortable = this.sortableFields;let defaultSort = this.sort;let sortDir = this.sortDir;let { limit, next, prev, fields, count, countOnly, page, getPages } = params;if (!fields) fields = this.getDefaultsFields();sort = filterSort(sort, sortable, defaultSort);return { sort, sortable, defaultSort, sortDir, limit, next, prev, fields, count, countOnly, page, getPages };}async getCursorData() {let data = this.cursorData;if (!data) data = await this.setCursorData();return data;}async setCursorData() {const cursorField = this.cursorField;const types = await this.getFieldsTypes();const cursorType = types[cursorField];this.cursorData = { cursorField, cursorType, fields: types };return this.cursorData;}getPageData(query, params) {return this.getPages({ query, params });}getAggPageData(aggregate, params) {return this.getPages({ aggregate, params });}async getPrevNext(query, project, data) {try {let { cursorField } = this;project = project || this.getDefaultsFields();if (!data) data = await this.getOne(query);if (data) data = data.data;if (!data) return;let value = query[cursorField] || data[cursorField];if (undefined === value) throw new Error(`Missing ${cursorField} value`);let prev = (await (0, _pagination.find)(this.db, { [cursorField]: { $lt: value } }, { [cursorField]: -1 }, 1, project))[0];let next = (await (0, _pagination.find)(this.db, { [cursorField]: { $gt: value } }, { [cursorField]: 1 }, 1, project))[0];return { prev, data, next };} catch (err) {return Promise.reject(err);}}async getPages({ aggregate, query, params }) {try {let pages = this.responseParams(params);let cursorData = await this.getCursorData();query = aggregate || query;let args = [this.db, cursorData, query, pages];let result = aggregate ? await (0, _pagination.aggregatePages)(...args) : await (0, _pagination.findPages)(...args);return formatResponse(result, pages);} catch (err) {return Promise.reject(err);}}fieldFilterParse(field, value, query) {return fieldFilterParse(field, value, query);}}exports.DataCollectorItem = DataCollectorItem;function formatResponse(result, pages) {if (!result) return;let { data, pagination } = result;pages = Object.assign(pages, pagination);return { pages, data };}async function getFieldsTypes(collection) {let doc = await collection.findOne();let fields = {};for (let p in doc) {let value = doc[p];let type = typeof value;type = value instanceof _mongodb.ObjectID ? _types.OBJECT_ID : type;fields[p] = type;}return fields;}function filterSort(sort, sortable, defaultSort) {let filteredSort = {}; // allow only one field to user sort if (Object.keys(sort).length > 1) return defaultSort;for (let field in sort) {if (undefined !== sortable[field]) filteredSort[field] = sort[field];}return Object.keys(filteredSort).length > 0 ? filteredSort : defaultSort;} // value: string| array of searched values | Object: 'value':true|false -function fieldFilterParse(field, value, query) {query = query || {};let fieldQuery; +function fieldFilterParse(field, value, query) {query = query || {};if (!field || !value || typeof field !== 'string') return query; + let fieldQuery; let inArr = []; let ninArr = []; if (typeof value === 'string') { diff --git a/dist/lib/collections.js b/dist/lib/collections.js index 52cc34aa..dc9ae63b 100644 --- a/dist/lib/collections.js +++ b/dist/lib/collections.js @@ -107,6 +107,14 @@ key: { blockNumber: 1 }, name: 'eventBlockNumberIndex' }, + { + key: { txHash: 1 }, + name: 'eventTxHashIndex' }, + + { + key: { blockHash: 1 }, + name: 'eventBlockHashIndex' }, + { key: { args: 1 }, name: 'eventsArgsIndex' }, diff --git a/dist/lib/types.js b/dist/lib/types.js index 7a744950..3cc8aa6f 100644 --- a/dist/lib/types.js +++ b/dist/lib/types.js @@ -1,4 +1,4 @@ -'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.OBJECT_ID = exports.BIG_NUMBER = exports.REMASC_NAME = exports.BRIDGE_NAME = exports.modules = exports.actions = exports.events = exports.tokensInterfaces = exports.contractsInterfaces = exports.addrTypes = exports.errors = exports.txTypes = undefined;var _errors = require('../lib/errors'); +'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.TOTAL_SUPPLY = exports.OBJECT_ID = exports.BIG_NUMBER = exports.REMASC_NAME = exports.BRIDGE_NAME = exports.modules = exports.actions = exports.events = exports.tokensInterfaces = exports.contractsInterfaces = exports.addrTypes = exports.errors = exports.txTypes = undefined;var _errors = require('../lib/errors'); const txTypes = exports.txTypes = { default: 'normal', @@ -68,6 +68,8 @@ const REMASC_NAME = exports.REMASC_NAME = 'remasc (native)'; const BIG_NUMBER = exports.BIG_NUMBER = 'BigNumber'; -const OBJECT_ID = exports.OBJECT_ID = 'ObjectID';exports.default = +const OBJECT_ID = exports.OBJECT_ID = 'ObjectID'; + +const TOTAL_SUPPLY = exports.TOTAL_SUPPLY = 21 * 10 ** 6;exports.default = { txTypes, errors, addrTypes, contractsInterfaces }; \ No newline at end of file diff --git a/dist/lib/utils.js b/dist/lib/utils.js index 4d03b151..4f9e8343 100644 --- a/dist/lib/utils.js +++ b/dist/lib/utils.js @@ -1,4 +1,4 @@ -'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.jsonDecode = exports.jsonEncode = exports.keccak256 = exports.base64toHex = exports.btoa = exports.atob = exports.includesAll = exports.hasValue = exports.arraySymmetricDifference = exports.arrayDifference = exports.arrayIntersection = exports.getBestBlock = exports.blockQuery = exports.isBlockHash = exports.checkBlockHash = exports.serialize = exports.bigNumberSum = exports.bigNumberToSring = exports.unSerializeBigNumber = exports.isSerializedBigNumber = exports.serializeBigNumber = exports.isBigNumber = exports.bigNumberDoc = exports.isValidAddress = exports.isAddress = exports.remove0x = exports.add0x = exports.isHexString = undefined;var _bignumber = require('bignumber.js'); +'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.jsonDecode = exports.jsonEncode = exports.keccak256 = exports.applyDecimals = exports.base64toHex = exports.btoa = exports.atob = exports.includesAll = exports.hasValue = exports.arraySymmetricDifference = exports.arrayDifference = exports.arrayIntersection = exports.getBestBlock = exports.blockQuery = exports.isBlockHash = exports.checkBlockHash = exports.serialize = exports.newBigNumber = exports.bigNumberDifference = exports.bigNumberSum = exports.bigNumberToSring = exports.unSerializeBigNumber = exports.isSerializedBigNumber = exports.serializeBigNumber = exports.isBigNumber = exports.bigNumberDoc = exports.isValidAddress = exports.isAddress = exports.remove0x = exports.add0x = exports.isHexString = undefined;var _bignumber = require('bignumber.js'); var _types = require('./types'); var _mongodb = require('mongodb'); var _keccak = require('keccak');var _keccak2 = _interopRequireDefault(_keccak);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} @@ -70,12 +70,20 @@ const bigNumberSum = exports.bigNumberSum = values => { let total = new _bignumber.BigNumber(0); values. forEach(value => { - value = isBigNumber(value) ? value : new _bignumber.BigNumber(value); + value = newBigNumber(value); total = total.plus(value); }); return total; }; +const bigNumberDifference = exports.bigNumberDifference = (a, b) => { + a = newBigNumber(a); + b = newBigNumber(b); + return a.minus(b); +}; + +const newBigNumber = exports.newBigNumber = value => isBigNumber(value) ? value : new _bignumber.BigNumber(value); + const isObj = value => { if (undefined === value || value === null) return false; let is = typeof value === 'object'; @@ -157,6 +165,13 @@ const base64toHex = exports.base64toHex = base64 => { }).join('').toLowerCase(); }; +const applyDecimals = exports.applyDecimals = (value, decimals = 18) => { + value = newBigNumber(value); + const divisor = new _bignumber.BigNumber(10).exponentiatedBy(parseInt(decimals)); + const result = value.dividedBy(divisor); + return result; +}; + const keccak256 = exports.keccak256 = (input, format = 'hex') => (0, _keccak2.default)('keccak256').update(input).digest(format); const jsonEncode = exports.jsonEncode = value => btoa(JSON.stringify(value)); diff --git a/dist/services/blocks/index.js b/dist/services/blocks/index.js index c98791bc..6af31458 100644 --- a/dist/services/blocks/index.js +++ b/dist/services/blocks/index.js @@ -46,9 +46,11 @@ _dataSource.dataBase.db().then(db => { } }; + /* eslint-disable-next-line no-unused-vars */ const Listener = startService('Listener', listenToMessage); const Checker = startService('Checker', listenToMessage); const Requester = startService('Requester', listenToMessage); + /* eslint-disable-next-line no-unused-vars */ const TxPool = startService('TxPool', listenToMessage, '../txPool.js'); }); }); diff --git a/dist/services/classes/Block.js b/dist/services/classes/Block.js index 5dd80010..e221d3f0 100644 --- a/dist/services/classes/Block.js +++ b/dist/services/classes/Block.js @@ -83,8 +83,7 @@ class Block extends _BcThing.BcThing { try { if (!data) throw new Error(`Fetch returns empty data for block #${this.hashOrNumber}`); data = this.serialize(data); - let block, txs, events, tokenAddresses; - ({ block, txs, events, tokenAddresses } = data); + let { block, txs, events, tokenAddresses } = data; // check transactions let txsErr = missmatchBlockTransactions(block, txs); @@ -179,7 +178,7 @@ class Block extends _BcThing.BcThing { block._replacedBy = newBlock.hash; block._events = events; block.transactions = txs; - await this.saveOrphanBlock(block); + await this.saveOrphanBlock(block).catch(err => this.log.debug(err)); await this.deleteBlockDataFromDb(block.hash, block.number); newBlock._replacedBlockHash = block.hash; return newBlock; @@ -368,17 +367,24 @@ const deleteBlockDataFromDb = exports.deleteBlockDataFromDb = async (blockHash, let hash = blockHash; let result = {}; let query = { $or: [{ blockHash }, { blockNumber }] }; - result.block = await db.Blocks.deleteOne({ hash }); - result.block = await db.Blocks.deleteOne({ number: blockNumber }); + + result.block = await db.Blocks.deleteMany({ $or: [{ hash }, { number: blockNumber }] }); let txs = (await db.Txs.find(query).toArray()) || []; - result.txs = await db.Txs.deleteMany(query); + let txsHashes = txs.map(tx => tx.hash); + + // remove txs + result.txs = await db.Txs.deleteMany({ hash: { $in: txsHashes } }); + // remove events by block result.events = await db.Events.deleteMany(query); - // remove event by tx - result.eventsByTxs = await Promise.all([...txs.map(tx => db.Events.deleteMany({ txHash: tx.hash }))]); - result.addresses = await db.Addrs.deleteMany( - { $or: [{ 'createdByTx.blockNumber': blockNumber }, { 'createdByTx.blockHash': blockHash }] }); + + // remove events by txs + result.eventsByTxs = await db.Events.deleteMany({ txHash: { $in: txsHashes } }); + + // remove contracts by blockHash + result.addresses = await db.Addrs.deleteMany({ 'createdByTx.blockHash': blockHash }); + return result; } catch (err) { return Promise.reject(err); diff --git a/dist/services/userEvents.js b/dist/services/userEvents.js deleted file mode 100644 index e3433e27..00000000 --- a/dist/services/userEvents.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict';var _dataSource = require('../lib/dataSource.js');var _dataSource2 = _interopRequireDefault(_dataSource); -var _blocksCollections = require('../lib/blocksCollections'); -var _config = require('../lib/config');var _config2 = _interopRequireDefault(_config); -var _nod3Connect = require('../lib/nod3Connect');var _nod3Connect2 = _interopRequireDefault(_nod3Connect); -var _Address = require('./classes/Address');var _Address2 = _interopRequireDefault(_Address); -var _Logger = require('../lib/Logger');var _Logger2 = _interopRequireDefault(_Logger); -var _types = require('../lib/types'); -var _utils = require('../lib/utils');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} - -const config = Object.assign({}, _config2.default.blocks); -const log = (0, _Logger2.default)('UserRequests', config.log); - -_dataSource2.default.then(db => { - const collections = (0, _blocksCollections.getDbBlocksCollections)(db); - const cache = new RequestCache(); - process.on('message', msg => { - let { action, params, block } = msg; - if (action && params && block) { - switch (action) { - case 'updateAddress': - updateAddress({ collections, cache, msg }, params); - break;} - - } - }); -}); - -const updateAddress = async ({ collections, cache, msg }, { address }) => { - try { - const { block, action, module } = msg; - const cached = cache.isRequested(block, [module, action, address]); - if (cached) { - msg.data = cached; - sendMessage(msg); - } else { - const Addr = new _Address2.default(address, { nod3: _nod3Connect2.default, collections }); - let result = await Addr.fetch(). - catch(err => { - log.error(err); - msg.error = _types.errors.TEMPORARILY_UNAVAILABLE; - sendMessage(msg); - }); - msg.result = result; - cache.set(block, [module, action, address], result); - const newBalance = result.balance ? result.balance.toString() : 0; - const dbData = Addr.dbData || {}; - const { balance, txBalance } = dbData; - if (newBalance > 0 || balance) { - if (!parseInt(txBalance)) await Addr.updateTxBalance(); - - await Addr.save().catch(err => { - log.error(`Error saving address ${address}, ${err}`); - sendMessage(msg); - }); - sendMessage(msg); - } else { - msg.data = result; - sendMessage(msg); - } - } - } catch (err) { - log.debug(err); - msg.error = err; - sendMessage(msg); - } -}; - -const sendMessage = msg => { - process.send((0, _utils.serialize)(msg)); -}; - -class RequestCache { - constructor() { - this.requested = {}; - this.block = null; - } - set(block, keys, value) { - this.setBlock(block); - this.requested[this.makeKey(keys)] = value; - } - isRequested(block, keys) { - this.setBlock(block); - return this.requested[this.makeKey(keys)]; - } - setBlock(block) { - if (block !== this.block) { - this.block = block; - this.requested = {}; - } - } - makeKey(args) { - return args.join('-'); - }} \ No newline at end of file diff --git a/dist/services/userEvents/RequestCache.js b/dist/services/userEvents/RequestCache.js new file mode 100644 index 00000000..b76565a5 --- /dev/null +++ b/dist/services/userEvents/RequestCache.js @@ -0,0 +1,25 @@ +'use strict';Object.defineProperty(exports, "__esModule", { value: true });class RequestCache { + constructor() { + this.requested = {}; + this.block = null; + } + set(block, keys, value) { + this.setBlock(block); + this.requested[this.makeKey(keys)] = value; + } + isRequested(block, keys) { + this.setBlock(block); + return this.requested[this.makeKey(keys)]; + } + setBlock(block) { + if (block !== this.block) { + this.block = block; + this.requested = {}; + } + } + makeKey(args) { + return args.join('-'); + }}exports.RequestCache = RequestCache;exports.default = + + +RequestCache; \ No newline at end of file diff --git a/dist/services/userEvents/updateAddress.js b/dist/services/userEvents/updateAddress.js new file mode 100644 index 00000000..d0a26a6d --- /dev/null +++ b/dist/services/userEvents/updateAddress.js @@ -0,0 +1,47 @@ +'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.updateAddress = undefined;var _types = require('../../lib/types'); +var _nod3Connect = require('../../lib/nod3Connect');var _nod3Connect2 = _interopRequireDefault(_nod3Connect); +var _Address = require('../classes/Address');var _Address2 = _interopRequireDefault(_Address);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} + +const updateAddress = exports.updateAddress = async ({ collections, cache, msg, log }, { address }) => { + try { + log = log || console; + msg = msg || {}; + const { block, action, module } = msg; + const cached = cache ? cache.isRequested(block, [module, action, address]) : null; + if (cached) { + msg.data = cached; + return msg; + } else { + const Addr = new _Address2.default(address, { nod3: _nod3Connect2.default, collections }); + let result = await Addr.fetch(). + catch(err => { + log.error(err); + msg.error = _types.errors.TEMPORARILY_UNAVAILABLE; + return msg; + }); + msg.result = result; + cache.set(block, [module, action, address], result); + const newBalance = result.balance ? result.balance.toString() : 0; + const dbData = Addr.dbData || {}; + const { balance, txBalance } = dbData; + if (newBalance > 0 || balance) { + if (!parseInt(txBalance)) await Addr.updateTxBalance(); + + await Addr.save().catch(err => { + log.error(`Error saving address ${address}, ${err}`); + return msg; + }); + return msg; + } else { + msg.data = result; + return msg; + } + } + } catch (err) { + log.debug(err); + msg.error = err; + return msg; + } +};exports.default = + +updateAddress; \ No newline at end of file diff --git a/dist/services/userEvents/userEventsService.js b/dist/services/userEvents/userEventsService.js new file mode 100644 index 00000000..1eb74559 --- /dev/null +++ b/dist/services/userEvents/userEventsService.js @@ -0,0 +1,33 @@ +'use strict';var _dataSource = require('../../lib/dataSource.js');var _dataSource2 = _interopRequireDefault(_dataSource); +var _blocksCollections = require('../../lib/blocksCollections'); +var _config = require('../../lib/config');var _config2 = _interopRequireDefault(_config); + +var _Logger = require('../../lib/Logger');var _Logger2 = _interopRequireDefault(_Logger); + +var _utils = require('../../lib/utils'); +var _RequestCache = require('./RequestCache'); +var _updateAddress = require('./updateAddress');var _updateAddress2 = _interopRequireDefault(_updateAddress);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} + +const config = Object.assign({}, _config2.default.blocks); +const log = (0, _Logger2.default)('UserRequests', config.log); + +_dataSource2.default.then(db => { + const collections = (0, _blocksCollections.getDbBlocksCollections)(db); + const cache = new _RequestCache.RequestCache(); + process.on('message', async msg => { + let { action, params, block } = msg; + + if (action && params && block) { + switch (action) { + case 'updateAddress': + msg = await (0, _updateAddress2.default)({ collections, cache, msg, log }, params); + sendMessage(msg); + break;} + + } + }); +}); + +const sendMessage = msg => { + process.send((0, _utils.serialize)(msg)); +}; \ No newline at end of file diff --git a/dist/tools/deleteBlocks.js b/dist/tools/deleteBlocks.js index e4b11a62..8e01ee97 100644 --- a/dist/tools/deleteBlocks.js +++ b/dist/tools/deleteBlocks.js @@ -7,18 +7,23 @@ _dataSource2.default.then(async db => { const options = new _BlocksBase.BlocksBase(db); const p = path => path.split('/').pop(); const help = () => { - (0, _cli.info)(`Use: ${p(process.argv[0])} ${p(process.argv[1])} [fromBlock-toBlock] ${_cli.orange} e.g. 400-6756`); + const myName = p(process.argv[1]); + (0, _cli.info)(`Use: ${p(process.argv[0])} ${myName} [blockNumber] | [fromBlock-toBlock]`); + (0, _cli.info)(`e.g. ${_cli.orange} ${myName} 400`); + (0, _cli.info)(`e.g. ${_cli.orange} ${myName} 400-456`); process.exit(0); }; let fromTo = process.argv[2]; if (!fromTo) help(); fromTo = fromTo.split('-'); - let f = fromTo[0]; - let t = fromTo[1]; + let [f, t] = fromTo; - if (!f && !t) help(); + if (!f) help(); + if (!t) t = f; + if (isNaN(f) || isNaN(t)) help(); if (f > t) help(); + try { let Q = []; while (t >= f) { diff --git a/dist/tools/getBlock.js b/dist/tools/getBlock.js index 175cfd0d..757c38ec 100644 --- a/dist/tools/getBlock.js +++ b/dist/tools/getBlock.js @@ -4,7 +4,7 @@ var _BlocksBase = require('../lib/BlocksBase');var _BlocksBase2 = _interopRequir var _cli = require('../lib/cli'); var _util = require('util');var _util2 = _interopRequireDefault(_util);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} -const hashOrNumber = process.argv[2] || 'latest'; +const hashOrNumber = process.argv[2]; const opt = process.argv[3]; const save = opt === '--save'; const json = opt === '--json'; @@ -46,7 +46,8 @@ async function getBlock(db, hashOrNumber) { } function help() { - (0, _cli.info)(`Usage: ${process.argv[1]} ${process.argv[1]} number|hash|latest [--json | --save ]`); + const myName = process.argv[1].split('/').pop(); + (0, _cli.info)(`Usage: ${process.argv[0]} ${myName} number|hash|latest [--json | --save ]`); process.exit(0); } diff --git a/dist/tools/getDbContracts.js b/dist/tools/getDbContracts.js index 594c9b75..2574bbca 100644 --- a/dist/tools/getDbContracts.js +++ b/dist/tools/getDbContracts.js @@ -1,6 +1,5 @@ 'use strict';var _dataSource = require('../lib/dataSource.js');var _dataSource2 = _interopRequireDefault(_dataSource);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} - _dataSource2.default.then(db => { let addresses = db.collection('addresses'); addresses.find({ type: 'contract' }). diff --git a/dist/tools/updateContractAccounts.js b/dist/tools/updateContractAccounts.js new file mode 100644 index 00000000..b23fc313 --- /dev/null +++ b/dist/tools/updateContractAccounts.js @@ -0,0 +1,57 @@ +'use strict';var _Contract = require('../services/classes/Contract');var _Contract2 = _interopRequireDefault(_Contract); +var _nod3Connect = require('../lib/nod3Connect');var _nod3Connect2 = _interopRequireDefault(_nod3Connect); +var _bignumber = require('bignumber.js');var _bignumber2 = _interopRequireDefault(_bignumber); +var _utils = require('../lib/utils'); +var _dataSource = require('../lib/dataSource');var _dataSource2 = _interopRequireDefault(_dataSource); +var _cli = require('../lib/cli');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} + +const contractAddress = process.argv[2]; +if (!(0, _utils.isAddress)(contractAddress)) help(); + +const contract = new _Contract2.default(contractAddress, null, _nod3Connect2.default); + +_dataSource2.default.then(async db => { + const collection = db.collection('tokensAddresses'); + let accounts = await collection.find({ contract: contractAddress }).toArray(); + let { errors, totalDiff } = await updateBalances(accounts, collection); + if (errors) { + (0, _cli.warn)(`Total Diff: ${totalDiff}`); + (0, _cli.error)(JSON.stringify(errors, null, 2)); + } + process.exit(0); +}); + +async function updateBalances(accounts, collection) { + const errors = []; + const total = accounts.length; + let result = {}; + for (let i = 0; i < total; i++) { + let account = accounts[i]; + let { address, balance } = account; + let msg = `${i + 1}/${total} ${address} `; + let Address = contract.addAddress(address); + let newBalance = await Address.getBalance(); + newBalance = (0, _utils.add0x)(newBalance.toString(16)); + if (balance !== newBalance) { + let difference = (0, _utils.add0x)(new _bignumber2.default(newBalance).minus(new _bignumber2.default(balance)).toString(16)); + const error = { address, balance, newBalance, difference }; + (0, _cli.warn)(`ERROR: ${msg}`); + (0, _cli.warn)(`${JSON.stringify(error, null, 2)}`); + errors.push(error); + await collection.updateOne({ address, contract: contractAddress }, { $set: { balance: newBalance } }); + } else { + (0, _cli.info)(msg); + } + } + if (errors.length) { + let totalDiff = (0, _utils.bigNumberSum)(errors.map(error => error.difference)).toString(16); + result = { errors, totalDiff }; + } + return result; +} + +function help() { + const myName = process.argv[1].split('/').pop(); + (0, _cli.info)(`Usage: ${process.argv[0]} ${myName} [address]`); + process.exit(0); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 506ddc51..39d7b87a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "rsk-explorer-api", - "version": "0.7.3", + "version": "0.7.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index be9eceaf..2e43a58b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rsk-explorer-api", - "version": "0.7.3", + "version": "0.7.4", "description": "", "main": "index.js", "scripts": {