bsv-sdk 0.20.0 → 0.22.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/lib/bsv/mcp/tools/broadcast_p2pkh.rb +5 -3
  4. data/lib/bsv/network/protocols/arc.rb +4 -30
  5. data/lib/bsv/network/protocols/arcade.rb +163 -0
  6. data/lib/bsv/network/protocols/chaintracks.rb +6 -3
  7. data/lib/bsv/network/protocols/jungle_bus.rb +6 -0
  8. data/lib/bsv/network/protocols.rb +1 -0
  9. data/lib/bsv/network/providers/gorilla_pool.rb +18 -18
  10. data/lib/bsv/network/util.rb +44 -0
  11. data/lib/bsv/network.rb +1 -0
  12. data/lib/bsv/transaction/chain_tracker.rb +74 -13
  13. data/lib/bsv/transaction/chain_trackers.rb +0 -10
  14. data/lib/bsv/transaction/fee_models/live_policy.rb +10 -8
  15. data/lib/bsv/version.rb +1 -1
  16. data/lib/bsv/wallet/errors.rb +65 -21
  17. data/lib/bsv/wallet/proto_wallet/validators.rb +7 -49
  18. data/lib/bsv/wallet/proto_wallet.rb +14 -1
  19. data/lib/bsv/wallet/serializer/abort_action.rb +38 -0
  20. data/lib/bsv/wallet/serializer/acquire_certificate.rb +171 -0
  21. data/lib/bsv/wallet/serializer/certificate.rb +184 -0
  22. data/lib/bsv/wallet/serializer/common.rb +207 -0
  23. data/lib/bsv/wallet/serializer/create_action_args.rb +259 -0
  24. data/lib/bsv/wallet/serializer/create_action_result.rb +85 -0
  25. data/lib/bsv/wallet/serializer/create_hmac.rb +67 -0
  26. data/lib/bsv/wallet/serializer/create_signature.rb +90 -0
  27. data/lib/bsv/wallet/serializer/decrypt.rb +60 -0
  28. data/lib/bsv/wallet/serializer/discover_by_attributes.rb +61 -0
  29. data/lib/bsv/wallet/serializer/discover_by_identity_key.rb +49 -0
  30. data/lib/bsv/wallet/serializer/discover_certificates_result.rb +39 -0
  31. data/lib/bsv/wallet/serializer/encrypt.rb +60 -0
  32. data/lib/bsv/wallet/serializer/get_header_for_height.rb +71 -0
  33. data/lib/bsv/wallet/serializer/get_height.rb +46 -0
  34. data/lib/bsv/wallet/serializer/get_network.rb +65 -0
  35. data/lib/bsv/wallet/serializer/get_public_key.rb +86 -0
  36. data/lib/bsv/wallet/serializer/get_version.rb +44 -0
  37. data/lib/bsv/wallet/serializer/internalize_action.rb +151 -0
  38. data/lib/bsv/wallet/serializer/list_actions.rb +348 -0
  39. data/lib/bsv/wallet/serializer/list_certificates.rb +124 -0
  40. data/lib/bsv/wallet/serializer/list_outputs.rb +167 -0
  41. data/lib/bsv/wallet/serializer/prove_certificate.rb +146 -0
  42. data/lib/bsv/wallet/serializer/relinquish_certificate.rb +56 -0
  43. data/lib/bsv/wallet/serializer/relinquish_output.rb +44 -0
  44. data/lib/bsv/wallet/serializer/reveal_counterparty_key_linkage.rb +108 -0
  45. data/lib/bsv/wallet/serializer/reveal_specific_key_linkage.rb +116 -0
  46. data/lib/bsv/wallet/serializer/sign_action_args.rb +94 -0
  47. data/lib/bsv/wallet/serializer/sign_action_result.rb +49 -0
  48. data/lib/bsv/wallet/serializer/status.rb +85 -0
  49. data/lib/bsv/wallet/serializer/verify_hmac.rb +67 -0
  50. data/lib/bsv/wallet/serializer/verify_signature.rb +101 -0
  51. data/lib/bsv/wallet/serializer.rb +180 -0
  52. data/lib/bsv/wallet/substrates/http_wallet_json.rb +129 -0
  53. data/lib/bsv/wallet/substrates/http_wallet_wire.rb +99 -0
  54. data/lib/bsv/wallet/wallet_wire.rb +20 -0
  55. data/lib/bsv/wallet/wallet_wire_processor.rb +61 -0
  56. data/lib/bsv/wallet/wallet_wire_transceiver.rb +61 -0
  57. data/lib/bsv/wallet/wire/calls.rb +79 -0
  58. data/lib/bsv/wallet/wire/frame.rb +181 -0
  59. data/lib/bsv/wallet/wire/reader_writer.rb +402 -0
  60. data/lib/bsv/wallet/wire/validation.rb +213 -0
  61. data/lib/bsv/wallet/wire.rb +13 -0
  62. data/lib/bsv/wallet.rb +17 -0
  63. metadata +46 -2
  64. data/lib/bsv/transaction/chain_trackers/chaintracks.rb +0 -83
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 wire codec for the +create_signature+ call (call byte 15).
7
+ #
8
+ # Port of go-sdk/wallet/serializer/create_signature.go.
9
+ module CreateSignature
10
+ HASH_SIZE = 32
11
+
12
+ # Args wire layout:
13
+ # [key-related params]
14
+ # [1 byte: data-type flag — 1=data, 2=hash_to_directly_sign]
15
+ # If flag=1: [VarInt data_len][data bytes]
16
+ # If flag=2: [32 bytes: hash]
17
+ # [optional_bool seek_permission]
18
+ module Args
19
+ module_function
20
+
21
+ def serialize(args)
22
+ data = args[:data] && Common.to_binary(args[:data])
23
+ hash = args[:hash_to_directly_sign] && Common.to_binary(args[:hash_to_directly_sign])
24
+
25
+ if data && hash
26
+ raise BSV::Wallet::InvalidParameterError.new(
27
+ 'data and hash_to_directly_sign',
28
+ 'not both provided — supply one or the other'
29
+ )
30
+ end
31
+ raise BSV::Wallet::InvalidParameterError.new('data or hash_to_directly_sign', 'present') unless data || hash
32
+
33
+ w = BSV::Wallet::Wire::Writer.new
34
+ Common.write_key_related_params(
35
+ w,
36
+ protocol_id: args[:protocol_id],
37
+ key_id: args[:key_id],
38
+ counterparty: args[:counterparty],
39
+ privileged: args[:privileged],
40
+ privileged_reason: args[:privileged_reason]
41
+ )
42
+
43
+ if data
44
+ w.write_byte(1)
45
+ w.write_varint(data.bytesize)
46
+ w.write_bytes(data)
47
+ else
48
+ w.write_byte(2)
49
+ w.write_bytes(hash)
50
+ end
51
+
52
+ w.write_optional_bool(args[:seek_permission])
53
+ w.buf
54
+ end
55
+
56
+ def deserialize(bytes)
57
+ r = BSV::Wallet::Wire::Reader.new(bytes)
58
+ params = Common.read_key_related_params(r)
59
+ flag = r.read_byte
60
+ payload = case flag
61
+ when 1
62
+ len = r.read_varint
63
+ { data: r.read_bytes(len) }
64
+ when 2
65
+ { hash_to_directly_sign: r.read_bytes(HASH_SIZE) }
66
+ else
67
+ raise ArgumentError, "invalid data-type flag: #{flag}"
68
+ end
69
+ seek_permission = r.read_optional_bool
70
+ params.merge(payload).merge(seek_permission: seek_permission)
71
+ end
72
+ end
73
+
74
+ # Result wire layout:
75
+ # [DER signature bytes — remaining payload]
76
+ module Result
77
+ module_function
78
+
79
+ def serialize(result)
80
+ Common.to_binary(result[:signature])
81
+ end
82
+
83
+ def deserialize(bytes)
84
+ { signature: bytes.b }
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 wire codec for the +decrypt+ call (call byte 12).
7
+ #
8
+ # Port of go-sdk/wallet/serializer/decrypt.go.
9
+ module Decrypt
10
+ # Args wire layout:
11
+ # [key-related params]
12
+ # [VarInt ciphertext_len][ciphertext bytes]
13
+ # [optional_bool seek_permission]
14
+ module Args
15
+ module_function
16
+
17
+ def serialize(args)
18
+ w = BSV::Wallet::Wire::Writer.new
19
+ Common.write_key_related_params(
20
+ w,
21
+ protocol_id: args[:protocol_id],
22
+ key_id: args[:key_id],
23
+ counterparty: args[:counterparty],
24
+ privileged: args[:privileged],
25
+ privileged_reason: args[:privileged_reason]
26
+ )
27
+ ciphertext = Common.to_binary(args[:ciphertext])
28
+ w.write_varint(ciphertext.bytesize)
29
+ w.write_bytes(ciphertext)
30
+ w.write_optional_bool(args[:seek_permission])
31
+ w.buf
32
+ end
33
+
34
+ def deserialize(bytes)
35
+ r = BSV::Wallet::Wire::Reader.new(bytes)
36
+ params = Common.read_key_related_params(r)
37
+ len = r.read_varint
38
+ ciphertext = r.read_bytes(len)
39
+ seek_permission = r.read_optional_bool
40
+ params.merge(ciphertext: ciphertext, seek_permission: seek_permission)
41
+ end
42
+ end
43
+
44
+ # Result wire layout:
45
+ # [plaintext bytes — remaining payload]
46
+ module Result
47
+ module_function
48
+
49
+ def serialize(result)
50
+ Common.to_binary(result[:plaintext])
51
+ end
52
+
53
+ def deserialize(bytes)
54
+ { plaintext: bytes.b }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 wire codec for the +discover_by_attributes+ call (call byte 22).
7
+ #
8
+ # Args wire layout:
9
+ # [varint: attribute_count] per entry: [varint-int key_bytes][varint-int value_bytes]
10
+ # [optional_uint32: limit]
11
+ # [optional_uint32: offset]
12
+ # [optional_bool: seek_permission]
13
+ #
14
+ # Result wire layout: see DiscoverCertificatesResult.
15
+ #
16
+ # Keys are written in sorted order (matching Go sort.Strings) to ensure
17
+ # deterministic encoding across SDK implementations.
18
+ module DiscoverByAttributes
19
+ module_function
20
+
21
+ def serialize_args(args)
22
+ w = Wire::Writer.new
23
+ attributes = args[:attributes] || {}
24
+ w.write_varint(attributes.length)
25
+ attributes.keys.sort.each do |k|
26
+ w.write_int_bytes(k.to_s.b)
27
+ w.write_int_bytes(attributes[k].to_s.b)
28
+ end
29
+ w.write_optional_uint32(args[:limit])
30
+ w.write_optional_uint32(args[:offset])
31
+ w.write_optional_bool(args[:seek_permission])
32
+ w.buf
33
+ end
34
+
35
+ def deserialize_args(bytes)
36
+ r = Wire::Reader.new(bytes)
37
+ count = r.read_varint
38
+ attributes = {}
39
+ count.times do
40
+ k = r.read_int_bytes.force_encoding('UTF-8')
41
+ v = r.read_int_bytes.force_encoding('UTF-8')
42
+ attributes[k] = v
43
+ end
44
+ limit = r.read_optional_uint32
45
+ offset = r.read_optional_uint32
46
+ seek_permission = r.read_optional_bool
47
+ { attributes: attributes, limit: limit, offset: offset,
48
+ seek_permission: seek_permission }
49
+ end
50
+
51
+ def serialize_result(result)
52
+ DiscoverCertificatesResult.serialize(result)
53
+ end
54
+
55
+ def deserialize_result(bytes)
56
+ DiscoverCertificatesResult.deserialize(bytes)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 wire codec for the +discover_by_identity_key+ call (call byte 21).
7
+ #
8
+ # Args wire layout:
9
+ # [33 bytes: identity_key compressed pubkey]
10
+ # [optional_uint32: limit]
11
+ # [optional_uint32: offset]
12
+ # [optional_bool: seek_permission]
13
+ #
14
+ # Result wire layout: see DiscoverCertificatesResult.
15
+ module DiscoverByIdentityKey
16
+ PUBKEY_SIZE = 33
17
+
18
+ module_function
19
+
20
+ def serialize_args(args)
21
+ w = Wire::Writer.new
22
+ w.write_bytes([args[:identity_key].to_s].pack('H*'))
23
+ w.write_optional_uint32(args[:limit])
24
+ w.write_optional_uint32(args[:offset])
25
+ w.write_optional_bool(args[:seek_permission])
26
+ w.buf
27
+ end
28
+
29
+ def deserialize_args(bytes)
30
+ r = Wire::Reader.new(bytes)
31
+ identity_key = r.read_bytes(PUBKEY_SIZE).unpack1('H*')
32
+ limit = r.read_optional_uint32
33
+ offset = r.read_optional_uint32
34
+ seek_permission = r.read_optional_bool
35
+ { identity_key: identity_key, limit: limit, offset: offset,
36
+ seek_permission: seek_permission }
37
+ end
38
+
39
+ def serialize_result(result)
40
+ DiscoverCertificatesResult.serialize(result)
41
+ end
42
+
43
+ def deserialize_result(bytes)
44
+ DiscoverCertificatesResult.deserialize(bytes)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # Shared BRC-103 result codec for discover_by_identity_key and
7
+ # discover_by_attributes (both return the same shape).
8
+ #
9
+ # Result wire layout:
10
+ # [varint: total_certificates]
11
+ # per certificate: [IdentityCertificate inline bytes (int-prefixed base cert + meta)]
12
+ module DiscoverCertificatesResult
13
+ module_function
14
+
15
+ # @param result [Hash] { total_certificates:, certificates: [IdentityCert Hash, ...] }
16
+ # @return [String] binary
17
+ def serialize(result)
18
+ certs = result[:certificates] || []
19
+ w = Wire::Writer.new
20
+ w.write_varint(certs.length)
21
+ certs.each do |cert|
22
+ cert_bytes = Certificate.serialize_identity_certificate(cert)
23
+ w.write_bytes(cert_bytes)
24
+ end
25
+ w.buf
26
+ end
27
+
28
+ # @param bytes [String] binary
29
+ # @return [Hash] { total_certificates:, certificates: [...] }
30
+ def deserialize(bytes)
31
+ r = Wire::Reader.new(bytes)
32
+ total = r.read_varint
33
+ certs = total.times.map { Certificate.deserialize_identity_certificate(r) }
34
+ { total_certificates: total, certificates: certs }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 wire codec for the +encrypt+ call (call byte 11).
7
+ #
8
+ # Port of go-sdk/wallet/serializer/encrypt.go.
9
+ module Encrypt
10
+ # Args wire layout:
11
+ # [key-related params: protocol + key_id + counterparty + privileged]
12
+ # [VarInt plaintext_len][plaintext bytes]
13
+ # [optional_bool seek_permission]
14
+ module Args
15
+ module_function
16
+
17
+ def serialize(args)
18
+ w = BSV::Wallet::Wire::Writer.new
19
+ Common.write_key_related_params(
20
+ w,
21
+ protocol_id: args[:protocol_id],
22
+ key_id: args[:key_id],
23
+ counterparty: args[:counterparty],
24
+ privileged: args[:privileged],
25
+ privileged_reason: args[:privileged_reason]
26
+ )
27
+ plaintext = Common.to_binary(args[:plaintext])
28
+ w.write_varint(plaintext.bytesize)
29
+ w.write_bytes(plaintext)
30
+ w.write_optional_bool(args[:seek_permission])
31
+ w.buf
32
+ end
33
+
34
+ def deserialize(bytes)
35
+ r = BSV::Wallet::Wire::Reader.new(bytes)
36
+ params = Common.read_key_related_params(r)
37
+ len = r.read_varint
38
+ plaintext = r.read_bytes(len)
39
+ seek_permission = r.read_optional_bool
40
+ params.merge(plaintext: plaintext, seek_permission: seek_permission)
41
+ end
42
+ end
43
+
44
+ # Result wire layout:
45
+ # [ciphertext bytes — remaining payload]
46
+ module Result
47
+ module_function
48
+
49
+ def serialize(result)
50
+ Common.to_binary(result[:ciphertext])
51
+ end
52
+
53
+ def deserialize(bytes)
54
+ { ciphertext: bytes.b }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 serialiser for the get_header_for_height call (call byte 26).
7
+ #
8
+ # Wire format:
9
+ # Args: [VarInt] height
10
+ # Result: [80 bytes] raw block header
11
+ #
12
+ # Port of go-sdk/wallet/serializer/get_header.go.
13
+ module GetHeaderForHeight
14
+ HEADER_BYTES = 80
15
+
16
+ module Args
17
+ module_function
18
+
19
+ # @param args [Hash] { height: Integer }
20
+ # @return [String] binary (varint-encoded height)
21
+ def serialize(args)
22
+ BSV::Transaction::VarInt.encode(args[:height].to_i)
23
+ end
24
+
25
+ # @param bytes [String] binary
26
+ # @return [Hash] { height: Integer }
27
+ def deserialize(bytes)
28
+ raise BSV::Wallet::InvalidParameterError.new('get_header_for_height args', 'at least 1 byte') if bytes.b.empty?
29
+
30
+ height, = BSV::Transaction::VarInt.decode(bytes.b, 0)
31
+ { height: height }
32
+ end
33
+ end
34
+
35
+ module Result
36
+ module_function
37
+
38
+ # @param result [Hash] { header: String } — 80-byte binary block header
39
+ # @return [String] 80-byte binary
40
+ # @raise [InvalidParameterError] if header is not exactly 80 bytes
41
+ def serialize(result)
42
+ header = result[:header].to_s.b
43
+ unless header.bytesize == HEADER_BYTES
44
+ raise BSV::Wallet::InvalidParameterError.new(
45
+ 'get_header_for_height result header',
46
+ "exactly #{HEADER_BYTES} bytes, got #{header.bytesize}"
47
+ )
48
+ end
49
+
50
+ header
51
+ end
52
+
53
+ # @param bytes [String] binary
54
+ # @return [Hash] { header: String }
55
+ # @raise [InvalidParameterError] if payload is not exactly 80 bytes
56
+ def deserialize(bytes)
57
+ data = bytes.b
58
+ unless data.bytesize == HEADER_BYTES
59
+ raise BSV::Wallet::InvalidParameterError.new(
60
+ 'get_header_for_height result',
61
+ "exactly #{HEADER_BYTES} bytes, got #{data.bytesize}"
62
+ )
63
+ end
64
+
65
+ { header: data }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 serialiser for the get_height call (call byte 25).
7
+ #
8
+ # Wire format — result only (no args payload):
9
+ # [VarInt] block height (uint32 range)
10
+ #
11
+ # Port of go-sdk/wallet/serializer/get_height.go.
12
+ module GetHeight
13
+ module Args
14
+ module_function
15
+
16
+ def serialize(_args = {})
17
+ ''.b
18
+ end
19
+
20
+ def deserialize(_bytes)
21
+ {}
22
+ end
23
+ end
24
+
25
+ module Result
26
+ module_function
27
+
28
+ # @param result [Hash] { height: Integer }
29
+ # @return [String] binary (varint-encoded height)
30
+ def serialize(result)
31
+ BSV::Transaction::VarInt.encode(result[:height].to_i)
32
+ end
33
+
34
+ # @param bytes [String] binary
35
+ # @return [Hash] { height: Integer }
36
+ def deserialize(bytes)
37
+ raise BSV::Wallet::InvalidParameterError.new('get_height result', 'at least 1 byte') if bytes.b.empty?
38
+
39
+ height, = BSV::Transaction::VarInt.decode(bytes.b, 0)
40
+ { height: height }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 serialiser for the get_network call (call byte 27).
7
+ #
8
+ # Wire format — result only (no args payload):
9
+ # [1 byte] 0x00 = mainnet, 0x01 = testnet
10
+ module GetNetwork
11
+ # Args is always empty — get_network takes no parameters.
12
+ module Args
13
+ module_function
14
+
15
+ def serialize(_args = {})
16
+ ''.b
17
+ end
18
+
19
+ def deserialize(_bytes)
20
+ {}
21
+ end
22
+ end
23
+
24
+ module Result
25
+ MAINNET_CODE = 0
26
+ TESTNET_CODE = 1
27
+
28
+ module_function
29
+
30
+ # @param result [Hash] { network: :mainnet | :testnet }
31
+ # @return [String] 1-byte binary
32
+ # @raise [InvalidParameterError] if +:network+ is not :mainnet or :testnet
33
+ def serialize(result)
34
+ code = case result[:network]
35
+ when :mainnet then MAINNET_CODE
36
+ when :testnet then TESTNET_CODE
37
+ else
38
+ raise BSV::Wallet::InvalidParameterError.new(
39
+ 'network', ":mainnet or :testnet, got #{result[:network].inspect}"
40
+ )
41
+ end
42
+ [code].pack('C')
43
+ end
44
+
45
+ # @param bytes [String] 1-byte binary
46
+ # @return [Hash] { network: :mainnet | :testnet }
47
+ # @raise [InvalidParameterError] if the byte is not 0x00 or 0x01
48
+ def deserialize(bytes)
49
+ data = bytes.b
50
+ raise BSV::Wallet::InvalidParameterError.new('get_network result', 'exactly 1 byte') unless data.bytesize == 1
51
+
52
+ case data.getbyte(0)
53
+ when MAINNET_CODE then { network: :mainnet }
54
+ when TESTNET_CODE then { network: :testnet }
55
+ else
56
+ raise BSV::Wallet::InvalidParameterError.new(
57
+ 'get_network result', "0x00 (mainnet) or 0x01 (testnet), got 0x#{data.unpack1('H*')}"
58
+ )
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 wire codec for the +get_public_key+ call (call byte 8).
7
+ #
8
+ # Port of go-sdk/wallet/serializer/get_public_key.go.
9
+ module GetPublicKey
10
+ IDENTITY_KEY_FLAG = 1
11
+ PUBKEY_SIZE = 33
12
+
13
+ # Args wire layout:
14
+ # [1 byte: identity_key flag — 0=no, 1=yes]
15
+ # If 0: [key-related params][optional_bool for_self]
16
+ # If 1: [privileged params only]
17
+ # [optional_bool seek_permission]
18
+ module Args
19
+ module_function
20
+
21
+ def serialize(args)
22
+ identity_key = args[:identity_key]
23
+ w = BSV::Wallet::Wire::Writer.new
24
+
25
+ if identity_key
26
+ w.write_byte(IDENTITY_KEY_FLAG)
27
+ Common.write_privileged_params(w, args[:privileged], args[:privileged_reason])
28
+ else
29
+ w.write_byte(0)
30
+ Common.write_key_related_params(
31
+ w,
32
+ protocol_id: args[:protocol_id],
33
+ key_id: args[:key_id],
34
+ counterparty: args[:counterparty],
35
+ privileged: args[:privileged],
36
+ privileged_reason: args[:privileged_reason]
37
+ )
38
+ w.write_optional_bool(args[:for_self])
39
+ end
40
+
41
+ w.write_optional_bool(args[:seek_permission])
42
+ w.buf
43
+ end
44
+
45
+ def deserialize(bytes)
46
+ r = BSV::Wallet::Wire::Reader.new(bytes)
47
+ flag = r.read_byte
48
+
49
+ if flag == IDENTITY_KEY_FLAG
50
+ privileged, reason = Common.read_privileged_params(r)
51
+ seek_permission = r.read_optional_bool
52
+ {
53
+ identity_key: true,
54
+ privileged: privileged,
55
+ privileged_reason: reason,
56
+ seek_permission: seek_permission
57
+ }
58
+ else
59
+ params = Common.read_key_related_params(r)
60
+ for_self = r.read_optional_bool
61
+ seek_permission = r.read_optional_bool
62
+ params.merge(identity_key: false, for_self: for_self, seek_permission: seek_permission)
63
+ end
64
+ end
65
+ end
66
+
67
+ # Result wire layout:
68
+ # [33 bytes: compressed public key]
69
+ module Result
70
+ module_function
71
+
72
+ def serialize(result)
73
+ pubkey = result[:public_key] || ''.b
74
+ pubkey.bytesize == PUBKEY_SIZE ? pubkey.b : [pubkey.to_s].pack('H*')
75
+ end
76
+
77
+ def deserialize(bytes)
78
+ raise ArgumentError, "public key too short: #{bytes.bytesize}" if bytes.bytesize < PUBKEY_SIZE
79
+
80
+ { public_key: bytes.byteslice(0, PUBKEY_SIZE) }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BSV
4
+ module Wallet
5
+ module Serializer
6
+ # BRC-103 serialiser for the get_version call (call byte 28).
7
+ #
8
+ # Wire format — result only (no args payload):
9
+ # [N bytes] raw UTF-8 version string (no length prefix)
10
+ #
11
+ # Port of go-sdk/wallet/serializer/get_version.go — the Go SDK emits
12
+ # the string bytes directly, with no varint length prefix.
13
+ module GetVersion
14
+ module Args
15
+ module_function
16
+
17
+ def serialize(_args = {})
18
+ ''.b
19
+ end
20
+
21
+ def deserialize(_bytes)
22
+ {}
23
+ end
24
+ end
25
+
26
+ module Result
27
+ module_function
28
+
29
+ # @param result [Hash] { version: String }
30
+ # @return [String] binary (raw UTF-8 bytes)
31
+ def serialize(result)
32
+ result[:version].to_s.b
33
+ end
34
+
35
+ # @param bytes [String] binary
36
+ # @return [Hash] { version: String }
37
+ def deserialize(bytes)
38
+ { version: bytes.b.force_encoding('UTF-8') }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end