bsv-wallet-postgres 0.6.0 → 0.100.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c61ec2b4c48854fcba55eeb47bb1d7b3e87129fbf01769e07fc6c30661d1a26
4
- data.tar.gz: 58f953f0a5d5fb10fb20259d821dc604ba842f8210f53d6f55be12e760ed927c
3
+ metadata.gz: ed26a116389338d9853d1f130e859425153122ff9d9d25c0e95bbf87a617eab8
4
+ data.tar.gz: d6c635708ee65fe370e1ca2df47e54534ac5656f1390e2e872c1c647c2d6d62c
5
5
  SHA512:
6
- metadata.gz: 5b51ceb9562b914012b2a86ee1c236501f9f714583a55d46a977e6418f0cf490497d7a42349210a0e0ee1436179617d45ded1afca815f0770d563aad8bf4051a
7
- data.tar.gz: 6f219ead476cf621c654e9692f955962f96f55d02b900bb03f2adfe1549b331abd714036e4af7ef32f1c322e72c452a64ebebdcda46cedc9fc239e601cc0bf5f
6
+ metadata.gz: dac6faf022d61a20a3bad311d5635144fe32b57f43959197d6d185d723cac6bb67c551c1ba97951190af51a7afc42a51c79e5889a24aaea6a7fa574ad367059a
7
+ data.tar.gz: 4d879ddce5e38fde65fb60020602c8875909c73d95bb44784e200e802e052a553f73ba437b4a78becb136e6bda19a0bac4a5fa54620e3afc9cde9947d24c1041
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Postgres
6
+ VERSION = '0.100.1'
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sequel'
3
+ warn '[DEPRECATION] The bsv-wallet-postgres gem is discontinued. ' \
4
+ 'PostgreSQL support is now built into the bsv-wallet gem itself. ' \
5
+ 'Remove bsv-wallet-postgres from your Gemfile and use bsv-wallet directly.'
6
+
4
7
  require 'bsv-wallet'
5
- require_relative 'bsv/wallet_postgres'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bsv-wallet-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.100.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Bettison
@@ -15,75 +15,38 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 0.9.0
19
- - - "<"
20
- - !ruby/object:Gem::Version
21
- version: '1.0'
18
+ version: 0.100.0
22
19
  type: :runtime
23
20
  prerelease: false
24
21
  version_requirements: !ruby/object:Gem::Requirement
25
22
  requirements:
26
23
  - - ">="
27
24
  - !ruby/object:Gem::Version
28
- version: 0.9.0
29
- - - "<"
30
- - !ruby/object:Gem::Version
31
- version: '1.0'
32
- - !ruby/object:Gem::Dependency
33
- name: pg
34
- requirement: !ruby/object:Gem::Requirement
35
- requirements:
36
- - - "~>"
37
- - !ruby/object:Gem::Version
38
- version: '1'
39
- type: :runtime
40
- prerelease: false
41
- version_requirements: !ruby/object:Gem::Requirement
42
- requirements:
43
- - - "~>"
44
- - !ruby/object:Gem::Version
45
- version: '1'
46
- - !ruby/object:Gem::Dependency
47
- name: sequel
48
- requirement: !ruby/object:Gem::Requirement
49
- requirements:
50
- - - "~>"
51
- - !ruby/object:Gem::Version
52
- version: '5'
53
- type: :runtime
54
- prerelease: false
55
- version_requirements: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: '5'
60
- description: Persistent Sequel/Postgres-backed BSV::Wallet::StorageAdapter implementation
61
- for production BSV wallet deployments.
25
+ version: 0.100.0
26
+ description: This gem is deprecated. PostgreSQL support is now built into the bsv-wallet
27
+ gem itself. Install bsv-wallet and set DATABASE_URL to a postgres:// URL — no additional
28
+ gem needed.
62
29
  executables: []
63
30
  extensions: []
64
31
  extra_rdoc_files: []
65
32
  files:
66
- - CHANGELOG.md
67
- - LICENSE
68
33
  - lib/bsv-wallet-postgres.rb
