@bopen-io/wallet-toolbox 2.15.0-bopen.1 → 2.15.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.
Files changed (231) hide show
  1. package/CHANGELOG.md +183 -45
  2. package/README.md +134 -98
  3. package/docs/client.md +2947 -3080
  4. package/docs/monitor.md +154 -165
  5. package/docs/no-send-expiry.md +7 -2
  6. package/docs/services.md +822 -885
  7. package/docs/setup.md +1 -46
  8. package/docs/storage.md +1636 -1654
  9. package/docs/wallet.md +1975 -2132
  10. package/out/src/CWIStyleWalletManager.d.ts +36 -5
  11. package/out/src/CWIStyleWalletManager.d.ts.map +1 -1
  12. package/out/src/CWIStyleWalletManager.js +356 -60
  13. package/out/src/CWIStyleWalletManager.js.map +1 -1
  14. package/out/src/Setup.d.ts +0 -10
  15. package/out/src/Setup.d.ts.map +1 -1
  16. package/out/src/Setup.js +0 -24
  17. package/out/src/Setup.js.map +1 -1
  18. package/out/src/Wallet.d.ts.map +1 -1
  19. package/out/src/Wallet.js +8 -3
  20. package/out/src/Wallet.js.map +1 -1
  21. package/out/src/WalletAuthenticationManager.d.ts +3 -0
  22. package/out/src/WalletAuthenticationManager.d.ts.map +1 -1
  23. package/out/src/WalletAuthenticationManager.js +86 -3
  24. package/out/src/WalletAuthenticationManager.js.map +1 -1
  25. package/out/src/WalletPermissionsManager.d.ts +63 -9
  26. package/out/src/WalletPermissionsManager.d.ts.map +1 -1
  27. package/out/src/WalletPermissionsManager.js +213 -49
  28. package/out/src/WalletPermissionsManager.js.map +1 -1
  29. package/out/src/monitor/Monitor.js +1 -1
  30. package/out/src/monitor/Monitor.js.map +1 -1
  31. package/out/src/monitor/MonitorDaemon.d.ts +0 -2
  32. package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
  33. package/out/src/monitor/MonitorDaemon.js +1 -9
  34. package/out/src/monitor/MonitorDaemon.js.map +1 -1
  35. package/out/src/monitor/monitorValidation.d.ts +2 -1
  36. package/out/src/monitor/monitorValidation.d.ts.map +1 -1
  37. package/out/src/monitor/monitorValidation.js +2 -2
  38. package/out/src/monitor/monitorValidation.js.map +1 -1
  39. package/out/src/monitor/tasks/TaskNewHeader.d.ts.map +1 -1
  40. package/out/src/monitor/tasks/TaskNewHeader.js +1 -1
  41. package/out/src/monitor/tasks/TaskNewHeader.js.map +1 -1
  42. package/out/src/monitor/tasks/TaskReviewUtxos.d.ts.map +1 -1
  43. package/out/src/monitor/tasks/TaskReviewUtxos.js +2 -1
  44. package/out/src/monitor/tasks/TaskReviewUtxos.js.map +1 -1
  45. package/out/src/sdk/WERR_errors.d.ts +4 -0
  46. package/out/src/sdk/WERR_errors.d.ts.map +1 -1
  47. package/out/src/sdk/WERR_errors.js +4 -0
  48. package/out/src/sdk/WERR_errors.js.map +1 -1
  49. package/out/src/sdk/WalletErrorFromJson.d.ts.map +1 -1
  50. package/out/src/sdk/WalletErrorFromJson.js +23 -2
  51. package/out/src/sdk/WalletErrorFromJson.js.map +1 -1
  52. package/out/src/sdk/WalletStorage.interfaces.d.ts +11 -0
  53. package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
  54. package/out/src/sdk/types.d.ts +12 -1
  55. package/out/src/sdk/types.d.ts.map +1 -1
  56. package/out/src/sdk/types.js +19 -2
  57. package/out/src/sdk/types.js.map +1 -1
  58. package/out/src/services/Services.d.ts.map +1 -1
  59. package/out/src/services/Services.js +5 -3
  60. package/out/src/services/Services.js.map +1 -1
  61. package/out/src/services/chaintracker/BHServiceClient.js +2 -2
  62. package/out/src/services/chaintracker/BHServiceClient.js.map +1 -1
  63. package/out/src/services/chaintracker/chaintracks/Chaintracks.js +2 -2
  64. package/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
  65. package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts.map +1 -1
  66. package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.js +3 -1
  67. package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.js.map +1 -1
  68. package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.d.ts.map +1 -1
  69. package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.js +3 -1
  70. package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.js.map +1 -1
  71. package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.js +1 -1
  72. package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.js.map +1 -1
  73. package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.js +1 -1
  74. package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.js.map +1 -1
  75. package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorChaintracksSSE.js +1 -1
  76. package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorChaintracksSSE.js.map +1 -1
  77. package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.d.ts.map +1 -1
  78. package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.js +2 -0
  79. package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.js.map +1 -1
  80. package/out/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.js +2 -2
  81. package/out/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.js.map +1 -1
  82. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js +6 -6
  83. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js.map +1 -1
  84. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js +2 -2
  85. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js.map +1 -1
  86. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts +0 -5
  87. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
  88. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +5 -13
  89. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
  90. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts +1 -0
  91. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
  92. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +11 -3
  93. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
  94. package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.d.ts.map +1 -1
  95. package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.js +13 -9
  96. package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.js.map +1 -1
  97. package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.d.ts.map +1 -1
  98. package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.js +2 -2
  99. package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.js.map +1 -1
  100. package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.d.ts.map +1 -1
  101. package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.js +2 -2
  102. package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.js.map +1 -1
  103. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts +23 -5
  104. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts.map +1 -1
  105. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js +58 -16
  106. package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js.map +1 -1
  107. package/out/src/services/createDefaultWalletServicesOptions.d.ts +6 -3
  108. package/out/src/services/createDefaultWalletServicesOptions.d.ts.map +1 -1
  109. package/out/src/services/createDefaultWalletServicesOptions.js +18 -6
  110. package/out/src/services/createDefaultWalletServicesOptions.js.map +1 -1
  111. package/out/src/services/networkConfig.d.ts +7 -0
  112. package/out/src/services/networkConfig.d.ts.map +1 -1
  113. package/out/src/services/networkConfig.js +25 -2
  114. package/out/src/services/networkConfig.js.map +1 -1
  115. package/out/src/services/providers/SdkWhatsOnChain.d.ts +8 -2
  116. package/out/src/services/providers/SdkWhatsOnChain.d.ts.map +1 -1
  117. package/out/src/services/providers/SdkWhatsOnChain.js +17 -6
  118. package/out/src/services/providers/SdkWhatsOnChain.js.map +1 -1
  119. package/out/src/services/validateMerklePathResult.d.ts +4 -3
  120. package/out/src/services/validateMerklePathResult.d.ts.map +1 -1
  121. package/out/src/services/validateMerklePathResult.js +6 -6
  122. package/out/src/services/validateMerklePathResult.js.map +1 -1
  123. package/out/src/signer/actionBatch/ActionBatchWorkspace.d.ts.map +1 -1
  124. package/out/src/signer/actionBatch/ActionBatchWorkspace.js +3 -2
  125. package/out/src/signer/actionBatch/ActionBatchWorkspace.js.map +1 -1
  126. package/out/src/signer/methods/createAction.d.ts +32 -1
  127. package/out/src/signer/methods/createAction.d.ts.map +1 -1
  128. package/out/src/signer/methods/createAction.js +56 -1
  129. package/out/src/signer/methods/createAction.js.map +1 -1
  130. package/out/src/signer/methods/internalizeAction.js +1 -1
  131. package/out/src/signer/methods/internalizeAction.js.map +1 -1
  132. package/out/src/signer/methods/signAction.js +8 -1
  133. package/out/src/signer/methods/signAction.js.map +1 -1
  134. package/out/src/storage/StorageIdb.js +4 -4
  135. package/out/src/storage/StorageIdb.js.map +1 -1
  136. package/out/src/storage/StorageKnex.d.ts +6 -5
  137. package/out/src/storage/StorageKnex.d.ts.map +1 -1
  138. package/out/src/storage/StorageKnex.js +321 -115
  139. package/out/src/storage/StorageKnex.js.map +1 -1
  140. package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
  141. package/out/src/storage/WalletStorageManager.js +5 -0
  142. package/out/src/storage/WalletStorageManager.js.map +1 -1
  143. package/out/src/storage/adminServer/adminServer.d.ts.map +1 -1
  144. package/out/src/storage/adminServer/adminServer.js +41 -3
  145. package/out/src/storage/adminServer/adminServer.js.map +1 -1
  146. package/out/src/storage/index.all.d.ts +0 -1
  147. package/out/src/storage/index.all.d.ts.map +1 -1
  148. package/out/src/storage/index.all.js +0 -1
  149. package/out/src/storage/index.all.js.map +1 -1
  150. package/out/src/storage/methods/ListOutputsSpecOp.d.ts.map +1 -1
  151. package/out/src/storage/methods/ListOutputsSpecOp.js +84 -0
  152. package/out/src/storage/methods/ListOutputsSpecOp.js.map +1 -1
  153. package/out/src/storage/methods/attemptToPostReqsToNetwork.d.ts.map +1 -1
  154. package/out/src/storage/methods/attemptToPostReqsToNetwork.js +7 -3
  155. package/out/src/storage/methods/attemptToPostReqsToNetwork.js.map +1 -1
  156. package/out/src/storage/methods/createAction.d.ts +5 -0
  157. package/out/src/storage/methods/createAction.d.ts.map +1 -1
  158. package/out/src/storage/methods/createAction.js +13 -6
  159. package/out/src/storage/methods/createAction.js.map +1 -1
  160. package/out/src/storage/methods/generateChange.d.ts +6 -0
  161. package/out/src/storage/methods/generateChange.d.ts.map +1 -1
  162. package/out/src/storage/methods/generateChange.js +10 -3
  163. package/out/src/storage/methods/generateChange.js.map +1 -1
  164. package/out/src/storage/methods/internalizeAction.d.ts +8 -1
  165. package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
  166. package/out/src/storage/methods/internalizeAction.js +106 -42
  167. package/out/src/storage/methods/internalizeAction.js.map +1 -1
  168. package/out/src/storage/methods/listActionsKnex.d.ts.map +1 -1
  169. package/out/src/storage/methods/listActionsKnex.js +1 -0
  170. package/out/src/storage/methods/listActionsKnex.js.map +1 -1
  171. package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
  172. package/out/src/storage/methods/listOutputsKnex.js +2 -1
  173. package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
  174. package/out/src/storage/methods/noSendExpiry.d.ts.map +1 -1
  175. package/out/src/storage/methods/noSendExpiry.js +14 -4
  176. package/out/src/storage/methods/noSendExpiry.js.map +1 -1
  177. package/out/src/storage/methods/purgeData.d.ts.map +1 -1
  178. package/out/src/storage/methods/purgeData.js +3 -0
  179. package/out/src/storage/methods/purgeData.js.map +1 -1
  180. package/out/src/storage/methods/reviewStatus.d.ts.map +1 -1
  181. package/out/src/storage/methods/reviewStatus.js +3 -0
  182. package/out/src/storage/methods/reviewStatus.js.map +1 -1
  183. package/out/src/storage/portable/index.js +12 -38
  184. package/out/src/storage/portable/index.js.map +1 -1
  185. package/out/src/storage/remoting/StorageClientBase.d.ts.map +1 -1
  186. package/out/src/storage/remoting/StorageClientBase.js +15 -5
  187. package/out/src/storage/remoting/StorageClientBase.js.map +1 -1
  188. package/out/src/storage/remoting/StorageServer.d.ts +4 -17
  189. package/out/src/storage/remoting/StorageServer.d.ts.map +1 -1
  190. package/out/src/storage/remoting/StorageServer.js +25 -23
  191. package/out/src/storage/remoting/StorageServer.js.map +1 -1
  192. package/out/src/storage/remoting/syncChunkBinary.d.ts +10 -0
  193. package/out/src/storage/remoting/syncChunkBinary.d.ts.map +1 -1
  194. package/out/src/storage/remoting/syncChunkBinary.js +15 -11
  195. package/out/src/storage/remoting/syncChunkBinary.js.map +1 -1
  196. package/out/src/storage/schema/KnexMigrations.d.ts +3 -7
  197. package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
  198. package/out/src/storage/schema/KnexMigrations.js +86 -166
  199. package/out/src/storage/schema/KnexMigrations.js.map +1 -1
  200. package/out/src/storage/sync/liveSyncGuards.d.ts +11 -0
  201. package/out/src/storage/sync/liveSyncGuards.d.ts.map +1 -0
  202. package/out/src/storage/sync/liveSyncGuards.js +22 -0
  203. package/out/src/storage/sync/liveSyncGuards.js.map +1 -0
  204. package/out/src/utility/actionOutputAuthorizations.d.ts +10 -0
  205. package/out/src/utility/actionOutputAuthorizations.d.ts.map +1 -0
  206. package/out/src/utility/actionOutputAuthorizations.js +25 -0
  207. package/out/src/utility/actionOutputAuthorizations.js.map +1 -0
  208. package/out/src/utility/index.all.d.ts +1 -0
  209. package/out/src/utility/index.all.d.ts.map +1 -1
  210. package/out/src/utility/index.all.js +1 -0
  211. package/out/src/utility/index.all.js.map +1 -1
  212. package/out/src/utility/index.client.d.ts +1 -0
  213. package/out/src/utility/index.client.d.ts.map +1 -1
  214. package/out/src/utility/index.client.js +1 -0
  215. package/out/src/utility/index.client.js.map +1 -1
  216. package/out/src/utility/numericTotalOutputs.d.ts +7 -0
  217. package/out/src/utility/numericTotalOutputs.d.ts.map +1 -0
  218. package/out/src/utility/numericTotalOutputs.js +15 -0
  219. package/out/src/utility/numericTotalOutputs.js.map +1 -0
  220. package/out/src/utility/utilityHelpers.d.ts.map +1 -1
  221. package/out/src/utility/utilityHelpers.js +2 -0
  222. package/out/src/utility/utilityHelpers.js.map +1 -1
  223. package/package.json +19 -24
  224. package/out/src/storage/adminServer/reqReviewQuery.d.ts +0 -41
  225. package/out/src/storage/adminServer/reqReviewQuery.d.ts.map +0 -1
  226. package/out/src/storage/adminServer/reqReviewQuery.js +0 -67
  227. package/out/src/storage/adminServer/reqReviewQuery.js.map +0 -1
  228. package/out/src/storage/knexPostgres.d.ts +0 -16
  229. package/out/src/storage/knexPostgres.d.ts.map +0 -1
  230. package/out/src/storage/knexPostgres.js +0 -34
  231. package/out/src/storage/knexPostgres.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StorageKnex = void 0;
