@breeztech/breez-sdk-spark 0.27.1 → 0.27.3-dev

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 (55) hide show
  1. package/README.md +9 -8
  2. package/bundler/breez_sdk_spark_wasm.d.ts +141 -16
  3. package/bundler/breez_sdk_spark_wasm.js +1 -1
  4. package/bundler/breez_sdk_spark_wasm_bg.js +190 -40
  5. package/bundler/breez_sdk_spark_wasm_bg.wasm +0 -0
  6. package/bundler/breez_sdk_spark_wasm_bg.wasm.d.ts +23 -11
  7. package/bundler/index.js +6 -13
  8. package/bundler/storage/index.js +89 -17
  9. package/deno/breez_sdk_spark_wasm.d.ts +141 -16
  10. package/deno/breez_sdk_spark_wasm.js +190 -40
  11. package/deno/breez_sdk_spark_wasm_bg.wasm +0 -0
  12. package/deno/breez_sdk_spark_wasm_bg.wasm.d.ts +23 -11
  13. package/nodejs/breez_sdk_spark_wasm.d.ts +141 -16
  14. package/nodejs/breez_sdk_spark_wasm.js +194 -40
  15. package/nodejs/breez_sdk_spark_wasm_bg.wasm +0 -0
  16. package/nodejs/breez_sdk_spark_wasm_bg.wasm.d.ts +23 -11
  17. package/nodejs/index.d.mts +3 -0
  18. package/nodejs/index.js +30 -120
  19. package/nodejs/index.mjs +4 -0
  20. package/nodejs/mysql-session-store/index.cjs +24 -7
  21. package/nodejs/mysql-session-store/migrations.cjs +6 -0
  22. package/nodejs/mysql-storage/index.cjs +36 -19
  23. package/nodejs/mysql-storage/migrations.cjs +24 -9
  24. package/nodejs/mysql-token-store/index.cjs +28 -18
  25. package/nodejs/postgres-session-store/index.cjs +25 -7
  26. package/nodejs/postgres-session-store/migrations.cjs +12 -9
  27. package/nodejs/postgres-storage/index.cjs +36 -19
  28. package/nodejs/postgres-storage/migrations.cjs +24 -9
  29. package/nodejs/postgres-token-store/index.cjs +32 -18
  30. package/nodejs/postgres-token-store/migrations.cjs +5 -9
  31. package/nodejs/postgres-tree-store/migrations.cjs +5 -9
  32. package/nodejs/storage/index.cjs +35 -14
  33. package/nodejs/storage/migrations.cjs +25 -15
  34. package/nodejs/tree-store/index.cjs +1 -1
  35. package/nodejs/tree-store/migrations.cjs +6 -13
  36. package/package.json +27 -6
  37. package/ssr/index.js +24 -0
  38. package/web/breez_sdk_spark_wasm.d.ts +164 -27
  39. package/web/breez_sdk_spark_wasm.js +190 -40
  40. package/web/breez_sdk_spark_wasm_bg.wasm +0 -0
  41. package/web/breez_sdk_spark_wasm_bg.wasm.d.ts +23 -11
  42. package/web/index.js +6 -13
  43. package/web/passkey-prf-provider/index.js +1 -0
  44. package/web/storage/index.js +89 -17
  45. package/breez-sdk-spark.tgz +0 -0
  46. package/itest/.gitignore +0 -2
  47. package/itest/database-drivers.test.js +0 -45
  48. package/itest/helpers/assert.test.js +0 -70
  49. package/itest/helpers/faucet.js +0 -68
  50. package/itest/helpers/lnurl-fixture.js +0 -229
  51. package/itest/helpers/scenario.js +0 -444
  52. package/itest/package-lock.json +0 -519
  53. package/itest/package.json +0 -18
  54. package/itest/scenarios.test.js +0 -47
  55. package/itest/smoke.test.js +0 -184
