@sangaman/xud
Version:
Exchange Union Daemon
149 lines • 7.36 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const assert_1 = __importDefault(require("assert"));
const sequelize_1 = __importDefault(require("sequelize"));
const enums_1 = require("../types/enums");
/** A class representing a connection to a SQL database. */
class DB {
constructor(config, logger) {
this.config = config;
this.logger = logger;
this.init = () => __awaiter(this, void 0, void 0, function* () {
let newDb = false;
try {
yield this.sequelize.authenticate();
const { host, port, database } = this.config;
this.logger.info(`connected to database. host:${host} port:${port} database:${database}`);
}
catch (err) {
if (DB.isDbDoesNotExistError(err)) {
newDb = true;
yield this.createDatabase();
}
else {
this.logger.error('unable to connect to the database', err);
throw err;
}
}
const { Node, Currency, Pair } = this.models;
const options = { logging: this.logger.verbose };
// sync schemas with the database in phases, according to FKs dependencies
yield Promise.all([
Node.sync(options),
Currency.sync(options),
]);
yield Promise.all([
Pair.sync(options),
]);
if (newDb) {
// populate new databases with default data
// TODO: make seed peers configurable
yield Node.bulkCreate([
{
nodePubKey: '02b66438730d1fcdf4a4ae5d3d73e847a272f160fee2938e132b52cab0a0d9cfc6',
addresses: [{ host: 'xud1.test.exchangeunion.com', port: 8885 }],
},
{
nodePubKey: '028599d05b18c0c3f8028915a17d603416f7276c822b6b2d20e71a3502bd0f9e0a',
addresses: [{ host: 'xud2.test.exchangeunion.com', port: 8885 }],
},
{
nodePubKey: '03fd337659e99e628d0487e4f87acf93e353db06f754dccc402f2de1b857a319d0',
addresses: [{ host: 'xud3.test.exchangeunion.com', port: 8885 }],
},
]);
yield Currency.bulkCreate([
{ id: 'BTC' },
{ id: 'LTC' },
{ id: 'ZRX' },
{ id: 'GNT' },
]);
yield Pair.bulkCreate([
{ baseCurrency: 'BTC', quoteCurrency: 'LTC', swapProtocol: enums_1.SwapProtocol.LND },
{ baseCurrency: 'ZRX', quoteCurrency: 'GNT', swapProtocol: enums_1.SwapProtocol.RAIDEN },
]);
}
});
this.close = () => {
return this.sequelize.close();
};
this.dropTables = () => {
return this.sequelize.drop();
};
this.truncate = () => __awaiter(this, void 0, void 0, function* () {
yield this.sequelize.transaction((t) => __awaiter(this, void 0, void 0, function* () {
const options = { raw: true, transaction: t };
yield this.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', options);
yield this.sequelize.query('truncate table pairs', options);
yield this.sequelize.query('truncate table currencies', options);
yield this.sequelize.query('truncate table nodes', options);
yield this.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', options);
}));
});
this.createSequelizeInstance = (config) => {
return new sequelize_1.default(Object.assign({}, config, { dialect: 'mysql', operatorsAliases: false, dialectOptions: {
multipleStatements: true,
} }));
};
this.loadModels = () => {
const models = {};
const modelsFolder = path_1.default.join(__dirname, 'models');
fs_1.default.readdirSync(modelsFolder)
.filter(file => (file.indexOf('.') !== 0) && (file !== path_1.default.basename(__filename)) && (file.slice(-3).match(/.js|.ts/)))
.forEach((file) => {
const model = this.sequelize.import(path_1.default.join(modelsFolder, file));
models[model.name] = model;
});
Object.keys(models).forEach((key) => {
const model = models[key];
if (model.associate) {
model.associate(models);
}
});
return models;
};
this.createDatabase = () => __awaiter(this, void 0, void 0, function* () {
try {
const _a = this.config, { database } = _a, databaselessConfig = __rest(_a, ["database"]);
const sequelize = this.createSequelizeInstance(databaselessConfig);
yield sequelize.authenticate();
yield sequelize.query(`CREATE DATABASE ${database} CHARACTER SET utf8 COLLATE utf8_general_ci;`);
yield sequelize.close();
}
catch (err) {
this.logger.error('unable to create the database', err);
throw err;
}
});
assert_1.default(Number.isInteger(config.port) && config.port > 1023 && config.port < 65536, 'port must be an integer between 1024 and 65535');
this.sequelize = this.createSequelizeInstance(this.config);
this.models = this.loadModels();
}
static isDbDoesNotExistError(err) {
return err instanceof sequelize_1.default.ConnectionError && err.original.code === 'ER_BAD_DB_ERROR';
}
}
exports.default = DB;
//# sourceMappingURL=DB.js.map