bitcore-node
Version:
A blockchain indexing node with extended capabilities using bitcore
213 lines • 9.69 kB
JavaScript
;
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.XrpTransactionStorage = exports.XrpTransactionModel = void 0;
const Loggify_1 = require("../../../decorators/Loggify");
const logger_1 = __importDefault(require("../../../logger"));
const baseTransaction_1 = require("../../../models/baseTransaction");
const cache_1 = require("../../../models/cache");
const coin_1 = require("../../../models/coin");
const events_1 = require("../../../models/events");
const config_1 = require("../../../services/config");
const storage_1 = require("../../../services/storage");
const utils_1 = require("../../../utils");
let XrpTransactionModel = class XrpTransactionModel extends baseTransaction_1.BaseTransaction {
constructor(storage = storage_1.Storage) {
super(storage);
}
onConnect() {
super.onConnect();
this.collection.createIndex({ chain: 1, network: 1, from: 1, nonce: 1 }, { background: true, sparse: true });
}
async batchImport(params) {
const txOps = await this.addTransactions({ ...params });
const coinOps = (await this.addCoins({ ...params }));
const batchSize = config_1.Config.get().maxPoolSize;
logger_1.default.debug('Writing Transactions: %o', txOps.length);
await Promise.all((0, utils_1.partition)(txOps, txOps.length / batchSize).map(txBatch => this.collection.bulkWrite(txBatch.map(op => this.toMempoolSafeUpsert(op, 0 /* SpentHeightIndicators.minimum */)), {
ordered: false
})));
await Promise.all((0, utils_1.partition)(coinOps, coinOps.length / batchSize).map(coinBatch => coin_1.CoinStorage.collection.bulkWrite(coinBatch.map(op => this.toMempoolSafeUpsert(op, 0 /* SpentHeightIndicators.minimum */)), { ordered: false })));
if (params.initialSyncComplete) {
await this.expireBalanceCache(coinOps);
}
// Create events for mempool txs
if (params.height != undefined && params.height < 0 /* SpentHeightIndicators.minimum */) {
for (let op of txOps) {
const filter = op.updateOne.filter;
const tx = { ...op.updateOne.update.$set, ...filter };
await events_1.EventStorage.signalTx(tx);
}
for (const coinOp of coinOps) {
const coin = { ...coinOp.updateOne.filter, ...coinOp.updateOne.update.$set };
await events_1.EventStorage.signalAddressCoin({
address: coin.address,
coin: {
value: coin.value,
address: coin.address,
chain: params.chain,
network: params.network,
mintTxid: coin.mintTxid
}
});
}
}
}
async expireBalanceCache(coinOps) {
let batch = new Array();
for (const coinOp of coinOps) {
const coin = { ...coinOp.updateOne.filter, ...coinOp.updateOne.update.$set };
const { address, chain, network } = coin;
batch.push({ address, chain, network });
}
for (const payload of batch) {
const { address, chain, network } = payload;
const lowerAddress = address.toLowerCase();
const cacheKey = `getBalanceForAddress-${chain}-${network}-${lowerAddress}`;
await cache_1.CacheStorage.expire(cacheKey);
}
}
async addTransactions(params) {
let { blockTimeNormalized, chain, height, network, parentChain, forkHeight } = params;
if (parentChain && forkHeight && height != undefined && height < forkHeight) {
const parentTxs = await exports.XrpTransactionStorage.collection
.find({ blockHeight: height, chain: parentChain, network })
.toArray();
return parentTxs.map(parentTx => {
return {
updateOne: {
filter: { txid: parentTx.txid, chain, network },
update: {
$set: {
...parentTx,
wallets: new Array()
}
},
upsert: true,
forceServerObjectId: true
}
};
});
}
else {
return Promise.all(params.txs.map(async (tx) => {
const { txid, wallets } = tx;
return {
updateOne: {
filter: { txid, chain, network },
update: {
$set: {
...tx,
blockTimeNormalized: tx.blockTimeNormalized || blockTimeNormalized,
wallets
}
},
upsert: true,
forceServerObjectId: true
}
};
}));
}
}
async addCoins(params) {
let { chain, height, network, parentChain, forkHeight } = params;
if (parentChain && forkHeight && height != undefined && height < forkHeight) {
const parentChainCoins = await coin_1.CoinStorage.collection
.find({ blockHeight: height, chain: parentChain, network })
.toArray();
return parentChainCoins.map((coin) => {
const { mintTxid } = coin;
return {
updateOne: {
filter: {
mintTxid,
mintIndex: coin.mintIndex,
chain,
network
},
update: {
$set: {
...coin,
wallets: []
}
},
upsert: true,
forceServerObjectId: true
}
};
});
}
else {
return params.coins.map((coin) => {
const { mintTxid, wallets, address } = coin;
return {
updateOne: {
filter: {
mintTxid,
mintIndex: coin.mintIndex,
chain,
network
},
update: {
$set: {
chain,
network,
address,
mintHeight: coin.mintHeight || height,
coinbase: coin.coinbase,
value: coin.value
},
$setOnInsert: {
wallets
}
},
upsert: true,
forceServerObjectId: true
}
};
});
}
}
getTransactions(params) {
let originalQuery = params.query;
const { query, options } = storage_1.Storage.getFindOptions(this, params.options);
const finalQuery = Object.assign({}, originalQuery, query);
return this.collection.find(finalQuery, options).addCursorFlag('noCursorTimeout', true);
}
_apiTransform(tx, options) {
const transaction = {
txid: tx.txid || '',
network: tx.network || '',
chain: tx.chain || '',
blockHeight: (0, utils_1.valueOrDefault)(tx.blockHeight, -1),
blockHash: tx.blockHash || '',
blockTime: tx.blockTime ? tx.blockTime.toISOString() : '',
blockTimeNormalized: tx.blockTimeNormalized ? tx.blockTimeNormalized.toISOString() : '',
fee: (0, utils_1.valueOrDefault)(tx.fee, -1),
value: (0, utils_1.valueOrDefault)(tx.value, -1),
from: tx.from || '',
nonce: (0, utils_1.valueOrDefault)(tx.nonce, -1),
to: (0, utils_1.valueOrDefault)(tx.to, ''),
currency: (0, utils_1.valueOrDefault)(tx.currency, 'XRP'),
invoiceID: (0, utils_1.valueOrDefault)(tx.invoiceID, '')
};
if (options && options.object) {
return transaction;
}
return JSON.stringify(transaction);
}
};
exports.XrpTransactionModel = XrpTransactionModel;
exports.XrpTransactionModel = XrpTransactionModel = __decorate([
Loggify_1.LoggifyClass
], XrpTransactionModel);
exports.XrpTransactionStorage = new XrpTransactionModel();
//# sourceMappingURL=transaction.js.map