@secondlayer/shared 6.37.1 → 6.38.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.
@@ -0,0 +1,57 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+ import { onChainPlane } from "../src/db/migration-role.ts";
4
+
5
+ /**
6
+ * BTC L1 settlement status for sBTC withdrawal sweeps (chain plane / SOURCE).
7
+ *
8
+ * sBTC `withdrawal-accept` events carry a `sweep_txid` — the Bitcoin tx the
9
+ * signers committed to broadcast — but the Stacks side never proves the sweep
10
+ * CONFIRMED on Bitcoin. The indexer's settlement-confirmer worker polls our own
11
+ * bitcoind for each sweep's confirmation count and records it here, so the API's
12
+ * withdrawal lifecycle can report real `btc_confirmations` / `settlement_confirmed`
13
+ * instead of a null placeholder.
14
+ *
15
+ * Keyed on `sweep_txid` (PK), not `request_id`: a request can produce more than
16
+ * one sweep over its life (RBF / signer rebroadcast under a new btc txid), and
17
+ * keying on the sweep preserves each broadcast's confirmation history rather than
18
+ * destructively overwriting on replacement. The S3 API LEFT JOIN selects by the
19
+ * indexed `request_id`.
20
+ *
21
+ * Two indexes: `request_id` for that join; a partial index on `last_checked_at`
22
+ * scoped to unconfirmed rows for the worker's "least-recently-checked first" drain.
23
+ */
24
+ export async function up(db: Kysely<unknown>): Promise<void> {
25
+ await onChainPlane(async () => {
26
+ await sql`SET lock_timeout = '30s'`.execute(db);
27
+ await sql`
28
+ CREATE TABLE IF NOT EXISTS sbtc_settlements (
29
+ sweep_txid TEXT PRIMARY KEY,
30
+ request_id BIGINT NOT NULL,
31
+ btc_confirmations INTEGER NOT NULL DEFAULT 0,
32
+ settlement_confirmed BOOLEAN NOT NULL DEFAULT false,
33
+ block_hash TEXT,
34
+ block_height INTEGER,
35
+ first_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
36
+ last_checked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
37
+ confirmed_at TIMESTAMPTZ,
38
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
39
+ )
40
+ `.execute(db);
41
+ await sql`
42
+ CREATE INDEX IF NOT EXISTS sbtc_settlements_request_id_idx
43
+ ON sbtc_settlements (request_id)
44
+ `.execute(db);
45
+ await sql`
46
+ CREATE INDEX IF NOT EXISTS sbtc_settlements_pending_idx
47
+ ON sbtc_settlements (last_checked_at)
48
+ WHERE settlement_confirmed = false
49
+ `.execute(db);
50
+ });
51
+ }
52
+
53
+ export async function down(db: Kysely<unknown>): Promise<void> {
54
+ await onChainPlane(async () => {
55
+ await sql`DROP TABLE IF EXISTS sbtc_settlements`.execute(db);
56
+ });
57
+ }
@@ -0,0 +1,31 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+ import { onControlPlane } from "../src/db/migration-role.ts";
4
+
5
+ /**
6
+ * Scan cursor for the sBTC settlement-confirmed webhook (control plane / TARGET).
7
+ *
8
+ * The settlement confirmer flips `sbtc_settlements.settlement_confirmed` on a
9
+ * Bitcoin confirmation — asynchronous to Stacks blocks, so the per-block
10
+ * `last_processed_block` cursor can't drive its webhook. The evaluator scans for
11
+ * `confirmed_at > last_settlement_scan_at` each tick and advances this watermark.
12
+ * Null = uninitialized → the evaluator fast-forwards it to now() and emits
13
+ * nothing (forward-only, no historical backfill), mirroring the block cursor.
14
+ */
15
+ export async function up(db: Kysely<unknown>): Promise<void> {
16
+ await onControlPlane(async () => {
17
+ await sql`
18
+ ALTER TABLE trigger_evaluator_state
19
+ ADD COLUMN IF NOT EXISTS last_settlement_scan_at TIMESTAMPTZ
20
+ `.execute(db);
21
+ });
22
+ }
23
+
24
+ export async function down(db: Kysely<unknown>): Promise<void> {
25
+ await onControlPlane(async () => {
26
+ await sql`
27
+ ALTER TABLE trigger_evaluator_state
28
+ DROP COLUMN IF EXISTS last_settlement_scan_at
29
+ `.execute(db);
30
+ });
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/shared",
3
- "version": "6.37.1",
3
+ "version": "6.38.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -153,10 +153,7 @@
153
153
  "import": "./dist/src/node/archive-client.js"
154
154
  }
155
155
  },
156
- "files": [
157
- "dist",
158
- "migrations"
159
- ],
156
+ "files": ["dist", "migrations"],
160
157
  "scripts": {
161
158
  "build": "bunup",
162
159
  "dev": "bunup --watch",