bsv-sdk 0.6.2 → 0.7.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: b3a34503ada1c79e20bfafede1357f26715000394c5b286e21bc40374c040729
4
- data.tar.gz: 594a0b52441b9a7c0e1dc8590174f06f27e196ce573a4244d722d1c5381636d3
3
+ metadata.gz: 27f8c2431bb1d2a33a2f068fc4f46a616eb1ce000b1e61309819a745b596d57f
4
+ data.tar.gz: 172cb6b1dd0eeff2cbaa2887ccef5454df6dd8f18ebf7be7b16fb342d09fa749
5
5
  SHA512:
6
- metadata.gz: 87b8c8198f8f6a29f783364a83d4983b77ea7119b316f1b4cce77b4bb60333cc3fb8134aecb9cc58327558fac3368803811f77dab6ec2a91a8f9cfabbb19418e
7
- data.tar.gz: ebaead0b459cc6fda02b8d6b233de420505dd4aa5f173f314d04cc24a2dc501744dfa3a62aab046ce2571ed3dba044cef5a1534ed33cf85fc4584357c52d9c50
6
+ metadata.gz: ec1fc0e96520b641f9d42d37fe88507f835c434304ea550b26b38544805ae318b5ccccd8fb3d4246ba798855af5a688e54ea865f20bcf2415dabed0bda46378e
7
+ data.tar.gz: f41066e6683556f6d09e17a4211b02d304880dad99104ea67b555a823af8d6adb9ff7f7ce526c9a18cc67602abab3e47408fc078fc624d15b9c105f1f9a73ca0
data/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.7.0] - 2026-04-06
9
+
10
+ ### Added
11
+
12
+ - **Wallet** — pluggable proof store for merkle proof persistence. The wallet is now a lightweight SPV node: `internalize_action` extracts and stores merkle proofs from incoming BEEF; `create_action` reattaches them to produce valid BEEF with BUMPs for ARC broadcast.
13
+ - `ProofStore` interface with `store_proof` / `resolve_proof`
14
+ - `LocalProofStore` default implementation using `StorageAdapter`
15
+ - `WalletClient` accepts injectable `proof_store:` parameter
16
+ - Transaction caching (`store_transaction` / `find_transaction`) for ancestry reconstruction
17
+ - **Wallet** — `StorageAdapter` gains `store_proof`, `find_proof`, `store_transaction`, `find_transaction` methods, implemented in both `MemoryStore` and `FileStore`.
18
+
19
+ ### Changed
20
+
21
+ - **Transaction** — `Beef#to_binary` now defaults to BEEF V1 (BRC-62) format, matching the TS reference SDK's `Transaction#toBEEF()`. ARC's parser does not support V2. Pass `version: BEEF_V2` for BRC-96 format. Atomic BEEF (BRC-95) inner envelope remains V2 per spec.
22
+
23
+ ### Fixed
24
+
25
+ - **Wallet** — `wire_source_from_storage` resolves merkle proofs via proof store so `to_beef` produces valid BEEF that ARC accepts. Previously, BEEF contained source transactions without proofs, causing ARC 463/468 rejections.
26
+
8
27
  ## [0.6.2] - 2026-04-06
9
28
 
10
29
  ### Added
@@ -152,35 +152,30 @@ module BSV
152
152
  from_binary([hex].pack('H*'))
153
153
  end
154
154
 
155
- # --- Serialisation (always V2) ---
155
+ # --- Serialisation ---
156
156
 
157
- # Serialise the BEEF bundle to V2 (BRC-96) binary format.
157
+ # Serialise the BEEF bundle to binary format.
158
158
  #
159
+ # Defaults to V1 (BRC-62) for compatibility with ARC and the
160
+ # reference TS SDK. Pass +version: BEEF_V2+ for BRC-96 format.
161
+ #
162
+ # @param version [Integer] BEEF_V1 (default) or BEEF_V2
159
163
  # @return [String] raw BEEF binary
160
- def to_binary
164
+ def to_binary(version: BEEF_V1)
161
165
  bump_map = build_bump_map
