beignet 0.2.0 → 0.3.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 (195) hide show
  1. package/README.md +284 -1
  2. package/dist/cli/beignet-node.js +1019 -47
  3. package/dist/cli/beignet-node.js.map +1 -1
  4. package/dist/cli/cli.js +1201 -16
  5. package/dist/cli/cli.js.map +1 -1
  6. package/dist/cli/config.js +21 -1
  7. package/dist/cli/config.js.map +1 -1
  8. package/dist/cli/daemon.js +342 -16
  9. package/dist/cli/daemon.js.map +1 -1
  10. package/dist/cli/errors.js +2 -0
  11. package/dist/cli/errors.js.map +1 -1
  12. package/dist/cli/openapi.js +1207 -14
  13. package/dist/cli/openapi.js.map +1 -1
  14. package/dist/cli/restore.js +89 -0
  15. package/dist/cli/restore.js.map +1 -0
  16. package/dist/cli/wallet-storage.js +34 -0
  17. package/dist/cli/wallet-storage.js.map +1 -0
  18. package/dist/electrum/index.js +105 -10
  19. package/dist/electrum/index.js.map +1 -1
  20. package/dist/lightning/advisor/fee-tuner.js +42 -0
  21. package/dist/lightning/advisor/fee-tuner.js.map +1 -0
  22. package/dist/lightning/advisor/index.js +9 -1
  23. package/dist/lightning/advisor/index.js.map +1 -1
  24. package/dist/lightning/advisor/rebalance-planner.js +55 -0
  25. package/dist/lightning/advisor/rebalance-planner.js.map +1 -0
  26. package/dist/lightning/backup/index.js +18 -0
  27. package/dist/lightning/backup/index.js.map +1 -0
  28. package/dist/lightning/backup/scb.js +42 -0
  29. package/dist/lightning/backup/scb.js.map +1 -0
  30. package/dist/lightning/chain/chain-monitor.js +27 -0
  31. package/dist/lightning/chain/chain-monitor.js.map +1 -1
  32. package/dist/lightning/chain/output-resolver.js +55 -6
  33. package/dist/lightning/chain/output-resolver.js.map +1 -1
  34. package/dist/lightning/chain/types.js +1 -0
  35. package/dist/lightning/chain/types.js.map +1 -1
  36. package/dist/lightning/channel/channel-manager.js +64 -0
  37. package/dist/lightning/channel/channel-manager.js.map +1 -1
  38. package/dist/lightning/channel/channel-state.js.map +1 -1
  39. package/dist/lightning/channel/channel.js +124 -4
  40. package/dist/lightning/channel/channel.js.map +1 -1
  41. package/dist/lightning/channel/dual-funding.js +6 -5
  42. package/dist/lightning/channel/dual-funding.js.map +1 -1
  43. package/dist/lightning/channel/types.js +3 -1
  44. package/dist/lightning/channel/types.js.map +1 -1
  45. package/dist/lightning/channel/validation.js +3 -3
  46. package/dist/lightning/channel/validation.js.map +1 -1
  47. package/dist/lightning/crypto/index.js +1 -0
  48. package/dist/lightning/crypto/index.js.map +1 -1
  49. package/dist/lightning/crypto/message-signing.js +116 -0
  50. package/dist/lightning/crypto/message-signing.js.map +1 -0
  51. package/dist/lightning/crypto/xchacha20poly1305.js +77 -0
  52. package/dist/lightning/crypto/xchacha20poly1305.js.map +1 -0
  53. package/dist/lightning/features/flags.js +1 -0
  54. package/dist/lightning/features/flags.js.map +1 -1
  55. package/dist/lightning/gossip/messages.js +37 -1
  56. package/dist/lightning/gossip/messages.js.map +1 -1
  57. package/dist/lightning/index.js +2 -1
  58. package/dist/lightning/index.js.map +1 -1
  59. package/dist/lightning/keys/wallet-keys.js +1 -0
  60. package/dist/lightning/keys/wallet-keys.js.map +1 -1
  61. package/dist/lightning/message/index.js +1 -0
  62. package/dist/lightning/message/index.js.map +1 -1
  63. package/dist/lightning/message/peer-storage.js +43 -0
  64. package/dist/lightning/message/peer-storage.js.map +1 -0
  65. package/dist/lightning/message/types.js +2 -0
  66. package/dist/lightning/message/types.js.map +1 -1
  67. package/dist/lightning/node/lightning-node.js +1583 -235
  68. package/dist/lightning/node/lightning-node.js.map +1 -1
  69. package/dist/lightning/node/types.js +18 -1
  70. package/dist/lightning/node/types.js.map +1 -1
  71. package/dist/lightning/offer/offer-manager.js +2 -5
  72. package/dist/lightning/offer/offer-manager.js.map +1 -1
  73. package/dist/lightning/offer/tlv.js +3 -1
  74. package/dist/lightning/offer/tlv.js.map +1 -1
  75. package/dist/lightning/storage/encryption.js +67 -0
  76. package/dist/lightning/storage/encryption.js.map +1 -0
  77. package/dist/lightning/storage/index.js +1 -0
  78. package/dist/lightning/storage/index.js.map +1 -1
  79. package/dist/lightning/storage/serialization.js +6 -2
  80. package/dist/lightning/storage/serialization.js.map +1 -1
  81. package/dist/lightning/storage/sqlite-storage.js +387 -33
  82. package/dist/lightning/storage/sqlite-storage.js.map +1 -1
  83. package/dist/lightning/watchtower/blob.js +135 -0
  84. package/dist/lightning/watchtower/blob.js.map +1 -0
  85. package/dist/lightning/watchtower/index.js +55 -0
  86. package/dist/lightning/watchtower/index.js.map +1 -0
  87. package/dist/lightning/watchtower/justice.js +182 -0
  88. package/dist/lightning/watchtower/justice.js.map +1 -0
  89. package/dist/lightning/watchtower/tower-connection.js +208 -0
  90. package/dist/lightning/watchtower/tower-connection.js.map +1 -0
  91. package/dist/lightning/watchtower/types.js +3 -0
  92. package/dist/lightning/watchtower/types.js.map +1 -0
  93. package/dist/lightning/watchtower/watchtower-client.js +402 -0
  94. package/dist/lightning/watchtower/watchtower-client.js.map +1 -0
  95. package/dist/lightning/watchtower/wtwire.js +201 -0
  96. package/dist/lightning/watchtower/wtwire.js.map +1 -0
  97. package/dist/shapes/electrum.js +32 -1
  98. package/dist/shapes/electrum.js.map +1 -1
  99. package/dist/shapes/wallet.js +11 -1
  100. package/dist/shapes/wallet.js.map +1 -1
  101. package/dist/transaction/index.js +163 -15
  102. package/dist/transaction/index.js.map +1 -1
  103. package/dist/types/cli/beignet-node.d.ts +144 -3
  104. package/dist/types/cli/daemon.d.ts +2 -0
  105. package/dist/types/cli/errors.d.ts +2 -0
  106. package/dist/types/cli/restore.d.ts +10 -0
  107. package/dist/types/cli/types.d.ts +228 -1
  108. package/dist/types/cli/wallet-storage.d.ts +3 -0
  109. package/dist/types/electrum/index.d.ts +12 -0
  110. package/dist/types/electrum.js +1 -0
  111. package/dist/types/electrum.js.map +1 -1
  112. package/dist/types/lightning/advisor/fee-tuner.d.ts +20 -0
  113. package/dist/types/lightning/advisor/index.d.ts +4 -0
  114. package/dist/types/lightning/advisor/rebalance-planner.d.ts +12 -0
  115. package/dist/types/lightning/backup/index.d.ts +1 -0
  116. package/dist/types/lightning/backup/scb.d.ts +24 -0
  117. package/dist/types/lightning/chain/chain-monitor.d.ts +1 -0
  118. package/dist/types/lightning/chain/types.d.ts +1 -0
  119. package/dist/types/lightning/channel/channel-manager.d.ts +7 -0
  120. package/dist/types/lightning/channel/channel-state.d.ts +2 -0
  121. package/dist/types/lightning/channel/channel.d.ts +6 -0
  122. package/dist/types/lightning/channel/dual-funding.d.ts +2 -1
  123. package/dist/types/lightning/channel/types.d.ts +2 -0
  124. package/dist/types/lightning/channel/validation.d.ts +1 -1
  125. package/dist/types/lightning/crypto/index.d.ts +1 -0
  126. package/dist/types/lightning/crypto/message-signing.d.ts +9 -0
  127. package/dist/types/lightning/crypto/xchacha20poly1305.d.ts +3 -0
  128. package/dist/types/lightning/features/flags.d.ts +1 -0
  129. package/dist/types/lightning/gossip/messages.d.ts +4 -0
  130. package/dist/types/lightning/index.d.ts +1 -0
  131. package/dist/types/lightning/keys/wallet-keys.d.ts +2 -1
  132. package/dist/types/lightning/message/index.d.ts +1 -0
  133. package/dist/types/lightning/message/peer-storage.d.ts +9 -0
  134. package/dist/types/lightning/message/types.d.ts +2 -0
  135. package/dist/types/lightning/node/lightning-node.d.ts +116 -4
  136. package/dist/types/lightning/node/types.d.ts +62 -1
  137. package/dist/types/lightning/storage/encryption.d.ts +11 -0
  138. package/dist/types/lightning/storage/index.d.ts +1 -0
  139. package/dist/types/lightning/storage/serialization.d.ts +2 -0
  140. package/dist/types/lightning/storage/sqlite-storage.d.ts +43 -3
  141. package/dist/types/lightning/storage/types.d.ts +62 -0
  142. package/dist/types/lightning/watchtower/blob.d.ts +32 -0
  143. package/dist/types/lightning/watchtower/index.d.ts +9 -0
  144. package/dist/types/lightning/watchtower/justice.d.ts +29 -0
  145. package/dist/types/lightning/watchtower/tower-connection.d.ts +34 -0
  146. package/dist/types/lightning/watchtower/types.d.ts +44 -0
  147. package/dist/types/lightning/watchtower/watchtower-client.d.ts +67 -0
  148. package/dist/types/lightning/watchtower/wtwire.d.ts +90 -0
  149. package/dist/types/shapes/electrum.d.ts +3 -1
  150. package/dist/types/transaction/index.d.ts +6 -0
  151. package/dist/types/transaction.js.map +1 -1
  152. package/dist/types/types/electrum.d.ts +3 -2
  153. package/dist/types/types/transaction.d.ts +1 -1
  154. package/dist/types/types/wallet.d.ts +78 -4
  155. package/dist/types/utils/descriptors.d.ts +2 -0
  156. package/dist/types/utils/fees.d.ts +3 -0
  157. package/dist/types/utils/helpers.d.ts +3 -1
  158. package/dist/types/utils/index.d.ts +5 -0
  159. package/dist/types/utils/multisig.d.ts +29 -0
  160. package/dist/types/utils/transaction.d.ts +7 -0
  161. package/dist/types/utils/wallet-storage-encryption.d.ts +3 -0
  162. package/dist/types/utils/wallet.d.ts +1 -1
  163. package/dist/types/utils/watch-only.d.ts +12 -0
  164. package/dist/types/wallet/constants.d.ts +1 -0
  165. package/dist/types/wallet/index.d.ts +61 -4
  166. package/dist/types/wallet.js +3 -0
  167. package/dist/types/wallet.js.map +1 -1
  168. package/dist/utils/derivation-path.js +8 -7
  169. package/dist/utils/derivation-path.js.map +1 -1
  170. package/dist/utils/descriptors.js +56 -0
  171. package/dist/utils/descriptors.js.map +1 -0
  172. package/dist/utils/electrum.js +10 -2
  173. package/dist/utils/electrum.js.map +1 -1
  174. package/dist/utils/fees.js +19 -0
  175. package/dist/utils/fees.js.map +1 -0
  176. package/dist/utils/helpers.js +22 -5
  177. package/dist/utils/helpers.js.map +1 -1
  178. package/dist/utils/index.js +5 -0
  179. package/dist/utils/index.js.map +1 -1
  180. package/dist/utils/multisig.js +90 -0
  181. package/dist/utils/multisig.js.map +1 -0
  182. package/dist/utils/transaction.js +30 -3
  183. package/dist/utils/transaction.js.map +1 -1
  184. package/dist/utils/wallet-storage-encryption.js +45 -0
  185. package/dist/utils/wallet-storage-encryption.js.map +1 -0
  186. package/dist/utils/wallet.js +3 -1
  187. package/dist/utils/wallet.js.map +1 -1
  188. package/dist/utils/watch-only.js +102 -0
  189. package/dist/utils/watch-only.js.map +1 -0
  190. package/dist/wallet/constants.js +2 -1
  191. package/dist/wallet/constants.js.map +1 -1
  192. package/dist/wallet/index.js +787 -30
  193. package/dist/wallet/index.js.map +1 -1
  194. package/docs/ROADMAP.md +292 -0
  195. package/package.json +1 -1
