bsv-sdk 0.22.0 → 0.23.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 +4 -4
- data/CHANGELOG.md +34 -0
- data/lib/bsv/network/protocols/arc.rb +4 -2
- data/lib/bsv/network/protocols/arcade.rb +2 -1
- data/lib/bsv/network/protocols/chaintracks.rb +21 -1
- data/lib/bsv/network/protocols/jungle_bus.rb +28 -0
- data/lib/bsv/network/protocols/woc_rest.rb +28 -1
- data/lib/bsv/transaction/chain_tracker.rb +6 -14
- data/lib/bsv/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce9ccc589a407c6ad98d92e40b9ac05925f3fbf32cc73aa235b9fd9a35b7ad43
|
|
4
|
+
data.tar.gz: 46992e9ea4f2465c4ca80ad2bb84e2591426610b46d1eea72e11171efdc271bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ac7da8fbd4e5cb9e0385bb3035dc34d44460232afe826b095d19cccc04faece15cd090045c49d7d176f68d7ba98b5a16105812c66ae8ac27d657df8682b8c499
|
|
7
|
+
data.tar.gz: 1b6946dd9762ac777aa8d1fff4392c96e30cfabd5c6b14f3eba7a8997e7ef0f8d5eca86383c131dfb479ce7f6ac94b7049bc50490edde5b0ff6b6994d8392629
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,40 @@ All notable changes to the `bsv-sdk` gem are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
6
6
|
and this gem adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.23.1 — 2026-06-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- `Protocols::Arcade#parse_broadcast_response`, `Protocols::ARC#parse_single_broadcast_response`,
|
|
12
|
+
and `Protocols::ARC#parse_batch_broadcast_response` now preserve the parsed response body as
|
|
13
|
+
`data:` on non-2xx responses. Previously the body was parsed only to extract an `error_message`,
|
|
14
|
+
then discarded — leaving callers with `data: nil` and no way to read `txStatus` / `extraInfo`
|
|
15
|
+
from synchronous broadcast failures (the terminal-rejection shape). Additive change; the 2xx
|
|
16
|
+
success path and ARC's existing 2xx-REJECTED branch are unchanged. (#793)
|
|
17
|
+
|
|
18
|
+
## 0.23.0 — 2026-06-03
|
|
19
|
+
|
|
20
|
+
### Changed (breaking)
|
|
21
|
+
- **Canonical block-header response shape across protocols.** `Protocols::JungleBus`,
|
|
22
|
+
`Protocols::Chaintracks`, and `Protocols::WoCREST` now emit the merkle root as
|
|
23
|
+
`'merkle_root'` (lowercase snake_case) in their `:get_block_header` and
|
|
24
|
+
`:get_block_headers` responses, replacing the upstream-specific names
|
|
25
|
+
(`'merkleroot'` for JungleBus/WoCREST, `'merkleRoot'` for Chaintracks). Consumers
|
|
26
|
+
reading the raw field directly from `provider.call(:get_block_header).data` must
|
|
27
|
+
migrate to the canonical key. Wire protocols stay honest about other fields;
|
|
28
|
+
only the merkle-root key is renamed. No shim. (#791)
|
|
29
|
+
- `WoCREST#:valid_root` now reads the normalised `merkle_root` key internally
|
|
30
|
+
(no behaviour change — same comparison output).
|
|
31
|
+
- `BSV::Transaction::ChainTracker#valid_root_for_height?` reads
|
|
32
|
+
`result.data['merkle_root']` directly; the previous private
|
|
33
|
+
`normalise_merkle_root` helper is removed. Subclass-override pattern unchanged.
|
|
34
|
+
|
|
35
|
+
### Note
|
|
36
|
+
- This is the "Pattern A" normalisation from #791 — push cosmetic field-name
|
|
37
|
+
divergence down into the wire-protocol classes where the data is semantically
|
|
38
|
+
identical across upstreams. Pattern B (broadcast / get_tx_status with
|
|
39
|
+
structurally divergent shapes) stays at the consumer layer and is not part of
|
|
40
|
+
this release.
|
|
41
|
+
|
|
8
42
|
## 0.22.0 — 2026-05-30
|
|
9
43
|
|
|
10
44
|
### Added
|
|
@@ -179,7 +179,8 @@ module BSV
|
|
|
179
179
|
return ProtocolResponse.new(
|
|
180
180
|
response,
|
|
181
181
|
http_success: false,
|
|
182
|
-
error_message: body['detail'] || body['title'] || "HTTP #{code}"
|
|
182
|
+
error_message: body['detail'] || body['title'] || "HTTP #{code}",
|
|
183
|
+
data: body
|
|
183
184
|
)
|
|
184
185
|
end
|
|
185
186
|
|
|
@@ -215,7 +216,8 @@ module BSV
|
|
|
215
216
|
return ProtocolResponse.new(
|
|
216
217
|
response,
|
|
217
218
|
http_success: false,
|
|
218
|
-
error_message: body.is_a?(Hash) ? (body['detail'] || body['title'] || "HTTP #{code}") : "HTTP #{code}"
|
|
219
|
+
error_message: body.is_a?(Hash) ? (body['detail'] || body['title'] || "HTTP #{code}") : "HTTP #{code}",
|
|
220
|
+
data: body.is_a?(Hash) || body.is_a?(Array) ? body : nil
|
|
219
221
|
)
|
|
220
222
|
end
|
|
221
223
|
|
|
@@ -127,7 +127,8 @@ module BSV
|
|
|
127
127
|
return ProtocolResponse.new(
|
|
128
128
|
response,
|
|
129
129
|
http_success: false,
|
|
130
|
-
error_message: body.is_a?(Hash) ? (body['reason'] || body['detail'] || "HTTP #{code}") : "HTTP #{code}"
|
|
130
|
+
error_message: body.is_a?(Hash) ? (body['reason'] || body['detail'] || "HTTP #{code}") : "HTTP #{code}",
|
|
131
|
+
data: body.is_a?(Hash) ? body : nil
|
|
131
132
|
)
|
|
132
133
|
end
|
|
133
134
|
|
|
@@ -21,7 +21,7 @@ module BSV
|
|
|
21
21
|
# result.data # => 800000
|
|
22
22
|
#
|
|
23
23
|
# result = ct.call(:get_block_header, 800_000)
|
|
24
|
-
# result.data # => { 'hash' => '...', 'height' => 800000, '
|
|
24
|
+
# result.data # => { 'hash' => '...', 'height' => 800000, 'merkle_root' => '...' }
|
|
25
25
|
#
|
|
26
26
|
# @note No public Chaintracks instance is hosted by major providers — GorillaPool
|
|
27
27
|
# serves chain data via JungleBus instead. For general chain-tracking against
|
|
@@ -40,6 +40,26 @@ module BSV
|
|
|
40
40
|
def initialize(base_url:, api_key: nil, auth: nil, http_client: nil)
|
|
41
41
|
super
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# Block-header escape hatch: normalises Chaintracks's +merkleRoot+ field
|
|
47
|
+
# to the canonical +merkle_root+ key. See issue #791 for the cross-protocol
|
|
48
|
+
# rationale.
|
|
49
|
+
def call_get_block_header(*, **)
|
|
50
|
+
response = default_call(:get_block_header, *, **)
|
|
51
|
+
return response unless response.http_success?
|
|
52
|
+
|
|
53
|
+
response.with(data: normalize_block_header(response.data))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def normalize_block_header(data)
|
|
57
|
+
return data unless data.is_a?(Hash) && data.key?('merkleRoot')
|
|
58
|
+
|
|
59
|
+
data = data.dup
|
|
60
|
+
data['merkle_root'] = data.delete('merkleRoot')
|
|
61
|
+
data
|
|
62
|
+
end
|
|
43
63
|
end
|
|
44
64
|
end
|
|
45
65
|
end
|
|
@@ -52,6 +52,34 @@ module BSV
|
|
|
52
52
|
def initialize(base_url:, api_key: nil, auth: nil, http_client: nil)
|
|
53
53
|
super
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Block-header escape hatch: normalises JungleBus's +merkleroot+ field
|
|
59
|
+
# to the canonical +merkle_root+ key. See issue #791 for the cross-protocol
|
|
60
|
+
# rationale.
|
|
61
|
+
def call_get_block_header(*, **)
|
|
62
|
+
response = default_call(:get_block_header, *, **)
|
|
63
|
+
return response unless response.http_success?
|
|
64
|
+
|
|
65
|
+
response.with(data: normalize_block_header(response.data))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def call_get_block_headers(*, **)
|
|
69
|
+
response = default_call(:get_block_headers, *, **)
|
|
70
|
+
return response unless response.http_success?
|
|
71
|
+
return response unless response.data.is_a?(Array)
|
|
72
|
+
|
|
73
|
+
response.with(data: response.data.map { |h| normalize_block_header(h) })
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def normalize_block_header(data)
|
|
77
|
+
return data unless data.is_a?(Hash) && data.key?('merkleroot')
|
|
78
|
+
|
|
79
|
+
data = data.dup
|
|
80
|
+
data['merkle_root'] = data.delete('merkleroot')
|
|
81
|
+
data
|
|
82
|
+
end
|
|
55
83
|
end
|
|
56
84
|
end
|
|
57
85
|
end
|
|
@@ -373,9 +373,36 @@ module BSV
|
|
|
373
373
|
result = default_call(:valid_root, height)
|
|
374
374
|
return result unless result.http_success?
|
|
375
375
|
|
|
376
|
-
|
|
376
|
+
data = normalize_block_header(result.data)
|
|
377
|
+
actual = data['merkle_root']
|
|
377
378
|
result.with(data: actual.to_s.downcase == root.to_s.downcase)
|
|
378
379
|
end
|
|
380
|
+
|
|
381
|
+
# Block-header escape hatch: normalises WoCREST's +merkleroot+ field
|
|
382
|
+
# to the canonical +merkle_root+ key. See issue #791 for the cross-protocol
|
|
383
|
+
# rationale.
|
|
384
|
+
def call_get_block_header(*, **)
|
|
385
|
+
response = default_call(:get_block_header, *, **)
|
|
386
|
+
return response unless response.http_success?
|
|
387
|
+
|
|
388
|
+
response.with(data: normalize_block_header(response.data))
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def call_get_block_headers(*, **)
|
|
392
|
+
response = default_call(:get_block_headers, *, **)
|
|
393
|
+
return response unless response.http_success?
|
|
394
|
+
return response unless response.data.is_a?(Array)
|
|
395
|
+
|
|
396
|
+
response.with(data: response.data.map { |h| normalize_block_header(h) })
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def normalize_block_header(data)
|
|
400
|
+
return data unless data.is_a?(Hash) && data.key?('merkleroot')
|
|
401
|
+
|
|
402
|
+
data = data.dup
|
|
403
|
+
data['merkle_root'] = data.delete('merkleroot')
|
|
404
|
+
data
|
|
405
|
+
end
|
|
379
406
|
end
|
|
380
407
|
end
|
|
381
408
|
end
|
|
@@ -70,8 +70,11 @@ module BSV
|
|
|
70
70
|
# Verify that a merkle root is valid for the given block height.
|
|
71
71
|
#
|
|
72
72
|
# Dispatches +:get_block_header+ to the configured provider. Returns +false+
|
|
73
|
-
# on 404 (block not found).
|
|
74
|
-
#
|
|
73
|
+
# on 404 (block not found). Relies on the wire-protocol classes that expose
|
|
74
|
+
# +:get_block_header+ (+Protocols::JungleBus+, +Protocols::Chaintracks+,
|
|
75
|
+
# +Protocols::WoCREST+) to emit the canonical +merkle_root+ key — see
|
|
76
|
+
# issue #791 for the Pattern A normalisation that absorbed the previous
|
|
77
|
+
# field-name shim.
|
|
75
78
|
#
|
|
76
79
|
# @param root [String] merkle root as a hex string
|
|
77
80
|
# @param height [Integer] block height
|
|
@@ -85,7 +88,7 @@ module BSV
|
|
|
85
88
|
return false if result.http_not_found?
|
|
86
89
|
raise result.error_message.to_s unless result.http_success?
|
|
87
90
|
|
|
88
|
-
actual =
|
|
91
|
+
actual = result.data.is_a?(Hash) ? result.data['merkle_root'] : nil
|
|
89
92
|
return false unless actual
|
|
90
93
|
|
|
91
94
|
actual.casecmp(root).zero?
|
|
@@ -106,17 +109,6 @@ module BSV
|
|
|
106
109
|
|
|
107
110
|
raise result.error_message.to_s
|
|
108
111
|
end
|
|
109
|
-
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
# Field-name diversity belongs at the Protocols::* layer; this is a
|
|
113
|
-
# transitional shim until the wire protocols return canonical shapes.
|
|
114
|
-
# See #791.
|
|
115
|
-
def normalise_merkle_root(body)
|
|
116
|
-
return nil unless body.is_a?(Hash)
|
|
117
|
-
|
|
118
|
-
body['merkleroot'] || body['merkleRoot'] || body['merkle_root']
|
|
119
|
-
end
|
|
120
112
|
end
|
|
121
113
|
end
|
|
122
114
|
end
|
data/lib/bsv/version.rb
CHANGED