@breeztech/breez-sdk-spark 0.14.0 → 0.15.1

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 (37) hide show
  1. package/breez-sdk-spark.tgz +0 -0
  2. package/bundler/breez_sdk_spark_wasm.d.ts +114 -40
  3. package/bundler/breez_sdk_spark_wasm.js +1 -1
  4. package/bundler/breez_sdk_spark_wasm_bg.js +118 -104
  5. package/bundler/breez_sdk_spark_wasm_bg.wasm +0 -0
  6. package/bundler/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
  7. package/deno/breez_sdk_spark_wasm.d.ts +114 -40
  8. package/deno/breez_sdk_spark_wasm.js +118 -104
  9. package/deno/breez_sdk_spark_wasm_bg.wasm +0 -0
  10. package/deno/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
  11. package/nodejs/breez_sdk_spark_wasm.d.ts +114 -40
  12. package/nodejs/breez_sdk_spark_wasm.js +121 -106
  13. package/nodejs/breez_sdk_spark_wasm_bg.wasm +0 -0
  14. package/nodejs/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
  15. package/nodejs/index.mjs +3 -2
  16. package/nodejs/mysql-session-manager/index.cjs +26 -8
  17. package/nodejs/mysql-session-manager/migrations.cjs +40 -3
  18. package/nodejs/mysql-storage/index.cjs +67 -48
  19. package/nodejs/mysql-storage/migrations.cjs +220 -85
  20. package/nodejs/mysql-token-store/index.cjs +133 -68
  21. package/nodejs/mysql-token-store/migrations.cjs +309 -80
  22. package/nodejs/mysql-tree-store/index.cjs +76 -41
  23. package/nodejs/mysql-tree-store/migrations.cjs +254 -71
  24. package/nodejs/postgres-session-manager/index.cjs +27 -9
  25. package/nodejs/postgres-session-manager/migrations.cjs +45 -6
  26. package/nodejs/postgres-storage/index.cjs +81 -62
  27. package/nodejs/postgres-storage/migrations.cjs +207 -79
  28. package/nodejs/postgres-token-store/index.cjs +111 -67
  29. package/nodejs/postgres-token-store/migrations.cjs +153 -61
  30. package/nodejs/postgres-tree-store/index.cjs +60 -42
  31. package/nodejs/postgres-tree-store/migrations.cjs +130 -46
  32. package/package.json +1 -1
  33. package/ssr/index.js +14 -9
  34. package/web/breez_sdk_spark_wasm.d.ts +126 -51
  35. package/web/breez_sdk_spark_wasm.js +118 -104
  36. package/web/breez_sdk_spark_wasm_bg.wasm +0 -0
  37. package/web/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