4
+ const validationHelpers_1 = require("@bsv/sdk/wallet/validationHelpers");
4
5
  const tables_1 = require("./schema/tables");
5
6
  const KnexMigrations_1 = require("./schema/KnexMigrations");
6
7
  const StorageProvider_1 = require("./StorageProvider");
@@ -10,9 +11,10 @@ const listOutputsKnex_1 = require("./methods/listOutputsKnex");
10
11
  const reviewStatus_1 = require("./methods/reviewStatus");
11
12
  const WERR_errors_1 = require("../sdk/WERR_errors");
12
13
  const utilityHelpers_1 = require("../utility/utilityHelpers");
14
+ const canonicalizeAtomicBeef_1 = require("../utility/canonicalizeAtomicBeef");
15
+ const internalizeAction_1 = require("./methods/internalizeAction");
13
16
  const managedChange_1 = require("./methods/managedChange");
14
17
  const preparedBeef_1 = require("./methods/preparedBeef");
15
- const knexPostgres_1 = require("./knexPostgres");
16
18
  // Keep bulk statements below conservative SQLite/MySQL bind-parameter
17
19
  // ceilings. The surrounding transaction still makes a complete pack atomic.
18
20
  const ACTION_BATCH_BLOB_SQL_CHUNK = 500;
@@ -48,7 +50,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
48
50
  if (options.knex == null)