69
- - lib/bsv/wallet_postgres.rb
70
- - lib/bsv/wallet_postgres/migrations/001_create_wallet_tables.rb
71
- - lib/bsv/wallet_postgres/migrations/002_add_output_state.rb
72
- - lib/bsv/wallet_postgres/migrations/003_add_wallet_settings.rb
73
- - lib/bsv/wallet_postgres/migrations/004_add_pending_metadata.rb
74
- - lib/bsv/wallet_postgres/migrations/005_add_txid_unique_index.rb
75
- - lib/bsv/wallet_postgres/migrations/006_create_broadcast_jobs.rb
76
- - lib/bsv/wallet_postgres/postgres_store.rb
77
- - lib/bsv/wallet_postgres/solid_queue_adapter.rb
78
- - lib/bsv/wallet_postgres/version.rb
79
- homepage: https://github.com/sgbett/bsv-ruby-sdk
34
+ - lib/bsv/wallet/postgres/version.rb
35
+ homepage: https://github.com/sgbett/bsv-wallet
80
36
  licenses:
81
37
  - LicenseRef-OpenBSV
82
38
  metadata:
83
- homepage_uri: https://github.com/sgbett/bsv-ruby-sdk
84
- source_code_uri: https://github.com/sgbett/bsv-ruby-sdk
85
- changelog_uri: https://github.com/sgbett/bsv-ruby-sdk/blob/master/gem/bsv-wallet-postgres/CHANGELOG.md
39
+ homepage_uri: https://github.com/sgbett/bsv-wallet
40
+ source_code_uri: https://github.com/sgbett/bsv-wallet
86
41
  rubygems_mfa_required: 'true'
42
+ post_install_message: |
43
+ ╔══════════════════════════════════════════════════════════════╗
44
+ ║ DEPRECATION NOTICE: bsv-wallet-postgres is discontinued. ║
45
+ ║ ║
46
+ ║ PostgreSQL support is now built into the bsv-wallet gem. ║
47
+ ║ Remove bsv-wallet-postgres from your Gemfile and use ║
48
+ ║ bsv-wallet directly with a postgres:// DATABASE_URL. ║
49
+ ╚══════════════════════════════════════════════════════════════╝
87
50
  rdoc_options: []
88
51
  require_paths:
89
52
  - lib
@@ -91,7 +54,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
54
  requirements:
92
55
  - - ">="
93
56
  - !ruby/object:Gem::Version
94
- version: '2.7'
57
+ version: '3.0'
95
58
  required_rubygems_version: !ruby/object:Gem::Requirement
96
59
  requirements:
97
60
  - - ">="
@@ -100,5 +63,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
63
  requirements: []
101
64
  rubygems_version: 4.0.10
102
65
  specification_version: 4
103
- summary: PostgreSQL storage adapter for bsv-wallet
66
+ summary: "[DEPRECATED] PostgreSQL adapter for bsv-wallet"
104
67
  test_files: []