162
166
  bumps_to_write = bump_map.values.sort_by { |entry| entry[:index] }.map { |entry| entry[:bump] }
163
167
 
164
- buf = [BEEF_V2].pack('V')
168
+ buf = [version].pack('V')
165
169
 
166
170
  buf << VarInt.encode(bumps_to_write.length)
167
171
  bumps_to_write.each { |bump| buf << bump.to_binary }
168
172
 
169
173
  buf << VarInt.encode(@transactions.length)
170
174
  @transactions.each do |beef_tx|
171
- case beef_tx.format
172
- when FORMAT_TXID_ONLY
173
- buf << [FORMAT_TXID_ONLY].pack('C')
174
- buf << beef_tx.known_txid
175
- when FORMAT_RAW_TX_AND_BUMP
176
- buf << [FORMAT_RAW_TX_AND_BUMP].pack('C')
177
- mp = beef_tx.transaction.merkle_path
178
- idx = bump_map[mp][:index]
179
- buf << VarInt.encode(idx)
180
- buf << beef_tx.transaction.to_binary
175
+ if version == BEEF_V2
176
+ write_v2_tx(buf, beef_tx, bump_map)
181
177
  else
182
- buf << [FORMAT_RAW_TX].pack('C')
183
- buf << beef_tx.transaction.to_binary
178
+ write_v1_tx(buf, beef_tx, bump_map)
184
179
  end
185
180
  end
186
181
 
@@ -203,7 +198,8 @@ module BSV
203
198
  # Write subject txid in internal byte order (reverse of display order),
204
199
  # matching JS and Go SDK conventions for Bitcoin binary formats.
205
200
  buf << subject_txid.b.reverse
206
- buf << to_binary
201
+ # BRC-95: inner envelope is always V2
202
+ buf << to_binary(version: BEEF_V2)
207
203
  buf
208
204
  end
209
205
 
@@ -606,6 +602,37 @@ module BSV
606
602
  end
607
603
  end
608
604
 
605
+ # V1 (BRC-62): raw_tx + has_bump(byte) [+ bump_index(varint)]
606
+ def write_v1_tx(buf, beef_tx, bump_map)
607
+ buf << beef_tx.transaction.to_binary
608
+ if beef_tx.format == FORMAT_RAW_TX_AND_BUMP
609
+ mp = beef_tx.transaction.merkle_path
610
+ idx = bump_map[mp][:index]
611
+ buf << [1].pack('C')
612
+ buf << VarInt.encode(idx)
613
+ else
614
+ buf << [0].pack('C')
615
+ end
616
+ end
617
+
618
+ # V2 (BRC-96): format_byte [+ bump_index(varint)] + raw_tx
619
+ def write_v2_tx(buf, beef_tx, bump_map)
620
+ case beef_tx.format
621
+ when FORMAT_TXID_ONLY
622
+ buf << [FORMAT_TXID_ONLY].pack('C')
623
+ buf << beef_tx.known_txid
624
+ when FORMAT_RAW_TX_AND_BUMP
625
+ buf << [FORMAT_RAW_TX_AND_BUMP].pack('C')
626
+ mp = beef_tx.transaction.merkle_path
627
+ idx = bump_map[mp][:index]
628
+ buf << VarInt.encode(idx)
629
+ buf << beef_tx.transaction.to_binary
630
+ else
631
+ buf << [FORMAT_RAW_TX].pack('C')
632
+ buf << beef_tx.transaction.to_binary
633
+ end
634
+ end
635
+
609
636
  def build_bump_map
610
637
  map = {}.compare_by_identity
611
638
  idx = 0
data/lib/bsv/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BSV
4
- VERSION = '0.6.2'
4
+ VERSION = '0.7.0'
5
5
  end
@@ -72,8 +72,26 @@ module BSV
72
72
  result
73
73
  end
74
74
 
75
+ def store_proof(txid, bump_hex)
76
+ super
77
+ save_proofs
78
+ end
79
+
80
+ def store_transaction(txid, tx_hex)
81
+ super
82
+ save_transactions
83
+ end
84
+
75
85
  private
76
86
 