49
51
  throw new WERR_errors_1.WERR_INVALID_PARAMETER('options.knex', 'valid');
50
52
  this.knex = options.knex;
51
- (0, knexPostgres_1.usePostgresInt8Numbers)(this.knex);
53
+ parsePostgresInt8AsNumber(this.knex);
52
54
  this.preparedBeefPolicy = (0, preparedBeef_1.validatePreparedBeefPolicy)(options.preparedBeef);
53
55
  this.preparedBeefCoordinator = new preparedBeef_1.PreparedBeefCoordinator(this);
54
56
  if (this.telemetry.enabled) {
@@ -57,6 +59,117 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
57
59
  this.knex.on('query-error', this.onQueryError);
58
60
  }
59
61
  }
62
+ receiptClockMs() {
63
+ switch (this.dbtype) {
64
+ case 'MySQL':
65
+ return this.knex.raw('CAST(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000 AS UNSIGNED)');
66
+ case 'Postgres':
67
+ return this.knex.raw('CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)');
68
+ case 'SQLite':
69
+ return this.knex.raw("CAST((julianday('now') - 2440587.5) * 86400000 AS INTEGER)");
70
+ default:
71
+ throw new WERR_errors_1.WERR_INTERNAL('wallet receipt claim requires a ready SQL storage provider');
72
+ }
73
+ }
74
+ receiptLeaseMs() {
75
+ return this.knex.raw('(? + ?)', [this.receiptClockMs(), 120_000]);
76
+ }
77
+ async acquireInternalizeReceipt(userId, txid) {
78
+ const ownerToken = (0, utilityHelpers_1.randomBytesBase64)(18);
79
+ const deadline = Date.now() + 30_000;
80
+ while (Date.now() < deadline) {
81
+ await this.knex('internalize_receipts')
82
+ .insert({
83
+ userId,
84
+ txid,
85
+ ownerToken,
86
+ state: 'pending',
87
+ leaseUntil: this.receiptLeaseMs(),
88
+ needsNewReceipt: false
89
+ })
90
+ .onConflict(['userId', 'txid'])
91
+ .ignore();
92
+ const previous = await this.knex('internalize_receipts')
93
+ .where({ userId, txid })
94
+ .first('ownerToken', 'state', 'needsNewReceipt');
95
+ if (previous == null)
96
+ continue;
97
+ const retryNew = Boolean(previous.needsNewReceipt);
98
+ const preserveComplete = previous.state === 'complete';
99
+ if (previous.ownerToken !== ownerToken) {
100
+ const changed = await this.knex('internalize_receipts')
101
+ .where({ userId, txid, ownerToken: previous.ownerToken })
102
+ .where(builder => builder.whereIn('state', ['retryable', 'complete']).orWhere('leaseUntil', '<=', this.receiptClockMs()))
103
+ .update({ ownerToken, state: 'pending', leaseUntil: this.receiptLeaseMs() });
104
+ if (changed !== 1) {
105
+ await new Promise(resolve => setTimeout(resolve, 100));
106
+ continue;
107
+ }
108
+ }
109
+ const activeRow = (trx) => {
110
+ const query = trx('internalize_receipts')
111
+ .where({ userId, txid, ownerToken, state: 'pending' })
112
+ .where('leaseUntil', '>', this.receiptClockMs());
113
+ return this.dbtype === 'SQLite' ? query : query.forUpdate();
114
+ };
115
+ const claim = {
116
+ retryNew,
117
+ assertActive: async (trx) => {
118
+ const active = await activeRow(trx).first('ownerToken');
119
+ if (active == null)
120
+ throw new WERR_errors_1.WERR_INTERNAL('wallet receipt claim expired or was superseded');
121
+ },
122
+ markNew: async (trx) => {
123
+ const changed = await activeRow(trx).update({ needsNewReceipt: true });
124
+ if (changed !== 1)
125
+ throw new WERR_errors_1.WERR_INTERNAL('wallet receipt claim expired or was superseded');
126
+ },
127
+ complete: async (trx) => {
128
+ const changed = await activeRow(trx).update({
129
+ state: 'complete',
130
+ needsNewReceipt: false,
131
+ leaseUntil: 0
132
+ });
133
+ if (changed !== 1)
134
+ throw new WERR_errors_1.WERR_INTERNAL('wallet receipt claim expired or was superseded');
135
+ }
136
+ };
137
+ return { ownerToken, claim, preserveComplete };
138
+ }
139
+ throw new WERR_errors_1.WERR_INTERNAL('wallet receipt is already being processed; retry after the active request finishes');
140
+ }
141
+ async internalizeAction(auth, args) {
142
+ (0, validationHelpers_1.validateInternalizeActionArgs)(args);
143
+ const userId = auth.userId;
144
+ if (userId == null)
145
+ throw new WERR_errors_1.WERR_UNAUTHORIZED();
146
+ const txid = (0, canonicalizeAtomicBeef_1.canonicalizeAtomicBeef)(args.tx).atomicTxid;
147
+ if (txid == null)
148
+ throw new WERR_errors_1.WERR_INVALID_PARAMETER('tx', 'an AtomicBEEF transaction');
149
+ const { ownerToken, claim, preserveComplete } = await this.acquireInternalizeReceipt(userId, txid);
150
+ try {
151
+ return await (0, internalizeAction_1.internalizeAction)(this, auth, args, claim);
152
+ }
153
+ finally {
154
+ // A successful writer marked its claim complete in the same transaction
155
+ // as the output records. Preserve that durable key across later merges;
156
+ // release an uncompleted key only when no new receipt header was marked.
157
+ const noNewReceipt = this.knex('internalize_receipts').where({
158
+ userId,
159
+ txid,
160
+ ownerToken,
161
+ state: 'pending',
162
+ needsNewReceipt: false
163
+ });
164
+ if (preserveComplete)
165
+ await noNewReceipt.update({ state: 'complete', leaseUntil: 0 });
166
+ else
167
+ await noNewReceipt.delete();
168
+ await this.knex('internalize_receipts')
169
+ .where({ userId, txid, ownerToken, state: 'pending', needsNewReceipt: true })
170
+ .update({ state: 'retryable', leaseUntil: 0 });
171
+ }
172
+ }
60
173
  databaseSystem() {
61
174
  const clientName = this.knex.client.config?.client ?? '';
62
175
  if (clientName.includes('sqlite'))
@@ -261,6 +374,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
261
374
  .whereNull('pb.preparedBeefId')
262
375
  .select('o.userId', 'o.txid as rootTxid')
263
376
  .groupBy('o.userId', 'o.txid')
377
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
264
378
  .orderByRaw('MIN(??)', ['o.outputId'])
265
379
  .limit(limit));
