"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.base58Regex = exports.mongoIdRegex = exports.randomHex = exports.minutesAgo = void 0;
exports.resetDatabase = resetDatabase;
exports.resetModel = resetModel;
exports.mockCollection = mockCollection;
exports.mockStorage = mockStorage;
exports.mockModel = mockModel;
exports.expectObjectToHaveProps = expectObjectToHaveProps;
exports.testCoin = testCoin;
const sinon_1 = __importDefault(require("sinon"));
const block_1 = require("../../src/models/block");
const cache_1 = require("../../src/models/cache");
const coin_1 = require("../../src/models/coin");
const events_1 = require("../../src/models/events");
const rateLimit_1 = require("../../src/models/rateLimit");
const state_1 = require("../../src/models/state");
const transaction_1 = require("../../src/models/transaction");
const wallet_1 = require("../../src/models/wallet");
const walletAddress_1 = require("../../src/models/walletAddress");
const storage_1 = require("../../src/services/storage");
const chai_1 = require("chai");
const crypto_1 = require("crypto");
async function resetDatabase() {
    console.log('Resetting database');
    await Promise.all([
        resetModel(block_1.BitcoinBlockStorage),
        resetModel(transaction_1.TransactionStorage),
        resetModel(coin_1.CoinStorage),
        resetModel(walletAddress_1.WalletAddressStorage),
        resetModel(wallet_1.WalletStorage),
        resetModel(state_1.StateStorage),
        resetModel(rateLimit_1.RateLimitStorage),
        resetModel(events_1.EventStorage),
        resetModel(cache_1.CacheStorage)
    ]);
}
async function resetModel(model) {
    return model.collection.deleteMany({});
}
function mockCollection(toReturn, collectionMethods = {}) {
    const mock = Object.assign({
        find: sinon_1.default.stub().returnsThis(),
        aggregate: sinon_1.default.stub().returnsThis(),
        count: sinon_1.default.stub().returnsThis(),
        sort: sinon_1.default.stub().returnsThis(),
        project: sinon_1.default.stub().returnsThis(),
        insertOne: sinon_1.default.stub().resolves(),
        insertMany: sinon_1.default.stub().resolves(),
        bulkWrite: sinon_1.default.stub().resolves(),
        remove: sinon_1.default.stub().resolves(),
        deleteOne: sinon_1.default.stub().resolves(),
        deleteMany: sinon_1.default.stub().resolves(),
        limit: sinon_1.default.stub().returnsThis(),
        toArray: sinon_1.default.stub().resolves(toReturn instanceof Array ? toReturn : [toReturn]),
        findOne: sinon_1.default.stub().resolves(toReturn),
        update: sinon_1.default.stub().resolves({ result: toReturn }),
        updateOne: sinon_1.default.stub().resolves(toReturn),
        updateMany: sinon_1.default.stub().resolves({ nModified: 1 }),
        addCursorFlag: sinon_1.default.stub().returnsThis()
    }, collectionMethods);
    return mock;
}
function mockStorage(toReturn, collectionMethods = {}) {
    storage_1.Storage.db = {
        collection: sinon_1.default.stub().returns(mockCollection(toReturn, collectionMethods))
    };
    return storage_1.Storage;
}
function mockModel(collectionName, toReturn, collectionMethods = {}) {
    if (!storage_1.Storage.db) {
        storage_1.Storage.db = {
            collection: sinon_1.default.stub().returns(mockCollection(toReturn, collectionMethods))
        };
    }
    const collectionFn = storage_1.Storage.db.collection;
    if (collectionFn.withArgs) {
        collectionFn.withArgs(collectionName).returns(mockCollection(toReturn, collectionMethods));
    }
}
function expectObjectToHaveProps(obj, props) {
    (0, chai_1.expect)(obj).to.include.all.keys(Object.keys(props));
    for (const key in props) {
        (0, chai_1.expect)(obj[key]).to.be.a(props[key]);
    }
}
;
function testCoin(coin) {
    (0, chai_1.expect)(coin, 'coin is undefined').to.exist;
    (0, chai_1.expect)(coin, 'coin is not an object').to.be.an('object');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('chain').that.is.a('string', 'coin.chain is not a string');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('network').that.is.a('string', 'coin.network is not a string');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('mintIndex').that.is.a('number', 'coin.mintIndex is not a number');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('mintTxid').that.is.a('string', 'coin.mintTxid is not a string');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('address').that.is.a('string', 'coin.address is not a string');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('coinbase').that.is.a('boolean', 'coin.coinbase is not a boolean');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('mintHeight').that.is.a('number', 'coin.mintHeight is not a number');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('script');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('spentHeight').that.is.a('number', 'coin.spentHeight is not a number');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('value').that.is.a('number', 'coin.value is not a number');
    (0, chai_1.expect)(coin, 'coin test').to.have.property('spentTxid').that.is.a('string', 'coin.spentTxid is not a string');
    if ('confirmations' in coin) {
        (0, chai_1.expect)(coin.confirmations, 'coin.confirmations is not a number').to.be.a('number');
    }
}
const minutesAgo = (minutes) => new Date(Date.now() - 1000 * 60 * minutes);
exports.minutesAgo = minutesAgo;
const randomHex = (characters) => (0, crypto_1.randomBytes)(Math.ceil(characters / 2.0)).toString('hex').slice(0, characters);
exports.randomHex = randomHex;
exports.mongoIdRegex = /^[a-f0-9]{24}$/;
exports.base58Regex = /^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/;
//# sourceMappingURL=index.js.map