capitalisk-dex 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "capitalisk-dex",
3
+ "version": "17.0.0",
4
+ "description": "Decentralized exchange module.",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "mocha --reporter spec --timeout 3000 --slow 3000"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Capitalisk/capitalisk-dex.git"
12
+ },
13
+ "keywords": [
14
+ "dex",
15
+ "decentralized",
16
+ "exchange",
17
+ "module"
18
+ ],
19
+ "author": "Jonathan Gros-Dubois",
20
+ "license": "GPL-3.0",
21
+ "dependencies": {
22
+ "big-order-book": "^2.0.0",
23
+ "proper-skip-list": "^4.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "mocha": "^7.2.0"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/Capitalisk/capitalisk-dex/issues"
30
+ },
31
+ "homepage": "https://github.com/Capitalisk/capitalisk-dex#readme"
32
+ }
@@ -0,0 +1,563 @@
1
+ const assert = require('assert');
2
+ const TradeEngine = require('../trade-engine');
3
+
4
+ describe('TradeEngine unit tests', async () => {
5
+ let tradeEngine;
6
+
7
+ beforeEach(async () => {
8
+ tradeEngine = new TradeEngine({
9
+ baseCurrency: 'lsk',
10
+ quoteCurrency: 'clsk',
11
+ baseOrderHeightExpiry: 100,
12
+ quoteOrderHeightExpiry: 100,
13
+ priceDecimalPrecision: 5
14
+ });
15
+ });
16
+
17
+ describe('Order matching', async () => {
18
+
19
+ it('Bid order is made with greater size but same price as ask', async () => {
20
+ let result;
21
+
22
+ result = tradeEngine.addOrder({
23
+ id: 'order0',
24
+ type: 'limit',
25
+ price: .1,
26
+ sourceChain: 'clsk',
27
+ targetChain: 'lsk',
28
+ height: 1,
29
+ targetWalletAddress: '22245678912345678222L',
30
+ senderAddress: '11111111111222222222L',
31
+ side: 'ask',
32
+ size: 100
33
+ });
34
+
35
+ result = tradeEngine.addOrder({
36
+ id: 'order1',
37
+ type: 'limit',
38
+ price: .1,
39
+ sourceChain: 'lsk',
40
+ targetChain: 'clsk',
41
+ height: 1,
42
+ targetWalletAddress: '11145678912345678111L',
43
+ senderAddress: '22222222211111111111L',
44
+ side: 'bid',
45
+ value: 100
46
+ });
47
+
48
+ assert.equal(result.takeSize, 100);
49
+ assert.equal(result.taker.id, 'order1');
50
+ assert.equal(result.taker.valueRemaining, 90);
51
+ });
52
+
53
+ it('Bid order is made with greater size and higher price than ask', async () => {
54
+ let result;
55
+
56
+ result = tradeEngine.addOrder({
57
+ id: 'order0',
58
+ type: 'limit',
59
+ price: .1,
60
+ sourceChain: 'clsk',
61
+ targetChain: 'lsk',
62
+ height: 1,
63
+ targetWalletAddress: '22245678912345678222L',
64
+ senderAddress: '11111111111222222222L',
65
+ side: 'ask',
66
+ size: 100
67
+ });
68
+
69
+ result = tradeEngine.addOrder({
70
+ id: 'order1',
71
+ type: 'limit',
72
+ price: .2,
73
+ sourceChain: 'lsk',
74
+ targetChain: 'clsk',
75
+ height: 1,
76
+ targetWalletAddress: '11145678912345678111L',
77
+ senderAddress: '33311111111222222333L',
78
+ side: 'bid',
79
+ value: 200
80
+ });
81
+
82
+ assert.equal(result.takeSize, 100);
83
+ assert.equal(result.takeValue, 10);
84
+ assert.equal(result.taker.id, 'order1');
85
+ assert.equal(result.taker.value, 200);
86
+ });
87
+
88
+ it('Multiple bid orders in series', async () => {
89
+ let result;
90
+
91
+ result = tradeEngine.addOrder({
92
+ id: 'order0',
93
+ type: 'limit',
94
+ price: .5,
95
+ sourceChain: 'clsk',
96
+ targetChain: 'lsk',
97
+ height: 1,
98
+ targetWalletAddress: '22245678912345678222L',
99
+ senderAddress: '11111111111222222222L',
100
+ side: 'ask',
101
+ size: 4000
102
+ });
103
+
104
+ result = tradeEngine.addOrder({
105
+ id: 'order1',
106
+ type: 'limit',
107
+ price: .5,
108
+ sourceChain: 'lsk',
109
+ targetChain: 'clsk',
110
+ height: 1,
111
+ targetWalletAddress: '11145678912345678111L',
112
+ senderAddress: '44411111111222222444L',
113
+ side: 'bid',
114
+ value: 4
115
+ });
116
+
117
+ assert.equal(result.makers[0].lastValueTaken, 4);
118
+
119
+ result = tradeEngine.addOrder({
120
+ id: 'order2',
121
+ type: 'limit',
122
+ price: .5,
123
+ sourceChain: 'lsk',
124
+ targetChain: 'clsk',
125
+ height: 1,
126
+ targetWalletAddress: '11145678912345678111L',
127
+ senderAddress: '55511111111222222555L',
128
+ side: 'bid',
129
+ value: 20
130
+ });
131
+
132
+ assert.equal(result.makers[0].lastValueTaken, 20);
133
+
134
+ result = tradeEngine.addOrder({
135
+ id: 'order3',
136
+ type: 'limit',
137
+ price: .5,
138
+ sourceChain: 'lsk',
139
+ targetChain: 'clsk',
140
+ height: 1,
141
+ targetWalletAddress: '11145678912345678111L',
142
+ senderAddress: '66611111111222222666L',
143
+ side: 'bid',
144
+ value: 6
145
+ });
146
+
147
+ assert.equal(result.makers[0].lastValueTaken, 6);
148
+ });
149
+
150
+ it('Order with the same ID is not added', async () => {
151
+ let result;
152
+
153
+ result = tradeEngine.addOrder({
154
+ id: 'order0',
155
+ type: 'limit',
156
+ price: .1,
157
+ sourceChain: 'clsk',
158
+ targetChain: 'lsk',
159
+ height: 1,
160
+ targetWalletAddress: '22245678912345678222L',
161
+ senderAddress: '11111111111222222222L',
162
+ side: 'ask',
163
+ size: 100
164
+ });
165
+
166
+ let error = null;
167
+
168
+ try {
169
+ result = tradeEngine.addOrder({
170
+ id: 'order0',
171
+ type: 'limit',
172
+ price: .1,
173
+ sourceChain: 'clsk',
174
+ targetChain: 'lsk',
175
+ height: 2,
176
+ targetWalletAddress: '22245678912345678222L',
177
+ senderAddress: '55511111111222222777L',
178
+ side: 'ask',
179
+ size: 1000
180
+ });
181
+ } catch (err) {
182
+ error = err;
183
+ }
184
+
185
+ assert.notEqual(error, null);
186
+ assert.equal(error.name, 'DuplicateOrderError');
187
+ });
188
+
189
+ it('Can get bid and ask iterators', async () => {
190
+ let result;
191
+
192
+ result = tradeEngine.addOrder({
193
+ id: 'order0',
194
+ type: 'limit',
195
+ price: .5,
196
+ sourceChain: 'clsk',
197
+ targetChain: 'lsk',
198
+ height: 1,
199
+ targetWalletAddress: '22245678912345678222L',
200
+ senderAddress: '11111111111222222222L',
201
+ side: 'ask',
202
+ size: 100
203
+ });
204
+
205
+ result = tradeEngine.addOrder({
206
+ id: 'order1',
207
+ type: 'limit',
208
+ price: .7,
209
+ sourceChain: 'clsk',
210
+ targetChain: 'lsk',
211
+ height: 1,
212
+ targetWalletAddress: '22245678912345678222L',
213
+ senderAddress: '11111111111222222222L',
214
+ side: 'ask',
215
+ size: 100
216
+ });
217
+
218
+ result = tradeEngine.addOrder({
219
+ id: 'order2',
220
+ type: 'limit',
221
+ price: .6,
222
+ sourceChain: 'clsk',
223
+ targetChain: 'lsk',
224
+ height: 1,
225
+ targetWalletAddress: '22245678912345678222L',
226
+ senderAddress: '11111111111222222222L',
227
+ side: 'ask',
228
+ size: 100
229
+ });
230
+
231
+ result = tradeEngine.addOrder({
232
+ id: 'order3',
233
+ type: 'limit',
234
+ price: .4,
235
+ sourceChain: 'clsk',
236
+ targetChain: 'lsk',
237
+ height: 1,
238
+ targetWalletAddress: '22245678912345678222L',
239
+ senderAddress: '11111111111222222222L',
240
+ side: 'bid',
241
+ value: 100
242
+ });
243
+
244
+ result = tradeEngine.addOrder({
245
+ id: 'order4',
246
+ type: 'limit',
247
+ price: .2,
248
+ sourceChain: 'clsk',
249
+ targetChain: 'lsk',
250
+ height: 1,
251
+ targetWalletAddress: '22245678912345678222L',
252
+ senderAddress: '11111111111222222222L',
253
+ side: 'bid',
254
+ value: 100
255
+ });
256
+
257
+ result = tradeEngine.addOrder({
258
+ id: 'order5',
259
+ type: 'limit',
260
+ price: .3,
261
+ sourceChain: 'clsk',
262
+ targetChain: 'lsk',
263
+ height: 1,
264
+ targetWalletAddress: '22245678912345678222L',
265
+ senderAddress: '11111111111222222222L',
266
+ side: 'bid',
267
+ value: 100
268
+ });
269
+
270
+ let bidOrders = [...tradeEngine.getBidIteratorFromMax()];
271
+ let askOrders = [...tradeEngine.getAskIteratorFromMin()];
272
+
273
+ assert.equal(JSON.stringify(bidOrders.map(bid => bid.price)), JSON.stringify([.4, .3, .2]));
274
+ assert.equal(JSON.stringify(askOrders.map(ask => ask.price)), JSON.stringify([.5, .6, .7]));
275
+ });
276
+
277
+ it('Can get and set snapshot of the order book', async () => {
278
+ let result;
279
+
280
+ result = tradeEngine.addOrder({
281
+ id: 'order0',
282
+ type: 'limit',
283
+ price: .5,
284
+ sourceChain: 'clsk',
285
+ targetChain: 'lsk',
286
+ height: 1,
287
+ targetWalletAddress: '22245678912345678222L',
288
+ senderAddress: '11111111111222222222L',
289
+ side: 'ask',
290
+ size: 100
291
+ });
292
+
293
+ result = tradeEngine.addOrder({
294
+ id: 'order1',
295
+ type: 'limit',
296
+ price: .5,
297
+ sourceChain: 'lsk',
298
+ targetChain: 'clsk',
299
+ height: 1,
300
+ targetWalletAddress: '11145678912345678111L',
301
+ senderAddress: '88811111111222222333L',
302
+ side: 'bid',
303
+ value: 4
304
+ });
305
+
306
+ result = tradeEngine.addOrder({
307
+ id: 'order2',
308
+ type: 'limit',
309
+ price: .5,
310
+ sourceChain: 'lsk',
311
+ targetChain: 'clsk',
312
+ height: 1,
313
+ targetWalletAddress: '11145678912345678111L',
314
+ senderAddress: '11555111111222226662L',
315
+ side: 'bid',
316
+ value: 20
317
+ });
318
+
319
+ let snapshot = tradeEngine.getSnapshot();
320
+ tradeEngine.clear();
321
+
322
+ let snapshotAfterClear = tradeEngine.getSnapshot();
323
+
324
+ assert.equal(JSON.stringify(snapshotAfterClear.askLimitOrders), '[]');
325
+ assert.equal(JSON.stringify(snapshotAfterClear.bidLimitOrders), '[]');
326
+
327
+ tradeEngine.setSnapshot(snapshot);
328
+
329
+ result = tradeEngine.addOrder({
330
+ id: 'order3',
331
+ type: 'limit',
332
+ price: .5,
333
+ sourceChain: 'lsk',
334
+ targetChain: 'clsk',
335
+ height: 1,
336
+ targetWalletAddress: '11145678912345678111L',
337
+ senderAddress: '77711111111222442222L',
338
+ side: 'bid',
339
+ value: 6
340
+ });
341
+
342
+ assert.equal(result.makers[0].lastValueTaken, 6);
343
+
344
+ result = tradeEngine.addOrder({
345
+ id: 'order4',
346
+ type: 'limit',
347
+ price: .5,
348
+ sourceChain: 'lsk',
349
+ targetChain: 'clsk',
350
+ height: 1,
351
+ targetWalletAddress: '11145678912345678111L',
352
+ senderAddress: '33331111111222222999L',
353
+ side: 'bid',
354
+ value: 25
355
+ });
356
+ assert.equal(result.makers[0].lastValueTaken, 20);
357
+ });
358
+
359
+ it('The lastSize and lastSizeTaken property should be updated on both taker and makers', async () => {
360
+ let result;
361
+
362
+ result = tradeEngine.addOrder({
363
+ id: 'order0',
364
+ type: 'limit',
365
+ price: .5,
366
+ sourceChain: 'lsk',
367
+ targetChain: 'clsk',
368
+ height: 1,
369
+ targetWalletAddress: '22245678912345678222L',
370
+ senderAddress: '11111111111222222222L',
371
+ side: 'bid',
372
+ value: 140000
373
+ });
374
+
375
+ result = tradeEngine.addOrder({
376
+ id: 'order841',
377
+ type: 'limit',
378
+ price: .55,
379
+ sourceChain: 'clsk',
380
+ targetChain: 'lsk',
381
+ height: 1,
382
+ targetWalletAddress: '11145678912345678111L',
383
+ senderAddress: '22222222211111111111L',
384
+ side: 'ask',
385
+ size: 11800
386
+ });
387
+
388
+ result = tradeEngine.addOrder({
389
+ id: 'order3',
390
+ type: 'limit',
391
+ price: .6,
392
+ sourceChain: 'clsk',
393
+ targetChain: 'lsk',
394
+ height: 1,
395
+ targetWalletAddress: '11145678912345678111L',
396
+ senderAddress: '22222222211111111111L',
397
+ side: 'ask',
398
+ size: 16700
399
+ });
400
+
401
+ result = tradeEngine.addOrder({
402
+ id: 'order567',
403
+ type: 'limit',
404
+ price: .56,
405
+ sourceChain: 'lsk',
406
+ targetChain: 'clsk',
407
+ height: 1,
408
+ targetWalletAddress: '11145678912345678111L',
409
+ senderAddress: '22222222211111111111L',
410
+ side: 'bid',
411
+ value: 19992
412
+ });
413
+
414
+ result = tradeEngine.addOrder({
415
+ id: 'order630',
416
+ type: 'limit',
417
+ price: .56,
418
+ sourceChain: 'clsk',
419
+ targetChain: 'lsk',
420
+ height: 1,
421
+ targetWalletAddress: '11145678912345678111L',
422
+ senderAddress: '22222222211111111111L',
423
+ side: 'ask',
424
+ size: 60000
425
+ });
426
+
427
+ assert.notEqual(result.makers[0], null);
428
+ assert.equal(Math.round(Number(result.makers[0].lastSizeTaken)), 24110);
429
+ });
430
+
431
+ it('Market bid order', async () => {
432
+ let result;
433
+
434
+ result = tradeEngine.addOrder({
435
+ id: 'order0',
436
+ type: 'limit',
437
+ price: .5,
438
+ sourceChain: 'clsk',
439
+ targetChain: 'lsk',
440
+ height: 1,
441
+ targetWalletAddress: '22245678912345678222L',
442
+ senderAddress: '11111111111222222222L',
443
+ side: 'ask',
444
+ size: 100
445
+ });
446
+
447
+ result = tradeEngine.addOrder({
448
+ id: 'order1',
449
+ type: 'market',
450
+ sourceChain: 'lsk',
451
+ targetChain: 'clsk',
452
+ height: 1,
453
+ targetWalletAddress: '11145678912345678111L',
454
+ senderAddress: '22222222211111111111L',
455
+ side: 'bid',
456
+ value: 10
457
+ });
458
+
459
+ assert.equal(result.takeSize, 20);
460
+ assert.equal(result.takeValue, 10);
461
+ assert.equal(result.taker.id, 'order1');
462
+ assert.equal(result.taker.valueRemaining, 0);
463
+ });
464
+
465
+ it('Market ask order', async () => {
466
+ let result;
467
+
468
+ result = tradeEngine.addOrder({
469
+ id: 'order0',
470
+ type: 'limit',
471
+ price: .5,
472
+ sourceChain: 'lsk',
473
+ targetChain: 'clsk',
474
+ height: 1,
475
+ targetWalletAddress: '22245678912345678222L',
476
+ senderAddress: '11111111111222222222L',
477
+ side: 'bid',
478
+ value: 50
479
+ });
480
+
481
+ result = tradeEngine.addOrder({
482
+ id: 'order1',
483
+ type: 'market',
484
+ sourceChain: 'clsk',
485
+ targetChain: 'lsk',
486
+ height: 1,
487
+ targetWalletAddress: '11145678912345678111L',
488
+ senderAddress: '22222222211111111111L',
489
+ side: 'ask',
490
+ size: 50
491
+ });
492
+
493
+ assert.equal(result.takeSize, 50);
494
+ assert.equal(result.takeValue, 25);
495
+ assert.equal(result.taker.id, 'order1');
496
+ assert.equal(result.taker.sizeRemaining, 0);
497
+ });
498
+
499
+ it('Large market bid order', async () => {
500
+ let result;
501
+
502
+ result = tradeEngine.addOrder({
503
+ id: 'order0',
504
+ type: 'limit',
505
+ price: .5,
506
+ sourceChain: 'clsk',
507
+ targetChain: 'lsk',
508
+ height: 1,
509
+ targetWalletAddress: '22245678912345678222L',
510
+ senderAddress: '11111111111222222222L',
511
+ side: 'ask',
512
+ size: 4000000000
513
+ });
514
+
515
+ result = tradeEngine.addOrder({
516
+ id: 'order1',
517
+ type: 'market',
518
+ sourceChain: 'lsk',
519
+ targetChain: 'clsk',
520
+ height: 1,
521
+ targetWalletAddress: '11145678912345678111L',
522
+ senderAddress: '22222222211111111111L',
523
+ side: 'bid',
524
+ value: 2000000000
525
+ });
526
+
527
+ assert.equal(result.takeSize, 4000000000);
528
+ assert.equal(result.takeValue, 2000000000);
529
+ });
530
+
531
+ it('Large market ask order', async () => {
532
+ let result;
533
+
534
+ result = tradeEngine.addOrder({
535
+ id: 'order0',
536
+ type: 'limit',
537
+ price: .5,
538
+ sourceChain: 'lsk',
539
+ targetChain: 'clsk',
540
+ height: 1,
541
+ targetWalletAddress: '22245678912345678222L',
542
+ senderAddress: '11111111111222222222L',
543
+ side: 'bid',
544
+ value: 500000000
545
+ });
546
+
547
+ result = tradeEngine.addOrder({
548
+ id: 'order1',
549
+ type: 'market',
550
+ sourceChain: 'clsk',
551
+ targetChain: 'lsk',
552
+ height: 1,
553
+ targetWalletAddress: '11145678912345678111L',
554
+ senderAddress: '22222222211111111111L',
555
+ side: 'ask',
556
+ size: 2000000000
557
+ });
558
+
559
+ assert.equal(result.takeSize, 1000000000);
560
+ assert.equal(result.takeValue, 500000000);
561
+ });
562
+ });
563
+ });