87
+ def proofs_path
88
+ File.join(@dir, 'proofs.json')
89
+ end
90
+
91
+ def transactions_path
92
+ File.join(@dir, 'transactions.json')
93
+ end
94
+
77
95
  def check_permissions
78
96
  dir_mode = File.stat(@dir).mode & 0o777
79
97
  if dir_mode != 0o700
@@ -81,7 +99,7 @@ module BSV
81
99
  'Other users may be able to access wallet data.')
82
100
  end
83
101
 
84
- [actions_path, outputs_path, certificates_path].each do |path|
102
+ [actions_path, outputs_path, certificates_path, proofs_path, transactions_path].each do |path|
85
103
  next unless File.exist?(path)
86
104
 
87
105
  file_mode = File.stat(path).mode & 0o777
@@ -108,6 +126,8 @@ module BSV
108
126
  @actions = load_file(actions_path)
109
127
  @outputs = load_file(outputs_path)
110
128
  @certificates = load_file(certificates_path)
129
+ @proofs = load_proofs_file
130
+ @transactions = load_transactions_file
111
131
  end
112
132
 
113
133
  def load_file(path)
@@ -134,6 +154,38 @@ module BSV
134
154
  write_file(certificates_path, @certificates)
135
155
  end
136
156
 
157
+ def save_proofs
158
+ json = JSON.pretty_generate(@proofs)
159
+ tmp = "#{proofs_path}.tmp"
160
+ File.open(tmp, File::WRONLY | File::CREAT | File::TRUNC, 0o600) { |f| f.write(json) }
161
+ File.rename(tmp, proofs_path)
162
+ end
163
+
164
+ def load_proofs_file
165
+ return {} unless File.exist?(proofs_path)
166
+
167
+ data = JSON.parse(File.read(proofs_path))
168
+ data.is_a?(Hash) ? data : {}
169
+ rescue JSON::ParserError
170
+ {}
171
+ end
172
+
173
+ def save_transactions
174
+ json = JSON.pretty_generate(@transactions)
175
+ tmp = "#{transactions_path}.tmp"
176
+ File.open(tmp, File::WRONLY | File::CREAT | File::TRUNC, 0o600) { |f| f.write(json) }
177
+ File.rename(tmp, transactions_path)
178
+ end
179
+
180
+ def load_transactions_file
181
+ return {} unless File.exist?(transactions_path)
182
+
183
+ data = JSON.parse(File.read(transactions_path))
184
+ data.is_a?(Hash) ? data : {}
185
+ rescue JSON::ParserError
186
+ {}
187
+ end
188
+
137
189
  def write_file(path, data)
138
190
  json = JSON.pretty_generate(stringify_keys_deep(data))
139
191
  tmp = "#{path}.tmp"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ # Default proof store — persists serialised merkle proofs via a
6
+ # {StorageAdapter}. Requires no external services.
7
+ #
8
+ # @example Using the default local proof store
9
+ # store = BSV::Wallet::MemoryStore.new
10
+ # proofs = BSV::Wallet::LocalProofStore.new(store)
11
+ # proofs.store_proof(txid_hex, merkle_path)
12
+ # proof = proofs.resolve_proof(txid_hex)
13
+ class LocalProofStore
14
+ include ProofStore
15
+
16
+ # @param storage [StorageAdapter] the underlying persistence adapter
17
+ def initialize(storage)
18
+ @storage = storage
19
+ end
20
+
21
+ # Serialise and store a merkle proof.
22
+ #
23
+ # @param txid [String] hex transaction ID
24
+ # @param merkle_path [BSV::Transaction::MerklePath] the proof to store
25
+ # @return [void]
26
+ def store_proof(txid, merkle_path)
27
+ @storage.store_proof(txid, merkle_path.to_hex)
28
+ end
29
+
30
+ # Resolve and deserialise a merkle proof.
31
+ #
32
+ # @param txid [String] hex transaction ID
33
+ # @return [BSV::Transaction::MerklePath, nil] the proof, or nil if unknown
34
+ def resolve_proof(txid)
35
+ bump_hex = @storage.find_proof(txid)
36
+ return unless bump_hex
37
+
38
+ BSV::Transaction::MerklePath.from_hex(bump_hex)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -13,6 +13,8 @@ module BSV
13
13
  @actions = []
