UNPKG

xud

Version:
260 lines 11.4 kB
"use strict"; 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 (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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const assert_1 = __importDefault(require("assert")); const fs_1 = require("fs"); const sequelize_1 = require("sequelize"); const enums_1 = require("../constants/enums"); const seeds_1 = require("../db/seeds"); const utils_1 = require("../utils/utils"); const migrations_1 = __importDefault(require("./migrations")); const Models = __importStar(require("./models")); function loadModels(sequelize) { const models = { Currency: Models.Currency(sequelize), Node: Models.Node(sequelize), Order: Models.Order(sequelize), Pair: Models.Pair(sequelize), ReputationEvent: Models.ReputationEvent(sequelize), SwapDeal: Models.SwapDeal(sequelize), Trade: Models.Trade(sequelize), Password: Models.Password(sequelize), }; models.Currency.hasMany(models.Pair, { as: 'quoteCurrencies', foreignKey: 'quoteCurrency', constraints: true, }); models.Currency.hasMany(models.Pair, { as: 'baseCurrencies', foreignKey: 'baseCurrency', constraints: true, }); models.Node.hasMany(models.ReputationEvent, { foreignKey: 'nodeId', constraints: true, }); models.Order.belongsTo(models.Node, { foreignKey: 'nodeId', constraints: true, }); models.Order.belongsTo(models.Pair, { foreignKey: 'pairId', constraints: false, }); models.Order.hasMany(models.Trade, { as: 'makerTrades', foreignKey: 'makerOrderId', constraints: true, }); models.Order.hasMany(models.Trade, { as: 'takerTrades', foreignKey: 'takerOrderId', constraints: true, }); models.Order.hasMany(models.SwapDeal, { foreignKey: 'orderId', constraints: true, }); models.Pair.belongsTo(models.Currency, { as: 'baseCurrencyInstance', constraints: true, foreignKey: 'baseCurrency', }); models.Pair.belongsTo(models.Currency, { as: 'takerCurrencyInstance', constraints: true, foreignKey: 'quoteCurrency', }); models.Pair.beforeBulkCreate(pairs => pairs.forEach(pair => pair.id = utils_1.derivePairId(pair))); models.Pair.beforeCreate((pair) => { pair.id = utils_1.derivePairId(pair); }); models.ReputationEvent.belongsTo(models.Node, { foreignKey: 'nodeId', constraints: true, }); models.SwapDeal.belongsTo(models.Order, { foreignKey: 'orderId', constraints: true, }); models.SwapDeal.belongsTo(models.Node, { foreignKey: 'nodeId', constraints: true, }); models.Trade.belongsTo(models.Order, { as: 'makerOrder', foreignKey: 'makerOrderId', constraints: true, }); models.Trade.belongsTo(models.Order, { as: 'takerOrder', foreignKey: 'takerOrderId', constraints: false, }); models.Trade.belongsTo(models.SwapDeal, { foreignKey: 'rHash', constraints: false, }); return models; } /** A class representing a connection to a SQL database. */ let DB = /** @class */ (() => { class DB { /** * @param storage the file path for the sqlite database file, if ':memory:' or not specified the db is stored in memory */ constructor(logger, storage) { this.logger = logger; this.storage = storage; /** * Initialize the connection to the database. * @param initDb whether to intialize a new database with default values if no database exists */ this.init = (network = enums_1.XuNetwork.SimNet, initDb = false) => __awaiter(this, void 0, void 0, function* () { const isNewDb = yield this.isNewDb(); try { yield this.sequelize.authenticate(); this.logger.info(`connected to database ${this.storage ? this.storage : 'in memory'}`); } catch (err) { this.logger.error('unable to connect to the database', err); throw err; } if (isNewDb) { yield this.sequelize.query(`PRAGMA user_version=${DB.VERSION};`); } // version is useful for tracking migrations & upgrades to the xud database when // the database schema is modified or restructured let version; const userVersionPragma = (yield this.sequelize.query('PRAGMA user_version;')); assert_1.default(Array.isArray(userVersionPragma) && Array.isArray(userVersionPragma[0])); const userVersion = userVersionPragma[0][0].user_version; assert_1.default(typeof userVersion === 'number'); version = userVersion; this.logger.trace(`db version is ${version}`); if (version <= DB.VERSION) { // if our db is not the latest version, we call each migration procedure necessary // to bring us from our current version up to the latest version. for (let n = version; n < DB.VERSION; n += 1) { this.logger.info(`migrating db from version ${n} to version ${n + 1}`); yield migrations_1.default[n](this.sequelize); yield this.sequelize.query(`PRAGMA user_version=${n + 1};`); this.logger.info(`migration to version ${n + 1} complete`); } } const { Node, Currency, Pair, ReputationEvent, SwapDeal, Order, Trade, Password } = this.models; // sync schemas with the database in phases, according to FKs dependencies yield Promise.all([ Node.sync(), Currency.sync(), Password.sync(), ]); // Pair is dependent on Currency, ReputationEvent is dependent on Node yield Promise.all([ Pair.sync(), ReputationEvent.sync(), ]); // Order is dependent on Pair yield Promise.all([ Order.sync(), ]); yield Promise.all([ Trade.sync(), SwapDeal.sync(), ]); if (initDb) { // initialize database with the seed nodes for the configured network const nodes = seeds_1.defaultNodes(network); if (nodes) { const existingNodes = yield Models.Node(this.sequelize).findAll(); const newNodes = nodes.filter(node => (!existingNodes.find(n => (n.nodePubKey === node.nodePubKey)))); if (newNodes.length > 0) { yield Node.bulkCreate(newNodes); } } // initialize database with the default currencies for the configured network const currencies = seeds_1.defaultCurrencies(network); if (currencies) { const existingCurrencies = yield Models.Currency(this.sequelize).findAll(); const newCurrencies = currencies.filter(currency => (!existingCurrencies.find(n => (n.id === currency.id)))); if (newCurrencies.length > 0) { yield Currency.bulkCreate(newCurrencies); } } // initialize database with the default trading pairs for the configured network const pairs = seeds_1.defaultPairs(network); if (pairs) { const existingPairs = yield Models.Pair(this.sequelize).findAll(); const newPairs = pairs.filter(pair => (!existingPairs.find(n => (n.baseCurrency === pair.baseCurrency && n.quoteCurrency === pair.quoteCurrency)))); if (newPairs.length > 0) { yield Pair.bulkCreate(newPairs); } } } }); /** * Checks whether the database is new, in other words whether we are not * loading a preexisting database from disk. */ this.isNewDb = () => __awaiter(this, void 0, void 0, function* () { if (this.storage && this.storage !== ':memory:') { // check if database file exists try { yield fs_1.promises.access(this.storage); return false; } catch (err) { if (err.code !== 'ENOENT') { // we ignore errors due to file not existing, otherwise throw throw err; } } } return true; }); this.close = () => { return this.sequelize.close(); }; this.sequelize = new sequelize_1.Sequelize({ storage, logging: this.logger.trace, dialect: 'sqlite', }); this.models = loadModels(this.sequelize); } } DB.VERSION = 1; return DB; })(); exports.default = DB; //# sourceMappingURL=DB.js.map