@bopen-io/wallet-toolbox 2.15.0-bopen.1 → 2.15.0-bopen.2
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/CHANGELOG.md +2 -47
- package/README.md +7 -73
- package/docs/client.md +2729 -3020
- package/docs/monitor.md +153 -164
- package/docs/services.md +710 -856
- package/docs/setup.md +1 -46
- package/docs/storage.md +1636 -1654
- package/docs/wallet.md +1842 -2090
- package/out/src/Setup.d.ts +0 -10
- package/out/src/Setup.d.ts.map +1 -1
- package/out/src/Setup.js +0 -24
- package/out/src/Setup.js.map +1 -1
- package/out/src/monitor/MonitorDaemon.d.ts +0 -2
- package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
- package/out/src/monitor/MonitorDaemon.js +1 -9
- package/out/src/monitor/MonitorDaemon.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts +0 -5
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +3 -11
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +0 -3
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +207 -115
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/adminServer/adminServer.d.ts.map +1 -1
- package/out/src/storage/adminServer/adminServer.js +41 -3
- package/out/src/storage/adminServer/adminServer.js.map +1 -1
- package/out/src/storage/index.all.d.ts +0 -1
- package/out/src/storage/index.all.d.ts.map +1 -1
- package/out/src/storage/index.all.js +0 -1
- package/out/src/storage/index.all.js.map +1 -1
- package/out/src/storage/methods/listActionsKnex.d.ts.map +1 -1
- package/out/src/storage/methods/listActionsKnex.js +1 -0
- package/out/src/storage/methods/listActionsKnex.js.map +1 -1
- package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
- package/out/src/storage/methods/listOutputsKnex.js +1 -0
- package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
- package/out/src/storage/methods/purgeData.d.ts.map +1 -1
- package/out/src/storage/methods/purgeData.js +3 -0
- package/out/src/storage/methods/purgeData.js.map +1 -1
- package/out/src/storage/methods/reviewStatus.d.ts.map +1 -1
- package/out/src/storage/methods/reviewStatus.js +3 -0
- package/out/src/storage/methods/reviewStatus.js.map +1 -1
- package/out/src/storage/portable/index.js +12 -38
- package/out/src/storage/portable/index.js.map +1 -1
- package/out/src/storage/remoting/StorageServer.d.ts +4 -17
- package/out/src/storage/remoting/StorageServer.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageServer.js +13 -22
- package/out/src/storage/remoting/StorageServer.js.map +1 -1
- package/out/src/storage/schema/KnexMigrations.d.ts +2 -7
- package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
- package/out/src/storage/schema/KnexMigrations.js +60 -162
- package/out/src/storage/schema/KnexMigrations.js.map +1 -1
- package/package.json +4 -5
- package/out/src/storage/adminServer/reqReviewQuery.d.ts +0 -41
- package/out/src/storage/adminServer/reqReviewQuery.d.ts.map +0 -1
- package/out/src/storage/adminServer/reqReviewQuery.js +0 -67
- package/out/src/storage/adminServer/reqReviewQuery.js.map +0 -1
- package/out/src/storage/knexPostgres.d.ts +0 -16
- package/out/src/storage/knexPostgres.d.ts.map +0 -1
- package/out/src/storage/knexPostgres.js +0 -34
- package/out/src/storage/knexPostgres.js.map +0 -1
|
@@ -12,7 +12,6 @@ const WERR_errors_1 = require("../sdk/WERR_errors");
|
|
|
12
12
|
const utilityHelpers_1 = require("../utility/utilityHelpers");
|
|
13
13
|
const managedChange_1 = require("./methods/managedChange");
|
|
14
14
|
const preparedBeef_1 = require("./methods/preparedBeef");
|
|
15
|
-
const knexPostgres_1 = require("./knexPostgres");
|
|
16
15
|
// Keep bulk statements below conservative SQLite/MySQL bind-parameter
|
|
17
16
|
// ceilings. The surrounding transaction still makes a complete pack atomic.
|
|
18
17
|
const ACTION_BATCH_BLOB_SQL_CHUNK = 500;
|
|
@@ -48,7 +47,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
48
47
|
if (options.knex == null)
|
|
49
48
|
throw new WERR_errors_1.WERR_INVALID_PARAMETER('options.knex', 'valid');
|
|
50
49
|
this.knex = options.knex;
|
|
51
|
-
(
|
|
50
|
+
parsePostgresInt8AsNumber(this.knex);
|
|
52
51
|
this.preparedBeefPolicy = (0, preparedBeef_1.validatePreparedBeefPolicy)(options.preparedBeef);
|
|
53
52
|
this.preparedBeefCoordinator = new preparedBeef_1.PreparedBeefCoordinator(this);
|
|
54
53
|
if (this.telemetry.enabled) {
|
|
@@ -261,6 +260,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
261
260
|
.whereNull('pb.preparedBeefId')
|
|
262
261
|
.select('o.userId', 'o.txid as rootTxid')
|
|
263
262
|
.groupBy('o.userId', 'o.txid')
|
|
263
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
264
264
|
.orderByRaw('MIN(??)', ['o.outputId'])
|
|
265
265
|
.limit(limit));
|
|
266
266
|
return rows;
|
|
@@ -387,6 +387,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
387
387
|
void this.whereExists(k
|
|
388
388
|
.select('*')
|
|
389
389
|
.from('transactions')
|
|
390
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
390
391
|
.whereRaw('?? = ?? and ?? = ?', [
|
|
391
392
|
'proven_txs.provenTxId',
|
|
392
393
|
'transactions.provenTxId',
|
|
@@ -414,6 +415,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
414
415
|
void this.whereExists(k
|
|
415
416
|
.select('*')
|
|
416
417
|
.from('transactions')
|
|
418
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
417
419
|
.whereRaw('proven_tx_reqs.txid = transactions.txid and ?? = ?', ['transactions.userId', args.userId]));
|
|
418
420
|
});
|
|
419
421
|
if (args.paged != null) {
|
|
@@ -435,6 +437,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
435
437
|
let q = k('tx_labels_map').whereExists(k
|
|
436
438
|
.select('*')
|
|
437
439
|
.from('tx_labels')
|
|
440
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
438
441
|
.whereRaw('?? = ?? and ?? = ?', [
|
|
439
442
|
'tx_labels.txLabelId',
|
|
440
443
|
'tx_labels_map.txLabelId',
|
|
@@ -460,6 +463,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
460
463
|
let q = k('output_tags_map').whereExists(k
|
|
461
464
|
.select('*')
|
|
462
465
|
.from('output_tags')
|
|
466
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
463
467
|
.whereRaw('?? = ?? and ?? = ?', [
|
|
464
468
|
'output_tags.outputTagId',
|
|
465
469
|
'output_tags_map.outputTagId',
|
|
@@ -532,20 +536,16 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
532
536
|
/**
|
|
533
537
|
* Insert one row and return its auto-increment primary key. MySQL and SQLite
|
|
534
538
|
* report the id as the insert result; Postgres requires a RETURNING clause.
|
|
535
|
-
*
|
|
536
|
-
* `recoverable` marks inserts that the findOrInsert helpers retry as a find
|
|
537
|
-
* after a duplicate-key error, in the same transaction; see `inSavepoint`.
|
|
538
539
|
*/
|
|
539
|
-
async insertReturningId(table, idColumn, row, trx
|
|
540
|
+
async insertReturningId(table, idColumn, row, trx) {
|
|
540
541
|
if (this.dbtype !== 'Postgres') {
|
|
541
542
|
const [id] = await this.toDb(trx)(table).insert(row);
|
|
542
543
|
return id;
|
|
543
544
|
}
|
|
544
|
-
|
|
545
|
+
return await this.inSavepoint(trx, async (db) => {
|
|
545
546
|
const [r] = await db(table).insert(row).returning(idColumn);
|
|
546
547
|
return r[idColumn];
|
|
547
|
-
};
|
|
548
|
-
return recoverable ? await this.inSavepoint(trx, insert) : await insert(this.toDb(trx));
|
|
548
|
+
});
|
|
549
549
|
}
|
|
550
550
|
/**
|
|
551
551
|
* The findOrInsert helpers catch a failed insert and find the row again in
|
|
@@ -562,7 +562,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
562
562
|
const e = await this.validateEntityForInsert(tx, trx);
|
|
563
563
|
if (e.provenTxId === 0)
|
|
564
564
|
delete e.provenTxId;
|
|
565
|
-
const id = await this.insertReturningId('proven_txs', 'provenTxId', e, trx
|
|
565
|
+
const id = await this.insertReturningId('proven_txs', 'provenTxId', e, trx);
|
|
566
566
|
tx.provenTxId = id;
|
|
567
567
|
return tx.provenTxId;
|
|
568
568
|
}
|
|
@@ -690,7 +690,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
690
690
|
const e = await this.validateEntityForInsert(tx, trx);
|
|
691
691
|
if (e.provenTxReqId === 0)
|
|
692
692
|
delete e.provenTxReqId;
|
|
693
|
-
const id = await this.insertReturningId('proven_tx_reqs', 'provenTxReqId', e, trx
|
|
693
|
+
const id = await this.insertReturningId('proven_tx_reqs', 'provenTxReqId', e, trx);
|
|
694
694
|
tx.provenTxReqId = id;
|
|
695
695
|
return tx.provenTxReqId;
|
|
696
696
|
}
|
|
@@ -737,7 +737,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
737
737
|
const e = await this.validateEntityForInsert(basket, trx, undefined, ['isDeleted']);
|
|
738
738
|
if (e.basketId === 0)
|
|
739
739
|
delete e.basketId;
|
|
740
|
-
const id = await this.insertReturningId('output_baskets', 'basketId', e, trx
|
|
740
|
+
const id = await this.insertReturningId('output_baskets', 'basketId', e, trx);
|
|
741
741
|
basket.basketId = id;
|
|
742
742
|
return basket.basketId;
|
|
743
743
|
}
|
|
@@ -745,7 +745,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
745
745
|
const e = await this.validateEntityForInsert(tx, trx);
|
|
746
746
|
if (e.transactionId === 0)
|
|
747
747
|
delete e.transactionId;
|
|
748
|
-
const id = await this.insertReturningId('transactions', 'transactionId', e, trx
|
|
748
|
+
const id = await this.insertReturningId('transactions', 'transactionId', e, trx);
|
|
749
749
|
tx.transactionId = id;
|
|
750
750
|
return tx.transactionId;
|
|
751
751
|
}
|
|
@@ -782,7 +782,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
782
782
|
const e = await this.validateEntityForInsert(tag, trx, undefined, ['isDeleted']);
|
|
783
783
|
if (e.outputTagId === 0)
|
|
784
784
|
delete e.outputTagId;
|
|
785
|
-
const id = await this.insertReturningId('output_tags', 'outputTagId', e, trx
|
|
785
|
+
const id = await this.insertReturningId('output_tags', 'outputTagId', e, trx);
|
|
786
786
|
tag.outputTagId = id;
|
|
787
787
|
return tag.outputTagId;
|
|
788
788
|
}
|
|
@@ -794,7 +794,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
794
794
|
const e = await this.validateEntityForInsert(label, trx, undefined, ['isDeleted']);
|
|
795
795
|
if (e.txLabelId === 0)
|
|
796
796
|
delete e.txLabelId;
|
|
797
|
-
const id = await this.insertReturningId('tx_labels', 'txLabelId', e, trx
|
|
797
|
+
const id = await this.insertReturningId('tx_labels', 'txLabelId', e, trx);
|
|
798
798
|
label.txLabelId = id;
|
|
799
799
|
return label.txLabelId;
|
|
800
800
|
}
|
|
@@ -1364,27 +1364,13 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1364
1364
|
if (isSQLite) {
|
|
1365
1365
|
await this.knex.raw('PRAGMA foreign_keys = OFF;');
|
|
1366
1366
|
}
|
|
1367
|
-
const isPostgres = this.knex.client.dialect === 'postgresql';
|
|
1368
1367
|
try {
|
|
1369
1368
|
const config = {
|
|
1370
|
-
migrationSource: new KnexMigrations_1.KnexMigrations(this.chain, storageName, storageIdentityKey, 1024
|
|
1369
|
+
migrationSource: new KnexMigrations_1.KnexMigrations(this.chain, storageName, storageIdentityKey, 1024),
|
|
1371
1370
|
// Keep DDL and its migration journal entry in the same transaction.
|
|
1372
1371
|
disableTransactions: false
|
|
1373
1372
|
};
|
|
1374
|
-
|
|
1375
|
-
// Postgres index migrations run outside a transaction (CREATE INDEX
|
|
1376
|
-
// CONCURRENTLY). When any pending migration does, knex's latest()
|
|
1377
|
-
// journals every migration of the batch outside its transaction, so
|
|
1378
|
-
// run one migration per up() to keep the others atomic with their journal row.
|
|
1379
|
-
for (;;) {
|
|
1380
|
-
const [, applied] = (await this.knex.migrate.up(config));
|
|
1381
|
-
if (applied.length === 0)
|
|
1382
|
-
break;
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
else {
|
|
1386
|
-
await this.knex.migrate.latest(config);
|
|
1387
|
-
}
|
|
1373
|
+
await this.knex.migrate.latest(config);
|
|
1388
1374
|
return await this.knex.migrate.currentVersion(config);
|
|
1389
1375
|
}
|
|
1390
1376
|
finally {
|
|
@@ -1619,6 +1605,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1619
1605
|
void this.select(1)
|
|
1620
1606
|
.from('action_batch_outputs as abo')
|
|
1621
1607
|
.join('action_batches as ab', 'abo.actionBatchId', 'ab.actionBatchId')
|
|
1608
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
1622
1609
|
.whereRaw('?? = ??', ['abo.outputId', 'o.outputId'])
|
|
1623
1610
|
.whereIn('ab.status', ['active', 'prepared'])
|
|
1624
1611
|
.where('ab.expiresAt', '>', now)
|
|
@@ -1653,6 +1640,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1653
1640
|
void this.select(1)
|
|
1654
1641
|
.from('action_batch_outputs as abo')
|
|
1655
1642
|
.join('action_batches as ab', 'abo.actionBatchId', 'ab.actionBatchId')
|
|
1643
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
1656
1644
|
.whereRaw('?? = ??', ['abo.outputId', 'o.outputId'])
|
|
1657
1645
|
.whereIn('ab.status', ['active', 'prepared'])
|
|
1658
1646
|
.where('ab.expiresAt', '>', now)
|
|
@@ -1687,6 +1675,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1687
1675
|
void this.select(1)
|
|
1688
1676
|
.from('action_batch_outputs as abo')
|
|
1689
1677
|
.join('action_batches as ab', 'abo.actionBatchId', 'ab.actionBatchId')
|
|
1678
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
1690
1679
|
.whereRaw('?? = ??', ['abo.outputId', 'o.outputId'])
|
|
1691
1680
|
.whereIn('ab.status', ['active', 'prepared'])
|
|
1692
1681
|
.where('ab.expiresAt', '>', now)
|
|
@@ -1876,6 +1865,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1876
1865
|
const status = ['completed', 'unproven'];
|
|
1877
1866
|
if (!excludeSending)
|
|
1878
1867
|
status.push('sending');
|
|
1868
|
+
let reservedConcurrently = false;
|
|
1879
1869
|
const r = await this.knex.transaction(async (trx) => {
|
|
1880
1870
|
const baseQuery = () => trx('outputs as o')
|
|
1881
1871
|
.join('transactions as t', 'o.transactionId', 't.transactionId')
|
|
@@ -1894,42 +1884,36 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1894
1884
|
.whereNot('o.derivationSuffix', '')
|
|
1895
1885
|
.whereNull('o.spentBy')
|
|
1896
1886
|
.whereNotExists(function () {
|
|
1887
|
+
// ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
|
|
1897
1888
|
void this.select(1).from('action_batch_outputs as abo').whereRaw('?? = ??', ['abo.outputId', 'o.outputId']);
|
|
1898
1889
|
})
|
|
1899
1890
|
.whereIn('t.status', status)
|
|
1900
1891
|
.select('o.*')
|
|
1901
1892
|
.forUpdate();
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
.first();
|
|
1919
|
-
return output;
|
|
1920
|
-
};
|
|
1921
|
-
let output = await selectOutput();
|
|
1893
|
+
let output;
|
|
1894
|
+
if (exactSatoshis !== undefined) {
|
|
1895
|
+
output = await baseQuery().where('o.satoshis', exactSatoshis).orderBy('o.outputId', 'asc').first();
|
|
1896
|
+
}
|
|
1897
|
+
output ??= await baseQuery()
|
|
1898
|
+
.where('o.satoshis', '>=', targetSatoshis)
|
|
1899
|
+
.orderBy('o.satoshis', 'asc')
|
|
1900
|
+
.orderBy('o.outputId', 'asc')
|
|
1901
|
+
.first();
|
|
1902
|
+
output ??= await baseQuery()
|
|
1903
|
+
.where('o.satoshis', '<', targetSatoshis)
|
|
1904
|
+
.orderBy('o.satoshis', 'desc')
|
|
1905
|
+
.orderBy('o.outputId', 'desc')
|
|
1906
|
+
.first();
|
|
1907
|
+
if (output == null)
|
|
1908
|
+
return undefined;
|
|
1922
1909
|
// Under Postgres READ COMMITTED the NOT EXISTS above uses the statement's
|
|
1923
1910
|
// snapshot, so an action batch reservation committed while the statement
|
|
1924
|
-
// waited for the row lock is not visible to it.
|
|
1925
|
-
|
|
1926
|
-
this.dbtype === 'Postgres' &&
|
|
1911
|
+
// waited for the row lock is not visible to it. Retry in a new transaction.
|
|
1912
|
+
if (this.dbtype === 'Postgres' &&
|
|
1927
1913
|
(await this.findReservedActionBatchOutputIds([output.outputId], trx)).length > 0) {
|
|
1928
|
-
|
|
1929
|
-
output = await selectOutput();
|
|
1930
|
-
}
|
|
1931
|
-
if (output == null)
|
|
1914
|
+
reservedConcurrently = true;
|
|
1932
1915
|
return undefined;
|
|
1916
|
+
}
|
|
1933
1917
|
await this.updateOutput(output.outputId, {
|
|
1934
1918
|
spendable: false,
|
|
1935
1919
|
spentBy: transactionId
|
|
@@ -1941,6 +1925,8 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
1941
1925
|
output.spentBy = transactionId;
|
|
1942
1926
|
return output;
|
|
1943
1927
|
});
|
|
1928
|
+
if (reservedConcurrently)
|
|
1929
|
+
return await this.allocateChangeInput(userId, basketId, targetSatoshis, exactSatoshis, excludeSending, transactionId);
|
|
1944
1930
|
return r;
|
|
1945
1931
|
}
|
|
1946
1932
|
async markChangeInputsSpent(outputIds, transactionId, trx) {
|
|
@@ -2006,8 +1992,8 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
2006
1992
|
return entities;
|
|
2007
1993
|
}
|
|
2008
1994
|
async adminStats(adminIdentityKey) {
|
|
2009
|
-
if (this.dbtype !== 'MySQL'
|
|
2010
|
-
throw new WERR_errors_1.WERR_NOT_IMPLEMENTED('adminStats, only MySQL
|
|
1995
|
+
if (this.dbtype !== 'MySQL')
|
|
1996
|
+
throw new WERR_errors_1.WERR_NOT_IMPLEMENTED('adminStats, only MySQL is supported');
|
|
2011
1997
|
const monitorEvent = (0, utilityHelpers_1.verifyOneOrNone)(await this.findMonitorEvents({
|
|
2012
1998
|
partial: { event: 'MonitorCallHistory' },
|
|
2013
1999
|
orderDescending: true,
|
|
@@ -2015,66 +2001,153 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
|
|
|
2015
2001
|
}));
|
|
2016
2002
|
const monitorStats = monitorEvent != null ? JSON.parse(monitorEvent.details) : undefined;
|
|
2017
2003
|
const servicesStats = this.getServices().getServicesCallHistory(true);
|
|
2018
|
-
const
|
|
2019
|
-
const
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2004
|
+
const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
|
|
2005
|
+
const oneWeekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
2006
|
+
const oneMonthAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
|
|
2007
|
+
const [[{ usersDay, usersMonth, usersWeek, usersTotal, transactionsDay, transactionsMonth, transactionsWeek, transactionsTotal, txCompletedDay, txCompletedMonth, txCompletedWeek, txCompletedTotal, txFailedDay, txFailedMonth, txFailedWeek, txFailedTotal, txAbandonedDay, txAbandonedMonth, txAbandonedWeek, txAbandonedTotal, txUnprocessedDay, txUnprocessedMonth, txUnprocessedWeek, txUnprocessedTotal, txSendingDay, txSendingMonth, txSendingWeek, txSendingTotal, txUnprovenDay, txUnprovenMonth, txUnprovenWeek, txUnprovenTotal, txUnsignedDay, txUnsignedMonth, txUnsignedWeek, txUnsignedTotal, txNosendDay, txNosendMonth, txNosendWeek, txNosendTotal, txNonfinalDay, txNonfinalMonth, txNonfinalWeek, txNonfinalTotal, txUnfailDay, txUnfailMonth, txUnfailWeek, txUnfailTotal, satoshisDefaultDay, satoshisDefaultMonth, satoshisDefaultWeek, satoshisDefaultTotal, satoshisOtherDay, satoshisOtherMonth, satoshisOtherWeek, satoshisOtherTotal, basketsDay, basketsMonth, basketsWeek, basketsTotal, labelsDay, labelsMonth, labelsWeek, labelsTotal, tagsDay, tagsMonth, tagsWeek, tagsTotal }]] = await this.knex.raw(`
|
|
2008
|
+
select
|
|
2009
|
+
(select count(*) from users where created_at > '${oneDayAgo}') as usersDay,
|
|
2010
|
+
(select count(*) from users where created_at > '${oneWeekAgo}') as usersWeek,
|
|
2011
|
+
(select count(*) from users where created_at > '${oneMonthAgo}') as usersMonth,
|
|
2012
|
+
(select count(*) from users) as usersTotal,
|
|
2013
|
+
(select count(*) from transactions where created_at > '${oneDayAgo}') as transactionsDay,
|
|
2014
|
+
(select count(*) from transactions where created_at > '${oneWeekAgo}') as transactionsWeek,
|
|
2015
|
+
(select count(*) from transactions where created_at > '${oneMonthAgo}') as transactionsMonth,
|
|
2016
|
+
(select count(*) from transactions) as transactionsTotal,
|
|
2017
|
+
(select count(*) from transactions where status = 'completed' and created_at > '${oneDayAgo}') as txCompletedDay,
|
|
2018
|
+
(select count(*) from transactions where status = 'completed' and created_at > '${oneWeekAgo}') as txCompletedWeek,
|
|
2019
|
+
(select count(*) from transactions where status = 'completed' and created_at > '${oneMonthAgo}') as txCompletedMonth,
|
|
2020
|
+
(select count(*) from transactions where status = 'completed') as txCompletedTotal,
|
|
2021
|
+
(select count(*) from transactions where status = 'failed' and not txid is null and created_at > '${oneDayAgo}') as txFailedDay,
|
|
2022
|
+
(select count(*) from transactions where status = 'failed' and not txid is null and created_at > '${oneWeekAgo}') as txFailedWeek,
|
|
2023
|
+
(select count(*) from transactions where status = 'failed' and not txid is null and created_at > '${oneMonthAgo}') as txFailedMonth,
|
|
2024
|
+
(select count(*) from transactions where status = 'failed' and not txid is null) as txFailedTotal,
|
|
2025
|
+
(select count(*) from transactions where status = 'failed' and txid is null and created_at > '${oneDayAgo}') as txAbandonedDay,
|
|
2026
|
+
(select count(*) from transactions where status = 'failed' and txid is null and created_at > '${oneWeekAgo}') as txAbandonedWeek,
|
|
2027
|
+
(select count(*) from transactions where status = 'failed' and txid is null and created_at > '${oneMonthAgo}') as txAbandonedMonth,
|
|
2028
|
+
(select count(*) from transactions where status = 'failed' and txid is null) as txAbandonedTotal,
|
|
2029
|
+
(select count(*) from transactions where status = 'unprocessed' and created_at > '${oneDayAgo}') as txUnprocessedDay,
|
|
2030
|
+
(select count(*) from transactions where status = 'unprocessed' and created_at > '${oneWeekAgo}') as txUnprocessedWeek,
|
|
2031
|
+
(select count(*) from transactions where status = 'unprocessed' and created_at > '${oneMonthAgo}') as txUnprocessedMonth,
|
|
2032
|
+
(select count(*) from transactions where status = 'unprocessed') as txUnprocessedTotal,
|
|
2033
|
+
(select count(*) from transactions where status = 'sending' and created_at > '${oneDayAgo}') as txSendingDay,
|
|
2034
|
+
(select count(*) from transactions where status = 'sending' and created_at > '${oneWeekAgo}') as txSendingWeek,
|
|
2035
|
+
(select count(*) from transactions where status = 'sending' and created_at > '${oneMonthAgo}') as txSendingMonth,
|
|
2036
|
+
(select count(*) from transactions where status = 'sending') as txSendingTotal,
|
|
2037
|
+
(select count(*) from transactions where status = 'unproven' and created_at > '${oneDayAgo}') as txUnprovenDay,
|
|
2038
|
+
(select count(*) from transactions where status = 'unproven' and created_at > '${oneWeekAgo}') as txUnprovenWeek,
|
|
2039
|
+
(select count(*) from transactions where status = 'unproven' and created_at > '${oneMonthAgo}') as txUnprovenMonth,
|
|
2040
|
+
(select count(*) from transactions where status = 'unproven') as txUnprovenTotal,
|
|
2041
|
+
(select count(*) from transactions where status = 'unsigned' and created_at > '${oneDayAgo}') as txUnsignedDay,
|
|
2042
|
+
(select count(*) from transactions where status = 'unsigned' and created_at > '${oneWeekAgo}') as txUnsignedWeek,
|
|
2043
|
+
(select count(*) from transactions where status = 'unsigned' and created_at > '${oneMonthAgo}') as txUnsignedMonth,
|
|
2044
|
+
(select count(*) from transactions where status = 'unsigned') as txUnsignedTotal,
|
|
2045
|
+
(select count(*) from transactions where status = 'nosend' and created_at > '${oneDayAgo}') as txNosendDay,
|
|
2046
|
+
(select count(*) from transactions where status = 'nosend' and created_at > '${oneWeekAgo}') as txNosendWeek,
|
|
2047
|
+
(select count(*) from transactions where status = 'nosend' and created_at > '${oneMonthAgo}') as txNosendMonth,
|
|
2048
|
+
(select count(*) from transactions where status = 'nosend') as txNosendTotal,
|
|
2049
|
+
(select count(*) from transactions where status = 'nonfinal' and created_at > '${oneDayAgo}') as txNonfinalDay,
|
|
2050
|
+
(select count(*) from transactions where status = 'nonfinal' and created_at > '${oneWeekAgo}') as txNonfinalWeek,
|
|
2051
|
+
(select count(*) from transactions where status = 'nonfinal' and created_at > '${oneMonthAgo}') as txNonfinalMonth,
|
|
2052
|
+
(select count(*) from transactions where status = 'nonfinal') as txNonfinalTotal,
|
|
2053
|
+
(select count(*) from transactions where status = 'unfail' and created_at > '${oneDayAgo}') as txUnfailDay,
|
|
2054
|
+
(select count(*) from transactions where status = 'unfail' and created_at > '${oneWeekAgo}') as txUnfailWeek,
|
|
2055
|
+
(select count(*) from transactions where status = 'unfail' and created_at > '${oneMonthAgo}') as txUnfailMonth,
|
|
2056
|
+
(select count(*) from transactions where status = 'unfail') as txUnfailTotal,
|
|
2057
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 1 and o.created_at > '${oneDayAgo}') as satoshisDefaultDay,
|
|
2058
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 1 and o.created_at > '${oneWeekAgo}') as satoshisDefaultWeek,
|
|
2059
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 1 and o.created_at > '${oneMonthAgo}') as satoshisDefaultMonth,
|
|
2060
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 1) as satoshisDefaultTotal,
|
|
2061
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 0 and not o.basketId is null and o.created_at > '${oneDayAgo}') as satoshisOtherDay,
|
|
2062
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 0 and not o.basketId is null and o.created_at > '${oneWeekAgo}') as satoshisOtherWeek,
|
|
2063
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 0 and not o.basketId is null and o.created_at > '${oneMonthAgo}') as satoshisOtherMonth,
|
|
2064
|
+
(select sum(o.satoshis) from outputs o, transactions t where o.transactionId = t.transactionId and t.status = 'completed' and o.spendable = 1 and o.change = 0 and not o.basketId is null) as satoshisOtherTotal,
|
|
2065
|
+
(select count(*) from output_baskets where created_at > '${oneDayAgo}') as basketsDay,
|
|
2066
|
+
(select count(*) from output_baskets where created_at > '${oneWeekAgo}') as basketsWeek,
|
|
2067
|
+
(select count(*) from output_baskets where created_at > '${oneMonthAgo}') as basketsMonth,
|
|
2068
|
+
(select count(*) from output_baskets) as basketsTotal,
|
|
2069
|
+
(select count(*) from tx_labels where created_at > '${oneDayAgo}') as labelsDay,
|
|
2070
|
+
(select count(*) from tx_labels where created_at > '${oneWeekAgo}') as labelsWeek,
|
|
2071
|
+
(select count(*) from tx_labels where created_at > '${oneMonthAgo}') as labelsMonth,
|
|
2072
|
+
(select count(*) from tx_labels) as labelsTotal,
|
|
2073
|
+
(select count(*) from output_tags where created_at > '${oneDayAgo}') as tagsDay,
|
|
2074
|
+
(select count(*) from output_tags where created_at > '${oneWeekAgo}') as tagsWeek,
|
|
2075
|
+
(select count(*) from output_tags where created_at > '${oneMonthAgo}') as tagsMonth,
|
|
2076
|
+
(select count(*) from output_tags) as tagsTotal
|
|
2077
|
+
`);
|
|
2072
2078
|
const r = {
|
|
2073
2079
|
monitorStats,
|
|
2074
2080
|
servicesStats,
|
|
2075
2081
|
requestedBy: adminIdentityKey,
|
|
2076
2082
|
when: new Date().toISOString(),
|
|
2077
|
-
|
|
2083
|
+
usersDay,
|
|
2084
|
+
usersWeek,
|
|
2085
|
+
usersMonth,
|
|
2086
|
+
usersTotal,
|
|
2087
|
+
transactionsDay,
|
|
2088
|
+
transactionsWeek,
|
|
2089
|
+
transactionsMonth,
|
|
2090
|
+
transactionsTotal,
|
|
2091
|
+
txCompletedDay,
|
|
2092
|
+
txCompletedWeek,
|
|
2093
|
+
txCompletedMonth,
|
|
2094
|
+
txCompletedTotal,
|
|
2095
|
+
txFailedDay,
|
|
2096
|
+
txFailedWeek,
|
|
2097
|
+
txFailedMonth,
|
|
2098
|
+
txFailedTotal,
|
|
2099
|
+
txAbandonedDay,
|
|
2100
|
+
txAbandonedWeek,
|
|
2101
|
+
txAbandonedMonth,
|
|
2102
|
+
txAbandonedTotal,
|
|
2103
|
+
txUnprocessedDay,
|
|
2104
|
+
txUnprocessedWeek,
|
|
2105
|
+
txUnprocessedMonth,
|
|
2106
|
+
txUnprocessedTotal,
|
|
2107
|
+
txSendingDay,
|
|
2108
|
+
txSendingWeek,
|
|
2109
|
+
txSendingMonth,
|
|
2110
|
+
txSendingTotal,
|
|
2111
|
+
txUnprovenDay,
|
|
2112
|
+
txUnprovenWeek,
|
|
2113
|
+
txUnprovenMonth,
|
|
2114
|
+
txUnprovenTotal,
|
|
2115
|
+
txUnsignedDay,
|
|
2116
|
+
txUnsignedWeek,
|
|
2117
|
+
txUnsignedMonth,
|
|
2118
|
+
txUnsignedTotal,
|
|
2119
|
+
txNosendDay,
|
|
2120
|
+
txNosendWeek,
|
|
2121
|
+
txNosendMonth,
|
|
2122
|
+
txNosendTotal,
|
|
2123
|
+
txNonfinalDay,
|
|
2124
|
+
txNonfinalWeek,
|
|
2125
|
+
txNonfinalMonth,
|
|
2126
|
+
txNonfinalTotal,
|
|
2127
|
+
txUnfailDay,
|
|
2128
|
+
txUnfailWeek,
|
|
2129
|
+
txUnfailMonth,
|
|
2130
|
+
txUnfailTotal,
|
|
2131
|
+
satoshisDefaultDay: Number(satoshisDefaultDay),
|
|
2132
|
+
satoshisDefaultWeek: Number(satoshisDefaultWeek),
|
|
2133
|
+
satoshisDefaultMonth: Number(satoshisDefaultMonth),
|
|
2134
|
+
satoshisDefaultTotal: Number(satoshisDefaultTotal),
|
|
2135
|
+
satoshisOtherDay: Number(satoshisOtherDay),
|
|
2136
|
+
satoshisOtherWeek: Number(satoshisOtherWeek),
|
|
2137
|
+
satoshisOtherMonth: Number(satoshisOtherMonth),
|
|
2138
|
+
satoshisOtherTotal: Number(satoshisOtherTotal),
|
|
2139
|
+
basketsDay,
|
|
2140
|
+
basketsWeek,
|
|
2141
|
+
basketsMonth,
|
|
2142
|
+
basketsTotal,
|
|
2143
|
+
labelsDay,
|
|
2144
|
+
labelsWeek,
|
|
2145
|
+
labelsMonth,
|
|
2146
|
+
labelsTotal,
|
|
2147
|
+
tagsDay,
|
|
2148
|
+
tagsWeek,
|
|
2149
|
+
tagsMonth,
|
|
2150
|
+
tagsTotal
|
|
2078
2151
|
};
|
|
2079
2152
|
return r;
|
|
2080
2153
|
}
|
|
@@ -2124,4 +2197,23 @@ function pagingKey(table) {
|
|
|
2124
2197
|
return [];
|
|
2125
2198
|
}
|
|
2126
2199
|
}
|
|
2200
|
+
const pgInt8Parsed = Symbol('pgInt8Parsed');
|
|
2201
|
+
/**
|
|
2202
|
+
* node-postgres returns int8 values (bigint columns such as satoshis, `count(*)`)
|
|
2203
|
+
* as strings. Set a parser on each connection this knex acquires so they come
|
|
2204
|
+
* back as numbers, as with mysql2 and better-sqlite3. The process-wide `pg.types`
|
|
2205
|
+
* defaults are left unchanged.
|
|
2206
|
+
*/
|
|
2207
|
+
function parsePostgresInt8AsNumber(knex) {
|
|
2208
|
+
const client = knex.client;
|
|
2209
|
+
if (client?.dialect !== 'postgresql' || client[pgInt8Parsed] === true)
|
|
2210
|
+
return;
|
|
2211
|
+
client[pgInt8Parsed] = true;
|
|
2212
|
+
const acquireConnection = client.acquireConnection.bind(client);
|
|
2213
|
+
client.acquireConnection = async () => {
|
|
2214
|
+
const connection = await acquireConnection();
|
|
2215
|
+
connection.setTypeParser(20, (value) => Number.parseInt(value, 10));
|
|
2216
|
+
return connection;
|
|
2217
|
+
};
|
|
2218
|
+
}
|
|
2127
2219
|
//# sourceMappingURL=StorageKnex.js.map
|