data/CHANGELOG.md DELETED
@@ -1,133 +0,0 @@
1
- # Changelog — bsv-wallet-postgres
2
-
3
- All notable changes to the `bsv-wallet-postgres` gem are documented here.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
- and this gem adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## 0.6.0 — 2026-04-21
9
-
10
- ### Added
11
- - `update_output_basket` implementation on `PostgresStore`, matching the new Store interface method
12
-
13
- ### Changed
14
- - Updated for bsv-wallet 0.10.0 namespace changes (`Interface`, `Client`, `Store`)
15
-
16
- ## 0.5.0 — 2026-04-16
17
-
18
- ### Changed — **Breaking**
19
-
20
- - `SolidQueueAdapter` now sets the wallet action status to `'unproven'` instead of `'completed'` on successful broadcast. Aligns with the status taxonomy change in bsv-wallet 0.9.0 (HLR #455). The `wallet_broadcast_jobs` row status is unchanged (job queue lifecycle is a separate domain).
21
-
22
- ### Added
23
-
24
- - `BroadcastQueue#broadcast_enabled?` interface method; `SolidQueueAdapter` returns `true` (broadcaster required at construction time). Enables `WalletClient#broadcast_enabled?` to detect a queue-embedded broadcaster.
25
-
26
- ### Changed
27
-
28
- - Minimum `bsv-wallet` version raised from `>= 0.6.0` to `>= 0.9.0`. Required for the new status taxonomy and `broadcast_enabled?` interface.
29
-
30
- ## 0.4.0 — 2026-04-12
31
-
32
- ### Added
33
- - `BSV::Wallet::SolidQueueAdapter` — PostgreSQL-backed async broadcast queue implementing the `BroadcastQueue` interface
34
- - Migration 006: `wallet_broadcast_jobs` table with `FOR UPDATE SKIP LOCKED` polling support
35
- - Background worker thread broadcasts transactions and promotes/rolls back wallet state
36
- - Recovery on restart via stale `locked_at` detection
37
- - Idempotent enqueue on duplicate txid (crash recovery)
38
- - `MAX_ATTEMPTS` enforcement (5) prevents infinite retry loops
39
- - Guard refuses MemoryStore attachment
40
-
41
- ### Fixed
42
- - Migration timestamps use `timestamptz` (matching migration 004 pattern)
43
- - `start()` check-and-set is atomic under mutex (prevents TOCTOU double-spawn)
44
- - Deserialization failures mark job as failed immediately (no tight retry loop)
45
-
46
- ## 0.3.1 — 2026-04-12
47
-
48
- ### Fixed
49
- - `update_action_status` now scopes to a single row by primary key, preventing unintended multi-row updates when duplicate txids exist
50
- - Added migration 005: unique index on `wallet_actions.txid` enforcing one action per transaction
51
-
52
- ## 0.3.0 — 2026-04-12
53
-
54
- ### Added
55
- - `update_action_status` and `delete_action` implementations for PostgresStore,
56
- matching the new StorageAdapter contract introduced in bsv-wallet 0.6.0 (#370)
57
-
58
- ## 0.2.0 — 2026-04-12
59
-
60
- ### Added
61
-
62
- - **Migration 004** — adds `satoshis`, `pending_since`, `pending_reference`,
63
- `no_send` columns and a partial index on `(state, basket)` for spendable
64
- rows (#353)
65
- - **`find_spendable_outputs(basket:, min_satoshis:, sort_order:)`** — query
66
- spendable outputs with backward-compatible COALESCE for legacy rows (#354)
67
- - **`update_output_state(outpoint, new_state, ...)`** — transition output
68
- state with JSONB data synchronisation (#354)
69
- - **`lock_utxos(outpoints, reference:, no_send:)`** — atomic
70
- `UPDATE ... WHERE state = 'spendable' RETURNING` pattern for concurrent
71
- safety (#355)
72
- - **`release_stale_pending!(timeout:)`** — recover stuck pending outputs,
73
- exempting `no_send` locks (#355)
74
- - **PostgresStore settings methods** — `store_setting` / `find_setting`
75
-
76
- ### Fixed
77
-
78
- - **Spendable boolean sync** — `update_output_state`, `lock_utxos`, and
79
- `release_stale_pending!` now keep the legacy `spendable` column in sync
80
- with the `state` column; `filter_outputs` uses dual-column WHERE clause
81
-
82
- ### Changed
83
-
84
- - Directory restructure — source moved to `gem/bsv-wallet-postgres/`
85
-
86
- ## 0.1.0 — 2026-04-09
87
-
88
- Initial release of `bsv-wallet-postgres`, a PostgreSQL-backed
89
- `BSV::Wallet::StorageAdapter` implementation. Unblocks production
90
- deployments of `bsv-wallet` where state has to survive container
91
- restarts, and makes multi-instance wallet services possible for the
92
- first time.
93
-
94
- ### Added
95
-
96
- - **`BSV::Wallet::PostgresStore`** — full
97
- `StorageAdapter` implementation over Sequel + Postgres. Passes the
98
- same shared conformance suite that MemoryStore and FileStore pass
99
- (53 examples), plus 10 postgres-specific specs covering upsert
100
- semantics, GIN tag queries, JSONB attribute containment, concurrent
101
- inserts, and migration idempotency.
102
-
103
- - **Shipped Sequel migration** at
104
- `lib/bsv/wallet_postgres/migrations/001_create_wallet_tables.rb`.
105
- Five tables (wallet_outputs, wallet_actions, wallet_certificates,
106
- wallet_proofs, wallet_transactions) with JSONB data columns,
107
- dedicated indexed columns for filter paths, and GIN indexes on the
108
- `tags` / `labels` arrays.
109
-
110
- - **`PostgresStore.migrate!(db)`** convenience
111
- wrapper over `Sequel::Migrator.run` so consumers can apply the
112
- shipped schema with a single call. Operators who prefer their own
113
- migration framework can copy the migration file instead.
114
-
115
- - **Docs** at `docs/guides/wallet-postgres.md` with
116
- a 30-second quickstart, schema overview, and production
117
- considerations (pool sizing, multi-instance, backups,
118
- thread-safety).
119
-
120
- ### Infrastructure
121
-
122
- - **CI postgres service**. The GitHub Actions test job now runs a
123
- Postgres 16 container and exposes `DATABASE_URL` to rspec, so the
124
- `:postgres`-tagged specs run against a live database on every
125
- Ruby matrix row (2.7 → 3.4). Local developers without Postgres
126
- still get a green suite — those specs skip gracefully.
127
-
128
- ### Dependencies
129
-
130
- - `bsv-wallet-postgres` runtime: `bsv-wallet >= 0.3.4, < 1.0`,
131
- `sequel ~> 5`, `pg ~> 1`. The wallet floor matches the pinning style
132
- `bsv-wallet` uses for its `bsv-sdk` dependency so security releases
133
- propagate.
data/LICENSE DELETED
@@ -1,86 +0,0 @@
1
- Open BSV License Version 5 – granted by BSV Association, Grafenauweg 6, 6300
2
- Zug, Switzerland (CHE-427.008.338) ("Licensor"), to you as a user (henceforth
3
- "You", "User" or "Licensee").
4
-
5
- For the purposes of this license, the definitions below have the following
6
- meanings:
7
-
8
- "Bitcoin Protocol" means the protocol implementation, cryptographic rules,
9
- network protocols, and consensus mechanisms in the Bitcoin White Paper as
10
- described here https://protocol.bsvblockchain.org.
11
-
12
- "Bitcoin White Paper" means the paper entitled 'Bitcoin: A Peer-to-Peer
13
- Electronic Cash System' published by 'Satoshi Nakamoto' in October 2008.
14
-
15
- "BSV Blockchains" means:
16
- (a) the Bitcoin blockchain containing block height #556767 with the hash
17
- "000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b" and
18
- that contains the longest honest persistent chain of blocks which has been
19
- produced in a manner which is consistent with the rules set forth in the
20
- Network Access Rules; and
21
- (b) the test blockchains that contain the longest honest persistent chains of
22
- blocks which has been produced in a manner which is consistent with the
23
- rules set forth in the Network Access Rules.
24
-
25
- "Network Access Rules" or "Rules" means the set of rules regulating the
26
- relationship between BSV Association and the nodes on BSV based on the Bitcoin
27
- Protocol rules and those set out in the Bitcoin White Paper, and available here
28
- https://bsvblockchain.org/network-access-rules.
29
-
30
- "Software" means the software the subject of this licence, including any/all
31
- intellectual property rights therein and associated documentation files.
32
-
33
- BSV Association grants permission, free of charge and on a non-exclusive and
34
- revocable basis, to any person obtaining a copy of the Software to deal in the
35
- Software without restriction, including without limitation the rights to use,
36
- copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
37
- Software, and to permit persons to whom the Software is furnished to do so,
38
- subject to and conditioned upon the following conditions:
39
-
40
- 1 - The text "© BSV Association," and this license shall be included in all
41
- copies or substantial portions of the Software.
42
- 2 - The Software, and any software that is derived from the Software or parts
43
- thereof, must only be used on the BSV Blockchains.
44
-
45
- For the avoidance of doubt, this license is granted subject to and conditioned
46
- upon your compliance with these terms only. In the event of non-compliance, the
47
- license shall extinguish and you can be enjoined from violating BSV's
48
- intellectual property rights (incl. damages and similar related claims).
49
-
50
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES REGARDING ENTITLEMENT,
52
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
53
- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS THEREOF BE LIABLE FOR ANY CLAIM,
54
- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
55
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56
- DEALINGS IN THE SOFTWARE.
57
-
58
-
59
- Version 0.1.1 of the Bitcoin SV software, and prior versions of software upon
60
- which it was based, were licensed under the MIT License, which is included below.
61
-
62
- The MIT License (MIT)
63
-
64
- Copyright (c) 2009-2010 Satoshi Nakamoto
65
- Copyright (c) 2009-2015 Bitcoin Developers
66
- Copyright (c) 2009-2017 The Bitcoin Core developers
67
- Copyright (c) 2017 The Bitcoin ABC developers
68
- Copyright (c) 2018 Bitcoin Association for BSV
69
- Copyright (c) 2023 BSV Association
70
-
71
- Permission is hereby granted, free of charge, to any person obtaining a copy of
72
- this software and associated documentation files (the "Software"), to deal in
73
- the Software without restriction, including without limitation the rights to
74
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
75
- the Software, and to permit persons to whom the Software is furnished to do so,
76
- subject to the following conditions:
77
-
78
- The above copyright notice and this permission notice shall be included in all
79
- copies or substantial portions of the Software.
80
-
81
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
83
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
84
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
85
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
86
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Initial wallet schema for BSV::Wallet::PostgresStore.
4
- #
5
- # Five tables, all indexed for the query patterns the Store
6
- # interface exposes. JSONB blobs hold the full hash the SDK stored so
7
- # adding fields to bsv-wallet's output/action/certificate records does
8
- # not require a schema change — only the fields we actively filter on
9
- # get dedicated indexed columns.
10
- Sequel.migration do
11
- change do
12
- create_table(:wallet_outputs) do
13
- primary_key :id
14
- String :outpoint, null: false, unique: true
15
- String :basket
16
- column :tags, 'text[]'
17
- TrueClass :spendable, null: false, default: true
18
- jsonb :data, null: false
19
- DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
20
- index %i[basket spendable]
21
- index :tags, type: :gin
22
- end
23
-
24
- create_table(:wallet_actions) do
25
- primary_key :id
26
- String :txid, null: false
27
- column :labels, 'text[]'
28
- jsonb :data, null: false
29
- DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
30
- index :labels, type: :gin
31
- end
32
-
33
- create_table(:wallet_certificates) do
34
- primary_key :id
35
- String :type, null: false
36
- String :serial_number, null: false
37
- String :certifier, null: false
38
- String :subject
39
- jsonb :data, null: false
40
- DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
41
- unique %i[type serial_number certifier], name: :wallet_certificates_natural_key
42
- index :certifier
43
- index :subject
44
- end
45
-
46
- create_table(:wallet_proofs) do
47
- String :txid, primary_key: true
48
- String :bump_hex, text: true, null: false
49
- DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
50
- end
51
-
52
- create_table(:wallet_transactions) do
53
- String :txid, primary_key: true
54
- String :tx_hex, text: true, null: false
55
- DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
56
- end
57
- end
58
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Add output lifecycle state column to wallet_outputs.
4
- #
5
- # Introduces a nullable +state+ text column alongside the existing boolean
6
- # +spendable+ column. The two fields are kept in sync by the application
7
- # layer (+PostgresStore#update_output_state+).
8
- #
9
- # === State values
10
- #
11
- # * +spendable+ — the output is available for coin selection
12
- # * +pending+ — the output has been selected but the spending transaction
13
- # has not yet been broadcast or confirmed
14
- # * +spent+ — the output has been consumed by a confirmed transaction
15
- #
16
- # === Backward compatibility
17
- #
18
- # Rows written before this migration have +state = NULL+. The application
19
- # treats +state IS NULL AND spendable = TRUE+ as equivalent to
20
- # +state = 'spendable'+ so that existing data continues to behave
21
- # correctly without a backfill.
22
- #
23
- # The migration is intentionally non-destructive: +state+ is nullable
24
- # so the migration itself applies instantly on large tables (no rewrite,
25
- # no default scan). A backfill can be run offline if required.
26
- Sequel.migration do
27
- change do
28
- alter_table(:wallet_outputs) do
29
- add_column :state, String, null: true
30
- add_index :state
31
- end
32
- end
33
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Add wallet settings table to BSV::Wallet::PostgresStore.
4
- #
5
- # Provides key-value persistence for wallet configuration (e.g. change
6
- # output parameters). Keys are short strings (e.g. 'change_params');
7
- # values are JSON-serialised strings so the schema never needs to change
8
- # when setting shapes evolve.
9
- #
10
- # The table uses +key+ as its primary key so +store_setting+ is a simple
11
- # upsert (insert-or-replace on conflict).
12
- Sequel.migration do
13
- change do
14
- create_table(:wallet_settings) do
15
- String :key, primary_key: true
16
- String :value, text: true, null: false
17
- DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
18
- end
19
- end
20
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Add pending lock metadata columns and satoshis to wallet_outputs.
4
- #
5
- # Introduces dedicated columns to support the auto-fund UTXO management
6
- # methods (+find_spendable_outputs+, +lock_utxos+, +update_output_state+,
7
- # +release_stale_pending!+) without requiring expensive JSONB extraction
8
- # on every query.
9
- #
10
- # === Columns added
11
- #
12
- # * +satoshis+ — bigint, nullable. Mirrors the value stored inside
13
- # the JSONB +data+ blob so that +find_spendable_outputs+
14
- # can +ORDER BY satoshis+ without casting. New writes
15
- # populate this column; existing rows leave it NULL
16
- # and queries fall back to +COALESCE(satoshis, (data->>'satoshis')::bigint, 0)+.
17
- #
18
- # * +pending_since+ — timestamp (UTC), nullable. Set to +NOW()+ when a
19
- # UTXO is locked via +lock_utxos+. Used by
20
- # +release_stale_pending!+ to identify stale locks.
21
- #
22
- # * +pending_reference+ — text, nullable. Caller-supplied label passed to
23
- # +lock_utxos+. Carried through for observability.
24
- #
25
- # * +no_send+ — boolean, default +false+. When +true+ the lock is
26
- # exempt from automatic stale recovery by
27
- # +release_stale_pending!+.
28
- #
29
- # === Index added
30
- #
31
- # A partial index on +(state, basket)+ filtered to rows where
32
- # +state IS NULL OR state = 'spendable'+ accelerates the hot path of
33
- # +find_spendable_outputs+: the vast majority of rows in a live wallet
34
- # are spendable, not pending or spent.
35
- #
36
- # === Backward compatibility
37
- #
38
- # All new columns are nullable (or carry a safe default). No existing rows
39
- # are modified. The application layer handles NULL values via +COALESCE+ or
40
- # explicit IS NULL checks.
41
- Sequel.migration do
42
- up do
43
- alter_table(:wallet_outputs) do
44
- add_column :satoshis, :bigint, null: true
45
- add_column :pending_since, :timestamptz, null: true
46
- add_column :pending_reference, String, null: true
47
- add_column :no_send, :boolean, null: false, default: false
48
- end
49
-
50
- # Partial index on spendable rows only — keeps the index small and
51
- # fast for the typical coin-selection scan.
52
- run <<~SQL
53
- CREATE INDEX wallet_outputs_spendable_basket_idx
54
- ON wallet_outputs (state, basket)
55
- WHERE (state IS NULL OR state = 'spendable');
56
- SQL
57
- end
58
-
59
- down do
60
- run 'DROP INDEX IF EXISTS wallet_outputs_spendable_basket_idx;'
61
-
62
- alter_table(:wallet_outputs) do
63
- drop_column :no_send
64
- drop_column :pending_reference
65
- drop_column :pending_since
66
- drop_column :satoshis
67
- end
68
- end
69
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Add a unique index on wallet_actions.txid.
4
- #
5
- # Within a single wallet there should be at most one action per transaction.
6
- # Without this constraint, concurrent inserts or retries could create duplicate
7
- # rows sharing the same txid, causing +update_action_status+ to update multiple
8
- # rows unintentionally.
9
- #
10
- # The index also accelerates the +where(txid:)+ lookups performed by
11
- # +update_action_status+ and +delete_action+.
12
- #
13
- # === Backward compatibility
14
- #
15
- # The migration will fail if duplicate txids already exist in the table. Clean
16
- # up any duplicates before running this migration:
17
- #
18
- # DELETE FROM wallet_actions a
19
- # USING wallet_actions b
20
- # WHERE a.id > b.id AND a.txid = b.txid;
21
- Sequel.migration do
22
- change do
23
- alter_table(:wallet_actions) do
24
- add_index :txid, unique: true, name: :wallet_actions_txid_unique
25
- end
26
- end
27
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Broadcast job queue table for the SolidQueueAdapter.
4
- #
5
- # Tracks outbound transactions that need to be broadcast to the network,
6
- # with state machine, retry counters, and advisory locking support so that
7
- # multiple worker processes can poll the queue without double-processing.
8
- #
9
- # === Columns
10
- #
11
- # * +txid+ — TEXT NOT NULL UNIQUE. Prevents duplicate queue entries
12
- # for the same transaction.
13
- #
14
- # * +status+ — TEXT NOT NULL DEFAULT 'unsent'. State machine values:
15
- # 'unsent', 'sending', 'completed', 'failed'.
16
- #
17
- # * +beef_hex+ — TEXT NOT NULL. Serialised BEEF payload to broadcast.
18
- #
19
- # * +input_outpoints+ — text[], nullable. Outpoints consumed by the tx, used
20
- # to release UTXOs on success or rollback on failure.
21
- #
22
- # * +change_outpoints+ — text[], nullable. Change outpoints created by the tx,
23
- # used to mark outputs spendable after confirmation.
24
- #
25
- # * +fund_ref+ — TEXT, nullable. Caller-supplied funding reference for
26
- # observability and reconciliation.
27
- #
28
- # * +attempts+ — INTEGER NOT NULL DEFAULT 0. Incremented on each
29
- # broadcast attempt; gates retry logic.
30
- #
31
- # * +last_error+ — TEXT, nullable. Message from the last failed attempt.
32
- #
33
- # * +locked_at+ — TIMESTAMPTZ, nullable. Set when a worker claims the
34
- # job; cleared on completion or stale-lock recovery.
35
- #
36
- # * +created_at+ — TIMESTAMPTZ NOT NULL DEFAULT NOW().
37
- #
38
- # * +updated_at+ — TIMESTAMPTZ NOT NULL DEFAULT NOW().
39
- #
40
- # === Index
41
- #
42
- # A composite index on +(status, locked_at)+ (named +broadcast_jobs_poll_idx+)
43
- # supports the hot-path poll query:
44
- #
45
- # WHERE status = 'unsent'
46
- # OR (status = 'sending' AND locked_at < NOW() - interval '300 seconds'
47
- # AND attempts < 5)
48
- # ORDER BY created_at
49
- # FOR UPDATE SKIP LOCKED
50
- Sequel.migration do
51
- change do
52
- create_table(:wallet_broadcast_jobs) do
53
- primary_key :id, type: :Bignum
54
- String :txid, null: false, unique: true
55
- String :status, null: false, default: 'unsent'
56
- String :beef_hex, text: true, null: false
57
- column :input_outpoints, 'text[]'
58
- column :change_outpoints, 'text[]'
59
- String :fund_ref
60
- Integer :attempts, null: false, default: 0
61
- String :last_error, text: true
62
- column :locked_at, :timestamptz
63
- column :created_at, :timestamptz, null: false, default: Sequel::CURRENT_TIMESTAMP
64
- column :updated_at, :timestamptz, null: false, default: Sequel::CURRENT_TIMESTAMP
65
- index %i[status locked_at], name: :broadcast_jobs_poll_idx
66
- end
67
- end
68
- end