From 4c26aff0bafc52053aaf928a4d1936bab4293950 Mon Sep 17 00:00:00 2001 From: rsercano Date: Wed, 23 Sep 2020 13:21:26 +0300 Subject: [PATCH 1/3] fix: checking for invoice support on lnd clients while verifying connection Signed-off-by: rsercano --- lib/lndclient/LndClient.ts | 21 ++++++++++++++++++++- lib/lndclient/errors.ts | 5 +++++ lib/swaps/SwapClient.ts | 8 +++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/lndclient/LndClient.ts b/lib/lndclient/LndClient.ts index 7822153ea..76d5b57fa 100644 --- a/lib/lndclient/LndClient.ts +++ b/lib/lndclient/LndClient.ts @@ -1,4 +1,5 @@ import assert from 'assert'; +import crypto from 'crypto'; import { promises as fs, watch } from 'fs'; import grpc, { ChannelCredentials, ClientReadableStream } from 'grpc'; import path from 'path'; @@ -242,6 +243,10 @@ class LndClient extends SwapClient { private unaryCall = (methodName: Exclude, params: T): Promise => { return new Promise((resolve, reject) => { + if (this.hasNoInvoiceSupport()) { + reject(errors.NO_INVOICE_SUPPORT); + return; + } if (!this.isOperational()) { reject(errors.DISABLED); return; @@ -337,7 +342,9 @@ class LndClient extends SwapClient { let version: string | undefined; let alias: string | undefined; let status = 'Ready'; - if (!this.isOperational()) { + if (this.hasNoInvoiceSupport()) { + status = errors.NO_INVOICE_SUPPORT(this.currency).message; + } else if (!this.isOperational()) { status = errors.DISABLED(this.currency).message; } else if (this.isDisconnected()) { status = errors.UNAVAILABLE(this.currency, this.status).message; @@ -493,6 +500,18 @@ class LndClient extends SwapClient { } this.invoices = new InvoicesClient(this.uri, this.credentials); + try { + const randomHash = crypto.randomBytes(32).toString('hex'); + this.logger.info(`checking hold invoice support with hash: ${randomHash}`); + + await this.addInvoice({ rHash: randomHash, units: 1 }); + await this.removeInvoice(randomHash); + } catch (err) { + const errStr = typeof(err) === 'string' ? err : JSON.stringify(err); + + this.logger.error(`could not add hold invoice, error: ${errStr}`); + this.setStatus(ClientStatus.NoHoldInvoiceSupport); + } if (this.walletUnlocker) { // WalletUnlocker service is disabled when the main Lightning service is available diff --git a/lib/lndclient/errors.ts b/lib/lndclient/errors.ts index d8a13f0cc..fddfd0a09 100644 --- a/lib/lndclient/errors.ts +++ b/lib/lndclient/errors.ts @@ -6,6 +6,7 @@ const errorCodes = { DISABLED: codesPrefix.concat('.1'), UNAVAILABLE: codesPrefix.concat('.2'), NO_ACTIVE_CHANNELS: codesPrefix.concat('.3'), + NO_INVOICE_SUPPORT: codesPrefix.concat('.4'), }; const errors = { @@ -21,6 +22,10 @@ const errors = { message: `lnd-${currency} has no active channels`, code: errorCodes.NO_ACTIVE_CHANNELS, }), + NO_INVOICE_SUPPORT: (currency: string) => ({ + message: `lnd-${currency} has no invoice support`, + code: errorCodes.NO_INVOICE_SUPPORT, + }), }; export { errorCodes }; diff --git a/lib/swaps/SwapClient.ts b/lib/swaps/SwapClient.ts index d184bf413..d31f02bba 100644 --- a/lib/swaps/SwapClient.ts +++ b/lib/swaps/SwapClient.ts @@ -23,6 +23,8 @@ enum ClientStatus { Unlocked, /** The client could not be initialized due to faulty configuration. */ Misconfigured, + /** The server is reachable but hold invoices are not supported. */ + NoHoldInvoiceSupport, } type ChannelBalance = { @@ -212,6 +214,7 @@ abstract class SwapClient extends EventEmitter { case ClientStatus.Disconnected: case ClientStatus.WaitingUnlock: case ClientStatus.OutOfSync: + case ClientStatus.NoHoldInvoiceSupport: // these statuses can only be set on an operational, initalized client validStatusTransition = this.isOperational(); break; @@ -355,7 +358,7 @@ abstract class SwapClient extends EventEmitter { * Returns `true` if the client is enabled and configured properly. */ public isOperational(): boolean { - return !this.isDisabled() && !this.isMisconfigured() && !this.isNotInitialized(); + return !this.isDisabled() && !this.isMisconfigured() && !this.isNotInitialized() && !this.hasNoInvoiceSupport(); } public isDisconnected(): boolean { return this.status === ClientStatus.Disconnected; @@ -369,6 +372,9 @@ abstract class SwapClient extends EventEmitter { public isOutOfSync(): boolean { return this.status === ClientStatus.OutOfSync; } + public hasNoInvoiceSupport(): boolean { + return this.status === ClientStatus.NoHoldInvoiceSupport; + } /** Ends all connections, subscriptions, and timers for for this client. */ public close() { From 17c7cb54c3a55189ca459a9a842a7e2aa4886a6b Mon Sep 17 00:00:00 2001 From: rsercano Date: Fri, 25 Sep 2020 09:18:21 +0300 Subject: [PATCH 2/3] fix: propagating currencies and pairs on database if initDB true even DB is filled Signed-off-by: rsercano --- lib/db/DB.ts | 37 +++++++++++-------------------------- test/unit/DB.spec.ts | 18 +----------------- 2 files changed, 12 insertions(+), 43 deletions(-) diff --git a/lib/db/DB.ts b/lib/db/DB.ts index 3d874c937..52f1a7ffa 100644 --- a/lib/db/DB.ts +++ b/lib/db/DB.ts @@ -1,4 +1,3 @@ -import { promises as fs } from 'fs'; import { derivePairId } from '../utils/utils'; import { ModelCtor, Sequelize } from 'sequelize'; import { XuNetwork } from '../constants/enums'; @@ -137,8 +136,6 @@ class DB { * @param initDb whether to intialize a new database with default values if no database exists */ public init = async (network = XuNetwork.SimNet, initDb = false): Promise => { - const shouldInitDb = initDb && await this.isNewDb(); - try { await this.sequelize.authenticate(); this.logger.info(`connected to database ${this.storage ? this.storage : 'in memory'}`); @@ -177,41 +174,29 @@ class DB { await Node.bulkCreate(newNodes); } } - } - - if (shouldInitDb) { // initialize database with the default currencies for the configured network const currencies = defaultCurrencies(network); if (currencies) { - await Currency.bulkCreate(currencies); + const existingCurrencies = await Models.Currency(this.sequelize).findAll(); + const newCurrencies = currencies.filter(currency => (!existingCurrencies.find(n => (n.id === currency.id)))); + + if (newCurrencies.length > 0) { + await Currency.bulkCreate(newCurrencies); + } } // initialize database with the default trading pairs for the configured network const pairs = defaultPairs(network); if (pairs) { - await Pair.bulkCreate(pairs); - } - } - } + const existingPairs = await Models.Pair(this.sequelize).findAll(); + const newPairs = pairs.filter(pair => (!existingPairs.find(n => (n.baseCurrency === pair.baseCurrency && + n.quoteCurrency === pair.quoteCurrency)))); - /** - * Checks whether the database is new, in other words whether we are not - * loading a preexisting database from disk. - */ - private isNewDb = async () => { - if (this.storage && this.storage !== ':memory:') { - // check if database file exists - try { - await fs.access(this.storage); - return false; - } catch (err) { - if (err.code !== 'ENOENT') { - // we ignore errors due to file not existing, otherwise throw - throw err; + if (newPairs.length > 0) { + await Pair.bulkCreate(newPairs); } } } - return true; } public close = () => { diff --git a/test/unit/DB.spec.ts b/test/unit/DB.spec.ts index cf5cc2177..d0cd239a8 100644 --- a/test/unit/DB.spec.ts +++ b/test/unit/DB.spec.ts @@ -7,7 +7,7 @@ import OrderBookRepository from '../../lib/orderbook/OrderBookRepository'; import P2PRepository from '../../lib/p2p/P2PRepository'; import SwapRepository from '../../lib/swaps/SwapRepository'; import { SwapDeal } from '../../lib/swaps/types'; -import { createOwnOrder, getTempDir } from '../utils'; +import { createOwnOrder } from '../utils'; import chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); @@ -156,19 +156,3 @@ describe('Database', () => { await db.close(); }); }); - -describe('isNewDb', () => { - it('should return true for a database in memory', async () => { - const dbInMemory = new DB(loggers.db); - expect(dbInMemory['isNewDb']()).to.eventually.be.true; - await dbInMemory.init(); - expect(dbInMemory['isNewDb']()).to.eventually.be.true; - }); - - it('should return true before a database on disk is created, false afterwards', async () => { - const dbInMemory = new DB(loggers.db, `${getTempDir(true)}/xud.db`); - expect(dbInMemory['isNewDb']()).to.eventually.be.true; - await dbInMemory.init(); - expect(dbInMemory['isNewDb']()).to.eventually.be.false; - }); -}); From d0e35a928cfe9919141c4d282759c514ac83feda Mon Sep 17 00:00:00 2001 From: Daniel McNally Date: Tue, 29 Sep 2020 12:53:55 -0400 Subject: [PATCH 3/3] test(db): init & seed value tests This refactors the database test suite to use jest instead of mocha and adds new test cases to test the database initialization logic that seeds new databases with default values depending on the network and also updates existing databases with new default values that don't exist in the db. --- test/jest/DB.spec.ts | 264 +++++++++++++++++++++++++++++++++++++++++++ test/unit/DB.spec.ts | 158 -------------------------- 2 files changed, 264 insertions(+), 158 deletions(-) create mode 100644 test/jest/DB.spec.ts delete mode 100644 test/unit/DB.spec.ts diff --git a/test/jest/DB.spec.ts b/test/jest/DB.spec.ts new file mode 100644 index 000000000..7f84f308d --- /dev/null +++ b/test/jest/DB.spec.ts @@ -0,0 +1,264 @@ +import { SwapClientType, SwapPhase, SwapRole, SwapState, XuNetwork } from '../../lib/constants/enums'; +import DB from '../../lib/db/DB'; +import { defaultCurrencies, defaultNodes, defaultPairs } from '../../lib/db/seeds'; +import { TradeCreationAttributes } from '../../lib/db/types'; +import Logger, { Level } from '../../lib/Logger'; +import OrderBookRepository from '../../lib/orderbook/OrderBookRepository'; +import P2PRepository from '../../lib/p2p/P2PRepository'; +import SwapRepository from '../../lib/swaps/SwapRepository'; +import { SwapDeal } from '../../lib/swaps/types'; +import { createOwnOrder } from '../utils'; + +const pairId = 'LTC/BTC'; +const loggers = Logger.createLoggers(Level.Warn); + +const price = 0.005; +const quantity = 10000000; +const peerPubKey = '03029c6a4d80c91da9e40529ec41c93b17cc9d7956b59c7d8334b0318d4a86aef8'; +const rHash = '62c8bbef4587cff4286246e63044dc3e454b5693fb5ebd0171b7e58644bfafe2'; + +const order = createOwnOrder(price, quantity, true); +const orderId = order.id; + +const deal: SwapDeal = { + quantity, + price, + peerPubKey, + rHash, + pairId, + role: SwapRole.Maker, + phase: SwapPhase.PaymentReceived, + state: SwapState.Completed, + orderId: order.id, + localId: order.localId, + isBuy: order.isBuy, + proposedQuantity: quantity, + takerCurrency: 'BTC', + makerCurrency: 'LTC', + takerAmount: 5000, + makerAmount: 1000000, + takerUnits: 5000, + makerUnits: 1000000, + takerCltvDelta: 144, + makerCltvDelta: 144, + rPreimage: '60743C0B6BFA885E30F101705764F43F8EF7E613DD0F07AD5178C7D9B1682B9E', + createTime: 1540716251106, + executeTime: 1540717251106, + completeTime: 1540718251106, +}; + +describe('Database', () => { + let db: DB; + let orderBookRepo: OrderBookRepository; + let p2pRepo: P2PRepository; + let swapRepo: SwapRepository; + + describe('initDb', () => { + const network = XuNetwork.SimNet; + const simnetNodes = defaultNodes(network)!; + const simnetCurrencies = defaultCurrencies(network)!; + const simnetPairs = defaultPairs(network)!; + + beforeEach(() => { + db = new DB(loggers.db); + orderBookRepo = new OrderBookRepository(db.models); + p2pRepo = new P2PRepository(db.models); + swapRepo = new SwapRepository(db.models); + }); + + it('should init the database from scratch', async () => { + await db.init(network, true); + const [nodes, currencies, pairs] = await Promise.all([ + p2pRepo.getNodes(), + orderBookRepo.getCurrencies(), + orderBookRepo.getPairs(), + ]); + + expect(nodes.length).toEqual(simnetNodes.length); + nodes.forEach((node, index) => { + const simnetNode = simnetNodes[index]; + expect(node.nodePubKey).toEqual(simnetNode.nodePubKey); + expect(node.addresses).toEqual(simnetNode.addresses); + }); + + expect(currencies.length).toEqual(simnetCurrencies.length); + currencies.forEach((currency, index) => { + const simnetCurrency = simnetCurrencies[index]; + expect(currency.id).toEqual(simnetCurrency.id); + expect(currency.tokenAddress ?? undefined).toEqual(simnetCurrency.tokenAddress); + }); + + expect(pairs.length).toEqual(simnetPairs.length); + pairs.forEach((pair, index) => { + const simnetPair = simnetPairs[index]; + expect(pair.baseCurrency).toEqual(simnetPair.baseCurrency); + expect(pair.quoteCurrency).toEqual(simnetPair.quoteCurrency); + }); + }); + + it('should add new default values to an existing db', async () => { + await db.init(); + + await Promise.all([ + orderBookRepo.addCurrency({ + id: 'ABC', + swapClient: SwapClientType.Connext, + decimalPlaces: 4, + }), + orderBookRepo.addCurrency({ + id: 'XYZ', + swapClient: SwapClientType.Connext, + decimalPlaces: 18, + }), + p2pRepo.addNodeIfNotExists({ + nodePubKey: peerPubKey, + addresses: [], + }), + ]); + await orderBookRepo.addPair({ + baseCurrency: 'ABC', + quoteCurrency: 'XYZ', + }); + await expect(orderBookRepo.getCurrencies()).resolves.toHaveLength(2); + await expect(orderBookRepo.getPairs()).resolves.toHaveLength(1); + await expect(p2pRepo.getNodes()).resolves.toHaveLength(1); + + await db.init(network, true); + + const [nodes, currencies, pairs] = await Promise.all([ + p2pRepo.getNodes(), + orderBookRepo.getCurrencies(), + orderBookRepo.getPairs(), + ]); + + expect(nodes.length).toEqual(simnetNodes.length + 1); + simnetNodes.forEach((simnetNode, index) => { + const node = nodes[index + 1]; + expect(node.nodePubKey).toEqual(simnetNode.nodePubKey); + expect(node.addresses).toEqual(simnetNode.addresses); + }); + + expect(currencies.length).toEqual(simnetCurrencies.length + 2); + simnetCurrencies.forEach((simnetCurrency, index) => { + const currency = currencies[index + 2]; + expect(currency.id).toEqual(simnetCurrency.id); + expect(currency.tokenAddress ?? undefined).toEqual(simnetCurrency.tokenAddress); + }); + + expect(pairs.length).toEqual(simnetPairs.length + 1); + simnetPairs.forEach((simnetPair, index) => { + const pair = pairs[index + 1]; + expect(pair.baseCurrency).toEqual(simnetPair.baseCurrency); + expect(pair.quoteCurrency).toEqual(simnetPair.quoteCurrency); + }); + }); + + afterEach(async () => { + await db.close(); + }); + }); + + describe('CRUD operations', () => { + beforeAll(async () => { + db = new DB(loggers.db); + await db.init(); + orderBookRepo = new OrderBookRepository(db.models); + p2pRepo = new P2PRepository(db.models); + swapRepo = new SwapRepository(db.models); + }); + + it('should add two currencies', async () => { + const btcPromise = orderBookRepo.addCurrency({ + id: 'BTC', + swapClient: SwapClientType.Lnd, + decimalPlaces: 8, + }); + const ltcPromise = orderBookRepo.addCurrency({ + id: 'LTC', + swapClient: SwapClientType.Lnd, + decimalPlaces: 8, + }); + await Promise.all([btcPromise, ltcPromise]); + await expect(orderBookRepo.getCurrencies()).resolves.toHaveLength(2); + }); + + it('should add a trading pair', async () => { + await orderBookRepo.addPair({ + baseCurrency: 'LTC', + quoteCurrency: 'BTC', + }); + await expect(orderBookRepo.getPairs()).resolves.toHaveLength(1); + }); + + it('should add a node', async () => { + await p2pRepo.addNodeIfNotExists({ + nodePubKey: peerPubKey, + addresses: [], + }); + }); + + it('should add an order', async () => { + await orderBookRepo.addOrderIfNotExists(order); + await expect(db.models.Order.count()).resolves.toEqual(1); + }); + + it('should not add the same order twice', async () => { + await orderBookRepo.addOrderIfNotExists(order); + await expect(db.models.Order.count()).resolves.toEqual(1); + }); + + it('should add a swap and a trade for the order', async () => { + await orderBookRepo.addOrderIfNotExists(order); + const { rHash } = deal; + const trade: TradeCreationAttributes = { rHash, quantity: deal.quantity!, makerOrderId: order.id }; + await orderBookRepo.addTrade(trade); + await swapRepo.saveSwapDeal(deal); + + const swapInstance = await db.models.SwapDeal.findOne({ where: { rHash } }); + expect(swapInstance!.orderId).toEqual(order.id); + const tradeInstance = await db.models.Trade.findOne({ where: { rHash } }); + expect(tradeInstance!.makerOrderId).toEqual(order.id); + }); + + it('should get a swap along with the order for the swap', async () => { + const swap = (await swapRepo.getSwapDeal(rHash))!; + expect(swap.Order!.id).toEqual(orderId); + const order = (await swap.getOrder())!; + expect(order.id).toEqual(orderId); + }); + + it('should get a swap along with its peer node', async () => { + const swap = (await swapRepo.getSwapDeal(rHash))!; + expect(swap.peerPubKey).toEqual(peerPubKey); + const node = (await swap.getNode())!; + expect(node.nodePubKey).toEqual(peerPubKey); + }); + + it('should add market orders and have their price in db be null', async () => { + const buyMarketOrder = createOwnOrder(Number.POSITIVE_INFINITY, quantity, true); + const sellMarketOrder = createOwnOrder(0, quantity, true); + await orderBookRepo.addOrderIfNotExists(buyMarketOrder); + await orderBookRepo.addOrderIfNotExists(sellMarketOrder); + const buyOrder = (await db.models.Order.findByPk(buyMarketOrder.id))!; + const sellOrder = (await db.models.Order.findByPk(sellMarketOrder.id))!; + expect(buyOrder.id).toEqual(buyMarketOrder.id); + expect(sellOrder.id).toEqual(sellMarketOrder.id); + expect(buyOrder.price).toBeNull(); + expect(sellOrder.price).toBeNull(); + }); + + it('should add two own orders and a trade between them', async () => { + const tradeQuantity = 10000000; + const maker = createOwnOrder(price, tradeQuantity, true); + const taker = createOwnOrder(price, tradeQuantity, false); + await Promise.all([orderBookRepo.addOrderIfNotExists(maker), orderBookRepo.addOrderIfNotExists(taker)]); + const trade: TradeCreationAttributes = { quantity: tradeQuantity, makerOrderId: maker.id, takerOrderId: taker.id }; + await orderBookRepo.addTrade(trade); + }); + + afterAll(async () => { + await db.close(); + }); + }); + +}); diff --git a/test/unit/DB.spec.ts b/test/unit/DB.spec.ts deleted file mode 100644 index d0cd239a8..000000000 --- a/test/unit/DB.spec.ts +++ /dev/null @@ -1,158 +0,0 @@ -import chai, { expect } from 'chai'; -import { SwapClientType, SwapPhase, SwapRole, SwapState } from '../../lib/constants/enums'; -import DB from '../../lib/db/DB'; -import { TradeCreationAttributes } from '../../lib/db/types'; -import Logger, { Level } from '../../lib/Logger'; -import OrderBookRepository from '../../lib/orderbook/OrderBookRepository'; -import P2PRepository from '../../lib/p2p/P2PRepository'; -import SwapRepository from '../../lib/swaps/SwapRepository'; -import { SwapDeal } from '../../lib/swaps/types'; -import { createOwnOrder } from '../utils'; -import chaiAsPromised = require('chai-as-promised'); - -chai.use(chaiAsPromised); - -const PAIR_ID = 'LTC/BTC'; -const loggers = Logger.createLoggers(Level.Warn); - -const price = 0.005; -const quantity = 10000000; -const peerPubKey = '03029c6a4d80c91da9e40529ec41c93b17cc9d7956b59c7d8334b0318d4a86aef8'; -const rHash = '62c8bbef4587cff4286246e63044dc3e454b5693fb5ebd0171b7e58644bfafe2'; - -const order = createOwnOrder(price, quantity, true); -const orderId = order.id; - -const deal: SwapDeal = { - quantity, - price, - peerPubKey, - rHash, - role: SwapRole.Maker, - phase: SwapPhase.PaymentReceived, - state: SwapState.Completed, - orderId: order.id, - localId: order.localId, - isBuy: order.isBuy, - proposedQuantity: quantity, - pairId: PAIR_ID, - takerCurrency: 'BTC', - makerCurrency: 'LTC', - takerAmount: 5000, - makerAmount: 1000000, - takerUnits: 5000, - makerUnits: 1000000, - takerCltvDelta: 144, - makerCltvDelta: 144, - rPreimage: '60743C0B6BFA885E30F101705764F43F8EF7E613DD0F07AD5178C7D9B1682B9E', - createTime: 1540716251106, - executeTime: 1540717251106, - completeTime: 1540718251106, -}; - -describe('Database', () => { - const db = new DB(loggers.db); - let orderBookRepo: OrderBookRepository; - let p2pRepo: P2PRepository; - let swapRepo: SwapRepository; - - before(async () => { - await db.init(); - orderBookRepo = new OrderBookRepository(db.models); - p2pRepo = new P2PRepository(db.models); - swapRepo = new SwapRepository(db.models); - }); - - it('should add two currencies', async () => { - const btcPromise = orderBookRepo.addCurrency({ - id: 'BTC', - swapClient: SwapClientType.Lnd, - decimalPlaces: 8, - }); - const ltcPromise = orderBookRepo.addCurrency({ - id: 'LTC', - swapClient: SwapClientType.Lnd, - decimalPlaces: 8, - }); - await Promise.all([btcPromise, ltcPromise]); - await expect(orderBookRepo.getCurrencies()).to.eventually.have.lengthOf(2); - }); - - it('should add a trading pair', async () => { - await orderBookRepo.addPair({ - baseCurrency: 'LTC', - quoteCurrency: 'BTC', - }); - await expect(orderBookRepo.getPairs()).to.eventually.have.lengthOf(1); - }); - - it('should add a node', async () => { - await p2pRepo.addNodeIfNotExists({ - nodePubKey: peerPubKey, - addresses: [], - }); - }); - - it('should add an order', async () => { - await orderBookRepo.addOrderIfNotExists(order); - await expect(db.models.Order.count()).to.eventually.equal(1); - }); - - it('should not add the same order twice', async () => { - await orderBookRepo.addOrderIfNotExists(order); - await expect(db.models.Order.count()).to.eventually.equal(1); - }); - - it('should add a swap and a trade for the order', async () => { - await orderBookRepo.addOrderIfNotExists(order); - const { rHash } = deal; - const trade: TradeCreationAttributes = { rHash, quantity: deal.quantity!, makerOrderId: order.id }; - await orderBookRepo.addTrade(trade); - await swapRepo.saveSwapDeal(deal); - - const swapInstance = await db.models.SwapDeal.findOne({ where: { rHash } }); - expect(swapInstance!.orderId).to.equal(order.id); - const tradeInstance = await db.models.Trade.findOne({ where: { rHash } }); - expect(tradeInstance!.makerOrderId).to.equal(order.id); - }); - - it('should get a swap along with the order for the swap', async () => { - const swap = (await swapRepo.getSwapDeal(rHash))!; - expect(swap.Order!.id).to.equal(orderId); - const order = (await swap.getOrder())!; - expect(order.id).to.equal(orderId); - }); - - it('should get a swap along with its peer node', async () => { - const swap = (await swapRepo.getSwapDeal(rHash))!; - expect(swap.peerPubKey).to.equal(peerPubKey); - const node = (await swap.getNode())!; - expect(node.nodePubKey).to.equal(peerPubKey); - }); - - it('should add market orders and have their price in db be null', async () => { - const buyMarketOrder = createOwnOrder(Number.POSITIVE_INFINITY, quantity, true); - const sellMarketOrder = createOwnOrder(0, quantity, true); - await orderBookRepo.addOrderIfNotExists(buyMarketOrder); - await orderBookRepo.addOrderIfNotExists(sellMarketOrder); - const buyOrder = (await db.models.Order.findByPk(buyMarketOrder.id))!; - const sellOrder = (await db.models.Order.findByPk(sellMarketOrder.id))!; - expect(buyOrder.id).to.equal(buyMarketOrder.id); - expect(sellOrder.id).to.equal(sellMarketOrder.id); - expect(buyOrder.price).to.be.null; - expect(sellOrder.price).to.be.null; - }); - - it('should add two own orders and a trade between them', async () => { - const tradeQuantity = 10000000; - const maker = createOwnOrder(price, tradeQuantity, true); - const taker = createOwnOrder(price, tradeQuantity, false); - await Promise.all([orderBookRepo.addOrderIfNotExists(maker), orderBookRepo.addOrderIfNotExists(taker)]); - const trade: TradeCreationAttributes = { quantity: tradeQuantity, makerOrderId: maker.id, takerOrderId: taker.id }; - await orderBookRepo.addTrade(trade); - }); - - after(async () => { - await db.close(); - }); -});