14
14
  @outputs = []
15
15
  @certificates = []
16
+ @proofs = {}
17
+ @transactions = {}
16
18
  end
17
19
 
18
20
  def store_action(action_data)
@@ -62,6 +64,22 @@ module BSV
62
64
  filter_certificates(query).length
63
65
  end
64
66
 
67
+ def store_proof(txid, bump_hex)
68
+ @proofs[txid] = bump_hex
69
+ end
70
+
71
+ def find_proof(txid)
72
+ @proofs[txid]
73
+ end
74
+
75
+ def store_transaction(txid, tx_hex)
76
+ @transactions[txid] = tx_hex
77
+ end
78
+
79
+ def find_transaction(txid)
80
+ @transactions[txid]
81
+ end
82
+
65
83
  def delete_certificate(type:, serial_number:, certifier:)
66
84
  idx = @certificates.index do |c|
67
85
  c[:type] == type && c[:serial_number] == serial_number && c[:certifier] == certifier
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ # Duck-typed interface for merkle proof persistence.
6
+ #
7
+ # Include this module in proof store implementations and override all
8
+ # methods. The default implementations raise NotImplementedError.
9
+ #
10
+ # Two implementations ship with the SDK:
11
+ # - {LocalProofStore} — persists proofs via a {StorageAdapter} (default)
12
+ # - Future: ChaintracksProofStore — resolves proofs from an external service
13
+ module ProofStore
14
+ # Store a merkle proof for a transaction.
15
+ #
16
+ # @param _txid [String] hex transaction ID
17
+ # @param _merkle_path [BSV::Transaction::MerklePath] the proof to store
18
+ # @return [void]
19
+ def store_proof(_txid, _merkle_path)
20
+ raise NotImplementedError, "#{self.class}#store_proof not implemented"
21
+ end
22
+
23
+ # Resolve a merkle proof for a transaction.
24
+ #
25
+ # @param _txid [String] hex transaction ID
26
+ # @return [BSV::Transaction::MerklePath, nil] the proof, or nil if unknown
27
+ def resolve_proof(_txid)
28
+ raise NotImplementedError, "#{self.class}#resolve_proof not implemented"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -50,6 +50,22 @@ module BSV
50
50
  def count_certificates(_query)
51
51
  raise NotImplementedError, "#{self.class}#count_certificates not implemented"
52
52
  end
53
+
54
+ def store_proof(_txid, _bump_hex)
55
+ raise NotImplementedError, "#{self.class}#store_proof not implemented"
56
+ end
57
+
58
+ def find_proof(_txid)
59
+ raise NotImplementedError, "#{self.class}#find_proof not implemented"
60
+ end
61
+
62
+ def store_transaction(_txid, _tx_hex)
63
+ raise NotImplementedError, "#{self.class}#store_transaction not implemented"
64
+ end
65
+
66
+ def find_transaction(_txid)
67
+ raise NotImplementedError, "#{self.class}#find_transaction not implemented"
68
+ end
53
69
  end
54
70
  end
55
71
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BSV
4
4
  module WalletInterface
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
@@ -35,17 +35,22 @@ module BSV
35
35
  # @return [String] the network ('mainnet' or 'testnet')
36
36
  attr_reader :network
37
37
 
38
+ # @return [ProofStore] the merkle proof persistence store
39
+ attr_reader :proof_store
40
+
38
41
  # @param key [BSV::Primitives::PrivateKey, String, KeyDeriver] signing key
39
42
  # @param storage [StorageAdapter] persistence adapter (default: FileStore).
40
43
  # Use +storage: MemoryStore.new+ for tests.
41
44
  # @param network [String] 'mainnet' (default) or 'testnet'
42
45
  # @param chain_provider [ChainProvider] blockchain data provider (default: NullChainProvider)
46
+ # @param proof_store [ProofStore, nil] merkle proof store (default: LocalProofStore backed by storage)
43
47
  # @param http_client [#request, nil] injectable HTTP client for certificate issuance
