UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

193 lines 8.69 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CoinStorage = exports.CoinModel = void 0; const Loggify_1 = require("../decorators/Loggify"); const logger_1 = __importDefault(require("../logger")); const libs_1 = require("../providers/libs"); const utils_1 = require("../utils"); const base_1 = require("./base"); const block_1 = require("./block"); let CoinModel = class CoinModel extends base_1.BaseModel { constructor(storage) { super('coins', storage); this.allowedPaging = [ { key: 'mintHeight', type: 'number' }, { key: 'spentHeight', type: 'number' } ]; } onConnect() { this.collection.createIndex({ mintTxid: 1, mintIndex: 1 }, { background: true }); this.collection.createIndex({ address: 1, chain: 1, network: 1 }, { background: true, partialFilterExpression: { spentHeight: { $lt: 0 } } }); this.collection.createIndex({ address: 1 }, { background: true }); this.collection.createIndex({ chain: 1, network: 1, mintHeight: 1 }, { background: true }); this.collection.createIndex({ spentTxid: 1 }, { background: true, sparse: true }); this.collection.createIndex({ chain: 1, network: 1, spentHeight: 1 }, { background: true }); this.collection.createIndex({ wallets: 1, spentHeight: 1, value: 1, mintHeight: 1 }, { background: true, partialFilterExpression: { 'wallets.0': { $exists: true } } }); this.collection.createIndex({ wallets: 1, spentTxid: 1 }, { background: true, partialFilterExpression: { 'wallets.0': { $exists: true } } }); this.collection.createIndex({ wallets: 1, mintTxid: 1 }, { background: true, partialFilterExpression: { 'wallets.0': { $exists: true } } }); } async getBalance(params, options = {}) { let { query } = params; const result = await this.collection .aggregate([ { $match: query }, { $project: { value: 1, status: { $cond: { if: { $gte: ['$mintHeight', 0 /* SpentHeightIndicators.minimum */] }, then: 'confirmed', else: 'unconfirmed' } }, _id: 0 } }, { $group: { _id: '$status', balance: { $sum: '$value' } } } ], options) .toArray(); return result.reduce((acc, cur) => { acc[cur._id] = cur.balance; acc.balance += cur.balance; return acc; }, { confirmed: 0, unconfirmed: 0, balance: 0 }); } async getBalanceAtTime(params) { let { query, time, chain, network } = params; const [block] = await block_1.BitcoinBlockStorage.collection .find({ $query: { chain, network, timeNormalized: { $lte: new Date(time) } } }) .limit(1) .sort({ timeNormalized: -1 }) .toArray(); const blockHeight = block.height; const combinedQuery = Object.assign({}, { $or: [{ spentHeight: { $gt: blockHeight } }, { spentHeight: { $lt: 0 /* SpentHeightIndicators.minimum */ } }], mintHeight: { $lte: blockHeight } }, query); return this.getBalance({ query: combinedQuery }, { hint: { wallets: 1, spentHeight: 1, value: 1, mintHeight: 1 } }); } resolveAuthhead(mintTxid, chain, network) { return this.collection .aggregate([ { $match: { mintTxid: mintTxid.toLowerCase(), mintIndex: 0, ...(typeof chain === 'string' ? { chain } : {}), ...(typeof network === 'string' ? { network } : {}) } }, { $graphLookup: { from: 'coins', startWith: '$spentTxid', connectFromField: 'spentTxid', connectToField: 'mintTxid', as: 'authheads', maxDepth: 1000000, restrictSearchWithMatch: { mintIndex: 0 } } }, { $project: { chain: '$chain', network: '$network', authbase: '$mintTxid', identityOutputs: { $filter: { input: '$authheads', as: 'authhead', cond: { $and: [ { $lte: ['$$authhead.spentHeight', -1] }, { $eq: ['$$authhead.chain', '$chain'] }, { $eq: ['$$authhead.network', '$network'] } ] } } } } } ]) .toArray(); } _apiTransform(coin, options) { // try to parse coin.address if its 'false' and script exists if (coin.address == 'false' && coin.script != undefined && coin.script.toString() != '') { try { const lib = libs_1.Libs.get(coin.chain).lib; const address = lib .Script(coin.script.toString('hex')) .toAddress(coin.network) .toString(); if (lib.Address.isValid(address, coin.network)) { coin.address = address; // update coin record in db - do it asynchronously as we don't need to wait for result exports.CoinStorage.collection.updateOne({ _id: coin._id }, { $set: { address: coin.address } }); } } catch (e) { logger_1.default.debug(`Could not parse address on "${coin.chain}:${coin.network}" for coin ${coin.mintTxid}[${coin.mintIndex}]`); } } const transform = { chain: (0, utils_1.valueOrDefault)(coin.chain, ''), network: (0, utils_1.valueOrDefault)(coin.network, ''), coinbase: (0, utils_1.valueOrDefault)(coin.coinbase, false), mintIndex: (0, utils_1.valueOrDefault)(coin.mintIndex, -1), spentTxid: (0, utils_1.valueOrDefault)(coin.spentTxid, ''), mintTxid: (0, utils_1.valueOrDefault)(coin.mintTxid, ''), mintHeight: (0, utils_1.valueOrDefault)(coin.mintHeight, -1), spentHeight: (0, utils_1.valueOrDefault)(coin.spentHeight, -4 /* SpentHeightIndicators.error */), address: (0, utils_1.valueOrDefault)(coin.address, ''), script: (0, utils_1.valueOrDefault)(coin.script, Buffer.alloc(0)).toString('hex'), value: (0, utils_1.valueOrDefault)(coin.value, -1), confirmations: (0, utils_1.valueOrDefault)(coin.confirmations ?? options?.confirmations, -1), sequenceNumber: (0, utils_1.valueOrDefault)(coin.sequenceNumber, undefined) }; if (options && options.object) { return transform; } return JSON.stringify(transform); } }; exports.CoinModel = CoinModel; exports.CoinModel = CoinModel = __decorate([ Loggify_1.LoggifyClass ], CoinModel); exports.CoinStorage = new CoinModel(); //# sourceMappingURL=coin.js.map