@@ -6,22 +6,42 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.SqliteStorage = void 0;
7
7
  const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
8
8
  const serialization_1 = require("./serialization");
9
+ const encryption_1 = require("./encryption");
9
10
  class SqliteStorage {
10
- constructor(dbPath, onCorruptRow) {
11
+ constructor(dbPath, onCorruptRow, opts) {
12
+ this.forwardingEventsMaxRows = 100000;
11
13
  this.db = new better_sqlite3_1.default(dbPath);
12
14
  this.onCorruptRow = onCorruptRow;
15
+ this.encryptionKey = opts?.encryptionKey;
13
16
  }
14
17
  reportCorruptRow(error) {
18
+ if (error instanceof encryption_1.StorageEncryptedError) {
19
+ throw error;
20
+ }
15
21
  if (this.onCorruptRow) {
16
22
  this.onCorruptRow(error);
17
23
  }
18
24
  }
25
+ _enc(value) {
26
+ return this.encryptionKey ? (0, encryption_1.encryptValue)(this.encryptionKey, value) : value;
27
+ }
28
+ _dec(value) {
29
+ if (!(0, encryption_1.isEncryptedValue)(value))
30
+ return value;
31
+ if (!this.encryptionKey) {
32
+ throw new encryption_1.StorageEncryptedError();
33
+ }
34
+ return (0, encryption_1.decryptValue)(this.encryptionKey, value);
35
+ }
19
36
  open(opts) {
20
37
  this.db.pragma('journal_mode = WAL');
21
38
  this.db.pragma(`synchronous = ${opts?.synchronous ?? 'FULL'}`);
22
39
  this.db.pragma('foreign_keys = ON');
23
40
  this.db.pragma('busy_timeout = 5000');
24
41
  this._createTables();
42
+ if (this.encryptionKey) {
43
+ this._encryptExistingData();
44
+ }
25
45
  }
26
46
  checkpoint() {
27
47
  this.db.pragma('wal_checkpoint(TRUNCATE)');
@@ -32,6 +52,38 @@ class SqliteStorage {
32
52
  async backup(destPath) {
33
53
  await this.db.backup(destPath);
34
54
  }
55
+ _encryptExistingData() {
56
+ const key = this.encryptionKey;
57
+ if (!key)
58
+ return;
59
+ this.db.transaction(() => {
60
+ for (const { table, pk, columns } of SqliteStorage.ENCRYPTED_COLUMNS) {
61
+ const rows = this.db
62
+ .prepare(`SELECT ${pk}, ${columns.join(', ')} FROM ${table}`)
63
+ .all();
64
+ for (const row of rows) {
65
+ const updates = [];
66
+ const params = [];
67
+ for (const col of columns) {
68
+ const raw = row[col];
69
+ if (raw === null || raw === undefined)
70
+ continue;
71
+ const text = typeof raw === 'string' ? raw : String(raw);
72
+ if ((0, encryption_1.isEncryptedValue)(text))
73
+ continue;
74
+ updates.push(`${col} = ?`);
75
+ params.push((0, encryption_1.encryptValue)(key, text));
76
+ }
77
+ if (updates.length === 0)
78
+ continue;
79
+ params.push(row[pk]);
80
+ this.db
81
+ .prepare(`UPDATE ${table} SET ${updates.join(', ')} WHERE ${pk} = ?`)
82
+ .run(...params);
83
+ }
84
+ }
85
+ })();
86
+ }
35
87
  _createTables() {
36
88
  this.db.exec(`
37
89
  CREATE TABLE IF NOT EXISTS channels (
@@ -152,6 +204,61 @@ class SqliteStorage {
152
204
  created_at INTEGER NOT NULL,
153
205
  completed_at INTEGER
154
206
  );
207
+
208
+ CREATE TABLE IF NOT EXISTS channel_policies (
209
+ channel_id TEXT PRIMARY KEY,
210
+ policy_json TEXT NOT NULL
211
+ );
212
+
213
+ CREATE TABLE IF NOT EXISTS peer_storage_blobs (
214
+ peer_pubkey TEXT PRIMARY KEY,
215
+ blob TEXT NOT NULL,
216
+ received_at INTEGER NOT NULL
217
+ );
218
+
219
+ CREATE TABLE IF NOT EXISTS forwarding_events (
220
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
221
+ settled_at INTEGER NOT NULL,
222
+ in_channel_id TEXT NOT NULL,
223
+ out_channel_id TEXT NOT NULL,
224
+ in_scid TEXT,
225
+ out_scid TEXT,
226
+ amount_in_msat TEXT NOT NULL,
227
+ amount_out_msat TEXT NOT NULL,
228
+ fee_msat TEXT NOT NULL
229
+ );
230
+ CREATE INDEX IF NOT EXISTS idx_forwarding_events_settled_at ON forwarding_events(settled_at);
231
+
232
+ CREATE TABLE IF NOT EXISTS watchtower_sessions (
233
+ session_id TEXT PRIMARY KEY,
234
+ tower_uri TEXT NOT NULL,
235
+ tower_pubkey TEXT NOT NULL,
236
+ session_key TEXT NOT NULL,
237
+ blob_type INTEGER NOT NULL,
238
+ max_updates INTEGER NOT NULL,
239
+ sweep_fee_rate TEXT NOT NULL,
240
+ seq_num INTEGER NOT NULL,
241
+ last_applied INTEGER NOT NULL,
242
+ created_at INTEGER NOT NULL
243
+ );
244
+ CREATE INDEX IF NOT EXISTS idx_watchtower_sessions_tower ON watchtower_sessions(tower_uri);
245
+
246
+ CREATE TABLE IF NOT EXISTS watchtower_updates (
247
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
248
+ tower_uri TEXT NOT NULL,
249
+ channel_id TEXT NOT NULL,
250
+ hint TEXT NOT NULL,
251
+ encrypted_blob TEXT NOT NULL,
252
+ seq_num INTEGER NOT NULL,
253
+ acked INTEGER NOT NULL,
254
+ created_at INTEGER NOT NULL
255
+ );
256
+ CREATE INDEX IF NOT EXISTS idx_watchtower_updates_pending ON watchtower_updates(tower_uri, acked);
257
+
258
+ CREATE TABLE IF NOT EXISTS wallet_data (
259
+ key TEXT PRIMARY KEY,
260
+ value TEXT NOT NULL
261
+ );
155
262
  `);
156
263
  this._runMigrations();
157
264
  }
@@ -160,7 +267,7 @@ class SqliteStorage {
160
267
  const json = JSON.stringify(serialized);
161
268
  this.db
162
269
  .prepare('INSERT OR REPLACE INTO channels (channel_id, state_json, peer_pubkey) VALUES (?, ?, ?)')
163
- .run(id, json, peerPubkey);
270
+ .run(id, this._enc(json), peerPubkey);
164
271
  }
165
272
  loadChannel(id) {
166
273
  const row = this.db
@@ -169,7 +276,7 @@ class SqliteStorage {
169
276
  if (!row)
170
277
  return null;
171
278
  return {
172
- state: (0, serialization_1.deserializeChannelState)(JSON.parse(row.state_json)),
279
+ state: (0, serialization_1.deserializeChannelState)(JSON.parse(this._dec(row.state_json))),
173
280
  peerPubkey: row.peer_pubkey
174
281
  };
175
282
  }
@@ -182,7 +289,7 @@ class SqliteStorage {
182
289
  try {
183
290
  results.push({
184
291
  channelId: row.channel_id,
185
- state: (0, serialization_1.deserializeChannelState)(JSON.parse(row.state_json)),
292
+ state: (0, serialization_1.deserializeChannelState)(JSON.parse(this._dec(row.state_json))),
186
293
  peerPubkey: row.peer_pubkey
187
294
  });
188
295
  }
@@ -200,7 +307,7 @@ class SqliteStorage {
200
307
  const json = JSON.stringify(serialized);
201
308
  this.db
202
309
  .prepare('INSERT OR REPLACE INTO payments (payment_hash, payment_json) VALUES (?, ?)')
203
- .run(paymentHash, json);
310
+ .run(paymentHash, this._enc(json));
204
311
  }
205
312
  loadPayment(paymentHash) {
206
313
  const row = this.db
@@ -208,7 +315,7 @@ class SqliteStorage {
208
315
  .get(paymentHash);
209
316
  if (!row)
210
317
  return null;
211
- return (0, serialization_1.deserializePaymentInfo)(JSON.parse(row.payment_json));
318
+ return (0, serialization_1.deserializePaymentInfo)(JSON.parse(this._dec(row.payment_json)));
212
319
  }
213
320
  loadAllPayments() {
214
321
  const rows = this.db
@@ -219,7 +326,7 @@ class SqliteStorage {
219
326
  try {
220
327
  results.push({
221
328
  paymentHash: row.payment_hash,
222
- payment: (0, serialization_1.deserializePaymentInfo)(JSON.parse(row.payment_json))
329
+ payment: (0, serialization_1.deserializePaymentInfo)(JSON.parse(this._dec(row.payment_json)))
223
330
  });
224
331
  }
225
332
  catch (err) {
@@ -236,7 +343,7 @@ class SqliteStorage {
236
343
  savePreimage(paymentHash, preimage) {
237
344
  this.db
238
345
  .prepare('INSERT OR REPLACE INTO preimages (payment_hash, preimage) VALUES (?, ?)')
239
- .run(paymentHash, preimage.toString('hex'));
346
+ .run(paymentHash, this._enc(preimage.toString('hex')));
240
347
  }
241
348
  loadPreimage(paymentHash) {
242
349
  const row = this.db
@@ -244,7 +351,7 @@ class SqliteStorage {
244
351
  .get(paymentHash);
245
352
  if (!row)
246
353
  return null;
247
- return Buffer.from(row.preimage, 'hex');
354
+ return Buffer.from(this._dec(row.preimage), 'hex');
248
355
  }
249
356
  loadAllPreimages() {
250
357
  const rows = this.db
@@ -255,7 +362,7 @@ class SqliteStorage {
255
362
  try {
256
363
  results.push({
257
364
  paymentHash: row.payment_hash,
258
- preimage: Buffer.from(row.preimage, 'hex')
365
+ preimage: Buffer.from(this._dec(row.preimage), 'hex')
259
366
  });
260
367
  }
261
368
  catch (err) {
@@ -290,7 +397,7 @@ class SqliteStorage {
290
397
  saveHtlcPaymentMapping(key, paymentHashHex) {
291
398
  this.db
292
399
  .prepare('INSERT OR REPLACE INTO htlc_payment_map (htlc_key, payment_hash_hex) VALUES (?, ?)')
293
- .run(key, paymentHashHex);
400
+ .run(key, this._enc(paymentHashHex));
294
401
  }
295
402
  loadAllHtlcPaymentMappings() {
296
403
  const rows = this.db
@@ -301,7 +408,7 @@ class SqliteStorage {
301
408
  try {
302
409
  results.push({
303
410
  key: row.htlc_key,
304
- paymentHashHex: row.payment_hash_hex
411
+ paymentHashHex: this._dec(row.payment_hash_hex)
305
412
  });
306
413
  }
307
414
  catch (err) {
@@ -316,7 +423,7 @@ class SqliteStorage {
316
423
  saveForwardedHtlc(outKey, inChannelId, inHtlcId) {
317
424
  this.db
318
425
  .prepare('INSERT OR REPLACE INTO forwarded_htlcs (out_key, in_channel_id, in_htlc_id) VALUES (?, ?, ?)')
319
- .run(outKey, inChannelId.toString('hex'), inHtlcId.toString());
426
+ .run(outKey, this._enc(inChannelId.toString('hex')), this._enc(inHtlcId.toString()));
320
427
  }
321
428
  loadAllForwardedHtlcs() {
322
429
  const rows = this.db
@@ -327,8 +434,8 @@ class SqliteStorage {
327
434
  try {
328
435
  results.push({
329
436
  outKey: row.out_key,
330
- inChannelId: Buffer.from(row.in_channel_id, 'hex'),
331
- inHtlcId: BigInt(row.in_htlc_id)
437
+ inChannelId: Buffer.from(this._dec(row.in_channel_id), 'hex'),
438
+ inHtlcId: BigInt(this._dec(row.in_htlc_id))
332
439
  });
333
440
  }
334
441
  catch (err) {
@@ -346,7 +453,7 @@ class SqliteStorage {
346
453
  const json = (0, serialization_1.serializeChainMonitorState)(state);
347
454
  this.db
348
455
  .prepare('INSERT OR REPLACE INTO chain_monitors (channel_id, state_json) VALUES (?, ?)')
349
- .run(channelId, json);
456
+ .run(channelId, this._enc(json));
350
457
  }
351
458
  loadChainMonitor(channelId) {
352
459
  const row = this.db
@@ -354,7 +461,7 @@ class SqliteStorage {
354
461
  .get(channelId);
355
462
  if (!row)
356
463
  return null;
357
- return (0, serialization_1.deserializeChainMonitorState)(row.state_json);
464
+ return (0, serialization_1.deserializeChainMonitorState)(this._dec(row.state_json));
358
465
  }
359
466
  loadAllChainMonitors() {
360
467
  const rows = this.db
@@ -365,7 +472,7 @@ class SqliteStorage {
365
472
  try {
366
473
  results.push({
367
474
  channelId: row.channel_id,
368
- state: (0, serialization_1.deserializeChainMonitorState)(row.state_json)
475
+ state: (0, serialization_1.deserializeChainMonitorState)(this._dec(row.state_json))
369
476
  });
370
477
  }
371
478
  catch (err) {
@@ -424,7 +531,7 @@ class SqliteStorage {
424
531
  savePaymentSecret(paymentHashHex, secret) {
425
532
  this.db
426
533
  .prepare('INSERT OR REPLACE INTO payment_secrets (payment_hash_hex, secret) VALUES (?, ?)')
427
- .run(paymentHashHex, secret.toString('hex'));
534
+ .run(paymentHashHex, this._enc(secret.toString('hex')));
428
535
  }
429
536
  loadAllPaymentSecrets() {
430
537
  const rows = this.db
@@ -435,7 +542,7 @@ class SqliteStorage {
435
542
  try {
436
543
  results.push({
437
544
  paymentHashHex: row.payment_hash_hex,
438
- secret: Buffer.from(row.secret, 'hex')
545
+ secret: Buffer.from(this._dec(row.secret), 'hex')
439
546
  });
440
547
  }
441
548
  catch (err) {
@@ -459,11 +566,12 @@ class SqliteStorage {
459
566
  description: invoice.description,
460
567
  expiry: invoice.expiry,
461
568
  createdAt: invoice.createdAt,
462
- hold: invoice.hold
569
+ hold: invoice.hold,
570
+ cancelledAt: invoice.cancelledAt
463
571
  });
464
572
  this.db
465
573
  .prepare('INSERT OR REPLACE INTO invoices (payment_hash_hex, invoice_json) VALUES (?, ?)')
466
- .run(paymentHashHex, json);
574
+ .run(paymentHashHex, this._enc(json));
467
575
  }
468
576
  loadAllInvoices() {
469
577
  const rows = this.db
@@ -472,7 +580,7 @@ class SqliteStorage {
472
580
  const results = [];
473
581
  for (const row of rows) {
474
582
  try {
475
- const parsed = JSON.parse(row.invoice_json);
583
+ const parsed = JSON.parse(this._dec(row.invoice_json));
476
584
  results.push({
477
585
  paymentHashHex: row.payment_hash_hex,
478
586
  invoice: {
@@ -484,7 +592,8 @@ class SqliteStorage {
484
592
  description: parsed.description,
485
593
  expiry: parsed.expiry,
486
594
  createdAt: parsed.createdAt,
487
- hold: parsed.hold
595
+ hold: parsed.hold,
596
+ cancelledAt: parsed.cancelledAt
488
597
  }
489
598
  });
490
599
  }
@@ -527,24 +636,33 @@ class SqliteStorage {
527
636
  saveChannelKeyIndex(channelId, channelIndex) {
528
637
  this.db
529
638
  .prepare('INSERT OR REPLACE INTO channel_key_indices (channel_id, channel_index) VALUES (?, ?)')
530
- .run(channelId, channelIndex);
639
+ .run(channelId, this.encryptionKey ? this._enc(String(channelIndex)) : channelIndex);
640
+ }
641
+ _decodeChannelIndex(value) {
642
+ return typeof value === 'number' ? value : Number(this._dec(value));
531
643
  }
532
644
  loadChannelKeyIndex(channelId) {
533
645
  const row = this.db
534
646
  .prepare('SELECT channel_index FROM channel_key_indices WHERE channel_id = ?')
535
647
  .get(channelId);
536
- return row ? row.channel_index : null;
648
+ return row ? this._decodeChannelIndex(row.channel_index) : null;
537
649
  }
538
650
  loadNextChannelIndex() {
539
- const row = this.db
540
- .prepare('SELECT MAX(channel_index) as max_idx FROM channel_key_indices')
541
- .get();
542
- return row && row.max_idx !== null ? row.max_idx + 1 : 1;
651
+ const rows = this.db
652
+ .prepare('SELECT channel_index FROM channel_key_indices')
653
+ .all();
654
+ let maxIdx = null;
655
+ for (const row of rows) {
656
+ const idx = this._decodeChannelIndex(row.channel_index);
657
+ if (maxIdx === null || idx > maxIdx)
658
+ maxIdx = idx;
659
+ }
660
+ return maxIdx !== null ? maxIdx + 1 : 1;
543
661
  }
544
662
  saveHtlcSharedSecret(key, secret) {
545
663
  this.db
546
664
  .prepare('INSERT OR REPLACE INTO htlc_shared_secrets (key, secret) VALUES (?, ?)')
547
- .run(key, secret.toString('hex'));
665
+ .run(key, this._enc(secret.toString('hex')));
548
666
  }
549
667
  deleteHtlcSharedSecret(key) {
550
668
  this.db.prepare('DELETE FROM htlc_shared_secrets WHERE key = ?').run(key);
@@ -558,7 +676,7 @@ class SqliteStorage {
558
676
  try {
559
677
  results.push({
560
678
  key: row.key,
561
- secret: Buffer.from(row.secret, 'hex')
679
+ secret: Buffer.from(this._dec(row.secret), 'hex')
562
680
  });
563
681
  }
564
682
  catch (err) {
@@ -621,6 +739,18 @@ class SqliteStorage {
621
739
  }
622
740
  },
623
741
  () => {
742
+ },
743
+ () => {
744
+ },
745
+ () => {
746
+ },
747
+ () => {
748
+ },
749
+ () => {
750
+ },
751
+ () => {
752
+ },
753
+ () => {
624
754
  }
625
755
  ];
626
756
  for (let v = currentVersion; v < targetVersion; v++) {
@@ -646,6 +776,198 @@ class SqliteStorage {
646
776
  .get(key);
647
777
  return row ? row.value : null;
648
778
  }
779
+ saveWalletData(key, value) {
780
+ this.db
781
+ .prepare('INSERT OR REPLACE INTO wallet_data (key, value) VALUES (?, ?)')
782
+ .run(key, this._enc(value));
783
+ }
784
+ loadWalletData(key) {
785
+ const row = this.db
786
+ .prepare('SELECT value FROM wallet_data WHERE key = ?')
787
+ .get(key);
788
+ return row ? this._dec(row.value) : null;
789
+ }
790
+ saveChannelPolicy(channelId, policy) {
791
+ this.db
792
+ .prepare('INSERT OR REPLACE INTO channel_policies (channel_id, policy_json) VALUES (?, ?)')
793
+ .run(channelId, JSON.stringify(policy));
794
+ }
795
+ loadAllChannelPolicies() {
796
+ const rows = this.db
797
+ .prepare('SELECT channel_id, policy_json FROM channel_policies')
798
+ .all();
799
+ const results = [];
800
+ for (const row of rows) {
801
+ try {
802
+ results.push({
803
+ channelId: row.channel_id,
804
+ policy: JSON.parse(row.policy_json)
805
+ });
806
+ }
807
+ catch (err) {
808
+ this.reportCorruptRow(err);
809
+ }
810
+ }
811
+ return results;
812
+ }
813
+ deleteChannelPolicy(channelId) {
814
+ this.db
815
+ .prepare('DELETE FROM channel_policies WHERE channel_id = ?')
816
+ .run(channelId);
817
+ }
818
+ savePeerStorageBlob(peerPubkey, blob, receivedAt) {
819
+ this.db
820
+ .prepare('INSERT OR REPLACE INTO peer_storage_blobs (peer_pubkey, blob, received_at) VALUES (?, ?, ?)')
821
+ .run(peerPubkey, this._enc(blob.toString('base64')), receivedAt);
822
+ }
823
+ loadPeerStorageBlob(peerPubkey) {
824
+ const row = this.db
825
+ .prepare('SELECT blob, received_at FROM peer_storage_blobs WHERE peer_pubkey = ?')
826
+ .get(peerPubkey);
827
+ if (!row)
828
+ return null;
829
+ return {
830
+ blob: Buffer.from(this._dec(row.blob), 'base64'),
831
+ receivedAt: row.received_at
832
+ };
833
+ }
834
+ deletePeerStorageBlob(peerPubkey) {
835
+ this.db
836
+ .prepare('DELETE FROM peer_storage_blobs WHERE peer_pubkey = ?')
837
+ .run(peerPubkey);
838
+ }
839
+ saveWatchtowerSession(session, sessionKey) {
840
+ this.db
841
+ .prepare(`INSERT OR REPLACE INTO watchtower_sessions
842
+ (session_id, tower_uri, tower_pubkey, session_key, blob_type,
843
+ max_updates, sweep_fee_rate, seq_num, last_applied, created_at)
844
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
845
+ .run(session.sessionId, session.towerUri, session.towerPubkey, this._enc(sessionKey.toString('base64')), session.blobType, session.maxUpdates, session.sweepFeeRate, session.seqNum, session.lastApplied, session.createdAt);
846
+ }
847
+ loadWatchtowerSessions() {
848
+ const rows = this.db
849
+ .prepare('SELECT * FROM watchtower_sessions')
850
+ .all();
851
+ return rows.map((r) => ({
852
+ sessionId: r.session_id,
853
+ towerUri: r.tower_uri,
854
+ towerPubkey: r.tower_pubkey,
855
+ sessionKey: Buffer.from(this._dec(r.session_key), 'base64'),
856
+ blobType: r.blob_type,
857
+ maxUpdates: r.max_updates,
858
+ sweepFeeRate: r.sweep_fee_rate,
859
+ seqNum: r.seq_num,
860
+ lastApplied: r.last_applied,
861
+ createdAt: r.created_at
862
+ }));
863
+ }
864
+ setWatchtowerSessionProgress(sessionId, seqNum, lastApplied) {
865
+ this.db
866
+ .prepare('UPDATE watchtower_sessions SET seq_num = ?, last_applied = ? WHERE session_id = ?')
867
+ .run(seqNum, lastApplied, sessionId);
868
+ }
869
+ deleteWatchtowerTower(towerUri) {
870
+ this.db.transaction(() => {
871
+ this.db
872
+ .prepare('DELETE FROM watchtower_sessions WHERE tower_uri = ?')
873
+ .run(towerUri);
874
+ this.db
875
+ .prepare('DELETE FROM watchtower_updates WHERE tower_uri = ?')
876
+ .run(towerUri);
877
+ })();
878
+ }
879
+ addWatchtowerUpdate(update) {
880
+ const info = this.db
881
+ .prepare(`INSERT INTO watchtower_updates
882
+ (tower_uri, channel_id, hint, encrypted_blob, seq_num, acked, created_at)
883
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
884
+ .run(update.towerUri, update.channelId, update.hint, this._enc(update.encryptedBlob), update.seqNum, update.acked ? 1 : 0, update.createdAt);
885
+ return Number(info.lastInsertRowid);
886
+ }
887
+ loadPendingWatchtowerUpdates() {
888
+ const rows = this.db
889
+ .prepare('SELECT * FROM watchtower_updates WHERE acked = 0 ORDER BY id ASC')
890
+ .all();
891
+ return rows.map((r) => ({
892
+ id: r.id,
893
+ towerUri: r.tower_uri,
894
+ channelId: r.channel_id,
895
+ hint: r.hint,
896
+ encryptedBlob: this._dec(r.encrypted_blob),
897
+ seqNum: r.seq_num,
898
+ acked: r.acked === 1,
899
+ createdAt: r.created_at
900
+ }));
901
+ }
902
+ markWatchtowerUpdateAcked(id, seqNum) {
903
+ this.db
904
+ .prepare('UPDATE watchtower_updates SET acked = 1, seq_num = ? WHERE id = ?')
905
+ .run(seqNum, id);
906
+ }
907
+ saveForwardingEvent(event) {
908
+ this.db
909
+ .prepare(`INSERT INTO forwarding_events
910
+ (settled_at, in_channel_id, out_channel_id, in_scid, out_scid,
911
+ amount_in_msat, amount_out_msat, fee_msat)
912
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
913
+ .run(event.settledAt, event.inChannelId, event.outChannelId, event.inScid ?? null, event.outScid ?? null, event.amountInMsat.toString(), event.amountOutMsat.toString(), event.feeMsat.toString());
914
+ this.db
915
+ .prepare('DELETE FROM forwarding_events WHERE id NOT IN (SELECT id FROM forwarding_events ORDER BY id DESC LIMIT ?)')
916
+ .run(this.forwardingEventsMaxRows);
917
+ }
918
+ listForwardingEvents(filter) {
919
+ let sql = 'SELECT id, settled_at, in_channel_id, out_channel_id, in_scid, out_scid, amount_in_msat, amount_out_msat, fee_msat FROM forwarding_events WHERE 1=1';
920
+ const params = [];
921
+ if (filter?.since !== undefined) {
922
+ sql += ' AND settled_at >= ?';
923
+ params.push(filter.since);
924
+ }
925
+ if (filter?.until !== undefined) {
926
+ sql += ' AND settled_at <= ?';
927
+ params.push(filter.until);
928
+ }
929
+ if (filter?.channelId !== undefined) {
930
+ sql += ' AND (in_channel_id = ? OR out_channel_id = ?)';
931
+ params.push(filter.channelId, filter.channelId);
932
+ }
933
+ sql += ' ORDER BY settled_at DESC, id DESC';
934
+ sql += ' LIMIT ?';
935
+ params.push(filter?.limit !== undefined && filter.limit > 0 ? filter.limit : 1000);
936
+ if (filter?.offset !== undefined && filter.offset > 0) {
937
+ sql += ' OFFSET ?';
938
+ params.push(filter.offset);
939
+ }
940
+ const rows = this.db.prepare(sql).all(...params);
941
+ return rows.map((row) => ({
942
+ id: row.id,
943
+ settledAt: row.settled_at,
944
+ inChannelId: row.in_channel_id,
945
+ outChannelId: row.out_channel_id,
946
+ inScid: row.in_scid ?? undefined,
947
+ outScid: row.out_scid ?? undefined,
948
+ amountInMsat: BigInt(row.amount_in_msat),
949
+ amountOutMsat: BigInt(row.amount_out_msat),
950
+ feeMsat: BigInt(row.fee_msat)
951
+ }));
952
+ }
953
+ getForwardingSummary(options) {
954
+ let sql = 'SELECT amount_out_msat, fee_msat FROM forwarding_events WHERE 1=1';
955
+ const params = [];
956
+ if (options?.since !== undefined) {
957
+ sql += ' AND settled_at >= ?';
958
+ params.push(options.since);
959
+ }
960
+ let count = 0;
961
+ let volumeOutMsat = 0n;
962
+ let feesEarnedMsat = 0n;
963
+ for (const row of this.db.prepare(sql).iterate(...params)) {
964
+ const r = row;
965
+ count++;
966
+ volumeOutMsat += BigInt(r.amount_out_msat);
967
+ feesEarnedMsat += BigInt(r.fee_msat);
968
+ }
969
+ return { count, volumeOutMsat, feesEarnedMsat };
970
+ }
649
971
  transaction(fn) {
650
972
  return this.db.transaction(fn)();
651
973
  }
@@ -713,5 +1035,37 @@ class SqliteStorage {
713
1035
  }
714
1036
  }
715
1037
  exports.SqliteStorage = SqliteStorage;
716
- SqliteStorage.CURRENT_SCHEMA_VERSION = 2;
1038
+ SqliteStorage.CURRENT_SCHEMA_VERSION = 8;
1039
+ SqliteStorage.ENCRYPTED_COLUMNS = [
1040
+ { table: 'channels', pk: 'channel_id', columns: ['state_json'] },
1041
+ { table: 'payments', pk: 'payment_hash', columns: ['payment_json'] },
1042
+ { table: 'preimages', pk: 'payment_hash', columns: ['preimage'] },
1043
+ {
1044
+ table: 'htlc_payment_map',
1045
+ pk: 'htlc_key',
1046
+ columns: ['payment_hash_hex']
1047
+ },
1048
+ {
1049
+ table: 'forwarded_htlcs',
1050
+ pk: 'out_key',
1051
+ columns: ['in_channel_id', 'in_htlc_id']
1052
+ },
1053
+ { table: 'chain_monitors', pk: 'channel_id', columns: ['state_json'] },
1054
+ { table: 'payment_secrets', pk: 'payment_hash_hex', columns: ['secret'] },
1055
+ { table: 'htlc_shared_secrets', pk: 'key', columns: ['secret'] },
1056
+ { table: 'invoices', pk: 'payment_hash_hex', columns: ['invoice_json'] },
1057
+ {
1058
+ table: 'channel_key_indices',
1059
+ pk: 'channel_id',
1060
+ columns: ['channel_index']
1061
+ },
1062
+ { table: 'peer_storage_blobs', pk: 'peer_pubkey', columns: ['blob'] },
1063
+ {
1064
+ table: 'watchtower_sessions',
1065
+ pk: 'session_id',
1066
+ columns: ['session_key']
1067
+ },
1068
+ { table: 'watchtower_updates', pk: 'id', columns: ['encrypted_blob'] },
1069
+ { table: 'wallet_data', pk: 'key', columns: ['value'] }
1070
+ ];
717
1071
  //# sourceMappingURL=sqlite-storage.js.map