44
- def initialize(key, storage: FileStore.new, network: 'mainnet', chain_provider: NullChainProvider.new, http_client: nil)
48
+ def initialize(key, storage: FileStore.new, network: 'mainnet', chain_provider: NullChainProvider.new, proof_store: nil, http_client: nil)
45
49
  super(key)
46
50
  @storage = storage
47
51
  @network = network
48
52
  @chain_provider = chain_provider
53
+ @proof_store = proof_store || LocalProofStore.new(storage)
49
54
  @http_client = http_client
50
55
  @pending = {}
51
56
  end
@@ -177,6 +182,7 @@ module BSV
177
182
  beef = BSV::Transaction::Beef.from_binary(beef_binary)
178
183
  tx = extract_subject_transaction(beef)
179
184
 
185
+ store_proofs_from_beef(beef)
180
186
  process_internalize_outputs(tx, args[:outputs])
181
187
  store_action(tx, args, status: 'completed')
182
188
  { accepted: true }
@@ -520,6 +526,35 @@ module BSV
520
526
 
521
527
  input.source_satoshis = stored[:satoshis]
522
528
  input.source_locking_script = BSV::Script::Script.from_hex(stored[:locking_script])
529
+
530
+ return unless stored[:source_tx_hex]
531
+
532
+ source_tx = BSV::Transaction::Transaction.from_hex(stored[:source_tx_hex])
533
+ txid_hex = outpoint.split('.').first
534
+ proof = @proof_store.resolve_proof(txid_hex)
535
+ source_tx.merkle_path = proof if proof
536
+
537
+ # Recursively wire ancestors of the source tx so to_beef can build a
538
+ # complete, valid BEEF with the full proof chain.
539
+ wire_source_tx_ancestors(source_tx) unless source_tx.merkle_path
540
+
541
+ input.source_transaction = source_tx
542
+ end
543
+
544
+ def wire_source_tx_ancestors(tx)
545
+ tx.inputs.each do |inp|
546
+ next if inp.source_transaction
547
+
548
+ ancestor_txid_hex = inp.prev_tx_id.reverse.unpack1('H*')
549
+ tx_hex = @storage.find_transaction(ancestor_txid_hex)
550
+ next unless tx_hex
551
+
552
+ ancestor_tx = BSV::Transaction::Transaction.from_hex(tx_hex)
553
+ proof = @proof_store.resolve_proof(ancestor_txid_hex)
554
+ ancestor_tx.merkle_path = proof if proof
555
+ wire_source_tx_ancestors(ancestor_tx) unless ancestor_tx.merkle_path
556
+ inp.source_transaction = ancestor_tx
557
+ end
523
558
  end
524
559
 
525
560
  def build_outputs(tx, outputs)
@@ -601,6 +636,8 @@ module BSV
601
636
  def store_tracked_outputs(txid, tx, output_specs)
602
637
  return unless output_specs
603
638
 
639
+ tx_hex = tx.to_hex
640
+
604
641
  output_specs.each do |spec|
605
642
  next unless spec[:basket]
606
643
 
@@ -617,7 +654,8 @@ module BSV
617
654
  basket: spec[:basket],
618
655
  tags: spec[:tags] || [],
619
656
  custom_instructions: spec[:custom_instructions],
620
- spendable: true
657
+ spendable: true,
658
+ source_tx_hex: tx_hex
621
659
  })
622
660
  end
623
661
  end
@@ -644,6 +682,16 @@ module BSV
644
682
 
645
683
  # --- Internalize helpers ---
646
684
 
685
+ def store_proofs_from_beef(beef)
686
+ beef.transactions.each do |beef_tx|
687
+ next unless beef_tx.transaction&.merkle_path
688
+
689
+ txid_hex = beef_tx.transaction.txid_hex
690
+ @proof_store.store_proof(txid_hex, beef_tx.transaction.merkle_path)
691
+ @storage.store_transaction(txid_hex, beef_tx.transaction.to_hex)
692
+ end
693
+ end
694
+
647
695
  def extract_subject_transaction(beef)
648
696
  return find_by_subject_txid(beef) if beef.subject_txid
649
697
 
