@breeztech/breez-sdk-spark 0.22.2 → 0.23.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.
- package/breez-sdk-spark.tgz +0 -0
- package/bundler/breez_sdk_spark_wasm.d.ts +65 -5
- package/bundler/breez_sdk_spark_wasm_bg.js +66 -27
- package/bundler/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/bundler/breez_sdk_spark_wasm_bg.wasm.d.ts +9 -6
- package/bundler/index.js +15 -2
- package/bundler/package.json +5 -0
- package/bundler/storage/index.js +6 -0
- package/bundler/tree-store/index.js +1518 -0
- package/bundler/tree-store/package.json +12 -0
- package/deno/breez_sdk_spark_wasm.d.ts +65 -5
- package/deno/breez_sdk_spark_wasm.js +66 -27
- package/deno/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/deno/breez_sdk_spark_wasm_bg.wasm.d.ts +9 -6
- package/nodejs/breez_sdk_spark_wasm.d.ts +65 -5
- package/nodejs/breez_sdk_spark_wasm.js +66 -27
- package/nodejs/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/nodejs/breez_sdk_spark_wasm_bg.wasm.d.ts +9 -6
- package/nodejs/index.js +11 -0
- package/nodejs/mysql-storage/index.cjs +9 -1
- package/nodejs/mysql-storage/migrations.cjs +6 -0
- package/nodejs/mysql-tree-store/index.cjs +296 -29
- package/nodejs/mysql-tree-store/migrations.cjs +198 -34
- package/nodejs/package.json +1 -0
- package/nodejs/postgres-storage/index.cjs +9 -1
- package/nodejs/postgres-storage/migrations.cjs +6 -0
- package/nodejs/postgres-tree-store/index.cjs +301 -40
- package/nodejs/postgres-tree-store/migrations.cjs +42 -0
- package/nodejs/storage/index.cjs +14 -3
- package/nodejs/storage/migrations.cjs +6 -0
- package/nodejs/tree-store/errors.cjs +13 -0
- package/nodejs/tree-store/index.cjs +1185 -0
- package/nodejs/tree-store/migrations.cjs +185 -0
- package/nodejs/tree-store/package.json +9 -0
- package/package.json +1 -1
- package/web/breez_sdk_spark_wasm.d.ts +74 -11
- package/web/breez_sdk_spark_wasm.js +66 -27
- package/web/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/web/breez_sdk_spark_wasm_bg.wasm.d.ts +9 -6
- package/web/index.js +15 -2
- package/web/package.json +5 -0
- package/web/storage/index.js +6 -0
- package/web/tree-store/index.js +1518 -0
- package/web/tree-store/package.json +12 -0
|
@@ -9,20 +9,52 @@ const MIGRATION_LOCK_NAME = "breez_mysql_tree_store_migration_lock";
|
|
|
9
9
|
const MIGRATION_LOCK_TIMEOUT = 60;
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Runs a single migration step. Plain strings
|
|
13
|
-
* (`
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
12
|
+
* Runs a single migration step. Plain strings must be idempotent on their own
|
|
13
|
+
* (e.g. `CREATE TABLE IF NOT EXISTS`, or an `ALTER` that re-applies to the same
|
|
14
|
+
* end state); anything whose bare form fails on replay is a tagged object
|
|
15
|
+
* (`dropPrimaryKey`, `dropForeignKey`, `addForeignKey`, `createIndex`,
|
|
16
|
+
* `addColumn`, `dropColumn`, `dropIndex`) guarded by an `information_schema`
|
|
17
|
+
* check (which also covers the `Disabled` foreign-key mode where the FK was
|
|
18
|
+
* never created). MySQL DDL implicitly commits, so if a migration crashes
|
|
19
|
+
* between two DDL statements the version row never gets recorded, and on retry
|
|
20
|
+
* an unguarded DROP/CREATE would fail because the object already exists or is
|
|
21
|
+
* already gone.
|
|
20
22
|
*/
|
|
21
23
|
async function runMigrationStep(conn, step) {
|
|
22
24
|
if (typeof step === "string") {
|
|
23
25
|
await conn.query(step);
|
|
24
26
|
return;
|
|
25
27
|
}
|
|
28
|
+
if (step.op === "createIndex") {
|
|
29
|
+
if (!(await _mysqlIndexExists(conn, step.table, step.name))) {
|
|
30
|
+
await conn.query(
|
|
31
|
+
`CREATE INDEX \`${step.name}\` ON \`${step.table}\` ${step.definition}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (step.op === "addColumn") {
|
|
37
|
+
if (!(await _mysqlColumnExists(conn, step.table, step.name))) {
|
|
38
|
+
await conn.query(
|
|
39
|
+
`ALTER TABLE \`${step.table}\` ADD COLUMN \`${step.name}\` ${step.definition}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (step.op === "dropColumn") {
|
|
45
|
+
if (await _mysqlColumnExists(conn, step.table, step.name)) {
|
|
46
|
+
await conn.query(
|
|
47
|
+
`ALTER TABLE \`${step.table}\` DROP COLUMN \`${step.name}\``
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (step.op === "dropIndex") {
|
|
53
|
+
if (await _mysqlIndexExists(conn, step.table, step.name)) {
|
|
54
|
+
await conn.query(`DROP INDEX \`${step.name}\` ON \`${step.table}\``);
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
26
58
|
if (step.op === "dropPrimaryKey") {
|
|
27
59
|
const [rows] = await conn.query(
|
|
28
60
|
`SELECT COUNT(*) AS c FROM information_schema.table_constraints
|
|
@@ -263,10 +295,24 @@ class MysqlTreeStoreMigrationManager {
|
|
|
263
295
|
leaf_id VARCHAR(255) NOT NULL PRIMARY KEY,
|
|
264
296
|
spent_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
|
|
265
297
|
)`,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
298
|
+
{
|
|
299
|
+
op: "createIndex",
|
|
300
|
+
table: "brz_tree_leaves",
|
|
301
|
+
name: "brz_idx_tree_leaves_available",
|
|
302
|
+
definition: "(status, is_missing_from_operators)",
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
op: "createIndex",
|
|
306
|
+
table: "brz_tree_leaves",
|
|
307
|
+
name: "brz_idx_tree_leaves_reservation",
|
|
308
|
+
definition: "(reservation_id)",
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
op: "createIndex",
|
|
312
|
+
table: "brz_tree_leaves",
|
|
313
|
+
name: "brz_idx_tree_leaves_added_at",
|
|
314
|
+
definition: "(added_at)",
|
|
315
|
+
},
|
|
270
316
|
];
|
|
271
317
|
if (foreignKeyModeEnforced) {
|
|
272
318
|
initialSql.push({
|
|
@@ -297,13 +343,22 @@ class MysqlTreeStoreMigrationManager {
|
|
|
297
343
|
{
|
|
298
344
|
name: "Promote leaf value to BIGINT column with covering index",
|
|
299
345
|
sql: [
|
|
300
|
-
|
|
301
|
-
|
|
346
|
+
{
|
|
347
|
+
op: "addColumn",
|
|
348
|
+
table: "brz_tree_leaves",
|
|
349
|
+
name: "value",
|
|
350
|
+
definition: "BIGINT NOT NULL DEFAULT 0",
|
|
351
|
+
},
|
|
302
352
|
`UPDATE brz_tree_leaves
|
|
303
353
|
SET value = CAST(JSON_UNQUOTE(JSON_EXTRACT(data, '$.value')) AS UNSIGNED)
|
|
304
354
|
WHERE value = 0`,
|
|
305
|
-
|
|
306
|
-
|
|
355
|
+
{
|
|
356
|
+
op: "createIndex",
|
|
357
|
+
table: "brz_tree_leaves",
|
|
358
|
+
name: "brz_idx_tree_leaves_slim",
|
|
359
|
+
definition:
|
|
360
|
+
"(status, is_missing_from_operators, reservation_id, value)",
|
|
361
|
+
},
|
|
307
362
|
],
|
|
308
363
|
},
|
|
309
364
|
{
|
|
@@ -318,14 +373,26 @@ class MysqlTreeStoreMigrationManager {
|
|
|
318
373
|
name: "brz_fk_tree_leaves_reservation",
|
|
319
374
|
},
|
|
320
375
|
|
|
321
|
-
// brz_tree_reservations: scope by user_id.
|
|
322
|
-
|
|
376
|
+
// brz_tree_reservations: scope by user_id. The combined DROP/ADD
|
|
377
|
+
// PRIMARY KEY re-applies to the same composite key, so it is left raw;
|
|
378
|
+
// ADD COLUMN would fail on replay, so it is guarded.
|
|
379
|
+
{
|
|
380
|
+
op: "addColumn",
|
|
381
|
+
table: "brz_tree_reservations",
|
|
382
|
+
name: "user_id",
|
|
383
|
+
definition: "VARBINARY(33) NULL",
|
|
384
|
+
},
|
|
323
385
|
`UPDATE brz_tree_reservations SET user_id = ${idLit} WHERE user_id IS NULL`,
|
|
324
386
|
`ALTER TABLE brz_tree_reservations MODIFY COLUMN user_id VARBINARY(33) NOT NULL`,
|
|
325
387
|
`ALTER TABLE brz_tree_reservations DROP PRIMARY KEY, ADD PRIMARY KEY (user_id, id)`,
|
|
326
388
|
|
|
327
389
|
// brz_tree_leaves: scope by user_id, rekey, optionally re-add composite FK.
|
|
328
|
-
|
|
390
|
+
{
|
|
391
|
+
op: "addColumn",
|
|
392
|
+
table: "brz_tree_leaves",
|
|
393
|
+
name: "user_id",
|
|
394
|
+
definition: "VARBINARY(33) NULL",
|
|
395
|
+
},
|
|
329
396
|
`UPDATE brz_tree_leaves SET user_id = ${idLit} WHERE user_id IS NULL`,
|
|
330
397
|
`ALTER TABLE brz_tree_leaves MODIFY COLUMN user_id VARBINARY(33) NOT NULL`,
|
|
331
398
|
`ALTER TABLE brz_tree_leaves DROP PRIMARY KEY, ADD PRIMARY KEY (user_id, id)`,
|
|
@@ -339,29 +406,58 @@ class MysqlTreeStoreMigrationManager {
|
|
|
339
406
|
},
|
|
340
407
|
]
|
|
341
408
|
: []),
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
409
|
+
{ op: "dropIndex", table: "brz_tree_leaves", name: "brz_idx_tree_leaves_available" },
|
|
410
|
+
{ op: "dropIndex", table: "brz_tree_leaves", name: "brz_idx_tree_leaves_reservation" },
|
|
411
|
+
{ op: "dropIndex", table: "brz_tree_leaves", name: "brz_idx_tree_leaves_added_at" },
|
|
412
|
+
{ op: "dropIndex", table: "brz_tree_leaves", name: "brz_idx_tree_leaves_slim" },
|
|
413
|
+
{
|
|
414
|
+
op: "createIndex",
|
|
415
|
+
table: "brz_tree_leaves",
|
|
416
|
+
name: "brz_idx_tree_leaves_user_available",
|
|
417
|
+
definition: "(user_id, status, is_missing_from_operators)",
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
op: "createIndex",
|
|
421
|
+
table: "brz_tree_leaves",
|
|
422
|
+
name: "brz_idx_tree_leaves_user_reservation",
|
|
423
|
+
definition: "(user_id, reservation_id)",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
op: "createIndex",
|
|
427
|
+
table: "brz_tree_leaves",
|
|
428
|
+
name: "brz_idx_tree_leaves_user_added_at",
|
|
429
|
+
definition: "(user_id, added_at)",
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
op: "createIndex",
|
|
433
|
+
table: "brz_tree_leaves",
|
|
434
|
+
name: "brz_idx_tree_leaves_user_slim",
|
|
435
|
+
definition:
|
|
436
|
+
"(user_id, status, is_missing_from_operators, reservation_id, value)",
|
|
437
|
+
},
|
|
353
438
|
|
|
354
439
|
// brz_tree_spent_leaves: scope by user_id.
|
|
355
|
-
|
|
440
|
+
{
|
|
441
|
+
op: "addColumn",
|
|
442
|
+
table: "brz_tree_spent_leaves",
|
|
443
|
+
name: "user_id",
|
|
444
|
+
definition: "VARBINARY(33) NULL",
|
|
445
|
+
},
|
|
356
446
|
`UPDATE brz_tree_spent_leaves SET user_id = ${idLit} WHERE user_id IS NULL`,
|
|
357
447
|
`ALTER TABLE brz_tree_spent_leaves MODIFY COLUMN user_id VARBINARY(33) NOT NULL`,
|
|
358
448
|
`ALTER TABLE brz_tree_spent_leaves DROP PRIMARY KEY, ADD PRIMARY KEY (user_id, leaf_id)`,
|
|
359
449
|
|
|
360
450
|
// brz_tree_swap_status was a singleton (PK id=1, CHECK id=1). Drop the PK
|
|
361
|
-
// and the id column, then re-key by user_id.
|
|
451
|
+
// and the id column, then re-key by user_id. dropPrimaryKey runs first so
|
|
452
|
+
// the trailing ADD PRIMARY KEY re-applies cleanly on replay.
|
|
362
453
|
{ op: "dropPrimaryKey", table: "brz_tree_swap_status" },
|
|
363
|
-
|
|
364
|
-
|
|
454
|
+
{ op: "dropColumn", table: "brz_tree_swap_status", name: "id" },
|
|
455
|
+
{
|
|
456
|
+
op: "addColumn",
|
|
457
|
+
table: "brz_tree_swap_status",
|
|
458
|
+
name: "user_id",
|
|
459
|
+
definition: "VARBINARY(33) NULL",
|
|
460
|
+
},
|
|
365
461
|
`UPDATE brz_tree_swap_status SET user_id = ${idLit} WHERE user_id IS NULL`,
|
|
366
462
|
`ALTER TABLE brz_tree_swap_status MODIFY COLUMN user_id VARBINARY(33) NOT NULL`,
|
|
367
463
|
`ALTER TABLE brz_tree_swap_status ADD PRIMARY KEY (user_id)`,
|
|
@@ -381,6 +477,65 @@ class MysqlTreeStoreMigrationManager {
|
|
|
381
477
|
`ALTER TABLE brz_tree_schema_migrations MODIFY COLUMN applied_at DATETIME(6) NOT NULL DEFAULT (UTC_TIMESTAMP(6))`,
|
|
382
478
|
],
|
|
383
479
|
},
|
|
480
|
+
{
|
|
481
|
+
// Mirrors Rust migration 6 in spark-mysql/src/tree_store.rs. Ancestor
|
|
482
|
+
// chain: intermediate nodes a leaf's exit chain walks through, kept
|
|
483
|
+
// separate from the spendable leaf pool and carrying no pool metadata.
|
|
484
|
+
// Each row is owned by the leaf it belongs to (`leaf_id` is part of the
|
|
485
|
+
// primary key), so a node shared by several leaves' chains stores one
|
|
486
|
+
// row per leaf rather than one deduplicated row. Multi-tenant from
|
|
487
|
+
// creation.
|
|
488
|
+
name: "Add ancestor chain table",
|
|
489
|
+
sql: [
|
|
490
|
+
`CREATE TABLE IF NOT EXISTS brz_tree_ancestors (
|
|
491
|
+
user_id VARBINARY(33) NOT NULL,
|
|
492
|
+
leaf_id VARCHAR(255) NOT NULL,
|
|
493
|
+
id VARCHAR(255) NOT NULL,
|
|
494
|
+
parent_node_id VARCHAR(255) NULL,
|
|
495
|
+
status VARCHAR(64) NOT NULL,
|
|
496
|
+
value BIGINT NOT NULL DEFAULT 0,
|
|
497
|
+
verifying_public_key VARCHAR(255) NOT NULL DEFAULT '',
|
|
498
|
+
data JSON NOT NULL,
|
|
499
|
+
PRIMARY KEY (user_id, leaf_id, id)
|
|
500
|
+
)`,
|
|
501
|
+
],
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
// Promote the remaining JSON fields that queries pull out of `data`
|
|
505
|
+
// into dedicated columns. `value` already got its own column in the
|
|
506
|
+
// "Promote leaf value" migration; this adds parent_node_id,
|
|
507
|
+
// verifying_public_key, and signing_public_key and backfills them.
|
|
508
|
+
// MySQL DDL auto-commits and has no ADD COLUMN IF NOT EXISTS, so the
|
|
509
|
+
// ADD COLUMNs are guarded ops (information_schema-checked) and the
|
|
510
|
+
// backfill is guarded by `WHERE verifying_public_key = ''`, so a replay
|
|
511
|
+
// after a mid-migration crash is a no-op.
|
|
512
|
+
name: "Promote leaf JSON fields to columns",
|
|
513
|
+
sql: [
|
|
514
|
+
{
|
|
515
|
+
op: "addColumn",
|
|
516
|
+
table: "brz_tree_leaves",
|
|
517
|
+
name: "parent_node_id",
|
|
518
|
+
definition: "VARCHAR(255) NULL",
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
op: "addColumn",
|
|
522
|
+
table: "brz_tree_leaves",
|
|
523
|
+
name: "verifying_public_key",
|
|
524
|
+
definition: "VARCHAR(255) NOT NULL DEFAULT ''",
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
op: "addColumn",
|
|
528
|
+
table: "brz_tree_leaves",
|
|
529
|
+
name: "signing_public_key",
|
|
530
|
+
definition: "VARCHAR(255) NOT NULL DEFAULT ''",
|
|
531
|
+
},
|
|
532
|
+
`UPDATE brz_tree_leaves SET
|
|
533
|
+
parent_node_id = NULLIF(data->>'$.parent_node_id', 'null'),
|
|
534
|
+
verifying_public_key = data->>'$.verifying_public_key',
|
|
535
|
+
signing_public_key = data->>'$.signing_keyshare.public_key'
|
|
536
|
+
WHERE verifying_public_key = ''`,
|
|
537
|
+
],
|
|
538
|
+
},
|
|
384
539
|
];
|
|
385
540
|
}
|
|
386
541
|
}
|
|
@@ -394,6 +549,15 @@ async function _mysqlTableExists(conn, tableName) {
|
|
|
394
549
|
return Number(rows[0].c) > 0;
|
|
395
550
|
}
|
|
396
551
|
|
|
552
|
+
async function _mysqlColumnExists(conn, tableName, columnName) {
|
|
553
|
+
const [rows] = await conn.query(
|
|
554
|
+
`SELECT COUNT(*) AS c FROM information_schema.columns
|
|
555
|
+
WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ?`,
|
|
556
|
+
[tableName, columnName]
|
|
557
|
+
);
|
|
558
|
+
return Number(rows[0].c) > 0;
|
|
559
|
+
}
|
|
560
|
+
|
|
397
561
|
async function _mysqlIndexExists(conn, tableName, indexName) {
|
|
398
562
|
const [rows] = await conn.query(
|
|
399
563
|
`SELECT COUNT(*) AS c FROM information_schema.statistics
|
package/nodejs/package.json
CHANGED
|
@@ -730,7 +730,7 @@ class PostgresStorage {
|
|
|
730
730
|
async listDeposits() {
|
|
731
731
|
try {
|
|
732
732
|
const result = await this.pool.query(
|
|
733
|
-
"SELECT txid, vout, amount_sats, is_mature, claim_error, refund_tx, refund_tx_id FROM brz_unclaimed_deposits WHERE user_id = $1",
|
|
733
|
+
"SELECT txid, vout, amount_sats, is_mature, claim_error, refund_tx, refund_tx_id, instant_claim_status FROM brz_unclaimed_deposits WHERE user_id = $1",
|
|
734
734
|
[this.identity]
|
|
735
735
|
);
|
|
736
736
|
|
|
@@ -742,6 +742,7 @@ class PostgresStorage {
|
|
|
742
742
|
claimError: row.claim_error || null,
|
|
743
743
|
refundTx: row.refund_tx,
|
|
744
744
|
refundTxId: row.refund_tx_id,
|
|
745
|
+
instantClaimStatus: row.instant_claim_status || null,
|
|
745
746
|
}));
|
|
746
747
|
} catch (error) {
|
|
747
748
|
throw new StorageError(
|
|
@@ -767,6 +768,13 @@ class PostgresStorage {
|
|
|
767
768
|
WHERE user_id = $3 AND txid = $4 AND vout = $5`,
|
|
768
769
|
[payload.refundTx, payload.refundTxid, this.identity, txid, vout]
|
|
769
770
|
);
|
|
771
|
+
} else if (payload.type === "instantClaim") {
|
|
772
|
+
await this.pool.query(
|
|
773
|
+
`UPDATE brz_unclaimed_deposits
|
|
774
|
+
SET instant_claim_status = $1
|
|
775
|
+
WHERE user_id = $2 AND txid = $3 AND vout = $4`,
|
|
776
|
+
[JSON.stringify(payload.status), this.identity, txid, vout]
|
|
777
|
+
);
|
|
770
778
|
} else {
|
|
771
779
|
throw new StorageError(`Unknown payload type: ${payload.type}`);
|
|
772
780
|
}
|
|
@@ -518,6 +518,12 @@ class PostgresMigrationManager {
|
|
|
518
518
|
ON brz_cross_chain_swaps(user_id, provider, is_terminal)`,
|
|
519
519
|
],
|
|
520
520
|
},
|
|
521
|
+
{
|
|
522
|
+
name: "Add instant claim status to brz_unclaimed_deposits",
|
|
523
|
+
sql: [
|
|
524
|
+
`ALTER TABLE brz_unclaimed_deposits ADD COLUMN instant_claim_status JSONB`,
|
|
525
|
+
],
|
|
526
|
+
},
|
|
521
527
|
];
|
|
522
528
|
}
|
|
523
529
|
}
|