@@ -54,20 +54,20 @@ class PostgresMigrationManager {
54
54
  const migrations = this._getMigrations(identity);
55
55
 
56
56
  if (currentVersion >= migrations.length) {
57
- this._log("info", `Database is up to date (version ${currentVersion})`);
57
+ this._log("INFO", `Database is up to date (version ${currentVersion})`);
58
58
  await client.query("COMMIT");
59
59
  return;
60
60
  }
61
61
 
62
62
  this._log(
63
- "info",
63
+ "INFO",
64
64
  `Migrating database from version ${currentVersion} to ${migrations.length}`
65
65
  );
66
66
 
67
67
  for (let i = currentVersion; i < migrations.length; i++) {
68
68
  const migration = migrations[i];
69
69
  const version = i + 1;
70
- this._log("debug", `Running migration ${version}: ${migration.name}`);
70
+ this._log("DEBUG", `Running migration ${version}: ${migration.name}`);
71
71
 
72
72
  for (const sql of migration.sql) {
73
73
  await client.query(sql);
@@ -80,7 +80,7 @@ class PostgresMigrationManager {
80
80
  }
81
81
 
82
82
  await client.query("COMMIT");
83
- this._log("info", "Database migration completed successfully");
83
+ this._log("INFO", "Database migration completed successfully");
84
84
  } catch (error) {
85
85
  await client.query("ROLLBACK").catch(() => {});
86
86
  throw new StorageError(
@@ -219,11 +219,7 @@ class PostgresMigrationManager {
219
219
  }
220
220
 
221
221
  _log(level, message) {
222
- if (this.logger && typeof this.logger.log === "function") {
223
- this.logger.log({ line: message, level });
224
- } else if (level === "error") {
225
- console.error(`[PostgresMigrationManager] ${message}`);
226
- }
222
+ this.logger?.log({ line: message, level });
227
223
  }
228
224
 
229
225
  /**
@@ -612,6 +608,25 @@ class PostgresMigrationManager {
612
608
  )`,
613
609
  ],
614
610
  },
611
+ {
612
+ // With the sync offset at 0, the SDK re-fetches every transfer on its
613
+ // next sync and fills in both columns for past withdrawals.
614
+ name: "Add withdrawal destination address and output index",
615
+ sql: [
616
+ `ALTER TABLE brz_payments ADD COLUMN withdraw_vout BIGINT`,
617
+ `ALTER TABLE brz_payments ADD COLUMN withdraw_destination_address TEXT`,
618
+ `UPDATE brz_settings
619
+ SET value = jsonb_set(value::jsonb, '{offset}', '0')::text
620
+ WHERE key = 'sync_offset' AND value IS NOT NULL`,
621
+ ],
622
+ },
623
+ {
624
+ name: "Add lightning address to brz_lnurl_receive_metadata and force its re-sync",
625
+ sql: [
626
+ `ALTER TABLE brz_lnurl_receive_metadata ADD COLUMN lightning_address TEXT`,
627
+ `DELETE FROM brz_settings WHERE key = 'lnurl_metadata_updated_after'`,
628
+ ],
629
+ },
615
630
  ];
616
631
  }
617
632
  }
@@ -383,7 +383,7 @@ class PostgresTokenStore {
383
383
  const metadata = _metadataFor(tokenOutputs.metadata, tokenIdentifier);
384
384
  if (!metadata) {
385
385
  this._log(
386
- "warn",
386
+ "WARN",
387
387
  `Skipping outputs of token ${tokenIdentifier}: no metadata provided`
388
388
  );
389
389
  continue;
@@ -629,31 +629,26 @@ class PostgresTokenStore {
629
629
  }
630
630
 
631
631
  // 2. Insert new outputs, grouped by the token each one names.
632
- for (const [tokenIdentifier, outputs] of _groupOutputsByToken(
632
+ const spentOutpoints = await this._spentOutpointsAmong(
633
+ client,
633
634
  outputsToAdd?.outputs
635
+ );
636
+ const unspentOutputs = (outputsToAdd?.outputs ?? []).filter(
637
+ (o) => !spentOutpoints.has(`${o.prevTxHash}:${o.prevTxVout}`)
638
+ );
639
+ for (const [tokenIdentifier, outputs] of _groupOutputsByToken(
640
+ unspentOutputs
634
641
  )) {
635
642
  const metadata = _metadataFor(outputsToAdd.metadata, tokenIdentifier);
636
643
  if (!metadata) {
637
644
  this._log(
638
- "warn",
645
+ "WARN",
639
646
  `Skipping outputs of token ${tokenIdentifier}: no metadata provided`
640
647
  );
641
648
  continue;
642
649
  }
643
650
  await this._upsertMetadata(client, metadata);
644
651
 
645
- // Clear spent status for outputs being (re-)added.
646
- const txHashes = outputs.map((o) => o.prevTxHash);
647
- const vouts = outputs.map((o) => o.prevTxVout);
648
- await client.query(
649
- `DELETE FROM brz_token_spent_outputs
650
- WHERE user_id = $1
651
- AND (prev_tx_hash, prev_tx_vout) IN (
652
- SELECT * FROM UNNEST($2::text[], $3::int[])
653
- )`,
654
- [this.identity, txHashes, vouts]
655
- );
656
-
657
652
  for (const output of outputs) {
658
653
  await this._insertSingleOutput(client, tokenIdentifier, output);
659
654
  }
@@ -1010,9 +1005,7 @@ class PostgresTokenStore {
1010
1005
  // ===== Private Helpers =====
1011
1006
 
1012
1007
  _log(level, message) {
1013
- if (this.logger && typeof this.logger.log === "function") {
1014
- this.logger.log({ line: message, level });
1015
- }
1008
+ this.logger?.log({ line: message, level });
1016
1009
  }
1017
1010
 
1018
1011
  /**
@@ -1205,6 +1198,27 @@ class PostgresTokenStore {
1205
1198
  );
1206
1199
  }
1207
1200
 
1201
+ async _spentOutpointsAmong(client, outputs) {
1202
+ if (!outputs || outputs.length === 0) {
1203
+ return new Set();
1204
+ }
1205
+ const result = await client.query(
1206
+ `SELECT prev_tx_hash, prev_tx_vout FROM brz_token_spent_outputs
1207
+ WHERE user_id = $1
1208
+ AND (prev_tx_hash, prev_tx_vout) IN (
1209
+ SELECT * FROM UNNEST($2::text[], $3::int[])
1210
+ )`,
1211
+ [
1212
+ this.identity,
1213
+ outputs.map((o) => o.prevTxHash),
1214
+ outputs.map((o) => o.prevTxVout),
1215
+ ]
1216
+ );
1217
+ return new Set(
1218
+ result.rows.map((r) => `${r.prev_tx_hash}:${r.prev_tx_vout}`)
1219
+ );
1220
+ }
1221
+
1208
1222
  /**
1209
1223
  * Insert a single output.
1210
1224
  */
@@ -58,20 +58,20 @@ class TokenStoreMigrationManager {
58
58
  const migrations = this._getMigrations(identity);
59
59
 
60
60
  if (currentVersion >= migrations.length) {
61
- this._log("info", `Token store database is up to date (version ${currentVersion})`);
61
+ this._log("INFO", `Token store database is up to date (version ${currentVersion})`);
62
62
  await client.query("COMMIT");
63
63
  return;
64
64
  }
65
65
 
66
66
  this._log(
67
- "info",
67
+ "INFO",
68
68
  `Migrating token store database from version ${currentVersion} to ${migrations.length}`
69
69
  );
70
70
 
71
71
  for (let i = currentVersion; i < migrations.length; i++) {
72
72
  const migration = migrations[i];
73
73
  const version = i + 1;
74
- this._log("debug", `Running token store migration ${version}: ${migration.name}`);
74
+ this._log("DEBUG", `Running token store migration ${version}: ${migration.name}`);
75
75
 
76
76
  for (const sql of migration.sql) {
77
77
  await client.query(sql);
@@ -84,7 +84,7 @@ class TokenStoreMigrationManager {
84
84
  }
85
85
 
86
86
  await client.query("COMMIT");
87
- this._log("info", "Token store database migration completed successfully");
87
+ this._log("INFO", "Token store database migration completed successfully");
88
88
  } catch (error) {
89
89
  await client.query("ROLLBACK").catch(() => {});
90
90
  throw new TokenStoreError(
@@ -187,11 +187,7 @@ class TokenStoreMigrationManager {
187
187
  }
188
188
 
189
189
  _log(level, message) {
190
- if (this.logger && typeof this.logger.log === "function") {
191
- this.logger.log({ line: message, level });
192
- } else if (level === "error") {
193
- console.error(`[TokenStoreMigrationManager] ${message}`);
194
- }
190
+ this.logger?.log({ line: message, level });
195
191
  }
196
192
 
197
193
  /**
@@ -58,20 +58,20 @@ class TreeStoreMigrationManager {
58
58
  const migrations = this._getMigrations(identity);
59
59
 
60
60
  if (currentVersion >= migrations.length) {
61
- this._log("info", `Tree store database is up to date (version ${currentVersion})`);
61
+ this._log("INFO", `Tree store database is up to date (version ${currentVersion})`);
62
62
  await client.query("COMMIT");
63
63
  return;
64
64
  }
65
65
 
66
66
  this._log(
67
- "info",
67
+ "INFO",
68
68
  `Migrating tree store database from version ${currentVersion} to ${migrations.length}`
69
69
  );
70
70
 
71
71
  for (let i = currentVersion; i < migrations.length; i++) {
72
72
  const migration = migrations[i];
73
73
  const version = i + 1;
74
- this._log("debug", `Running tree store migration ${version}: ${migration.name}`);
74
+ this._log("DEBUG", `Running tree store migration ${version}: ${migration.name}`);
75
75
 
76
76
  for (const sql of migration.sql) {
77
77
  await client.query(sql);
@@ -84,7 +84,7 @@ class TreeStoreMigrationManager {
84
84
  }
85
85
 
86
86
  await client.query("COMMIT");
87
- this._log("info", "Tree store database migration completed successfully");
87
+ this._log("INFO", "Tree store database migration completed successfully");
88
88
  } catch (error) {
89
89
  await client.query("ROLLBACK").catch(() => {});
90
90
  throw new TreeStoreError(
@@ -179,11 +179,7 @@ class TreeStoreMigrationManager {
179
179
  }
180
180
 
181
181
  _log(level, message) {
182
- if (this.logger && typeof this.logger.log === "function") {
183
- this.logger.log({ line: message, level });
184
- } else if (level === "error") {
185
- console.error(`[TreeStoreMigrationManager] ${message}`);
186
- }
182
+ this.logger?.log({ line: message, level });
187
183
  }
188
184
 
189
185
  /**
@@ -18,7 +18,7 @@ try {
18
18
  Database = require("better-sqlite3");
19
19
  } catch (fallbackError) {
20
20
  throw new Error(
21
- `better-sqlite3 not found. Please install it in your project: npm install better-sqlite3@^9.2.2\n` +
21
+ `better-sqlite3 not found. Please install it in your project: npm install better-sqlite3@^12.2.0\n` +
22
22
  `Original error: ${error.message}\nFallback error: ${fallbackError.message}`
23
23
  );
24
24
  }
@@ -49,6 +49,8 @@ const SELECT_PAYMENT_SQL = `
49
49
  p.timestamp,
50
50
  p.method,
51
51
  p.withdraw_tx_id,
52
+ p.withdraw_vout,
53
+ p.withdraw_destination_address,
52
54
  pd.tx_id AS deposit_tx_id,
53
55
  pd.vout AS deposit_vout,
54
56
  p.spark,
@@ -72,6 +74,7 @@ const SELECT_PAYMENT_SQL = `
72
74
  lrm.nostr_zap_request AS lnurl_nostr_zap_request,
73
75
  lrm.nostr_zap_receipt AS lnurl_nostr_zap_receipt,
74
76
  lrm.sender_comment AS lnurl_sender_comment,
77
+ lrm.lightning_address AS lnurl_lightning_address,
75
78
  lrm.payment_hash AS lnurl_payment_hash,
76
79
  pm.parent_payment_id
77
80
  FROM payments p
@@ -367,13 +370,15 @@ class SqliteStorage {
367
370
  this._runPaymentUpsert(payment);
368
371
  shouldEmit = true;
369
372
  } else if (stored === next) {
370
- console.debug(
373
+ this._log(
374
+ "DEBUG",
371
375
  `Skipping redundant payment event: id=${payment.id} status=${next}`
372
376
  );
373
377
  this._runPaymentUpsert(payment);
374
378
  shouldEmit = false;
375
379
  } else if (this._isFinalPaymentStatus(stored)) {
376
- console.warn(
380
+ this._log(
381
+ "WARN",
377
382
  `Skipping payment update (would replace terminal status): id=${payment.id} stored=${stored} new=${next}`
378
383
  );
379
384
  shouldEmit = false;
@@ -395,8 +400,8 @@ class SqliteStorage {
395
400
 
396
401
  _runPaymentUpsert(payment) {
397
402
  const paymentInsert = this.db.prepare(
398
- `INSERT INTO payments (id, payment_type, status, amount, fees, timestamp, method, withdraw_tx_id, spark)
399
- VALUES (@id, @paymentType, @status, @amount, @fees, @timestamp, @method, @withdrawTxId, @spark)
403
+ `INSERT INTO payments (id, payment_type, status, amount, fees, timestamp, method, withdraw_tx_id, withdraw_vout, withdraw_destination_address, spark)
404
+ VALUES (@id, @paymentType, @status, @amount, @fees, @timestamp, @method, @withdrawTxId, @withdrawVout, @withdrawDestinationAddress, @spark)
400
405
  ON CONFLICT(id) DO UPDATE SET
401
406
  payment_type=excluded.payment_type,
402
407
  status=excluded.status,
@@ -405,6 +410,8 @@ class SqliteStorage {
405
410
  timestamp=excluded.timestamp,
406
411
  method=excluded.method,
407
412
  withdraw_tx_id=excluded.withdraw_tx_id,
413
+ withdraw_vout=excluded.withdraw_vout,
414
+ withdraw_destination_address=excluded.withdraw_destination_address,
408
415
  spark=excluded.spark`
409
416
  );
410
417
  const depositInsert = this.db.prepare(
@@ -447,6 +454,7 @@ class SqliteStorage {
447
454
  htlc_details=COALESCE(excluded.htlc_details, payment_details_spark.htlc_details)`
448
455
  );
449
456
 
457
+ const withdraw = payment.details?.type === "withdraw" ? payment.details : null;
450
458
  paymentInsert.run({
451
459
  id: payment.id,
452
460
  paymentType: payment.paymentType,
@@ -455,8 +463,9 @@ class SqliteStorage {
455
463
  fees: payment.fees.toString(),
456
464
  timestamp: payment.timestamp,
457
465
  method: payment.method ? toJson(payment.method) : null,
458
- withdrawTxId:
459
- payment.details?.type === "withdraw" ? payment.details.txId : null,
466
+ withdrawTxId: withdraw?.txId ?? null,
467
+ withdrawVout: withdraw?.vout ?? null,
468
+ withdrawDestinationAddress: withdraw?.destinationAddress ?? null,
460
469
  spark: payment.details?.type === "spark" ? 1 : null,
461
470
  });
462
471
 
@@ -510,6 +519,10 @@ class SqliteStorage {
510
519
  }
511
520
  }
512
521
 
522
+ _log(level, line) {
523
+ this.logger?.log({ line, level });
524
+ }
525
+
513
526
  _normalizePaymentStatus(status) {
514
527
  return typeof status === "string" ? status.toLowerCase() : status;
515
528
  }
@@ -580,7 +593,7 @@ class SqliteStorage {
580
593
  /**
581
594
  * Gets payments that have any of the specified parent payment IDs.
582
595
  * @param {string[]} parentPaymentIds - Array of parent payment IDs
583
- * @returns {Promise<Object>} Map of parentPaymentId -> array of RelatedPayment objects
596
+ * @returns {Promise<Object>} Map of parentPaymentId -> array of Payment objects
584
597
  */
585
598
  getPaymentsByParentIds(parentPaymentIds) {
586
599
  try {
@@ -1015,7 +1028,7 @@ class SqliteStorage {
1015
1028
  setLnurlMetadata(metadata) {
1016
1029
  try {
1017
1030
  const stmt = this.db.prepare(
1018
- "INSERT OR REPLACE INTO lnurl_receive_metadata (payment_hash, nostr_zap_request, nostr_zap_receipt, sender_comment) VALUES (?, ?, ?, ?)"
1031
+ "INSERT OR REPLACE INTO lnurl_receive_metadata (payment_hash, nostr_zap_request, nostr_zap_receipt, sender_comment, lightning_address) VALUES (?, ?, ?, ?, ?)"
1019
1032
  );
1020
1033
 
1021
1034
  const transaction = this.db.transaction(() => {
@@ -1024,7 +1037,8 @@ class SqliteStorage {
1024
1037
  item.paymentHash,
1025
1038
  item.nostrZapRequest || null,
1026
1039
  item.nostrZapReceipt || null,
1027
- item.senderComment || null
1040
+ item.senderComment || null,
1041
+ item.lightningAddress || null
1028
1042
  );
1029
1043
  }
1030
1044
  });
@@ -1088,6 +1102,7 @@ class SqliteStorage {
1088
1102
  nostrZapRequest: row.lnurl_nostr_zap_request || null,
1089
1103
  nostrZapReceipt: row.lnurl_nostr_zap_receipt || null,
1090
1104
  senderComment: row.lnurl_sender_comment || null,
1105
+ lightningAddress: row.lnurl_lightning_address || null,
1091
1106
  };
1092
1107
  }
1093
1108
 
@@ -1102,10 +1117,16 @@ class SqliteStorage {
1102
1117
  }
1103
1118
  }
1104
1119
  } else if (row.withdraw_tx_id) {
1105
- details = {
1106
- type: "withdraw",
1107
- txId: row.withdraw_tx_id,
1108
- };
1120
+ // A withdrawal stored before the SDK kept these values has no details
1121
+ // until the next sync rewrites it.
1122
+ if (row.withdraw_vout != null && row.withdraw_destination_address != null) {
1123
+ details = {
1124
+ type: "withdraw",
1125
+ txId: row.withdraw_tx_id,
1126
+ vout: row.withdraw_vout,
1127
+ destinationAddress: row.withdraw_destination_address,
1128
+ };
1129
+ }
1109
1130
  } else if (row.deposit_tx_id) {
1110
1131
  details = {
1111
1132
  type: "deposit",
@@ -21,12 +21,12 @@ class MigrationManager {
21
21
  targetVersion = targetVersion ?? this.migrations.length;
22
22
 
23
23
  if (currentVersion >= targetVersion) {
24
- this._log("info", `Database is up to date (version ${currentVersion})`);
24
+ this._log("INFO", `Database is up to date (version ${currentVersion})`);
25
25
  return;
26
26
  }
27
27
 
28
28
  this._log(
29
- "info",
29
+ "INFO",
30
30
  `Migrating database from version ${currentVersion} to ${targetVersion}`
31
31
  );
32
32
 
@@ -34,7 +34,7 @@ class MigrationManager {
34
34
  const transaction = this.db.transaction(() => {
35
35
  for (let i = currentVersion; i < targetVersion; i++) {
36
36
  const migration = this.migrations[i];
37
- this._log("debug", `Running migration ${i + 1}: ${migration.name}`);
37
+ this._log("DEBUG", `Running migration ${i + 1}: ${migration.name}`);
38
38
 
39
39
  if (Array.isArray(migration.sql)) {
40
40
  migration.sql.forEach((sql) => this.db.exec(sql));
@@ -46,7 +46,7 @@ class MigrationManager {
46
46
  });
47
47
 
48
48
  transaction();
49
- this._log("info", `Database migration completed successfully`);
49
+ this._log("INFO", `Database migration completed successfully`);
50
50
  } catch (error) {
51
51
  throw new this.StorageError(
52
52
  `Migration failed at version ${currentVersion}: ${error.message}`,
@@ -64,7 +64,7 @@ class MigrationManager {
64
64
  return row.user_version || 0;
65
65
  } catch (error) {
66
66
  this._log(
67
- "warn",
67
+ "WARN",
68
68
  `Failed to get database version, assuming 0: ${error.message}`
69
69
  );
70
70
  return 0;
@@ -79,16 +79,7 @@ class MigrationManager {
79
79
  }
80
80
 
81
81
  _log(level, message) {
82
- if (this.logger && typeof this.logger.log === "function") {
83
- this.logger.log({
84
- line: message,
85
- level: level,
86
- });
87
- } else if (level === "error") {
88
- // Fallback to console.error for errors only
89
- console.error(`[MigrationManager] ${message}`);
90
- }
91
- // For info/debug/warn levels, only log if logger is provided
82
+ this.logger?.log({ line: message, level });
92
83
  }
93
84
 
94
85
  /**
@@ -559,6 +550,25 @@ class MigrationManager {
559
550
  )`,
560
551
  ],
561
552
  },
553
+ {
554
+ // With the sync offset at 0, the SDK re-fetches every transfer on its
555
+ // next sync and fills in both columns for past withdrawals.
556
+ name: "Add withdrawal destination address and output index",
557
+ sql: [
558
+ `ALTER TABLE payments ADD COLUMN withdraw_vout INTEGER`,
559
+ `ALTER TABLE payments ADD COLUMN withdraw_destination_address TEXT`,
560
+ `UPDATE settings
561
+ SET value = json_set(value, '$.offset', 0)
562
+ WHERE key = 'sync_offset' AND json_valid(value)`,
563
+ ],
564
+ },
565
+ {
566
+ name: "Add lightning address to lnurl_receive_metadata and force its re-sync",
567
+ sql: [
568
+ `ALTER TABLE lnurl_receive_metadata ADD COLUMN lightning_address TEXT`,
569
+ `DELETE FROM settings WHERE key = 'lnurl_metadata_updated_after'`,
570
+ ],
571
+ },
562
572
  ];
563
573
  }
564
574
  }
@@ -49,7 +49,7 @@ try {
49
49
  Database = require("better-sqlite3");
50
50
  } catch (fallbackError) {
51
51
  throw new Error(
52
- `better-sqlite3 not found. Please install it in your project: npm install better-sqlite3@^9.2.2\n` +
52
+ `better-sqlite3 not found. Please install it in your project: npm install better-sqlite3@^12.2.0\n` +
53
53
  `Original error: ${error.message}\nFallback error: ${fallbackError.message}`
54
54
  );
55
55
  }
@@ -26,12 +26,12 @@ class TreeStoreMigrationManager {
26
26
  targetVersion = targetVersion ?? this.migrations.length;
27
27
 
28
28
  if (currentVersion >= targetVersion) {
29
- this._log("info", `Tree store is up to date (version ${currentVersion})`);
29
+ this._log("INFO", `Tree store is up to date (version ${currentVersion})`);
30
30
  return;
31
31
  }
32
32
 
33
33
  this._log(
34
- "info",
34
+ "INFO",
35
35
  `Migrating tree store from version ${currentVersion} to ${targetVersion}`
36
36
  );
37
37
 
@@ -39,7 +39,7 @@ class TreeStoreMigrationManager {
39
39
  const transaction = this.db.transaction(() => {
40
40
  for (let i = currentVersion; i < targetVersion; i++) {
41
41
  const migration = this.migrations[i];
42
- this._log("debug", `Running migration ${i + 1}: ${migration.name}`);
42
+ this._log("DEBUG", `Running migration ${i + 1}: ${migration.name}`);
43
43
 
44
44
  if (Array.isArray(migration.sql)) {
45
45
  migration.sql.forEach((sql) => this.db.exec(sql));
@@ -51,7 +51,7 @@ class TreeStoreMigrationManager {
51
51
  });
52
52
 
53
53
  transaction();
54
- this._log("info", `Tree store migration completed successfully`);
54
+ this._log("INFO", `Tree store migration completed successfully`);
55
55
  } catch (error) {
56
56
  throw new this.TreeStoreError(
57
57
  `Migration failed at version ${currentVersion}: ${error.message}`,
@@ -83,7 +83,7 @@ class TreeStoreMigrationManager {
83
83
  return row.version || 0;
84
84
  } catch (error) {
85
85
  this._log(
86
- "warn",
86
+ "WARN",
87
87
  `Failed to get tree store version, assuming 0: ${error.message}`
88
88
  );
89
89
  return 0;
@@ -100,14 +100,7 @@ class TreeStoreMigrationManager {
100
100
  }
101
101
 
102
102
  _log(level, message) {
103
- if (this.logger && typeof this.logger.log === "function") {
104
- this.logger.log({
105
- line: message,
106
- level: level,
107
- });
108
- } else if (level === "error") {
109
- console.error(`[TreeStoreMigrationManager] ${message}`);
110
- }
103
+ this.logger?.log({ line: message, level });
111
104
  }
112
105
 
113
106
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@breeztech/breez-sdk-spark",
3
- "version": "0.27.1",
3
+ "version": "0.27.3-dev",
4
4
  "description": "Breez Spark SDK",
5
5
  "repository": "https://github.com/breez/spark-sdk",
6
6
  "author": "Breez <contact@breez.technology> (https://github.com/breez)",
@@ -14,13 +14,23 @@
14
14
  "deno",
15
15
  "nodejs",
16
16
  "web",
17
- "ssr",
18
- "!examples"
17
+ "ssr"
19
18
  ],
19
+ "types": "./nodejs/index.d.ts",
20
20
  "exports": {
21
21
  "./bundler": "./bundler/index.js",
22
22
  "./deno": "./deno/breez_sdk_spark_wasm.js",
23
- "./nodejs": "./nodejs/index.js",
23
+ "./nodejs": {
24
+ "import": {
25
+ "types": "./nodejs/index.d.mts",
26
+ "default": "./nodejs/index.mjs"
27
+ },
28
+ "require": {
29
+ "types": "./nodejs/index.d.ts",
30
+ "default": "./nodejs/index.js"
31
+ },
32
+ "default": "./nodejs/index.js"
33
+ },
24
34
  "./web": "./web/index.js",
25
35
  "./ssr": "./ssr/index.js",
26
36
  "./passkey-prf-provider": {
@@ -30,10 +40,21 @@
30
40
  },
31
41
  ".": {
32
42
  "node": {
33
- "import": "./nodejs/index.mjs",
34
- "require": "./nodejs/index.js"
43
+ "import": {
44
+ "types": "./nodejs/index.d.mts",
45
+ "default": "./nodejs/index.mjs"
46
+ },
47
+ "require": {
48
+ "types": "./nodejs/index.d.ts",
49
+ "default": "./nodejs/index.js"
50
+ },
51
+ "default": "./nodejs/index.js"
35
52
  },
36
53
  "deno": "./deno/breez_sdk_spark_wasm.js",
54
+ "require": {
55
+ "types": "./nodejs/index.d.ts",
56
+ "default": "./web/index.js"
57
+ },
37
58
  "default": "./web/index.js"
38
59
  }
39
60
  },
package/ssr/index.js CHANGED
@@ -48,6 +48,11 @@ export function createTurnkeySigningOnlySigner(...args) {
48
48
  return _module.createTurnkeySigningOnlySigner(...args);
49
49
  }
50
50
 
51
+ export function defaultBridgingConfig(...args) {
52
+ if (!_module) _notInitialized('defaultBridgingConfig');
53
+ return _module.defaultBridgingConfig(...args);
54
+ }
55
+
51
56
  export function defaultConfig(...args) {
52
57
  if (!_module) _notInitialized('defaultConfig');
53
58
  return _module.defaultConfig(...args);
@@ -98,6 +103,11 @@ export function mysqlStorage(...args) {
98
103
  return _module.mysqlStorage(...args);
99
104
  }
100
105
 
106
+ export function newBridgingClient(...args) {
107
+ if (!_module) _notInitialized('newBridgingClient');
108
+ return _module.newBridgingClient(...args);
109
+ }
110
+
101
111
  export function newRestChainService(...args) {
102
112
  if (!_module) _notInitialized('newRestChainService');
103
113
  return _module.newRestChainService(...args);
@@ -152,6 +162,20 @@ export class BreezSdk {
152
162
  }
153
163
  }
154
164
 
165
+ export class BridgingClient {
166
+ constructor(...args) {
167
+ if (!_module) _notInitialized('new BridgingClient');
168
+ return new _module.BridgingClient(...args);
169
+ }
170
+ }
171
+
172
+ export class ConsoleLogger {
173
+ constructor(...args) {
174
+ if (!_module) _notInitialized('new ConsoleLogger');
175
+ return new _module.ConsoleLogger(...args);
176
+ }
177
+ }
178
+
155
179
  export class DefaultCpfpSigner {
156
180
  constructor(...args) {
157
181
  if (!_module) _notInitialized('new DefaultCpfpSigner');