bsv-wallet 0.3.4 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f3c7d9f919b64229f0c2c9c99a05fbd58850803af74861157f884ade90f7af6
4
- data.tar.gz: c655fbf296f6a4a3ed554681b8ab673c8dd3d108d37e6832cbf48814b3ed2169
3
+ metadata.gz: e7f0eba4cf58a9a63db79d2b731700f5d2d3ae04b82416ccc0288a1c5659a365
4
+ data.tar.gz: 2453264034fbbe664ced66bd853e8e5b4a52eb668e87a6eb01fd71e5b589d61b
5
5
  SHA512:
6
- metadata.gz: 87e2b8653d787445a281fb78393e380857799852908487cbef82af26a3e1e04f16df5f67ce295ed4162742527d7ebc5d1380b4670f8a949b78d4c44524e6ab66
7
- data.tar.gz: 9d288d1787f7448278eb95de1e96e41384e0c06141c755812549b9bc693c0269b8361cf31982f6b38472be3418ef575e7f373bde11d3ef0892743041c14dab10
6
+ metadata.gz: '092fa8e32a2ac7b7b4429c0fe715858ba16bba9869530cb97c4dfab0ff5730b2b2ff018da87a60cea5c5beaf7e527945c1158127e27806825db8ba29e895e2ed'
7
+ data.tar.gz: 68c27f04fa860ce116c7ddaa1a76a25b4ccfc56ab4b8b3af454dbbf5b2f452c719b884df92497b01ff6b74dbcb4eced994fbe519a51443bf7200a87cdaed65df
@@ -0,0 +1,267 @@
1
+ # Changelog — bsv-wallet
2
+
3
+ All notable changes to the `bsv-wallet` 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.4.0 — 2026-04-10
9
+
10
+ ### Added
11
+
12
+ - **Protocol-ID normalisation** (F8.7): `Validators.validate_protocol_id!` now
13
+ strips and downcases the name before applying rules, so `' MyProtocol '` and
14
+ `'myprotocol'` are treated identically and cannot silently fork to different
15
+ key-derivation paths.
16
+ - **Permission-rule constants** (F8.8): Reserved prefix/suffix strings are now
17
+ named constants on `BSV::Wallet::Validators` (`RESERVED_PROTOCOL_PREFIXES`,
18
+ `RESERVED_PROTOCOL_SUFFIX`, `RESERVED_BASKET_PREFIXES`, `RESERVED_BASKET_SUFFIX`,
19
+ `RESERVED_BASKET_NAME`), making them discoverable and documentable.
20
+ - **BEEF verification in `internalize_action`** (F8.14): The BEEF bundle is now
21
+ verified via `Beef#verify` before any outputs are stored. If the bundle is
22
+ structurally invalid, a `WalletError` is raised rather than storing unverified
23
+ data. When the chain provider supports `valid_root_for_height?`, full SPV
24
+ verification is performed.
25
+ - **Depth cap and cycle detection in `wire_source_tx_ancestors`** (F8.18):
26
+ Recursion is now bounded by `WalletClient::ANCESTOR_DEPTH_CAP` (64 levels)
27
+ and a visited-txid `Set`, preventing stack overflow on deep or cyclic
28
+ transaction ancestry chains.
29
+
30
+ ### Changed
31
+
32
+ - **`ProtoWallet#create_signature` default counterparty** (P305.1): The default
33
+ value for `counterparty` has changed from `'self'` to `'anyone'`, matching the
34
+ behaviour of `ts-sdk`'s `ProtoWallet.createSignature`. Callers that rely on
35
+ the `'self'` derivation path when omitting `counterparty:` must now pass
36
+ `counterparty: 'self'` explicitly.
37
+
38
+ ### Migration notes
39
+
40
+ **P305.1 — `create_signature` counterparty default change (breaking)**
41
+
42
+ Previously, calling `wallet.create_signature({ protocol_id: ..., key_id: ...,
43
+ data: ... })` without a `counterparty:` key would derive using `'self'`. It now
44
+ derives using `'anyone'`. This changes the resulting private key and therefore
45
+ the signature. If your application omits `counterparty:`, add
46
+ `counterparty: 'self'` to preserve the old behaviour.
47
+
48
+ **F8.14 — BEEF verification now mandatory in `internalize_action`**
49
+
50
+ Calls to `internalize_action` that previously succeeded with a malformed or
51
+ unverifiable BEEF will now raise `BSV::Wallet::WalletError`. In practice this
52
+ only affects callers passing synthetic or hand-crafted BEEF bytes; legitimate
53
+ BEEF produced by `create_action` or broadcast round-trips will continue to work.
54
+
55
+ ### Added
56
+
57
+ - **Shared conformance suite** for `StorageAdapter`
58
+ implementations at `spec/support/shared_examples_for_storage_adapter.rb`.
59
+ `MemoryStore` and `FileStore` now both drive their behavioural
60
+ tests through `it_behaves_like 'a storage adapter'`, and the
61
+ extraction backfilled previously-missing coverage (certificate
62
+ `:attributes` filter, `count_certificates`, proof and transaction
63
+ round-trip, pagination ordering).
64
+
65
+ ## 0.3.4 — 2026-04-08
66
+
67
+ Paired security patch release. Three P0 findings from the
68
+ [2026-04-08 cross-SDK compliance review](.architecture/reviews/20260408-cross-sdk-compliance-review.md)
69
+ plus follow-up hardening from the PR review pass. Must be installed
70
+ together — the `bsv-wallet` gemspec now pins its `bsv-sdk` dependency
71
+ to `>= 0.8.2, < 1.0` to enforce the paired upgrade and prevent a stale
72
+ pair where one gem has its fixes and the other doesn't.
73
+
74
+ Two GitHub Security Advisories accompany this release (draft until
75
+ CVE IDs return from MITRE):
76
+
77
+
78
+ ### Security
79
+
80
+ - **`acquire_certificate` now verifies certifier signatures** before
81
+ persisting (BRC-52). Both the `'direct'` and `'issuance'` acquisition
82
+ paths previously wrote user-supplied `signature:` values to storage
83
+ without any verification — a caller could forge a certificate that
84
+ `list_certificates` / `prove_certificate` would later treat as
85
+ authentic. This was a credential forgery primitive masquerading as
86
+ an API finding. The new `BSV::Wallet::CertificateSignature` module
87
+ builds the canonical BRC-52 preimage (matching the TS reference
88
+ `Certificate#toBinary(false)` byte-for-byte) and delegates to
89
+ `ProtoWallet#verify_signature`. Invalid certificates raise
90
+ `BSV::Wallet::CertificateSignature::InvalidError` and are not
91
+ persisted. Closes F8.15 (and the verification aspect of F8.16).
92
+
93
+
94
+
95
+ ### Changed
96
+
97
+ - **`bsv-wallet.gemspec` bsv-sdk dependency pinned** to
98
+ `>= 0.8.2, < 1.0`. The previous `~> 0.4` constraint was stale (wallet
99
+ hasn't been tested against bsv-sdk 0.4.x in months) and would have
100
+ let a user install `bsv-wallet 0.3.4` against an old `bsv-sdk` that
101
+ was missing F1.3 and F5.13. Technically breaking — any consumer
102
+ pinned to `bsv-sdk < 0.8.2` must upgrade — but un-breaking in
103
+ practice: it forces users to the known-good pair rather than a
104
+ silently-broken combination.
105
+
106
+ ### Internal
107
+
108
+ - `lib/bsv/wallet_interface/**/*` added to the
109
+ `Metrics/ModuleLength` exclusion list (was previously only excluded
110
+ from `Metrics/ClassLength`). The new `CertificateSignature` module
111
+ triggered the discrepancy.
112
+ - Review-feedback hardening bundled into the same PR to
113
+ keep the security-patch window small: case-insensitive ARC failure
114
+ matching, `Base64.strict_decode64` on BRC-52 preimage fields,
115
+ `EncodingError` rescue in `CertificateSignature.verify!`, rejection
116
+ of mixed string / symbol duplicate field names, malformed 2xx
117
+ rejection in ARC, and even-length guard on hex signatures.
118
+
119
+ ### Migration notes
120
+
121
+ - **Existing `bsv-wallet` users** pinned to `bsv-sdk ~> 0.4` will need
122
+ to relax their constraint or upgrade. Anything installed before
123
+ `bsv-wallet 0.3.4` is vulnerable to the F8.15 certificate forgery
124
+ primitive.
125
+ - **Callers passing negative integers to `VarInt.encode`** (unlikely —
126
+ the docstring already disallowed it) will now get an `ArgumentError`
127
+ instead of silent corruption. Fix: pass non-negative values.
128
+ - **Callers relying on ARC broadcaster silently succeeding for INVALID
129
+ / MALFORMED / MINED_IN_STALE_BLOCK / ORPHAN responses** will now see
130
+ `BroadcastError` raised. Fix: handle the error — the previous
131
+ behaviour was objectively wrong and any downstream logic that
132
+ tolerated it was silently corrupt.
133
+ - **Callers of `acquire_certificate` with a fake or untrusted
134
+ `signature:` field** will now see
135
+ `BSV::Wallet::CertificateSignature::InvalidError`. Fix: ensure the
136
+ certificate has been properly signed by the declared certifier.
137
+
138
+ ### Test suite
139
+
140
+ - 3112 examples, 0 failures (up from 3080 on 0.8.1)
141
+ - 16 new regression tests for F1.3, F5.13, and F8.15
142
+ - 16 further regression tests for the review-feedback hardening
143
+ - Ruby 2.7 — 3.4 matrix green
144
+ - CodeQL clean; RuboCop clean across 266 files
145
+
146
+ ## 0.3.3 — 2026-04-06
147
+
148
+ ### Fixed
149
+
150
+ - `finalize_action` now stores the spending transaction so subsequent
151
+ `internalize_action` / proof resolution flows can find it. Previously the
152
+ wallet remembered the inputs and outputs but not the finalised tx itself.
153
+
154
+ ## 0.3.2 — 2026-04-06
155
+
156
+ ### Fixed
157
+
158
+ - `internalize_action` now stores **all** transactions from the
159
+ incoming BEEF, not just the proven ones. Unproven ancestors are needed for
160
+ later BEEF reconstruction in `create_action` → `to_beef`.
161
+
162
+ ## 0.3.1 — 2026-04-06
163
+
164
+ ### Fixed
165
+
166
+ - `internalize_action` now stores the subject transaction hex (not
167
+ just its proof and outputs), so the wallet can rebuild BEEF for spends of
168
+ the inbound outputs without re-fetching the tx.
169
+
170
+ ## 0.3.0 — 2026-04-06
171
+
172
+ ### Added
173
+
174
+ - **Pluggable proof store** for merkle proof persistence. The wallet
175
+ is now a lightweight SPV node: `internalize_action` extracts and stores
176
+ merkle proofs from incoming BEEF; `create_action` reattaches them to
177
+ produce valid BEEF with BUMPs for ARC broadcast.
178
+ - `ProofStore` interface with `store_proof` / `resolve_proof`.
179
+ - `LocalProofStore` default implementation using `StorageAdapter`.
180
+ - `WalletClient` accepts injectable `proof_store:` parameter.
181
+ - Transaction caching (`store_transaction` / `find_transaction`) for
182
+ ancestry reconstruction.
183
+ - `StorageAdapter` gains `store_proof`, `find_proof`,
184
+ `store_transaction`, `find_transaction` methods, implemented in both
185
+ `MemoryStore` and `FileStore`.
186
+
187
+ ### Fixed
188
+
189
+ - `wire_source_from_storage` resolves merkle proofs via proof store
190
+ so `to_beef` produces valid BEEF that ARC accepts. Previously, BEEF
191
+ contained source transactions without proofs, causing ARC 463/468
192
+ rejections.
193
+
194
+ ## 0.2.2 — 2026-04-06
195
+
196
+ ### Fixed
197
+
198
+ - `to_beef` now includes source transactions in the BEEF output, not
199
+ just the subject transaction. Without ancestors, ARC could not validate the
200
+ spend graph.
201
+
202
+ ## 0.2.1 — 2026-04-06
203
+
204
+ ### Added
205
+
206
+ - `WalletClient#create_action` now accepts `UnlockingScriptTemplate`
207
+ objects (e.g. `P2PKH`) as input unlocking scripts, enabling template-based
208
+ signing without BEEF.
209
+ - `wire_source_from_storage` fallback populates `source_satoshis`
210
+ and `source_locking_script` from wallet storage when BEEF is absent or
211
+ incomplete, enabling BIP-143 sighash computation for wallet-tracked
212
+ outputs.
213
+ - `finalize_action` resolves template inputs via `sign_all` before
214
+ serialisation.
215
+ - `MemoryStore#filter_outputs` supports outpoint filtering for
216
+ efficient single-output lookups.
217
+
218
+ The sdk gem was re-released alongside this wallet change with no
219
+ behavioural changes of its own.
220
+
221
+ ## 0.2.0 — 2026-04-01
222
+
223
+ ### Added
224
+
225
+ #### Primitives
226
+
227
+
228
+ #### Transaction
229
+
230
+
231
+ #### Wallet
232
+
233
+ - **FileStore** — JSON file-backed persistent storage, now the
234
+ default for `WalletClient`. Data survives process restarts. `MemoryStore`
235
+ becomes explicit opt-in for tests.
236
+ - **File permissions** — directory created with 0700, files with
237
+ 0600. Warns via Logger on startup if permissions are too open.
238
+
239
+ ## 0.1.2 — 2026-03-30
240
+
241
+ ### Added
242
+
243
+ #### Script
244
+
245
+
246
+ #### Transaction
247
+
248
+
249
+ #### Wallet
250
+
251
+ - **BRC-31 Auth/Peer** — mutual authentication with nonce-based
252
+ challenges, ECDSA signatures, and session management.
253
+ - **BRC-100 wire protocol** — binary ABI serialisation for all 28
254
+ BRC-100 methods (call codes 1-28, VarInt encoding).
255
+ - **Certificate issuance** — `acquire_certificate` with
256
+ `'issuance'` protocol (POST to certifier URL).
257
+
258
+ ### Fixed
259
+
260
+ - Subject and certifier pinned in certificate issuance response
261
+ (not overridable by remote certifier).
262
+ - Wire reader negative `privileged_reason` length crash.
263
+
264
+ This was the first formal `bsv-wallet` gem release tag. Wallet code that
265
+ landed in master before this date (notably the BRC-100 identity certificate
266
+ methods and the BRC-100 blockchain-data / authentication methods committed
267
+ during the sdk-0.3.1 window) is part of this gem's initial released state.
@@ -141,7 +141,7 @@ module BSV
141
141
  # @param originator [String, nil] FQDN of the originating application
142
142
  # @return [Hash] { signature: Array<Integer> } DER-encoded signature as byte array
143
143
  def create_signature(args, originator: nil)
144
- counterparty = args[:counterparty] || 'self'
144
+ counterparty = args[:counterparty] || 'anyone'
145
145
  priv_key = @key_deriver.derive_private_key(args[:protocol_id], args[:key_id], counterparty)
146
146
 
147
147
  hash = if args[:hash_to_directly_sign]
@@ -3,6 +3,23 @@
3
3
  module BSV
4
4
  module Wallet
5
5
  module Validators
6
+ # Reserved protocol name prefixes (BRC-44 and BRC-98).
7
+ # Names beginning with any of these strings are disallowed.
8
+ RESERVED_PROTOCOL_PREFIXES = ['admin', 'p '].freeze
9
+
10
+ # Suffix that is disallowed on protocol names.
11
+ RESERVED_PROTOCOL_SUFFIX = ' protocol'
12
+
13
+ # Reserved basket name prefixes.
14
+ # Basket names beginning with any of these strings are disallowed.
15
+ RESERVED_BASKET_PREFIXES = ['admin', 'p '].freeze
16
+
17
+ # Suffix that is disallowed on basket names.
18
+ RESERVED_BASKET_SUFFIX = ' basket'
19
+
20
+ # Basket name that is globally reserved and cannot be used.
21
+ RESERVED_BASKET_NAME = 'default'
22
+
6
23
  module_function
7
24
 
8
25
  # BRC-100 protocol ID rules:
@@ -14,6 +31,10 @@ module BSV
14
31
  # - must not end with ' protocol'
15
32
  # - must not start with 'admin' (BRC-44)
16
33
  # - must not start with 'p ' (BRC-98 reserved)
34
+ #
35
+ # The name is normalised (stripped and downcased) before validation so
36
+ # that ' MyProtocol ' and 'myprotocol' are treated identically and do not
37
+ # silently fork to different key-derivation paths (F8.7).
17
38
  def validate_protocol_id!(protocol_id)
18
39
  unless protocol_id.is_a?(Array) && protocol_id.length == 2
19
40
  raise InvalidParameterError.new('protocol_id',
@@ -24,13 +45,19 @@ module BSV
24
45
  raise InvalidParameterError.new('protocol_id security level', '0, 1, or 2') unless [0, 1, 2].include?(level)
25
46
  raise InvalidParameterError.new('protocol_id name', 'a String') unless name.is_a?(String)
26
47
 
48
+ name = name.strip.downcase
49
+
27
50
  max_length = name.start_with?('specific linkage revelation') ? 430 : 400
28
51
  raise InvalidParameterError.new('protocol_id name', "between 5 and #{max_length} characters") if name.length < 5 || name.length > max_length
29
52
  raise InvalidParameterError.new('protocol_id name', 'lowercase letters, numbers, and spaces only') unless name.match?(/\A[a-z0-9 ]+\z/)
30
53
  raise InvalidParameterError.new('protocol_id name', 'free of consecutive spaces') if name.include?(' ')
31
- raise InvalidParameterError.new('protocol_id name', 'not ending with " protocol"') if name.end_with?(' protocol')
32
- raise InvalidParameterError.new('protocol_id name', 'not starting with "admin"') if name.start_with?('admin')
33
- raise InvalidParameterError.new('protocol_id name', 'not starting with "p "') if name.start_with?('p ')
54
+ if name.end_with?(RESERVED_PROTOCOL_SUFFIX)
55
+ raise InvalidParameterError.new('protocol_id name', "not ending with \"#{RESERVED_PROTOCOL_SUFFIX}\"")
56
+ end
57
+
58
+ RESERVED_PROTOCOL_PREFIXES.each do |prefix|
59
+ raise InvalidParameterError.new('protocol_id name', "not starting with \"#{prefix}\"") if name.start_with?(prefix)
60
+ end
34
61
  end
35
62
 
36
63
  # Key ID: 1-800 bytes
@@ -67,10 +94,12 @@ module BSV
67
94
  raise InvalidParameterError.new('basket', 'between 5 and 300 characters') if basket.length < 5 || basket.length > 300
68
95
  raise InvalidParameterError.new('basket', 'lowercase letters, numbers, and spaces only') unless basket.match?(/\A[a-z0-9 ]+\z/)
69
96
  raise InvalidParameterError.new('basket', 'free of consecutive spaces') if basket.include?(' ')
70
- raise InvalidParameterError.new('basket', 'not ending with " basket"') if basket.end_with?(' basket')
71
- raise InvalidParameterError.new('basket', 'not starting with "admin"') if basket.start_with?('admin')
72
- raise InvalidParameterError.new('basket', 'not equal to "default"') if basket == 'default'
73
- raise InvalidParameterError.new('basket', 'not starting with "p "') if basket.start_with?('p ')
97
+ raise InvalidParameterError.new('basket', "not ending with \"#{RESERVED_BASKET_SUFFIX}\"") if basket.end_with?(RESERVED_BASKET_SUFFIX)
98
+
99
+ RESERVED_BASKET_PREFIXES.each do |prefix|
100
+ raise InvalidParameterError.new('basket', "not starting with \"#{prefix}\"") if basket.start_with?(prefix)
101
+ end
102
+ raise InvalidParameterError.new('basket', "not equal to \"#{RESERVED_BASKET_NAME}\"") if basket == RESERVED_BASKET_NAME
74
103
  end
75
104
 
76
105
  # Label: 1-300 characters
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BSV
4
4
  module WalletInterface
5
- VERSION = '0.3.4'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -4,6 +4,7 @@ require 'securerandom'
4
4
  require 'base64'
5
5
  require 'net/http'
6
6
  require 'json'
7
+ require 'set'
7
8
  require 'uri'
8
9
 
9
10
  module BSV
@@ -180,6 +181,13 @@ module BSV
180
181
  validate_internalize_action!(args)
181
182
  beef_binary = args[:tx].pack('C*')
182
183
  beef = BSV::Transaction::Beef.from_binary(beef_binary)
184
+
185
+ # F8.14: verify the BEEF bundle before trusting its contents.
186
+ # Pass the chain provider if it supports SPV root verification;
187
+ # otherwise fall back to structural validation via valid?.
188
+ chain_tracker = @chain_provider.respond_to?(:valid_root_for_height?) ? @chain_provider : nil
189
+ raise WalletError, 'BEEF verification failed: the bundle is structurally invalid' unless beef.verify(chain_tracker)
190
+
183
191
  tx = extract_subject_transaction(beef)
184
192
 
185
193
  store_proofs_from_beef(beef)
@@ -400,6 +408,10 @@ module BSV
400
408
  { total_certificates: total, certificates: certs.map { |c| cert_without_keyring(c) } }
401
409
  end
402
410
 
411
+ # Maximum ancestor depth to traverse when wiring source transactions.
412
+ # Guards against stack overflow on pathologically deep or cyclic chains.
413
+ ANCESTOR_DEPTH_CAP = 64
414
+
403
415
  private
404
416
 
405
417
  # --- Validation ---
@@ -542,18 +554,28 @@ module BSV
542
554
  input.source_transaction = source_tx
543
555
  end
544
556
 
545
- def wire_source_tx_ancestors(tx)
557
+ def wire_source_tx_ancestors(tx, visited: nil, depth: 0)
558
+ return if depth >= ANCESTOR_DEPTH_CAP
559
+
560
+ visited ||= Set.new
561
+ tx_txid = tx.txid_hex
562
+ return if visited.include?(tx_txid)
563
+
564
+ visited.add(tx_txid)
565
+
546
566
  tx.inputs.each do |inp|
547
567
  next if inp.source_transaction
548
568
 
549
569
  ancestor_txid_hex = inp.prev_tx_id.reverse.unpack1('H*')
570
+ next if visited.include?(ancestor_txid_hex)
571
+
550
572
  tx_hex = @storage.find_transaction(ancestor_txid_hex)
551
573
  next unless tx_hex
552
574
 
553
575
  ancestor_tx = BSV::Transaction::Transaction.from_hex(tx_hex)
554
576
  proof = @proof_store.resolve_proof(ancestor_txid_hex)
555
577
  ancestor_tx.merkle_path = proof if proof
556
- wire_source_tx_ancestors(ancestor_tx) unless ancestor_tx.merkle_path
578
+ wire_source_tx_ancestors(ancestor_tx, visited: visited, depth: depth + 1) unless ancestor_tx.merkle_path
557
579
  inp.source_transaction = ancestor_tx
558
580
  end
559
581
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bsv-wallet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Bettison
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-04-08 00:00:00.000000000 Z
10
+ date: 2026-04-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -29,7 +29,7 @@ dependencies:
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.8.2
32
+ version: 0.9.0
33
33
  - - "<"
34
34
  - !ruby/object:Gem::Version
35
35
  version: '1.0'
@@ -39,7 +39,7 @@ dependencies:
39
39
  requirements:
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 0.8.2
42
+ version: 0.9.0
43
43
  - - "<"
44
44
  - !ruby/object:Gem::Version
45
45
  version: '1.0'
@@ -49,6 +49,7 @@ executables: []
49
49
  extensions: []
50
50
  extra_rdoc_files: []
51
51
  files:
52
+ - CHANGELOG-wallet.md
52
53
  - LICENSE
53
54
  - lib/bsv-wallet.rb
54
55
  - lib/bsv/wallet_interface.rb
@@ -81,7 +82,7 @@ licenses:
81
82
  metadata:
82
83
  homepage_uri: https://github.com/sgbett/bsv-ruby-sdk
83
84
  source_code_uri: https://github.com/sgbett/bsv-ruby-sdk
84
- changelog_uri: https://github.com/sgbett/bsv-ruby-sdk/blob/master/CHANGELOG.md
85
+ changelog_uri: https://github.com/sgbett/bsv-ruby-sdk/blob/master/CHANGELOG-wallet.md
85
86
  rubygems_mfa_required: 'true'
86
87
  rdoc_options: []
87
88
  require_paths: