bsv-wallet-postgres 0.5.0 → 0.100.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -115
- data/LICENSE +23 -80
- data/db/migrations/001_create_schema.rb +261 -0
- data/db/migrations/002_action_id_cascade.rb +66 -0
- data/db/migrations/003_schema_constraints.rb +297 -0
- data/db/migrations/004_drop_tx_reqs.rb +32 -0
- data/lib/bsv/wallet/postgres/action.rb +80 -0
- data/lib/bsv/wallet/postgres/action_label.rb +14 -0
- data/lib/bsv/wallet/postgres/arc_adapter.rb +32 -0
- data/lib/bsv/wallet/postgres/basket.rb +13 -0
- data/lib/bsv/wallet/postgres/block.rb +13 -0
- data/lib/bsv/wallet/postgres/broadcast.rb +87 -0
- data/lib/bsv/wallet/postgres/broadcast_callback.rb +54 -0
- data/lib/bsv/wallet/postgres/broadcast_queue.rb +98 -0
- data/lib/bsv/wallet/postgres/certificate.rb +13 -0
- data/lib/bsv/wallet/postgres/certificate_field.rb +13 -0
- data/lib/bsv/wallet/postgres/display_txid.rb +25 -0
- data/lib/bsv/wallet/postgres/input.rb +14 -0
- data/lib/bsv/wallet/postgres/label.rb +15 -0
- data/lib/bsv/wallet/postgres/output.rb +64 -0
- data/lib/bsv/wallet/postgres/output_basket.rb +15 -0
- data/lib/bsv/wallet/postgres/output_detail.rb +12 -0
- data/lib/bsv/wallet/postgres/output_tag.rb +14 -0
- data/lib/bsv/wallet/postgres/proof_store.rb +109 -0
- data/lib/bsv/wallet/postgres/setting.rb +32 -0
- data/lib/bsv/wallet/postgres/spendable.rb +12 -0
- data/lib/bsv/wallet/postgres/store.rb +580 -0
- data/lib/bsv/wallet/postgres/tag.rb +15 -0
- data/lib/bsv/wallet/postgres/tx_proof.rb +16 -0
- data/lib/bsv/wallet/postgres/utxo_pool.rb +58 -0
- data/lib/bsv/wallet/postgres/version.rb +9 -0
- data/lib/bsv/wallet/postgres.rb +77 -0
- data/lib/bsv-wallet-postgres.rb +1 -1
- metadata +49 -35
- data/lib/bsv/wallet_postgres/migrations/001_create_wallet_tables.rb +0 -58
- data/lib/bsv/wallet_postgres/migrations/002_add_output_state.rb +0 -33
- data/lib/bsv/wallet_postgres/migrations/003_add_wallet_settings.rb +0 -20
- data/lib/bsv/wallet_postgres/migrations/004_add_pending_metadata.rb +0 -69
- data/lib/bsv/wallet_postgres/migrations/005_add_txid_unique_index.rb +0 -27
- data/lib/bsv/wallet_postgres/migrations/006_create_broadcast_jobs.rb +0 -68
- data/lib/bsv/wallet_postgres/postgres_store.rb +0 -482
- data/lib/bsv/wallet_postgres/solid_queue_adapter.rb +0 -328
- data/lib/bsv/wallet_postgres/version.rb +0 -7
- data/lib/bsv/wallet_postgres.rb +0 -13
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
# PostgreSQL adapter for bsv-wallet.
|
|
6
|
+
#
|
|
7
|
+
# Call {.connect} before using any models. Loads the pg_enum and pg_array
|
|
8
|
+
# Sequel extensions and sets Sequel::Model.db for all models in this namespace.
|
|
9
|
+
module Postgres
|
|
10
|
+
autoload :VERSION, 'bsv/wallet/postgres/version'
|
|
11
|
+
|
|
12
|
+
# Component services (Layer 2a)
|
|
13
|
+
autoload :Store, 'bsv/wallet/postgres/store'
|
|
14
|
+
autoload :UTXOPool, 'bsv/wallet/postgres/utxo_pool'
|
|
15
|
+
autoload :BroadcastQueue, 'bsv/wallet/postgres/broadcast_queue'
|
|
16
|
+
autoload :BroadcastCallback, 'bsv/wallet/postgres/broadcast_callback'
|
|
17
|
+
autoload :ProofStore, 'bsv/wallet/postgres/proof_store'
|
|
18
|
+
autoload :ArcAdapter, 'bsv/wallet/postgres/arc_adapter'
|
|
19
|
+
|
|
20
|
+
# Shared concerns
|
|
21
|
+
require_relative 'postgres/display_txid'
|
|
22
|
+
|
|
23
|
+
# Models (Layer 2b — atomic services)
|
|
24
|
+
autoload :Block, 'bsv/wallet/postgres/block'
|
|
25
|
+
autoload :TxProof, 'bsv/wallet/postgres/tx_proof'
|
|
26
|
+
autoload :Action, 'bsv/wallet/postgres/action'
|
|
27
|
+
autoload :Broadcast, 'bsv/wallet/postgres/broadcast'
|
|
28
|
+
autoload :Basket, 'bsv/wallet/postgres/basket'
|
|
29
|
+
autoload :Output, 'bsv/wallet/postgres/output'
|
|
30
|
+
autoload :Spendable, 'bsv/wallet/postgres/spendable'
|
|
31
|
+
autoload :OutputDetail, 'bsv/wallet/postgres/output_detail'
|
|
32
|
+
autoload :OutputBasket, 'bsv/wallet/postgres/output_basket'
|
|
33
|
+
autoload :Input, 'bsv/wallet/postgres/input'
|
|
34
|
+
autoload :Label, 'bsv/wallet/postgres/label'
|
|
35
|
+
autoload :ActionLabel, 'bsv/wallet/postgres/action_label'
|
|
36
|
+
autoload :Tag, 'bsv/wallet/postgres/tag'
|
|
37
|
+
autoload :OutputTag, 'bsv/wallet/postgres/output_tag'
|
|
38
|
+
autoload :Certificate, 'bsv/wallet/postgres/certificate'
|
|
39
|
+
autoload :CertificateField, 'bsv/wallet/postgres/certificate_field'
|
|
40
|
+
|
|
41
|
+
autoload :Setting, 'bsv/wallet/postgres/setting'
|
|
42
|
+
|
|
43
|
+
class << self
|
|
44
|
+
# @return [Sequel::Database, nil] the connected database
|
|
45
|
+
attr_reader :db
|
|
46
|
+
|
|
47
|
+
# Establish a database connection for all models.
|
|
48
|
+
#
|
|
49
|
+
# @param url_or_db [String, Sequel::Database] connection URL or existing database
|
|
50
|
+
# @return [Sequel::Database]
|
|
51
|
+
def connect(url_or_db)
|
|
52
|
+
@db = url_or_db.is_a?(Sequel::Database) ? url_or_db : Sequel.connect(url_or_db)
|
|
53
|
+
@db.extension :pg_enum
|
|
54
|
+
@db.extension :pg_array
|
|
55
|
+
@db.extension :pg_json
|
|
56
|
+
Sequel::Model.db = @db
|
|
57
|
+
@db
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Disconnect and clear the database reference.
|
|
61
|
+
def disconnect
|
|
62
|
+
@db&.disconnect
|
|
63
|
+
@db = nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Run pending migrations against the connected database.
|
|
67
|
+
#
|
|
68
|
+
# @param target [Integer, nil] optional target migration version
|
|
69
|
+
def migrate!(target: nil)
|
|
70
|
+
Sequel.extension :migration
|
|
71
|
+
migrations_path = File.expand_path('../../db/migrations', __dir__)
|
|
72
|
+
Sequel::Migrator.run(@db, migrations_path, target: target)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
data/lib/bsv-wallet-postgres.rb
CHANGED
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.
|
|
4
|
+
version: 0.100.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Simon Bettison
|
|
@@ -15,74 +15,88 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0
|
|
19
|
-
- - "<"
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version: '1.0'
|
|
18
|
+
version: '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
|
|
29
|
-
- - "<"
|
|
30
|
-
- !ruby/object:Gem::Version
|
|
31
|
-
version: '1.0'
|
|
25
|
+
version: '0'
|
|
32
26
|
- !ruby/object:Gem::Dependency
|
|
33
|
-
name:
|
|
27
|
+
name: sequel
|
|
34
28
|
requirement: !ruby/object:Gem::Requirement
|
|
35
29
|
requirements:
|
|
36
30
|
- - "~>"
|
|
37
31
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: '
|
|
32
|
+
version: '5.0'
|
|
39
33
|
type: :runtime
|
|
40
34
|
prerelease: false
|
|
41
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
42
36
|
requirements:
|
|
43
37
|
- - "~>"
|
|
44
38
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: '
|
|
39
|
+
version: '5.0'
|
|
46
40
|
- !ruby/object:Gem::Dependency
|
|
47
|
-
name:
|
|
41
|
+
name: pg
|
|
48
42
|
requirement: !ruby/object:Gem::Requirement
|
|
49
43
|
requirements:
|
|
50
|
-
- - "
|
|
44
|
+
- - ">="
|
|
51
45
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: '
|
|
46
|
+
version: '0'
|
|
53
47
|
type: :runtime
|
|
54
48
|
prerelease: false
|
|
55
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
56
50
|
requirements:
|
|
57
|
-
- - "
|
|
51
|
+
- - ">="
|
|
58
52
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: '
|
|
60
|
-
description:
|
|
61
|
-
for
|
|
53
|
+
version: '0'
|
|
54
|
+
description: Sequel models, migrations, and concrete Store/BroadcastQueue/ProofStore
|
|
55
|
+
implementations for the bsv-wallet gem, backed by PostgreSQL.
|
|
62
56
|
executables: []
|
|
63
57
|
extensions: []
|
|
64
58
|
extra_rdoc_files: []
|
|
65
59
|
files:
|
|
66
60
|
- CHANGELOG.md
|
|
67
61
|
- LICENSE
|
|
62
|
+
- db/migrations/001_create_schema.rb
|
|
63
|
+
- db/migrations/002_action_id_cascade.rb
|
|
64
|
+
- db/migrations/003_schema_constraints.rb
|
|
65
|
+
- db/migrations/004_drop_tx_reqs.rb
|
|
68
66
|
- lib/bsv-wallet-postgres.rb
|
|
69
|
-
- lib/bsv/
|
|
70
|
-
- lib/bsv/
|
|
71
|
-
- lib/bsv/
|
|
72
|
-
- lib/bsv/
|
|
73
|
-
- lib/bsv/
|
|
74
|
-
- lib/bsv/
|
|
75
|
-
- lib/bsv/
|
|
76
|
-
- lib/bsv/
|
|
77
|
-
- lib/bsv/
|
|
78
|
-
- lib/bsv/
|
|
79
|
-
|
|
67
|
+
- lib/bsv/wallet/postgres.rb
|
|
68
|
+
- lib/bsv/wallet/postgres/action.rb
|
|
69
|
+
- lib/bsv/wallet/postgres/action_label.rb
|
|
70
|
+
- lib/bsv/wallet/postgres/arc_adapter.rb
|
|
71
|
+
- lib/bsv/wallet/postgres/basket.rb
|
|
72
|
+
- lib/bsv/wallet/postgres/block.rb
|
|
73
|
+
- lib/bsv/wallet/postgres/broadcast.rb
|
|
74
|
+
- lib/bsv/wallet/postgres/broadcast_callback.rb
|
|
75
|
+
- lib/bsv/wallet/postgres/broadcast_queue.rb
|
|
76
|
+
- lib/bsv/wallet/postgres/certificate.rb
|
|
77
|
+
- lib/bsv/wallet/postgres/certificate_field.rb
|
|
78
|
+
- lib/bsv/wallet/postgres/display_txid.rb
|
|
79
|
+
- lib/bsv/wallet/postgres/input.rb
|
|
80
|
+
- lib/bsv/wallet/postgres/label.rb
|
|
81
|
+
- lib/bsv/wallet/postgres/output.rb
|
|
82
|
+
- lib/bsv/wallet/postgres/output_basket.rb
|
|
83
|
+
- lib/bsv/wallet/postgres/output_detail.rb
|
|
84
|
+
- lib/bsv/wallet/postgres/output_tag.rb
|
|
85
|
+
- lib/bsv/wallet/postgres/proof_store.rb
|
|
86
|
+
- lib/bsv/wallet/postgres/setting.rb
|
|
87
|
+
- lib/bsv/wallet/postgres/spendable.rb
|
|
88
|
+
- lib/bsv/wallet/postgres/store.rb
|
|
89
|
+
- lib/bsv/wallet/postgres/tag.rb
|
|
90
|
+
- lib/bsv/wallet/postgres/tx_proof.rb
|
|
91
|
+
- lib/bsv/wallet/postgres/utxo_pool.rb
|
|
92
|
+
- lib/bsv/wallet/postgres/version.rb
|
|
93
|
+
homepage: https://github.com/sgbett/bsv-wallet
|
|
80
94
|
licenses:
|
|
81
95
|
- LicenseRef-OpenBSV
|
|
82
96
|
metadata:
|
|
83
|
-
homepage_uri: https://github.com/sgbett/bsv-
|
|
84
|
-
source_code_uri: https://github.com/sgbett/bsv-
|
|
85
|
-
changelog_uri: https://github.com/sgbett/bsv-
|
|
97
|
+
homepage_uri: https://github.com/sgbett/bsv-wallet
|
|
98
|
+
source_code_uri: https://github.com/sgbett/bsv-wallet
|
|
99
|
+
changelog_uri: https://github.com/sgbett/bsv-wallet/blob/master/gem/bsv-wallet-postgres/CHANGELOG.md
|
|
86
100
|
rubygems_mfa_required: 'true'
|
|
87
101
|
rdoc_options: []
|
|
88
102
|
require_paths:
|
|
@@ -91,7 +105,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
91
105
|
requirements:
|
|
92
106
|
- - ">="
|
|
93
107
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: '
|
|
108
|
+
version: '3.0'
|
|
95
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
110
|
requirements:
|
|
97
111
|
- - ">="
|
|
@@ -100,5 +114,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
100
114
|
requirements: []
|
|
101
115
|
rubygems_version: 4.0.10
|
|
102
116
|
specification_version: 4
|
|
103
|
-
summary: PostgreSQL
|
|
117
|
+
summary: PostgreSQL adapter for bsv-wallet
|
|
104
118
|
test_files: []
|
|
@@ -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 StorageAdapter
|
|
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
|