266
380
  return rows;
@@ -387,6 +501,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
387
501
  void this.whereExists(k
388
502
  .select('*')
389
503
  .from('transactions')
504
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
390
505
  .whereRaw('?? = ?? and ?? = ?', [
391
506
  'proven_txs.provenTxId',
392
507
  'transactions.provenTxId',
@@ -414,6 +529,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
414
529
  void this.whereExists(k
415
530
  .select('*')
416
531
  .from('transactions')
532
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
417
533
  .whereRaw('proven_tx_reqs.txid = transactions.txid and ?? = ?', ['transactions.userId', args.userId]));
418
534
  });
419
535
  if (args.paged != null) {
@@ -435,6 +551,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
435
551
  let q = k('tx_labels_map').whereExists(k
436
552
  .select('*')
437
553
  .from('tx_labels')
554
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
438
555
  .whereRaw('?? = ?? and ?? = ?', [
439
556
  'tx_labels.txLabelId',
440
557
  'tx_labels_map.txLabelId',
@@ -460,6 +577,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
460
577
  let q = k('output_tags_map').whereExists(k
461
578
  .select('*')
462
579
  .from('output_tags')
580
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
463
581
  .whereRaw('?? = ?? and ?? = ?', [
464
582
  'output_tags.outputTagId',
465
583
  'output_tags_map.outputTagId',
@@ -532,20 +650,16 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
532
650
  /**
533
651
  * Insert one row and return its auto-increment primary key. MySQL and SQLite
534
652
  * 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
653
  */
539
- async insertReturningId(table, idColumn, row, trx, recoverable = false) {
654
+ async insertReturningId(table, idColumn, row, trx) {
540
655
  if (this.dbtype !== 'Postgres') {
541
656
  const [id] = await this.toDb(trx)(table).insert(row);
542
657
  return id;
543
658
  }
544
- const insert = async (db) => {
659
+ return await this.inSavepoint(trx, async (db) => {
545
660
  const [r] = await db(table).insert(row).returning(idColumn);
546
661
  return r[idColumn];
547
- };
548
- return recoverable ? await this.inSavepoint(trx, insert) : await insert(this.toDb(trx));
662
+ });
549
663
  }
550
664
  /**
551
665
  * The findOrInsert helpers catch a failed insert and find the row again in
@@ -562,7 +676,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
562
676
  const e = await this.validateEntityForInsert(tx, trx);
563
677
  if (e.provenTxId === 0)
564
678
  delete e.provenTxId;
565
- const id = await this.insertReturningId('proven_txs', 'provenTxId', e, trx, true);
679
+ const id = await this.insertReturningId('proven_txs', 'provenTxId', e, trx);
566
680
  tx.provenTxId = id;
567
681
  return tx.provenTxId;
568
682
  }
@@ -690,7 +804,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
690
804
  const e = await this.validateEntityForInsert(tx, trx);
691
805
  if (e.provenTxReqId === 0)
692
806
  delete e.provenTxReqId;
693
- const id = await this.insertReturningId('proven_tx_reqs', 'provenTxReqId', e, trx, true);
807
+ const id = await this.insertReturningId('proven_tx_reqs', 'provenTxReqId', e, trx);
694
808
  tx.provenTxReqId = id;
695
809
  return tx.provenTxReqId;
696
810
  }
@@ -737,7 +851,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
737
851
  const e = await this.validateEntityForInsert(basket, trx, undefined, ['isDeleted']);
738
852
  if (e.basketId === 0)
739
853
  delete e.basketId;
740
- const id = await this.insertReturningId('output_baskets', 'basketId', e, trx, true);
854
+ const id = await this.insertReturningId('output_baskets', 'basketId', e, trx);
741
855
  basket.basketId = id;
742
856
  return basket.basketId;
743
857
  }
@@ -745,7 +859,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
745
859
  const e = await this.validateEntityForInsert(tx, trx);
746
860
  if (e.transactionId === 0)
747
861
  delete e.transactionId;
748
- const id = await this.insertReturningId('transactions', 'transactionId', e, trx, true);
862
+ const id = await this.insertReturningId('transactions', 'transactionId', e, trx);
749
863
  tx.transactionId = id;
750
864
  return tx.transactionId;
751
865
  }
@@ -782,7 +896,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
782
896
  const e = await this.validateEntityForInsert(tag, trx, undefined, ['isDeleted']);
783
897
  if (e.outputTagId === 0)
784
898
  delete e.outputTagId;
785
- const id = await this.insertReturningId('output_tags', 'outputTagId', e, trx, true);
899
+ const id = await this.insertReturningId('output_tags', 'outputTagId', e, trx);
786
900
  tag.outputTagId = id;
787
901
  return tag.outputTagId;
788
902
  }
@@ -794,7 +908,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
794
908
  const e = await this.validateEntityForInsert(label, trx, undefined, ['isDeleted']);
795
909
  if (e.txLabelId === 0)
796
910
  delete e.txLabelId;
797
- const id = await this.insertReturningId('tx_labels', 'txLabelId', e, trx, true);
911
+ const id = await this.insertReturningId('tx_labels', 'txLabelId', e, trx);
798
912
  label.txLabelId = id;
799
913
  return label.txLabelId;
800
914
  }
@@ -1364,27 +1478,13 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1364
1478
  if (isSQLite) {
1365
1479
  await this.knex.raw('PRAGMA foreign_keys = OFF;');
1366
1480
  }
1367
- const isPostgres = this.knex.client.dialect === 'postgresql';
1368
1481
  try {
1369
1482
  const config = {
1370
- migrationSource: new KnexMigrations_1.KnexMigrations(this.chain, storageName, storageIdentityKey, 1024, isPostgres ? 'Postgres' : undefined),
1483
+ migrationSource: new KnexMigrations_1.KnexMigrations(this.chain, storageName, storageIdentityKey, 1024),
1371
1484
  // Keep DDL and its migration journal entry in the same transaction.
1372
1485
  disableTransactions: false
1373
1486
  };
1374
- if (isPostgres) {
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
- }
1487
+ await this.knex.migrate.latest(config);
1388
1488
  return await this.knex.migrate.currentVersion(config);
1389
1489
  }
1390
1490
  finally {
@@ -1619,6 +1719,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1619
1719
  void this.select(1)
1620
1720
  .from('action_batch_outputs as abo')
1621
1721
  .join('action_batches as ab', 'abo.actionBatchId', 'ab.actionBatchId')
1722
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
1622
1723
  .whereRaw('?? = ??', ['abo.outputId', 'o.outputId'])
1623
1724
  .whereIn('ab.status', ['active', 'prepared'])
1624
1725
  .where('ab.expiresAt', '>', now)
@@ -1653,6 +1754,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1653
1754
  void this.select(1)
1654
1755
  .from('action_batch_outputs as abo')
1655
1756
  .join('action_batches as ab', 'abo.actionBatchId', 'ab.actionBatchId')
1757
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
1656
1758
  .whereRaw('?? = ??', ['abo.outputId', 'o.outputId'])
1657
1759
  .whereIn('ab.status', ['active', 'prepared'])
1658
1760
  .where('ab.expiresAt', '>', now)
@@ -1687,6 +1789,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1687
1789
  void this.select(1)
1688
1790
  .from('action_batch_outputs as abo')
1689
1791
  .join('action_batches as ab', 'abo.actionBatchId', 'ab.actionBatchId')
1792
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
1690
1793
  .whereRaw('?? = ??', ['abo.outputId', 'o.outputId'])
1691
1794
  .whereIn('ab.status', ['active', 'prepared'])
1692
1795
  .where('ab.expiresAt', '>', now)
@@ -1876,6 +1979,7 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1876
1979
  const status = ['completed', 'unproven'];
1877
1980
  if (!excludeSending)
1878
1981
  status.push('sending');
1982
+ let reservedConcurrently = false;
1879
1983
  const r = await this.knex.transaction(async (trx) => {
1880
1984
  const baseQuery = () => trx('outputs as o')
1881
1985
  .join('transactions as t', 'o.transactionId', 't.transactionId')
@@ -1894,42 +1998,36 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1894
1998
  .whereNot('o.derivationSuffix', '')
1895
1999
  .whereNull('o.spentBy')
1896
2000
  .whereNotExists(function () {
2001
+ // ?? quotes identifiers: Postgres lowercases unquoted names, so camelCase columns must be quoted.
1897
2002
  void this.select(1).from('action_batch_outputs as abo').whereRaw('?? = ??', ['abo.outputId', 'o.outputId']);
1898
2003
  })
1899
2004
  .whereIn('t.status', status)
1900
2005
  .select('o.*')
1901
2006
  .forUpdate();
1902
- const excluded = [];
1903
- const candidates = () => excluded.length > 0 ? baseQuery().whereNotIn('o.outputId', excluded) : baseQuery();
1904
- const selectOutput = async () => {
1905
- let output;
1906
- if (exactSatoshis !== undefined) {
1907
- output = await candidates().where('o.satoshis', exactSatoshis).orderBy('o.outputId', 'asc').first();
1908
- }
1909
- output ??= await candidates()
1910
- .where('o.satoshis', '>=', targetSatoshis)
1911
- .orderBy('o.satoshis', 'asc')
1912
- .orderBy('o.outputId', 'asc')
1913
- .first();
1914
- output ??= await candidates()
1915
- .where('o.satoshis', '<', targetSatoshis)
1916
- .orderBy('o.satoshis', 'desc')
1917
- .orderBy('o.outputId', 'desc')
1918
- .first();
1919
- return output;
1920
- };
1921
- let output = await selectOutput();
2007
+ let output;
2008
+ if (exactSatoshis !== undefined) {
2009
+ output = await baseQuery().where('o.satoshis', exactSatoshis).orderBy('o.outputId', 'asc').first();
2010
+ }
2011
+ output ??= await baseQuery()
2012
+ .where('o.satoshis', '>=', targetSatoshis)
2013
+ .orderBy('o.satoshis', 'asc')
2014
+ .orderBy('o.outputId', 'asc')
2015
+ .first();
2016
+ output ??= await baseQuery()
2017
+ .where('o.satoshis', '<', targetSatoshis)
2018
+ .orderBy('o.satoshis', 'desc')
2019
+ .orderBy('o.outputId', 'desc')
2020
+ .first();
2021
+ if (output == null)
2022
+ return undefined;
1922
2023
  // Under Postgres READ COMMITTED the NOT EXISTS above uses the statement's
1923
2024
  // snapshot, so an action batch reservation committed while the statement
1924
- // waited for the row lock is not visible to it. Re-check with a new statement.
1925
- while (output != null &&
1926
- this.dbtype === 'Postgres' &&
2025
+ // waited for the row lock is not visible to it. Retry in a new transaction.
2026
+ if (this.dbtype === 'Postgres' &&
1927
2027
  (await this.findReservedActionBatchOutputIds([output.outputId], trx)).length > 0) {
1928
- excluded.push(output.outputId);
1929
- output = await selectOutput();
1930
- }
1931
- if (output == null)
2028
+ reservedConcurrently = true;
1932
2029
  return undefined;
2030
+ }
1933
2031
  await this.updateOutput(output.outputId, {
1934
2032
  spendable: false,
1935
2033
  spentBy: transactionId
@@ -1941,6 +2039,8 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
1941
2039
  output.spentBy = transactionId;
1942
2040
  return output;
1943
2041
  });
2042
+ if (reservedConcurrently)
2043
+ return await this.allocateChangeInput(userId, basketId, targetSatoshis, exactSatoshis, excludeSending, transactionId);
1944
2044
  return r;
1945
2045
  }
1946
2046
  async markChangeInputsSpent(outputIds, transactionId, trx) {
@@ -2006,8 +2106,8 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
2006
2106
  return entities;
2007
2107
  }
2008
2108
  async adminStats(adminIdentityKey) {
2009
- if (this.dbtype !== 'MySQL' && this.dbtype !== 'Postgres')
2010
- throw new WERR_errors_1.WERR_NOT_IMPLEMENTED('adminStats, only MySQL and Postgres are supported');
2109
+ if (this.dbtype !== 'MySQL')
2110
+ throw new WERR_errors_1.WERR_NOT_IMPLEMENTED('adminStats, only MySQL is supported');
2011
2111
  const monitorEvent = (0, utilityHelpers_1.verifyOneOrNone)(await this.findMonitorEvents({
2012
2112
  partial: { event: 'MonitorCallHistory' },
2013
2113
  orderDescending: true,
@@ -2015,66 +2115,153 @@ class StorageKnex extends StorageProvider_1.StorageProvider {
2015
2115
  }));
2016
2116
  const monitorStats = monitorEvent != null ? JSON.parse(monitorEvent.details) : undefined;
2017
2117
  const servicesStats = this.getServices().getServicesCallHistory(true);
2018
- const day = 24 * 60 * 60 * 1000;
2019
- const now = Date.now();
2020
- const periods = [
2021
- ['Day', new Date(now - day)],
2022
- ['Week', new Date(now - 7 * day)],
2023
- ['Month', new Date(now - 30 * day)],
2024
- ['Total', undefined]
2025
- ];
2026
- const k = this.knex;
2027
- const count = (table, createdAt = 'created_at') => (since) => {
2028
- const q = k(table).count('*');
2029
- if (since != null)
2030
- void q.where(createdAt, '>', this.validateDateForWhere(since));
2031
- return q;
2032
- };
2033
- const txCount = (status) => (since) => count('transactions')(since).where({ status });
2034
- const satoshis = (change) => (since) => {
2035
- const q = k('outputs as o')
2036
- .join('transactions as t', 'o.transactionId', 't.transactionId')
2037
- .where({ 't.status': 'completed', 'o.spendable': true, 'o.change': change })
2038
- .sum('o.satoshis');
2039
- if (!change)
2040
- void q.whereNotNull('o.basketId');
2041
- if (since != null)
2042
- void q.where('o.created_at', '>', this.validateDateForWhere(since));
2043
- return q;
2044
- };
2045
- const stats = [
2046
- ['users', count('users')],
2047
- ['transactions', count('transactions')],
2048
- ['txCompleted', txCount('completed')],
2049
- ['txFailed', since => txCount('failed')(since).whereNotNull('txid')],
2050
- ['txAbandoned', since => txCount('failed')(since).whereNull('txid')],
2051
- ['txUnprocessed', txCount('unprocessed')],
2052
- ['txSending', txCount('sending')],
2053
- ['txUnproven', txCount('unproven')],
2054
- ['txUnsigned', txCount('unsigned')],
2055
- ['txNosend', txCount('nosend')],
2056
- ['txNonfinal', txCount('nonfinal')],
2057
- ['txUnfail', txCount('unfail')],
2058
- ['satoshisDefault', satoshis(true)],
2059
- ['satoshisOther', satoshis(false)],
2060
- ['baskets', count('output_baskets')],
2061
- ['labels', count('tx_labels')],
2062
- ['tags', count('output_tags')]
2063
- ];
2064
- // One statement of scalar subqueries; knex quotes the camelCase identifiers per dialect.
2065
- const columns = {};
2066
- for (const [name, query] of stats) {
2067
- for (const [period, since] of periods)
2068
- columns[`${name}${period}`] = query(since);
2069
- }
2070
- const [row] = (await k.select(columns));
2071
- const values = Object.fromEntries(Object.keys(columns).map(name => [name, Number(row[name] ?? 0)]));
2118
+ const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
2119
+ const oneWeekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
2120
+ const oneMonthAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
2121
+ 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(`
2122
+ select
2123
+ (select count(*) from users where created_at > '${oneDayAgo}') as usersDay,
2124
+ (select count(*) from users where created_at > '${oneWeekAgo}') as usersWeek,
2125
+ (select count(*) from users where created_at > '${oneMonthAgo}') as usersMonth,
2126
+ (select count(*) from users) as usersTotal,
2127
+ (select count(*) from transactions where created_at > '${oneDayAgo}') as transactionsDay,
2128
+ (select count(*) from transactions where created_at > '${oneWeekAgo}') as transactionsWeek,
2129
+ (select count(*) from transactions where created_at > '${oneMonthAgo}') as transactionsMonth,
2130
+ (select count(*) from transactions) as transactionsTotal,
2131
+ (select count(*) from transactions where status = 'completed' and created_at > '${oneDayAgo}') as txCompletedDay,
2132
+ (select count(*) from transactions where status = 'completed' and created_at > '${oneWeekAgo}') as txCompletedWeek,
2133
+ (select count(*) from transactions where status = 'completed' and created_at > '${oneMonthAgo}') as txCompletedMonth,
2134
+ (select count(*) from transactions where status = 'completed') as txCompletedTotal,
2135
+ (select count(*) from transactions where status = 'failed' and not txid is null and created_at > '${oneDayAgo}') as txFailedDay,
2136
+ (select count(*) from transactions where status = 'failed' and not txid is null and created_at > '${oneWeekAgo}') as txFailedWeek,
2137
+ (select count(*) from transactions where status = 'failed' and not txid is null and created_at > '${oneMonthAgo}') as txFailedMonth,
2138
+ (select count(*) from transactions where status = 'failed' and not txid is null) as txFailedTotal,
2139
+ (select count(*) from transactions where status = 'failed' and txid is null and created_at > '${oneDayAgo}') as txAbandonedDay,
2140
+ (select count(*) from transactions where status = 'failed' and txid is null and created_at > '${oneWeekAgo}') as txAbandonedWeek,
2141
+ (select count(*) from transactions where status = 'failed' and txid is null and created_at > '${oneMonthAgo}') as txAbandonedMonth,
2142
+ (select count(*) from transactions where status = 'failed' and txid is null) as txAbandonedTotal,
2143
+ (select count(*) from transactions where status = 'unprocessed' and created_at > '${oneDayAgo}') as txUnprocessedDay,
2144
+ (select count(*) from transactions where status = 'unprocessed' and created_at > '${oneWeekAgo}') as txUnprocessedWeek,
2145
+ (select count(*) from transactions where status = 'unprocessed' and created_at > '${oneMonthAgo}') as txUnprocessedMonth,
2146
+ (select count(*) from transactions where status = 'unprocessed') as txUnprocessedTotal,
2147
+ (select count(*) from transactions where status = 'sending' and created_at > '${oneDayAgo}') as txSendingDay,
2148
+ (select count(*) from transactions where status = 'sending' and created_at > '${oneWeekAgo}') as txSendingWeek,
2149
+ (select count(*) from transactions where status = 'sending' and created_at > '${oneMonthAgo}') as txSendingMonth,
2150
+ (select count(*) from transactions where status = 'sending') as txSendingTotal,
2151
+ (select count(*) from transactions where status = 'unproven' and created_at > '${oneDayAgo}') as txUnprovenDay,
2152
+ (select count(*) from transactions where status = 'unproven' and created_at > '${oneWeekAgo}') as txUnprovenWeek,
2153
+ (select count(*) from transactions where status = 'unproven' and created_at > '${oneMonthAgo}') as txUnprovenMonth,
2154
+ (select count(*) from transactions where status = 'unproven') as txUnprovenTotal,
2155
+ (select count(*) from transactions where status = 'unsigned' and created_at > '${oneDayAgo}') as txUnsignedDay,
2156
+ (select count(*) from transactions where status = 'unsigned' and created_at > '${oneWeekAgo}') as txUnsignedWeek,
2157
+ (select count(*) from transactions where status = 'unsigned' and created_at > '${oneMonthAgo}') as txUnsignedMonth,
2158
+ (select count(*) from transactions where status = 'unsigned') as txUnsignedTotal,
2159
+ (select count(*) from transactions where status = 'nosend' and created_at > '${oneDayAgo}') as txNosendDay,
2160
+ (select count(*) from transactions where status = 'nosend' and created_at > '${oneWeekAgo}') as txNosendWeek,
2161
+ (select count(*) from transactions where status = 'nosend' and created_at > '${oneMonthAgo}') as txNosendMonth,
2162
+ (select count(*) from transactions where status = 'nosend') as txNosendTotal,
2163
+ (select count(*) from transactions where status = 'nonfinal' and created_at > '${oneDayAgo}') as txNonfinalDay,
2164
+ (select count(*) from transactions where status = 'nonfinal' and created_at > '${oneWeekAgo}') as txNonfinalWeek,
2165
+ (select count(*) from transactions where status = 'nonfinal' and created_at > '${oneMonthAgo}') as txNonfinalMonth,
2166
+ (select count(*) from transactions where status = 'nonfinal') as txNonfinalTotal,
2167
+ (select count(*) from transactions where status = 'unfail' and created_at > '${oneDayAgo}') as txUnfailDay,
2168
+ (select count(*) from transactions where status = 'unfail' and created_at > '${oneWeekAgo}') as txUnfailWeek,
2169
+ (select count(*) from transactions where status = 'unfail' and created_at > '${oneMonthAgo}') as txUnfailMonth,
2170
+ (select count(*) from transactions where status = 'unfail') as txUnfailTotal,
2171
+ (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,
2172
+ (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,
2173
+ (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,
2174
+ (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,
2175
+ (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,
2176
+ (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,
2177
+ (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,
2178
+ (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,
2179
+ (select count(*) from output_baskets where created_at > '${oneDayAgo}') as basketsDay,
2180
+ (select count(*) from output_baskets where created_at > '${oneWeekAgo}') as basketsWeek,
2181
+ (select count(*) from output_baskets where created_at > '${oneMonthAgo}') as basketsMonth,
2182
+ (select count(*) from output_baskets) as basketsTotal,
2183
+ (select count(*) from tx_labels where created_at > '${oneDayAgo}') as labelsDay,
2184
+ (select count(*) from tx_labels where created_at > '${oneWeekAgo}') as labelsWeek,
2185
+ (select count(*) from tx_labels where created_at > '${oneMonthAgo}') as labelsMonth,
2186
+ (select count(*) from tx_labels) as labelsTotal,
2187
+ (select count(*) from output_tags where created_at > '${oneDayAgo}') as tagsDay,
2188
+ (select count(*) from output_tags where created_at > '${oneWeekAgo}') as tagsWeek,
2189
+ (select count(*) from output_tags where created_at > '${oneMonthAgo}') as tagsMonth,
2190
+ (select count(*) from output_tags) as tagsTotal
2191
+ `);
2072
2192
  const r = {
2073
2193
  monitorStats,
2074
2194
  servicesStats,
2075
2195
  requestedBy: adminIdentityKey,
2076
2196
  when: new Date().toISOString(),
2077
- ...values
2197
+ usersDay,
2198
+ usersWeek,
2199
+ usersMonth,
2200
+ usersTotal,
2201
+ transactionsDay,
2202
+ transactionsWeek,
2203
+ transactionsMonth,
2204
+ transactionsTotal,
2205
+ txCompletedDay,
2206
+ txCompletedWeek,
2207
+ txCompletedMonth,
2208
+ txCompletedTotal,
2209
+ txFailedDay,
2210
+ txFailedWeek,
2211
+ txFailedMonth,
2212
+ txFailedTotal,
2213
+ txAbandonedDay,
2214
+ txAbandonedWeek,
2215
+ txAbandonedMonth,
2216
+ txAbandonedTotal,
2217
+ txUnprocessedDay,
2218
+ txUnprocessedWeek,
2219
+ txUnprocessedMonth,
2220
+ txUnprocessedTotal,
2221
+ txSendingDay,
2222
+ txSendingWeek,
2223
+ txSendingMonth,
2224
+ txSendingTotal,
2225
+ txUnprovenDay,
2226
+ txUnprovenWeek,
2227
+ txUnprovenMonth,
2228
+ txUnprovenTotal,
2229
+ txUnsignedDay,
2230
+ txUnsignedWeek,
2231
+ txUnsignedMonth,
2232
+ txUnsignedTotal,
2233
+ txNosendDay,
2234
+ txNosendWeek,
2235
+ txNosendMonth,
2236
+ txNosendTotal,
2237
+ txNonfinalDay,
2238
+ txNonfinalWeek,
2239
+ txNonfinalMonth,
2240
+ txNonfinalTotal,
2241
+ txUnfailDay,
2242
+ txUnfailWeek,
2243
+ txUnfailMonth,
2244
+ txUnfailTotal,
2245
+ satoshisDefaultDay: Number(satoshisDefaultDay),
2246
+ satoshisDefaultWeek: Number(satoshisDefaultWeek),
2247
+ satoshisDefaultMonth: Number(satoshisDefaultMonth),
2248
+ satoshisDefaultTotal: Number(satoshisDefaultTotal),
2249
+ satoshisOtherDay: Number(satoshisOtherDay),
2250
+ satoshisOtherWeek: Number(satoshisOtherWeek),
2251
+ satoshisOtherMonth: Number(satoshisOtherMonth),
2252
+ satoshisOtherTotal: Number(satoshisOtherTotal),
2253
+ basketsDay,
2254
+ basketsWeek,
2255
+ basketsMonth,
2256
+ basketsTotal,
2257
+ labelsDay,
2258
+ labelsWeek,
2259
+ labelsMonth,
2260
+ labelsTotal,
2261
+ tagsDay,
2262
+ tagsWeek,
2263
+ tagsMonth,
2264
+ tagsTotal
2078
2265
  };
2079
2266
  return r;
2080
2267
  }
@@ -2124,4 +2311,23 @@ function pagingKey(table) {
2124
2311
  return [];
2125
2312
  }
2126
2313
  }
2314
+ const pgInt8Parsed = Symbol('pgInt8Parsed');
2315
+ /**
2316
+ * node-postgres returns int8 values (bigint columns such as satoshis, `count(*)`)
2317
+ * as strings. Set a parser on each connection this knex acquires so they come
2318
+ * back as numbers, as with mysql2 and better-sqlite3. The process-wide `pg.types`
2319
+ * defaults are left unchanged.
2320
+ */
2321
+ function parsePostgresInt8AsNumber(knex) {
2322
+ const client = knex.client;
2323
+ if (client?.dialect !== 'postgresql' || client[pgInt8Parsed] === true)
2324
+ return;
2325
+ client[pgInt8Parsed] = true;
2326
+ const acquireConnection = client.acquireConnection.bind(client);
2327
+ client.acquireConnection = async () => {
2328
+ const connection = await acquireConnection();
2329
+ connection.setTypeParser(20, (value) => Number.parseInt(value, 10));
2330
+ return connection;
2331
+ };
2332
+ }
2127
2333
  //# sourceMappingURL=StorageKnex.js.map