@abcpros/bitcore-wallet-service
Version:
A service for Mutisig HD Bitcoin Wallets
1,324 lines • 86.6 kB
JavaScript
"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