@@ -660,6 +708,7 @@ module BSV
660
708
 
661
709
  def process_internalize_outputs(tx, output_specs)
662
710
  txid = tx.txid_hex
711
+ tx_hex = tx.to_hex
663
712
 
664
713
  output_specs.each do |spec|
665
714
  output_index = spec[:output_index]
@@ -668,16 +717,16 @@ module BSV
668
717
 
669
718
  case spec[:protocol]
670
719
  when 'wallet payment'
671
- internalize_payment(txid, output_index, tx_output, spec[:payment_remittance])
720
+ internalize_payment(txid, output_index, tx_output, spec[:payment_remittance], tx_hex)
672
721
  when 'basket insertion'
673
- internalize_basket(txid, output_index, tx_output, spec[:insertion_remittance])
722
+ internalize_basket(txid, output_index, tx_output, spec[:insertion_remittance], tx_hex)
674
723
  else
675
724
  raise InvalidParameterError.new('protocol', '"wallet payment" or "basket insertion"')
676
725
  end
677
726
  end
678
727
  end
679
728
 
680
- def internalize_payment(txid, output_index, tx_output, remittance)
729
+ def internalize_payment(txid, output_index, tx_output, remittance, tx_hex = nil)
681
730
  unless remittance
682
731
  raise InvalidParameterError.new('payment_remittance',
683
732
  'present for wallet payment protocol')
@@ -705,11 +754,12 @@ module BSV
705
754
  spendable: true,
706
755
  sender_identity_key: sender_key,
707
756
  derivation_prefix: prefix,
708
- derivation_suffix: suffix
757
+ derivation_suffix: suffix,
758
+ source_tx_hex: tx_hex
709
759
  })
710
760
  end
711
761
 
712
- def internalize_basket(txid, output_index, tx_output, remittance)
762
+ def internalize_basket(txid, output_index, tx_output, remittance, tx_hex = nil)
713
763
  unless remittance
714
764
  raise InvalidParameterError.new('insertion_remittance',
715
765
  'present for basket insertion protocol')
@@ -724,7 +774,8 @@ module BSV
724
774
  basket: remittance[:basket],
725
775
  tags: remittance[:tags] || [],
726
776
  custom_instructions: remittance[:custom_instructions],
727
- spendable: true
777
+ spendable: true,
778
+ source_tx_hex: tx_hex
728
779
  })
729
780
  end
730
781
 
@@ -14,6 +14,8 @@ module BSV
14
14
  autoload :StorageAdapter, 'bsv/wallet_interface/storage_adapter'
15
15
  autoload :MemoryStore, 'bsv/wallet_interface/memory_store'
16
16
  autoload :FileStore, 'bsv/wallet_interface/file_store'
17
+ autoload :ProofStore, 'bsv/wallet_interface/proof_store'
18
+ autoload :LocalProofStore, 'bsv/wallet_interface/local_proof_store'
17
19
  autoload :ChainProvider, 'bsv/wallet_interface/chain_provider'
18
20
  autoload :NullChainProvider, 'bsv/wallet_interface/null_chain_provider'
19
21
  autoload :WalletClient, 'bsv/wallet_interface/wallet_client'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bsv-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Bettison
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-04-05 00:00:00.000000000 Z
10
+ date: 2026-04-06 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: A Ruby library for interacting with the BSV Blockchain — keys, scripts,
13
13
  transactions, and more.
@@ -130,8 +130,10 @@ files:
130
130
  - lib/bsv/wallet_interface/file_store.rb
131
131
  - lib/bsv/wallet_interface/interface.rb
132
132
  - lib/bsv/wallet_interface/key_deriver.rb
133
+ - lib/bsv/wallet_interface/local_proof_store.rb
133
134
  - lib/bsv/wallet_interface/memory_store.rb
134
135
  - lib/bsv/wallet_interface/null_chain_provider.rb
136
+ - lib/bsv/wallet_interface/proof_store.rb
135
137
  - lib/bsv/wallet_interface/proto_wallet.rb
136
138
  - lib/bsv/wallet_interface/storage_adapter.rb
137
139
  - lib/bsv/wallet_interface/validators.rb