@@ -71,9 +71,19 @@ class MysqlTokenStore {
71
71
  * @param {import('mysql2/promise').Pool} pool
72
72
  * @param {Buffer|Uint8Array} identity - 33-byte secp256k1 compressed pubkey
73
73
  * identifying the tenant. All reads and writes are scoped by this.
74
+ * @param {"Enforced"|"Disabled"} [foreignKeyMode="Enforced"] - whether
75
+ * migrations create database-enforced foreign keys.
74
76
  * @param {object} [logger]
77
+ * @param {boolean} [runMigration=true] - whether to run schema migrations
78
+ * on initialize.
75
79
  */
76
- constructor(pool, identity, logger = null) {
80
+ constructor(
81
+ pool,
82
+ identity,
83
+ foreignKeyMode = "Enforced",
84
+ logger = null,
85
+ runMigration = true
86
+ ) {
77
87
  if (!identity || identity.length !== 33) {
78
88
  throw new TokenStoreError(
79
89
  "tenant identity (33-byte secp256k1 pubkey) is required"
@@ -82,13 +92,20 @@ class MysqlTokenStore {
82
92
  this.pool = pool;
83
93
  this.identity = Buffer.from(identity);
84
94
  this.lockName = _identityLockName(TOKEN_STORE_LOCK_PREFIX, identity);
95
+ this.foreignKeyMode = foreignKeyMode;
85
96
  this.logger = logger;
97
+ this.runMigration = runMigration;
86
98
  }
87
99
 
88
100
  async initialize() {
89
101
  try {
90
- const migrationManager = new MysqlTokenStoreMigrationManager(this.logger);
91
- await migrationManager.migrate(this.pool, this.identity);
102
+ if (this.runMigration) {
103
+ const migrationManager = new MysqlTokenStoreMigrationManager(
104
+ this.logger,
105
+ this.foreignKeyMode
106
+ );
107
+ await migrationManager.migrate(this.pool, this.identity);
108
+ }
92
109
  return this;
93
110
  } catch (error) {
94
111
  throw new TokenStoreError(
@@ -187,9 +204,9 @@ class MysqlTokenStore {
187
204
 
188
205
  const [swapRows] = await conn.query(
189
206
  `SELECT
190
- (SELECT EXISTS(SELECT 1 FROM token_reservations WHERE user_id = ? AND purpose = 'Swap')) AS has_active_swap,
207
+ (SELECT EXISTS(SELECT 1 FROM brz_token_reservations WHERE user_id = ? AND purpose = 'Swap')) AS has_active_swap,
191
208
  COALESCE(
192
- (SELECT (last_completed_at >= ?) FROM token_swap_status WHERE user_id = ?),
209
+ (SELECT (last_completed_at >= ?) FROM brz_token_swap_status WHERE user_id = ?),
193
210
  0
194
211
  ) AS swap_completed`,
195
212
  [this.identity, refreshTimestamp, this.identity]
@@ -204,18 +221,18 @@ class MysqlTokenStore {
204
221
  refreshTimestamp.getTime() - SPENT_MARKER_CLEANUP_THRESHOLD_MS
205
222
  );
206
223
  await conn.query(
207
- "DELETE FROM token_spent_outputs WHERE user_id = ? AND spent_at < ?",
224
+ "DELETE FROM brz_token_spent_outputs WHERE user_id = ? AND spent_at < ?",
208
225
  [this.identity, cleanupCutoff]
209
226
  );
210
227
 
211
228
  const [spentRows] = await conn.query(
212
- "SELECT output_id FROM token_spent_outputs WHERE user_id = ? AND spent_at >= ?",
229
+ "SELECT output_id FROM brz_token_spent_outputs WHERE user_id = ? AND spent_at >= ?",
213
230
  [this.identity, refreshTimestamp]
214
231
  );
215
232
  const spentIds = new Set(spentRows.map((r) => r.output_id));
216
233
 
217
234
  await conn.query(
218
- "DELETE FROM token_outputs WHERE user_id = ? AND reservation_id IS NULL AND added_at < ?",
235
+ "DELETE FROM brz_token_outputs WHERE user_id = ? AND reservation_id IS NULL AND added_at < ?",
219
236
  [this.identity, refreshTimestamp]
220
237
  );
221
238
 
@@ -228,8 +245,8 @@ class MysqlTokenStore {
228
245
 
229
246
  const [reservedRows] = await conn.query(
230
247
  `SELECT r.id, o.id AS output_id
231
- FROM token_reservations r
232
- JOIN token_outputs o
248
+ FROM brz_token_reservations r
249
+ JOIN brz_token_outputs o
233
250
  ON o.reservation_id = r.id AND o.user_id = r.user_id
234
251
  WHERE r.user_id = ?`,
235
252
  [this.identity]
@@ -261,11 +278,11 @@ class MysqlTokenStore {
261
278
  if (reservationsToDelete.length > 0) {
262
279
  const placeholders = buildPlaceholders(reservationsToDelete.length);
263
280
  await conn.query(
264
- `DELETE FROM token_outputs WHERE user_id = ? AND reservation_id IN (${placeholders})`,
281
+ `DELETE FROM brz_token_outputs WHERE user_id = ? AND reservation_id IN (${placeholders})`,
265
282
  [this.identity, ...reservationsToDelete]
266
283
  );
267
284
  await conn.query(
268
- `DELETE FROM token_reservations WHERE user_id = ? AND id IN (${placeholders})`,
285
+ `DELETE FROM brz_token_reservations WHERE user_id = ? AND id IN (${placeholders})`,
269
286
  [this.identity, ...reservationsToDelete]
270
287
  );
271
288
  }
@@ -275,13 +292,13 @@ class MysqlTokenStore {
275
292
  outputsToRemoveFromReservation.length
276
293
  );
277
294
  await conn.query(
278
- `DELETE FROM token_outputs WHERE user_id = ? AND id IN (${placeholders})`,
295
+ `DELETE FROM brz_token_outputs WHERE user_id = ? AND id IN (${placeholders})`,
279
296
  [this.identity, ...outputsToRemoveFromReservation]
280
297
  );
281
298
 
282
299
  const [emptyRows] = await conn.query(
283
- `SELECT r.id FROM token_reservations r
284
- LEFT JOIN token_outputs o
300
+ `SELECT r.id FROM brz_token_reservations r
301
+ LEFT JOIN brz_token_outputs o
285
302
  ON o.reservation_id = r.id AND o.user_id = r.user_id
286
303
  WHERE r.user_id = ? AND o.id IS NULL`,
287
304
  [this.identity]
@@ -290,23 +307,23 @@ class MysqlTokenStore {
290
307
  if (emptyIds.length > 0) {
291
308
  const emptyPlaceholders = buildPlaceholders(emptyIds.length);
292
309
  await conn.query(
293
- `DELETE FROM token_reservations WHERE user_id = ? AND id IN (${emptyPlaceholders})`,
310
+ `DELETE FROM brz_token_reservations WHERE user_id = ? AND id IN (${emptyPlaceholders})`,
294
311
  [this.identity, ...emptyIds]
295
312
  );
296
313
  }
297
314
  }
298
315
 
299
316
  const [reservedOutputRows] = await conn.query(
300
- "SELECT id FROM token_outputs WHERE user_id = ? AND reservation_id IS NOT NULL",
317
+ "SELECT id FROM brz_token_outputs WHERE user_id = ? AND reservation_id IS NOT NULL",
301
318
  [this.identity]
302
319
  );
303
320
  const reservedOutputIds = new Set(reservedOutputRows.map((r) => r.id));
304
321
 
305
322
  await conn.query(
306
- `DELETE FROM token_metadata
323
+ `DELETE FROM brz_token_metadata
307
324
  WHERE user_id = ?
308
325
  AND identifier NOT IN (
309
- SELECT DISTINCT token_identifier FROM token_outputs WHERE user_id = ?
326
+ SELECT DISTINCT token_identifier FROM brz_token_outputs WHERE user_id = ?
310
327
  )`,
311
328
  [this.identity, this.identity]
312
329
  );
@@ -357,10 +374,10 @@ class MysqlTokenStore {
357
374
  ELSE 0
358
375
  END
359
376
  ), 0) AS CHAR) AS balance
360
- FROM token_metadata m
361
- JOIN token_outputs o
377
+ FROM brz_token_metadata m
378
+ JOIN brz_token_outputs o
362
379
  ON o.token_identifier = m.identifier AND o.user_id = m.user_id
363
- LEFT JOIN token_reservations r
380
+ LEFT JOIN brz_token_reservations r
364
381
  ON o.reservation_id = r.id AND o.user_id = r.user_id
365
382
  WHERE m.user_id = ?
366
383
  GROUP BY m.identifier, m.issuer_public_key, m.name, m.ticker,
@@ -398,10 +415,10 @@ class MysqlTokenStore {
398
415
  o.token_public_key, o.token_amount, o.token_identifier,
399
416
  o.prev_tx_hash, o.prev_tx_vout, o.reservation_id,
400
417
  r.purpose
401
- FROM token_metadata m
402
- LEFT JOIN token_outputs o
418
+ FROM brz_token_metadata m
419
+ LEFT JOIN brz_token_outputs o
403
420
  ON o.token_identifier = m.identifier AND o.user_id = m.user_id
404
- LEFT JOIN token_reservations r
421
+ LEFT JOIN brz_token_reservations r
405
422
  ON o.reservation_id = r.id AND o.user_id = r.user_id
406
423
  WHERE m.user_id = ?
407
424
  ORDER BY m.identifier, CAST(o.token_amount AS DECIMAL(65,0)) ASC`,
@@ -470,10 +487,10 @@ class MysqlTokenStore {
470
487
  o.token_public_key, o.token_amount, o.token_identifier,
471
488
  o.prev_tx_hash, o.prev_tx_vout, o.reservation_id,
472
489
  r.purpose
473
- FROM token_metadata m
474
- LEFT JOIN token_outputs o
490
+ FROM brz_token_metadata m
491
+ LEFT JOIN brz_token_outputs o
475
492
  ON o.token_identifier = m.identifier AND o.user_id = m.user_id
476
- LEFT JOIN token_reservations r
493
+ LEFT JOIN brz_token_reservations r
477
494
  ON o.reservation_id = r.id AND o.user_id = r.user_id
478
495
  WHERE m.user_id = ? AND ${whereClause}
479
496
  ORDER BY CAST(o.token_amount AS DECIMAL(65,0)) ASC`,
@@ -518,32 +535,62 @@ class MysqlTokenStore {
518
535
  }
519
536
  }
520
537
 
521
- async insertTokenOutputs(tokenOutputs) {
538
+ /**
539
+ * Atomically remove spent outputs and insert new outputs.
540
+ * @param {Array<[string, number]>} outputsToRemove - Array of [prevTxHash, prevTxVout] tuples
541
+ * @param {Object|null} outputsToAdd - Token outputs to insert (with metadata)
542
+ * @returns {Promise<void>}
543
+ */
544
+ async updateTokenOutputs(outputsToRemove, outputsToAdd) {
522
545
  try {
523
546
  await this._withTransaction(async (conn) => {
524
- await this._upsertMetadata(conn, tokenOutputs.metadata);
525
-
526
- const outputIds = tokenOutputs.outputs.map((o) => o.output.id);
527
- if (outputIds.length > 0) {
528
- const placeholders = buildPlaceholders(outputIds.length);
529
- await conn.query(
530
- `DELETE FROM token_spent_outputs WHERE user_id = ? AND output_id IN (${placeholders})`,
531
- [this.identity, ...outputIds]
532
- );
547
+ // 1. Remove spent outputs and mark as spent.
548
+ if (outputsToRemove && outputsToRemove.length > 0) {
549
+ for (const [txHash, vout] of outputsToRemove) {
550
+ const [rows] = await conn.query(
551
+ "SELECT id FROM brz_token_outputs WHERE user_id = ? AND prev_tx_hash = ? AND prev_tx_vout = ?",
552
+ [this.identity, txHash, vout]
553
+ );
554
+ if (rows.length > 0) {
555
+ const outputId = rows[0].id;
556
+ await conn.query(
557
+ "DELETE FROM brz_token_outputs WHERE user_id = ? AND id = ?",
558
+ [this.identity, outputId]
559
+ );
560
+ await conn.query(
561
+ "INSERT IGNORE INTO brz_token_spent_outputs (user_id, output_id, spent_at) VALUES (?, ?, NOW())",
562
+ [this.identity, outputId]
563
+ );
564
+ }
565
+ }
533
566
  }
534
567
 
535
- for (const output of tokenOutputs.outputs) {
536
- await this._insertSingleOutput(
537
- conn,
538
- tokenOutputs.metadata.identifier,
539
- output
540
- );
568
+ // 2. Insert new outputs.
569
+ if (outputsToAdd) {
570
+ await this._upsertMetadata(conn, outputsToAdd.metadata);
571
+
572
+ const outputIds = outputsToAdd.outputs.map((o) => o.output.id);
573
+ if (outputIds.length > 0) {
574
+ const placeholders = buildPlaceholders(outputIds.length);
575
+ await conn.query(
576
+ `DELETE FROM brz_token_spent_outputs WHERE user_id = ? AND output_id IN (${placeholders})`,
577
+ [this.identity, ...outputIds]
578
+ );
579
+ }
580
+
581
+ for (const output of outputsToAdd.outputs) {
582
+ await this._insertSingleOutput(
583
+ conn,
584
+ outputsToAdd.metadata.identifier,
585
+ output
586
+ );
587
+ }
541
588
  }
542
589
  });
543
590
  } catch (error) {
544
591
  if (error instanceof TokenStoreError) throw error;
545
592
  throw new TokenStoreError(
546
- `Failed to insert token outputs: ${error.message}`,
593
+ `Failed to update token outputs: ${error.message}`,
547
594
  error
548
595
  );
549
596
  }
@@ -576,7 +623,7 @@ class MysqlTokenStore {
576
623
  }
577
624
 
578
625
  const [metadataRows] = await conn.query(
579
- "SELECT * FROM token_metadata WHERE user_id = ? AND identifier = ?",
626
+ "SELECT * FROM brz_token_metadata WHERE user_id = ? AND identifier = ?",
580
627
  [this.identity, tokenIdentifier]
581
628
  );
582
629
 
@@ -593,7 +640,7 @@ class MysqlTokenStore {
593
640
  o.withdraw_bond_sats, o.withdraw_relative_block_locktime,
594
641
  o.token_public_key, o.token_amount, o.token_identifier,
595
642
  o.prev_tx_hash, o.prev_tx_vout
596
- FROM token_outputs o
643
+ FROM brz_token_outputs o
597
644
  WHERE o.user_id = ? AND o.token_identifier = ? AND o.reservation_id IS NULL`,
598
645
  [this.identity, tokenIdentifier]
599
646
  );
@@ -680,7 +727,7 @@ class MysqlTokenStore {
680
727
  const reservationId = this._generateId();
681
728
 
682
729
  await conn.query(
683
- "INSERT INTO token_reservations (user_id, id, purpose) VALUES (?, ?, ?)",
730
+ "INSERT INTO brz_token_reservations (user_id, id, purpose) VALUES (?, ?, ?)",
684
731
  [this.identity, reservationId, purpose]
685
732
  );
686
733
 
@@ -688,7 +735,7 @@ class MysqlTokenStore {
688
735
  if (selectedIds.length > 0) {
689
736
  const placeholders = buildPlaceholders(selectedIds.length);
690
737
  await conn.query(
691
- `UPDATE token_outputs SET reservation_id = ? WHERE user_id = ? AND id IN (${placeholders})`,
738
+ `UPDATE brz_token_outputs SET reservation_id = ? WHERE user_id = ? AND id IN (${placeholders})`,
692
739
  [reservationId, this.identity, ...selectedIds]
693
740
  );
694
741
  }
@@ -713,11 +760,11 @@ class MysqlTokenStore {
713
760
  // Clear reservation_id from outputs first — the composite FK uses NO
714
761
  // ACTION (a whole-row SET NULL would null user_id, which is NOT NULL).
715
762
  await conn.query(
716
- "UPDATE token_outputs SET reservation_id = NULL WHERE user_id = ? AND reservation_id = ?",
763
+ "UPDATE brz_token_outputs SET reservation_id = NULL WHERE user_id = ? AND reservation_id = ?",
717
764
  [this.identity, id]
718
765
  );
719
766
  await conn.query(
720
- "DELETE FROM token_reservations WHERE user_id = ? AND id = ?",
767
+ "DELETE FROM brz_token_reservations WHERE user_id = ? AND id = ?",
721
768
  [this.identity, id]
722
769
  );
723
770
  });
@@ -734,11 +781,11 @@ class MysqlTokenStore {
734
781
  try {
735
782
  // _withWriteTransaction acquires the GET_LOCK so this serializes
736
783
  // against `setTokensOutputs`. Without it, a concurrent setTokensOutputs
737
- // could read token_spent_outputs before our marker commits and re-insert
784
+ // could read brz_token_spent_outputs before our marker commits and re-insert
738
785
  // the just-spent output as Available.
739
786
  await this._withWriteTransaction(async (conn) => {
740
787
  const [reservationRows] = await conn.query(
741
- "SELECT purpose FROM token_reservations WHERE user_id = ? AND id = ?",
788
+ "SELECT purpose FROM brz_token_reservations WHERE user_id = ? AND id = ?",
742
789
  [this.identity, id]
743
790
  );
744
791
  if (reservationRows.length === 0) {
@@ -747,7 +794,7 @@ class MysqlTokenStore {
747
794
  const isSwap = reservationRows[0].purpose === "Swap";
748
795
 
749
796
  const [reservedRows] = await conn.query(
750
- "SELECT id FROM token_outputs WHERE user_id = ? AND reservation_id = ?",
797
+ "SELECT id FROM brz_token_outputs WHERE user_id = ? AND reservation_id = ?",
751
798
  [this.identity, id]
752
799
  );
753
800
  const reservedOutputIds = reservedRows.map((r) => r.id);
@@ -762,18 +809,18 @@ class MysqlTokenStore {
762
809
  }
763
810
  // Suppress duplicate-PK errors only.
764
811
  await conn.query(
765
- `INSERT INTO token_spent_outputs (user_id, output_id) VALUES ${valueClauses}
812
+ `INSERT INTO brz_token_spent_outputs (user_id, output_id) VALUES ${valueClauses}
766
813
  ON DUPLICATE KEY UPDATE output_id = output_id`,
767
814
  params
768
815
  );
769
816
  }
770
817
 
771
818
  await conn.query(
772
- "DELETE FROM token_outputs WHERE user_id = ? AND reservation_id = ?",
819
+ "DELETE FROM brz_token_outputs WHERE user_id = ? AND reservation_id = ?",
773
820
  [this.identity, id]
774
821
  );
775
822
  await conn.query(
776
- "DELETE FROM token_reservations WHERE user_id = ? AND id = ?",
823
+ "DELETE FROM brz_token_reservations WHERE user_id = ? AND id = ?",
777
824
  [this.identity, id]
778
825
  );
779
826
 
@@ -781,17 +828,17 @@ class MysqlTokenStore {
781
828
  // (and thus has no row) gets one created lazily.
782
829
  if (isSwap) {
783
830
  await conn.query(
784
- `INSERT INTO token_swap_status (user_id, last_completed_at) VALUES (?, NOW(6))
831
+ `INSERT INTO brz_token_swap_status (user_id, last_completed_at) VALUES (?, NOW(6))
785
832
  ON DUPLICATE KEY UPDATE last_completed_at = VALUES(last_completed_at)`,
786
833
  [this.identity]
787
834
  );
788
835
  }
789
836
 
790
837
  await conn.query(
791
- `DELETE FROM token_metadata
838
+ `DELETE FROM brz_token_metadata
792
839
  WHERE user_id = ?
793
840
  AND identifier NOT IN (
794
- SELECT DISTINCT token_identifier FROM token_outputs WHERE user_id = ?
841
+ SELECT DISTINCT token_identifier FROM brz_token_outputs WHERE user_id = ?
795
842
  )`,
796
843
  [this.identity, this.identity]
797
844
  );
@@ -839,11 +886,11 @@ class MysqlTokenStore {
839
886
  /// user_id (NOT NULL).
840
887
  async _cleanupStaleReservations(conn) {
841
888
  await conn.query(
842
- `UPDATE token_outputs SET reservation_id = NULL
889
+ `UPDATE brz_token_outputs SET reservation_id = NULL
843
890
  WHERE user_id = ?
844
891
  AND reservation_id IN (
845
892
  SELECT id FROM (
846
- SELECT id FROM token_reservations
893
+ SELECT id FROM brz_token_reservations
847
894
  WHERE user_id = ?
848
895
  AND created_at < DATE_SUB(NOW(6), INTERVAL ? SECOND)
849
896
  ) AS stale
@@ -851,7 +898,7 @@ class MysqlTokenStore {
851
898
  [this.identity, this.identity, RESERVATION_TIMEOUT_SECS]
852
899
  );
853
900
  await conn.query(
854
- `DELETE FROM token_reservations
901
+ `DELETE FROM brz_token_reservations
855
902
  WHERE user_id = ? AND created_at < DATE_SUB(NOW(6), INTERVAL ? SECOND)`,
856
903
  [this.identity, RESERVATION_TIMEOUT_SECS]
857
904
  );
@@ -859,7 +906,7 @@ class MysqlTokenStore {
859
906
 
860
907
  async _upsertMetadata(conn, metadata) {
861
908
  await conn.query(
862
- `INSERT INTO token_metadata
909
+ `INSERT INTO brz_token_metadata
863
910
  (user_id, identifier, issuer_public_key, name, ticker, decimals, max_supply,
864
911
  is_freezable, creation_entity_public_key)
865
912
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -890,7 +937,7 @@ class MysqlTokenStore {
890
937
  // conflict only — unlike INSERT IGNORE, FK / NOT NULL / type errors
891
938
  // still propagate.
892
939
  await conn.query(
893
- `INSERT INTO token_outputs
940
+ `INSERT INTO brz_token_outputs
894
941
  (user_id, id, token_identifier, owner_public_key, revocation_commitment,
895
942
  withdraw_bond_sats, withdraw_relative_block_locktime,
896
943
  token_public_key, token_amount, prev_tx_hash, prev_tx_vout, added_at)
@@ -963,11 +1010,29 @@ function createMysqlPool(config) {
963
1010
  */
964
1011
  async function createMysqlTokenStore(config, identity, logger = null) {
965
1012
  const pool = createMysqlPool(config);
966
- return createMysqlTokenStoreWithPool(pool, identity, logger);
1013
+ return createMysqlTokenStoreWithPool(
1014
+ pool,
1015
+ identity,
1016
+ config.foreignKeyMode || "Enforced",
1017
+ logger,
1018
+ config.runMigration !== false
1019
+ );
967
1020
  }
968
1021
 
969
- async function createMysqlTokenStoreWithPool(pool, identity, logger = null) {
970
- const store = new MysqlTokenStore(pool, identity, logger);
1022
+ async function createMysqlTokenStoreWithPool(
1023
+ pool,
1024
+ identity,
1025
+ foreignKeyMode = "Enforced",
1026
+ logger = null,
1027
+ runMigration = true
1028
+ ) {
1029
+ const store = new MysqlTokenStore(
1030
+ pool,
1031
+ identity,
1032
+ foreignKeyMode,
1033
+ logger,
1034
+ runMigration
1035
+ );
971
1036
  await store.initialize();
972
1037
  return store;
973
1038
  }