UNPKG

@abcpros/bitcore-wallet-service

Version:
1,324 lines 86.6 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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 __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Storage = void 0; var async = __importStar(require("async")); var lodash_1 = __importStar(require("lodash")); var moment_1 = __importDefault(require("moment")); var mongodb = __importStar(require("mongodb")); var logger_1 = __importDefault(require("./logger")); var model_1 = require("./model"); var mongoDbQueue = require('../../node_modules/mongodb-queue'); var BCHAddressTranslator = require('./bchaddresstranslator'); var $ = require('preconditions').singleton(); var collections = { WALLETS: 'wallets', USER: 'user', USER_CONVERSION: 'user_conversion', COIN_CONFIG: 'coin_config', KEYS: 'keys', KEYS_CONVERSION: 'keys_conversion', TXS: 'txs', ADDRESSES: 'addresses', ADVERTISEMENTS: 'advertisements', NOTIFICATIONS: 'notifications', COPAYERS_LOOKUP: 'copayers_lookup', PREFERENCES: 'preferences', EMAIL_QUEUE: 'email_queue', CACHE: 'cache', FIAT_RATES2: 'fiat_rates2', TX_NOTES: 'tx_notes', SESSIONS: 'sessions', PUSH_NOTIFICATION_SUBS: 'push_notification_subs', TX_CONFIRMATION_SUBS: 'tx_confirmation_subs', LOCKS: 'locks', DONATION: 'donation', TOKEN_INFO: 'token_info', ORDER_INFO: 'order_info', CONVERSION_ORDER_INFO: 'conversion_order_info', MERCHANT_ORDER: 'merchant_order', USER_WATCH_ADDRESS: 'user_watch_address', ORDER_INFO_NOTI: 'order_info_noti', ORDER_QUEUE: 'order_queue' }; var Common = require('./common'); var Constants = Common.Constants; var Defaults = Common.Defaults; var ObjectID = mongodb.ObjectID; var objectIdDate = function (date) { return Math.floor(date / 1000).toString(16) + '0000000000000000'; }; var Storage = (function () { function Storage(opts) { var _this = this; if (opts === void 0) { opts = {}; } this.walletCheck = function (params) { return __awaiter(_this, void 0, void 0, function () { var walletId; var _this = this; return __generator(this, function (_a) { walletId = params.walletId; return [2, new Promise(function (resolve) { var addressStream = _this.db.collection(collections.ADDRESSES).find({ walletId: walletId }); var sum = 0; var lastAddress; addressStream.on('data', function (walletAddress) { if (walletAddress.address) { lastAddress = walletAddress.address.replace(/:.*$/, ''); var addressSum = Buffer.from(lastAddress).reduce(function (tot, cur) { return (tot + cur) % Number.MAX_SAFE_INTEGER; }); sum = (sum + addressSum) % Number.MAX_SAFE_INTEGER; } }); addressStream.on('end', function () { resolve({ lastAddress: lastAddress, sum: sum }); }); })]; }); }); }; opts = opts || {}; this.db = opts.db; } Storage.createIndexes = function (db) { logger_1.default.info('Creating DB indexes'); if (!db.collection) { console.log('[storage.ts.55] no db.collection'); logger_1.default.error('DB not ready'); return; } db.collection(collections.USER).createIndex({ id: 1 }); db.collection(collections.USER_CONVERSION).createIndex({ id: 1 }); db.collection(collections.COIN_CONFIG).createIndex({ id: 1 }); db.collection(collections.KEYS).createIndex({ id: 1 }); db.collection(collections.KEYS_CONVERSION).createIndex({ id: 1 }); db.collection(collections.WALLETS).createIndex({ id: 1 }); db.collection(collections.DONATION).createIndex({ txidDonation: 1 }); db.collection(collections.TOKEN_INFO).createIndex({ id: 1 }); db.collection(collections.ORDER_INFO).createIndex({ id: 1 }); db.collection(collections.CONVERSION_ORDER_INFO).createIndex({ id: 1 }); db.collection(collections.MERCHANT_ORDER).createIndex({ id: 1 }); db.collection(collections.USER_WATCH_ADDRESS).createIndex({ id: 1 }); db.collection(collections.ORDER_INFO_NOTI).createIndex({ id: 1 }); db.collection(collections.COPAYERS_LOOKUP).createIndex({ copayerId: 1 }); db.collection(collections.COPAYERS_LOOKUP).createIndex({ walletId: 1 }); db.collection(collections.TXS).createIndex({ walletId: 1, id: 1 }); db.collection(collections.TXS).createIndex({ walletId: 1, isPending: 1, txid: 1 }); db.collection(collections.TXS).createIndex({ walletId: 1, createdOn: -1 }); db.collection(collections.TXS).createIndex({ txid: 1 }); db.collection(collections.NOTIFICATIONS).createIndex({ walletId: 1, id: 1 }); db.collection(collections.ADVERTISEMENTS).createIndex({ advertisementId: 1, title: 1 }, { unique: true }); db.collection(collections.ADDRESSES).createIndex({ walletId: 1, createdOn: 1 }); db.collection(collections.ADDRESSES).createIndex({ address: 1 }, { unique: true }); db.collection(collections.ADDRESSES).createIndex({ address: 1, beRegistered: 1 }); db.collection(collections.ADDRESSES).createIndex({ walletId: 1, address: 1 }); db.collection(collections.EMAIL_QUEUE).createIndex({ id: 1 }); db.collection(collections.EMAIL_QUEUE).createIndex({ notificationId: 1 }); db.collection(collections.CACHE).createIndex({ walletId: 1, type: 1, key: 1 }); db.collection(collections.TX_NOTES).createIndex({ walletId: 1, txid: 1 }); db.collection(collections.PREFERENCES).createIndex({ walletId: 1 }); db.collection(collections.FIAT_RATES2).createIndex({ coin: 1, code: 1, ts: 1 }); db.collection(collections.PUSH_NOTIFICATION_SUBS).createIndex({ copayerId: 1 }); db.collection(collections.TX_CONFIRMATION_SUBS).createIndex({ copayerId: 1, txid: 1 }); db.collection(collections.TX_CONFIRMATION_SUBS).createIndex({ isActive: 1, copayerId: 1 }); db.collection(collections.SESSIONS).createIndex({ copayerId: 1 }); }; Storage.prototype.connect = function (opts, cb) { var _this = this; opts = opts || {}; if (this.db) return cb(); var config = opts.mongoDb || {}; if (opts.secondaryPreferred) { if (config.uri.indexOf('?') > 0) { config.uri = config.uri + '&'; } else { config.uri = config.uri + '?'; } config.uri = config.uri + 'readPreference=secondaryPreferred'; logger_1.default.info('Read operations set to secondaryPreferred'); } if (!config.dbname) { logger_1.default.error('No dbname at config.'); return cb(new Error('No dbname at config.')); } mongodb.MongoClient.connect(config.uri, { useUnifiedTopology: true }, function (err, client) { if (err) { logger_1.default.error('Unable to connect to the mongoDB. Check the credentials.'); return cb(err); } _this.db = client.db(config.dbname); _this.client = client; _this.queue = mongoDbQueue(_this.db, 'donation_queue'); _this.orderQueue = mongoDbQueue(_this.db, 'order_queue'); _this.conversionOrderQueue = mongoDbQueue(_this.db, 'conversion_order_queue'); _this.merchantOrderQueue = mongoDbQueue(_this.db, 'merchant_order_queue'); logger_1.default.info("Connection established to db: " + config.uri); Storage.createIndexes(_this.db); return cb(); }); }; Storage.prototype.disconnect = function (cb) { var _this = this; if (this.client) { this.client.close(function (err) { if (err) return cb(err); _this.db = null; _this.client = null; return cb(); }); } else { return cb(); } }; Storage.prototype.fetchWallet = function (id, cb) { if (!this.db) return cb('not ready'); this.db.collection(collections.WALLETS).findOne({ id: id }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, model_1.Wallet.fromObj(result)); }); }; Storage.prototype.storeWallet = function (wallet, cb) { this.db.collection(collections.WALLETS).replaceOne({ id: wallet.id }, wallet.toObject(), { w: 1, upsert: true }, cb); }; Storage.prototype.storeDonation = function (donationStorage, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', donationStorage); return; } this.db.collection(collections.DONATION).insertOne(donationStorage, { w: 1 }, cb); }; Storage.prototype.storeTokenInfo = function (tokenInfo, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', tokenInfo); return; } this.db.collection(collections.TOKEN_INFO).insertOne(tokenInfo, { w: 1 }, cb); }; Storage.prototype.fetchTokenInfoById = function (tokenId, cb) { if (!this.db) return cb(); this.db.collection(collections.TOKEN_INFO).findOne({ id: tokenId }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchTokenInfo = function (cb) { if (!this.db) return cb(); this.db .collection(collections.TOKEN_INFO) .find({}) .toArray(function (err, result) { if (err) return cb(err); return cb(null, result); }); }; Storage.prototype.fetchDonationByTxid = function (txidDonation, cb) { if (!this.db) return cb(); this.db.collection(collections.DONATION).findOne({ txidDonation: txidDonation }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchDonationInToday = function (cb) { var start = moment_1.default() .utc() .startOf('day') .valueOf(); var end = moment_1.default() .utc() .endOf('day') .valueOf(); this.db .collection(collections.DONATION) .find({ createdOn: { $gte: start, $lt: end } }) .toArray(function (err, result) { var donationInToday = lodash_1.default.filter(result, function (item) { return item.txidDonation; }); return cb(null, donationInToday); }); }; Storage.prototype.updateDonation = function (donationInfo, cb) { this.db.collection(collections.DONATION).updateOne({ txidDonation: donationInfo.txidDonation }, { $set: { txidGiveLotus: donationInfo.txidGiveLotus, isGiven: donationInfo.isGiven, error: donationInfo.error } }, { upsert: false }, cb); }; Storage.prototype.storeUser = function (user, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', user); return; } this.db.collection(collections.USER).update({ email: user.email }, { $setOnInsert: user }, { upsert: true }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.storeUserConversion = function (user, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', user); return; } this.db.collection(collections.USER_CONVERSION).update({ email: user.email }, { $setOnInsert: user }, { upsert: true }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchUserByEmail = function (email, cb) { if (!this.db) return cb(); this.db.collection(collections.USER).findOne({ email: email }, function (err, result) { if (err) return cb(err); if (!result) return cb('Can not find user in db'); return cb(null, result); }); }; Storage.prototype.fetchUserConversionByEmail = function (email, cb) { if (!this.db) return cb(); this.db.collection(collections.USER_CONVERSION).findOne({ email: email }, function (err, result) { if (err) return cb(err); if (!result) return cb('Can not find user conversion in db'); return cb(null, result); }); }; Storage.prototype.storeKeys = function (keys, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', keys); return; } this.db.collection(collections.KEYS).insertOne(keys, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.storeKeysConversion = function (keys, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', keys); return; } this.db.collection(collections.KEYS_CONVERSION).insertOne(keys, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchKeys = function (cb) { if (!this.db) return cb(); this.db.collection(collections.KEYS).findOne({}, function (err, result) { if (err) return cb(err); if (!result) return cb(null, null); return cb(null, result); }); }; Storage.prototype.fetchKeysConversion = function (cb) { if (!this.db) return cb(); this.db.collection(collections.KEYS_CONVERSION).findOne({}, function (err, result) { if (err) return cb(err); if (!result) return cb(null, null); return cb(null, result); }); }; Storage.prototype.updateKeys = function (keys, cb) { this.db.collection(collections.KEYS).findOneAndUpdate({}, { $set: { keyFund: keys.keyFund, keyReceive: keys.keyReceive, hashPassword: keys.hashPassword, hashRecoveryKey: keys.hashRecoveryKey } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update keys')); return cb(null, result); }); }; Storage.prototype.updateKeysConversion = function (keys, cb) { this.db.collection(collections.KEYS_CONVERSION).findOneAndUpdate({}, { $set: { keyFund: keys.keyFund, hashPassword: keys.hashPassword, hashRecoveryKey: keys.hashRecoveryKey, lastModified: new Date() } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update key conversion')); return cb(null, result); }); }; Storage.prototype.updateOrder = function (orderInfo, cb) { this.db.collection(collections.ORDER_INFO).updateOne({ id: orderInfo.id }, { $set: { adddressUserDeposit: orderInfo.adddressUserDeposit, updatedRate: orderInfo.updatedRate, status: orderInfo.status, isSentToFund: orderInfo.isSentToFund, isSentToUser: orderInfo.isSentToUser, listTxIdUserDeposit: orderInfo.listTxIdUserDeposit, listTxIdUserReceive: orderInfo.listTxIdUserReceive, error: orderInfo.error, pendingReason: orderInfo.pendingReason, lastModified: new Date(), isResolve: orderInfo.isResolve, note: orderInfo.note, isInQueue: orderInfo.isInQueue, actualSent: orderInfo.actualSent, actualReceived: orderInfo.actualReceived } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update order')); return cb(null, result); }); }; Storage.prototype.updateOrderById = function (orderId, orderInfo, cb) { this.db.collection(collections.ORDER_INFO).updateOne({ id: orderId }, { $set: { adddressUserDeposit: orderInfo.adddressUserDeposit, updatedRate: orderInfo.updatedRate, status: orderInfo.status, isSentToFund: orderInfo.isSentToFund, isSentToUser: orderInfo.isSentToUser, listTxIdUserDeposit: orderInfo.listTxIdUserDeposit, listTxIdUserReceive: orderInfo.listTxIdUserReceive, error: orderInfo.error, pendingReason: orderInfo.pendingReason, lastModified: new Date(), isResolve: orderInfo.isResolve, note: orderInfo.note, actualSent: orderInfo.actualSent, actualReceived: orderInfo.actualReceived } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update order')); return cb(null, result); }); }; Storage.prototype.updateOrderStatus = function (id, status, cb) { this.db.collection(collections.ORDER_INFO).updateOne({ id: id }, { $set: { status: status } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update order')); return cb(null, result); }); }; Storage.prototype.updateConversionOrder = function (orderInfo, cb) { this.db.collection(collections.CONVERSION_ORDER_INFO).updateOne({ txIdFromUser: orderInfo.txIdFromUser }, { $set: { txIdSentToUser: orderInfo.txIdSentToUser, lastModified: new Date(), error: orderInfo.error, pendingReason: orderInfo.pendingReason, status: orderInfo.status } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update order')); return cb(null, result); }); }; Storage.prototype.updateMerchantOrder = function (merchantOrder, cb) { this.db.collection(collections.MERCHANT_ORDER).updateOne({ txIdFromUser: merchantOrder.txIdFromUser }, { $set: { status: merchantOrder.status, txIdMerchantPayment: merchantOrder.txIdMerchantPayment, lastModified: new Date(), error: merchantOrder.error } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update merchant order')); return cb(null, result); }); }; Storage.prototype.updateListCoinConfig = function (listCoinConfig, cb) { if (!this.db) { logger_1.default.warn('Trying to update list coin config with close DB', listCoinConfig); return; } var bulk = this.db.collection(collections.COIN_CONFIG).initializeUnorderedBulkOp(); for (var i = 0; i < listCoinConfig.length; i++) { var coinConfig = listCoinConfig[i]; var ObjectId = require('mongodb').ObjectId; bulk.find({ _id: ObjectId(coinConfig._id) }).update({ $set: { isEnableSwap: coinConfig.isEnableSwap, isEnableReceive: coinConfig.isEnableReceive, min: coinConfig.min, max: coinConfig.max, serviceFee: coinConfig.serviceFee, settleFee: coinConfig.settleFee, networkFee: coinConfig.networkFee, isSwap: coinConfig.isSwap, isReceive: coinConfig.isReceive, dailyLimit: coinConfig.dailyLimit || 0 } }); } bulk .execute() .then(function (result) { return cb(null, result); }) .catch(function (e) { return cb(e); }); }; Storage.prototype.storeOrderInfo = function (orderInfo, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', orderInfo); return; } this.db.collection(collections.ORDER_INFO).insertOne(orderInfo, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchOrderinfoById = function (orderId, cb) { this.db.collection(collections.ORDER_INFO).findOne({ id: orderId }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Your order could not be found, please re-enter!')); return cb(null, result); }); }; Storage.prototype.fetchConversionOrderInfoByTxIdFromUser = function (txIdFromUser, cb) { this.db.collection(collections.CONVERSION_ORDER_INFO).findOne({ txIdFromUser: txIdFromUser }, function (err, result) { if (err) return cb(err); return cb(null, result); }); }; Storage.prototype.fetchMerchantOrderByTxIdFromUser = function (txIdFromUser, cb) { this.db.collection(collections.MERCHANT_ORDER).findOne({ txIdFromUser: txIdFromUser }, function (err, result) { if (err) return cb(err); return cb(null, result); }); }; Storage.prototype.storeConversionOrderInfo = function (conversionOrderInfo, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', conversionOrderInfo); return; } this.db.collection(collections.CONVERSION_ORDER_INFO).insertOne(conversionOrderInfo, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.storeMerchantOrder = function (merchantOrder, cb) { if (!this.db) { logger_1.default.warn('Trying to store merchant order with close DB', merchantOrder); return; } this.db.collection(collections.MERCHANT_ORDER).insertOne(merchantOrder, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.storeUserWatchAddress = function (user, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', user); return; } this.db.collection(collections.USER_WATCH_ADDRESS).insertOne(user, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.updateUserWatchAddress = function (user, cb) { this.db.collection(collections.USER_WATCH_ADDRESS).updateOne({ msgId: user.msgId }, { $set: { address: user.address } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update order')); return cb(null, result); }); }; Storage.prototype.removeUserWatchAddress = function (userInfo, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', userInfo); return; } this.db.collection(collections.USER_WATCH_ADDRESS).deleteOne(userInfo, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchAllAddressByMsgId = function (msgId, cb) { this.db .collection(collections.USER_WATCH_ADDRESS) .find({ msgId: msgId }) .toArray(function (err, listUserInfo) { if (err) return cb(err); if (!listUserInfo || listUserInfo.length === 0) return cb(null, null); var listAddress = lodash_1.default.map(listUserInfo, function (user) { return user.address; }); return cb(null, listAddress); }); }; Storage.prototype.fetchAllMsgIdByAddress = function (address, cb) { this.db .collection(collections.USER_WATCH_ADDRESS) .find({ address: address }) .toArray(function (err, listUserInfo) { if (err) return cb(err); if (!listUserInfo || listUserInfo.length === 0) return cb(null, null); var listMsgId = lodash_1.default.map(listUserInfo, function (user) { return user.msgId; }); return cb(null, listMsgId); }); }; Storage.prototype.storeOrderInfoNoti = function (orderInfoNoti, cb) { if (!this.db) { logger_1.default.warn('Trying to store a orderInfoNoti with close DB', orderInfoNoti); return; } this.db.collection(collections.ORDER_INFO_NOTI).insertOne(orderInfoNoti, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.fetchOrderInfoNoti = function (opts, cb) { if (!this.db) { logger_1.default.warn('Trying to store a orderInfoNoti with close DB'); return; } var queryObject = {}; var queryReceivedTxId = null; var queryPendingReason = null; var queryError = null; if (opts) { if (opts.receivedTxId) { queryReceivedTxId = { receivedTxId: opts.receivedTxId }; } else if (opts.pendingReason) { queryPendingReason = { pendingReason: opts.pendingReason }; } else if (opts.error) { queryError = { error: opts.error }; } } queryObject = Object.assign({}, { orderId: opts.orderId }, queryReceivedTxId && __assign({}, queryReceivedTxId), queryPendingReason && __assign({}, queryPendingReason), queryError && __assign({}, queryError)); this.db.collection(collections.ORDER_INFO_NOTI).findOne(queryObject, function (err, result) { if (err) return cb(err); if (!result) return cb(null); return cb(null, result); }); }; Storage.prototype.fetchAllOrderInfo = function (opts, cb) { var coinConfigFilter = opts.coinConfigFilter || null; var queryObject = {}; var queryDate = null; var queryFromCoin = null; var queryFromNetwork = null; var queryToNetwork = null; var queryToCoin = null; var queryStatus = null; var queryIsInQueue = null; var queryOrderId = null; if (coinConfigFilter) { if (coinConfigFilter.fromDate && coinConfigFilter.toDate) { queryDate = { lastModified: { $gte: new Date(coinConfigFilter.fromDate), $lte: new Date(coinConfigFilter.toDate) } }; } if (coinConfigFilter.fromCoinCode) { queryFromCoin = { fromCoinCode: coinConfigFilter.fromCoinCode }; } if (coinConfigFilter.fromNetwork) { queryFromNetwork = { fromNetwork: coinConfigFilter.fromNetwork }; } if (coinConfigFilter.toCoinCode) { queryToCoin = { toCoinCode: coinConfigFilter.toCoinCode }; } if (coinConfigFilter.toNetwork) { queryToNetwork = { toNetwork: coinConfigFilter.toNetwork }; } if (coinConfigFilter.status) { queryStatus = { status: coinConfigFilter.status }; } if (!lodash_1.isUndefined(coinConfigFilter.isInQueue) && !lodash_1.isNull(coinConfigFilter.isInQueue)) { queryIsInQueue = { status: coinConfigFilter.status }; } if (coinConfigFilter.orderId && coinConfigFilter.orderId.length > 0) { queryOrderId = { id: coinConfigFilter.orderId }; } queryObject = Object.assign({}, queryDate && __assign({}, queryDate), queryFromCoin && __assign({}, queryFromCoin), queryToCoin && __assign({}, queryToCoin), queryStatus && __assign({}, queryStatus), queryFromNetwork && __assign({}, queryFromNetwork), queryToNetwork && __assign({}, queryToNetwork), queryIsInQueue && __assign({}, queryIsInQueue), queryOrderId && __assign({}, queryOrderId)); } this.db .collection(collections.ORDER_INFO) .find(queryObject) .sort(opts.query) .limit(opts.limit) .skip(opts.skip) .toArray(function (err, listOrderInfo) { if (err) return cb(err); if (listOrderInfo.length === 0) return cb(new Error('Not found any order')); else return cb(null, listOrderInfo); }); }; Storage.prototype.fetchAllOrderInfoNotInQueue = function (cb) { this.db .collection(collections.ORDER_INFO) .find({ $or: [{ status: 'waiting' }, { status: 'processing' }] }) .sort({ lastModified: 1 }) .toArray(function (err, listOrderInfo) { if (err) return cb(err); else return cb(null, listOrderInfo); }); }; Storage.prototype.fetchAllOrderInfoInQueue = function (cb) { this.db .collection(collections.ORDER_QUEUE) .find() .toArray(function (err, listOrderInfo) { if (err) return cb(err); else return cb(null, listOrderInfo); }); }; Storage.prototype.countAllOrderInfo = function (opts) { var coinConfigFilter = opts.coinConfigFilter || null; var queryObject = {}; var queryDate = null; var queryFromCoin = null; var queryFromNetwork = null; var queryToNetwork = null; var queryToCoin = null; var queryStatus = null; var queryIsInQueue = null; var queryOrderId = null; if (coinConfigFilter) { if (coinConfigFilter.fromDate && coinConfigFilter.toDate) { queryDate = { lastModified: { $gte: new Date(coinConfigFilter.fromDate), $lte: new Date(coinConfigFilter.toDate) } }; } if (coinConfigFilter.fromCoinCode) { queryFromCoin = { fromCoinCode: coinConfigFilter.fromCoinCode }; } if (coinConfigFilter.fromNetwork) { queryFromNetwork = { fromNetwork: coinConfigFilter.fromNetwork }; } if (coinConfigFilter.toCoinCode) { queryToCoin = { toCoinCode: coinConfigFilter.toCoinCode }; } if (coinConfigFilter.toNetwork) { queryToNetwork = { toNetwork: coinConfigFilter.toNetwork }; } if (coinConfigFilter.status) { queryStatus = { status: coinConfigFilter.status }; } if (!lodash_1.isUndefined(coinConfigFilter.isInQueue) && !lodash_1.isNull(coinConfigFilter.isInQueue)) { queryIsInQueue = { status: coinConfigFilter.status }; } if (coinConfigFilter.orderId && coinConfigFilter.orderId.length > 0) { queryOrderId = { id: coinConfigFilter.orderId }; } queryObject = Object.assign({}, queryDate && __assign({}, queryDate), queryFromCoin && __assign({}, queryFromCoin), queryToCoin && __assign({}, queryToCoin), queryStatus && __assign({}, queryStatus), queryFromNetwork && __assign({}, queryFromNetwork), queryToNetwork && __assign({}, queryToNetwork), queryIsInQueue && __assign({}, queryIsInQueue), queryOrderId && __assign({}, queryOrderId)); } return this.db .collection(collections.ORDER_INFO) .find(queryObject) .sort(opts.query) .count(); }; Storage.prototype.fetchAllConversionOrderInfo = function (opts, cb) { this.db .collection(collections.CONVERSION_ORDER_INFO) .find({}) .sort({ _id: -1 }) .toArray(function (err, listConversionOrderInfo) { if (err) return cb(err); if (listConversionOrderInfo.length === 0) return cb(new Error('Not found any conversion order')); else return cb(null, listConversionOrderInfo); }); }; Storage.prototype.countAllConversionOrderInfo = function (opts) { return this.db .collection(collections.CONVERSION_ORDER_INFO) .find({}) .sort({ _id: -1 }) .count(); }; Storage.prototype.fetchAllCoinConfig = function (cb) { this.db .collection(collections.COIN_CONFIG) .find() .toArray(function (err, listCoinConfig) { if (err) return cb(err); else return cb(null, listCoinConfig); }); }; Storage.prototype.storeListCoinConfig = function (listCoinConfig, cb) { if (!this.db) { logger_1.default.warn('Trying to store a notification with close DB', listCoinConfig); return; } this.db.collection(collections.COIN_CONFIG).insertMany(listCoinConfig, { w: 1 }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return cb(null, result); }); }; Storage.prototype.updateCoinConfig = function (coinConfig, cb) { this.db.collection(collections.COIN_CONFIG).updateOne({ code: coinConfig.code, network: coinConfig.network }, { $set: { isSupport: coinConfig.isSupport } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update coin config')); return cb(null, result); }); }; Storage.prototype.updateDailyLimitCoinConfig = function (coinConfig, cb) { this.db.collection(collections.COIN_CONFIG).updateOne({ code: coinConfig.code, network: coinConfig.network }, { $set: { dailyLimit: coinConfig.dailyLimit, dailyLimitUsage: coinConfig.dailyLimitUsage } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update daily limit for coin config')); return cb(null, result); }); }; Storage.prototype.resetAllDailyLimitUsageInCoinConfig = function (cb) { this.db.collection(collections.COIN_CONFIG).updateMany({}, { $set: { dailyLimitUsage: 0 } }, { upsert: false }, function (err, result) { if (err) return cb(err); if (!result) return cb(new Error('Can not update daily limit for coin config')); return cb(null, result); }); }; Storage.prototype.storeWalletAndUpdateCopayersLookup = function (wallet, cb) { var _this = this; var copayerLookups = lodash_1.default.map(wallet.copayers, function (copayer) { try { $.checkState(copayer.requestPubKeys, 'Failed state: copayer.requestPubkeys undefined at <storeWalletAndUpdateCopayersLookup()>'); } catch (e) { return cb(e); } return { copayerId: copayer.id, walletId: wallet.id, requestPubKeys: copayer.requestPubKeys }; }); this.db.collection(collections.COPAYERS_LOOKUP).deleteMany({ walletId: wallet.id }, { w: 1 }, function (err) { if (err) return cb(err); _this.db.collection(collections.COPAYERS_LOOKUP).insertMany(copayerLookups, { w: 1 }, function (err) { if (err) return cb(err); return _this.storeWallet(wallet, cb); }); }); }; Storage.prototype.fetchCopayerLookup = function (copayerId, cb) { this.db.collection(collections.COPAYERS_LOOKUP).findOne({ copayerId: copayerId }, function (err, result) { if (err) return cb(err); if (!result) return cb(); if (!result.requestPubKeys) { result.requestPubKeys = [ { key: result.requestPubKey, signature: result.signature } ]; } return cb(null, result); }); }; Storage.prototype.fetchAllAddressInUserWatchAddress = function (cb) { this.db .collection(collections.USER_WATCH_ADDRESS) .distinct('address') .then(function (listAddress) { return cb(null, listAddress); }) .catch(function (e) { return cb(e); }); }; Storage.prototype._completeTxData = function (walletId, txs, cb) { this.fetchWallet(walletId, function (err, wallet) { if (err) return cb(err); lodash_1.default.each([].concat(txs), function (tx) { tx.derivationStrategy = wallet.derivationStrategy || 'BIP45'; tx.creatorName = wallet.getCopayer(tx.creatorId).name; lodash_1.default.each(tx.actions, function (action) { action.copayerName = wallet.getCopayer(action.copayerId).name; }); if (tx.status == 'accepted') tx.raw = tx.getRawTx(); }); return cb(null, txs); }); }; Storage.prototype.fetchTx = function (walletId, txProposalId, cb) { var _this = this; if (!this.db) return cb(); this.db.collection(collections.TXS).findOne({ id: txProposalId, walletId: walletId }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return _this._completeTxData(walletId, model_1.TxProposal.fromObj(result), cb); }); }; Storage.prototype.fetchTxByHash = function (hash, cb) { var _this = this; if (!this.db) return cb(); this.db.collection(collections.TXS).findOne({ txid: hash }, function (err, result) { if (err) return cb(err); if (!result) return cb(); return _this._completeTxData(result.walletId, model_1.TxProposal.fromObj(result), cb); }); }; Storage.prototype.fetchLastTxs = function (walletId, creatorId, limit, cb) { this.db .collection(collections.TXS) .find({ walletId: walletId, creatorId: creatorId }, { limit: limit || 5 }) .sort({ createdOn: -1 }) .toArray(function (err, result) { if (err) return cb(err); if (!result) return cb(); var txs = lodash_1.default.map(result, function (tx) { return model_1.TxProposal.fromObj(tx); }); return cb(null, txs); }); }; Storage.prototype.fetchEthPendingTxs = function (multisigTxpsInfo) { var _this = this; return new Promise(function (resolve, reject) { _this.db .collection(collections.TXS) .find({ txid: { $in: multisigTxpsInfo.map(function (txpInfo) { return txpInfo.transactionHash; }) } }) .sort({ createdOn: -1 }) .toArray(function (err, result) { return __awaiter(_this, void 0, void 0, function () { var multisigTxpsInfoByTransactionHash, actionsById, txs; return __generator(this, function (_a) { if (err) return [2, reject(err)]; if (!result) return [2, reject()]; multisigTxpsInfoByTransactionHash = lodash_1.default.groupBy(multisigTxpsInfo, 'transactionHash'); actionsById = {}; txs = lodash_1.default.compact(lodash_1.default.map(result, function (tx) { if (!tx.multisigContractAddress) { return undefined; } tx.status = 'pending'; tx.multisigTxId = multisigTxpsInfoByTransactionHash[tx.txid][0].transactionId; tx.actions.forEach(function (action) { if (lodash_1.default.some(multisi