bsv-sdk 0.20.0 → 0.23.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 +106 -0
- data/lib/bsv/mcp/tools/broadcast_p2pkh.rb +5 -3
- data/lib/bsv/network/protocols/arc.rb +4 -30
- data/lib/bsv/network/protocols/arcade.rb +163 -0
- data/lib/bsv/network/protocols/chaintracks.rb +27 -4
- data/lib/bsv/network/protocols/jungle_bus.rb +34 -0
- data/lib/bsv/network/protocols/woc_rest.rb +28 -1
- data/lib/bsv/network/protocols.rb +1 -0
- data/lib/bsv/network/providers/gorilla_pool.rb +18 -18
- data/lib/bsv/network/util.rb +44 -0
- data/lib/bsv/network.rb +1 -0
- data/lib/bsv/transaction/chain_tracker.rb +66 -13
- data/lib/bsv/transaction/chain_trackers.rb +0 -10
- data/lib/bsv/transaction/fee_models/live_policy.rb +10 -8
- data/lib/bsv/version.rb +1 -1
- data/lib/bsv/wallet/errors.rb +65 -21
- data/lib/bsv/wallet/proto_wallet/validators.rb +7 -49
- data/lib/bsv/wallet/proto_wallet.rb +14 -1
- data/lib/bsv/wallet/serializer/abort_action.rb +38 -0
- data/lib/bsv/wallet/serializer/acquire_certificate.rb +171 -0
- data/lib/bsv/wallet/serializer/certificate.rb +184 -0
- data/lib/bsv/wallet/serializer/common.rb +207 -0
- data/lib/bsv/wallet/serializer/create_action_args.rb +259 -0
- data/lib/bsv/wallet/serializer/create_action_result.rb +85 -0
- data/lib/bsv/wallet/serializer/create_hmac.rb +67 -0
- data/lib/bsv/wallet/serializer/create_signature.rb +90 -0
- data/lib/bsv/wallet/serializer/decrypt.rb +60 -0
- data/lib/bsv/wallet/serializer/discover_by_attributes.rb +61 -0
- data/lib/bsv/wallet/serializer/discover_by_identity_key.rb +49 -0
- data/lib/bsv/wallet/serializer/discover_certificates_result.rb +39 -0
- data/lib/bsv/wallet/serializer/encrypt.rb +60 -0
- data/lib/bsv/wallet/serializer/get_header_for_height.rb +71 -0
- data/lib/bsv/wallet/serializer/get_height.rb +46 -0
- data/lib/bsv/wallet/serializer/get_network.rb +65 -0
- data/lib/bsv/wallet/serializer/get_public_key.rb +86 -0
- data/lib/bsv/wallet/serializer/get_version.rb +44 -0
- data/lib/bsv/wallet/serializer/internalize_action.rb +151 -0
- data/lib/bsv/wallet/serializer/list_actions.rb +348 -0
- data/lib/bsv/wallet/serializer/list_certificates.rb +124 -0
- data/lib/bsv/wallet/serializer/list_outputs.rb +167 -0
- data/lib/bsv/wallet/serializer/prove_certificate.rb +146 -0
- data/lib/bsv/wallet/serializer/relinquish_certificate.rb +56 -0
- data/lib/bsv/wallet/serializer/relinquish_output.rb +44 -0
- data/lib/bsv/wallet/serializer/reveal_counterparty_key_linkage.rb +108 -0
- data/lib/bsv/wallet/serializer/reveal_specific_key_linkage.rb +116 -0
- data/lib/bsv/wallet/serializer/sign_action_args.rb +94 -0
- data/lib/bsv/wallet/serializer/sign_action_result.rb +49 -0
- data/lib/bsv/wallet/serializer/status.rb +85 -0
- data/lib/bsv/wallet/serializer/verify_hmac.rb +67 -0
- data/lib/bsv/wallet/serializer/verify_signature.rb +101 -0
- data/lib/bsv/wallet/serializer.rb +180 -0
- data/lib/bsv/wallet/substrates/http_wallet_json.rb +129 -0
- data/lib/bsv/wallet/substrates/http_wallet_wire.rb +99 -0
- data/lib/bsv/wallet/wallet_wire.rb +20 -0
- data/lib/bsv/wallet/wallet_wire_processor.rb +61 -0
- data/lib/bsv/wallet/wallet_wire_transceiver.rb +61 -0
- data/lib/bsv/wallet/wire/calls.rb +79 -0
- data/lib/bsv/wallet/wire/frame.rb +181 -0
- data/lib/bsv/wallet/wire/reader_writer.rb +402 -0
- data/lib/bsv/wallet/wire/validation.rb +213 -0
- data/lib/bsv/wallet/wire.rb +13 -0
- data/lib/bsv/wallet.rb +17 -0
- metadata +46 -2
- data/lib/bsv/transaction/chain_trackers/chaintracks.rb +0 -83
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
module Serializer
|
|
6
|
+
# BRC-103 serialiser for create_action result (call byte 1).
|
|
7
|
+
#
|
|
8
|
+
# Wire layout (port of go-sdk/wallet/serializer/create_action_result.go):
|
|
9
|
+
# [1 byte] 0x00 success sentinel (frame-level, already checked by Frame)
|
|
10
|
+
# [flag + 32 bytes] txid (wire-order) with flag byte: 0=absent, 1=present
|
|
11
|
+
# [flag + int_bytes] tx (BEEF bytes) with flag byte: 0=absent, 1=present + varint_len
|
|
12
|
+
# [optional_bytes] no_send_change encoded outpoints (NegativeOne = nil)
|
|
13
|
+
# [send_with_results] varint count + txid + status_byte each
|
|
14
|
+
# [1 byte flag] signable_transaction: 0=absent, 1=present
|
|
15
|
+
# If signable_transaction present:
|
|
16
|
+
# [int_bytes] tx (BEEF bytes)
|
|
17
|
+
# [int_bytes] reference bytes
|
|
18
|
+
module CreateActionResult
|
|
19
|
+
module_function
|
|
20
|
+
|
|
21
|
+
# @param result [Hash]
|
|
22
|
+
# @return [String] binary
|
|
23
|
+
def serialize(result)
|
|
24
|
+
w = Wire::Writer.new
|
|
25
|
+
w.write_byte(0) # success sentinel
|
|
26
|
+
|
|
27
|
+
txid_bytes = result[:txid] ? [result[:txid]].pack('H*').reverse : nil
|
|
28
|
+
w.write_optional_bytes_with_flag(txid_bytes, fixed_size: 32)
|
|
29
|
+
w.write_optional_bytes_with_flag(result[:tx])
|
|
30
|
+
|
|
31
|
+
no_send_change_bytes = Common.encode_outpoints(result[:no_send_change])
|
|
32
|
+
w.write_int_bytes(no_send_change_bytes)
|
|
33
|
+
|
|
34
|
+
Common.write_send_with_results(w, result[:send_with_results])
|
|
35
|
+
|
|
36
|
+
signable = result[:signable_transaction]
|
|
37
|
+
if signable
|
|
38
|
+
w.write_byte(1)
|
|
39
|
+
w.write_int_bytes(signable[:tx])
|
|
40
|
+
w.write_int_bytes(signable[:reference])
|
|
41
|
+
else
|
|
42
|
+
w.write_byte(0)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
w.buf
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param bytes [String] binary
|
|
49
|
+
# @return [Hash]
|
|
50
|
+
def deserialize(bytes)
|
|
51
|
+
raise ArgumentError, 'empty response data' if bytes.b.empty?
|
|
52
|
+
|
|
53
|
+
r = Wire::Reader.new(bytes)
|
|
54
|
+
|
|
55
|
+
status = r.read_byte
|
|
56
|
+
raise ArgumentError, "response indicates failure: #{status}" unless status.zero?
|
|
57
|
+
|
|
58
|
+
txid_raw = r.read_optional_bytes_with_flag(fixed_size: 32)
|
|
59
|
+
txid_hex = txid_raw&.reverse&.unpack1('H*')
|
|
60
|
+
tx = r.read_optional_bytes_with_flag
|
|
61
|
+
|
|
62
|
+
no_send_change_bytes = r.read_int_bytes
|
|
63
|
+
no_send_change = Common.decode_outpoints(no_send_change_bytes.empty? ? nil : no_send_change_bytes)
|
|
64
|
+
|
|
65
|
+
send_with_results = Common.read_send_with_results(r)
|
|
66
|
+
|
|
67
|
+
signable_flag = r.read_byte
|
|
68
|
+
signable_transaction = if signable_flag == 1
|
|
69
|
+
tx_bytes = r.read_int_bytes
|
|
70
|
+
ref_bytes = r.read_int_bytes
|
|
71
|
+
{ tx: tx_bytes, reference: ref_bytes }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
result = {}
|
|
75
|
+
result[:txid] = txid_hex unless txid_hex.nil?
|
|
76
|
+
result[:tx] = tx unless tx.nil?
|
|
77
|
+
result[:no_send_change] = no_send_change unless no_send_change.nil?
|
|
78
|
+
result[:send_with_results] = send_with_results unless send_with_results.nil?
|
|
79
|
+
result[:signable_transaction] = signable_transaction unless signable_transaction.nil?
|
|
80
|
+
result
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
module Serializer
|
|
6
|
+
# BRC-103 wire codec for the +create_hmac+ call (call byte 13).
|
|
7
|
+
#
|
|
8
|
+
# Port of go-sdk/wallet/serializer/create_hmac.go.
|
|
9
|
+
module CreateHmac
|
|
10
|
+
HMAC_SIZE = 32
|
|
11
|
+
|
|
12
|
+
# Args wire layout:
|
|
13
|
+
# [key-related params]
|
|
14
|
+
# [VarInt data_len][data bytes]
|
|
15
|
+
# [optional_bool seek_permission]
|
|
16
|
+
module Args
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
def serialize(args)
|
|
20
|
+
w = BSV::Wallet::Wire::Writer.new
|
|
21
|
+
Common.write_key_related_params(
|
|
22
|
+
w,
|
|
23
|
+
protocol_id: args[:protocol_id],
|
|
24
|
+
key_id: args[:key_id],
|
|
25
|
+
counterparty: args[:counterparty],
|
|
26
|
+
privileged: args[:privileged],
|
|
27
|
+
privileged_reason: args[:privileged_reason]
|
|
28
|
+
)
|
|
29
|
+
data = Common.to_binary(args[:data])
|
|
30
|
+
w.write_varint(data.bytesize)
|
|
31
|
+
w.write_bytes(data)
|
|
32
|
+
w.write_optional_bool(args[:seek_permission])
|
|
33
|
+
w.buf
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def deserialize(bytes)
|
|
37
|
+
r = BSV::Wallet::Wire::Reader.new(bytes)
|
|
38
|
+
params = Common.read_key_related_params(r)
|
|
39
|
+
len = r.read_varint
|
|
40
|
+
data = r.read_bytes(len)
|
|
41
|
+
seek_permission = r.read_optional_bool
|
|
42
|
+
params.merge(data: data, seek_permission: seek_permission)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Result wire layout:
|
|
47
|
+
# [32 bytes: HMAC-SHA-256]
|
|
48
|
+
module Result
|
|
49
|
+
module_function
|
|
50
|
+
|
|
51
|
+
def serialize(result)
|
|
52
|
+
hmac = Common.to_binary(result[:hmac])
|
|
53
|
+
raise ArgumentError, "HMAC must be #{HMAC_SIZE} bytes, got #{hmac.bytesize}" unless hmac.bytesize == HMAC_SIZE
|
|
54
|
+
|
|
55
|
+
hmac
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def deserialize(bytes)
|
|
59
|
+
raise ArgumentError, "HMAC result too short: #{bytes.bytesize}" if bytes.bytesize < HMAC_SIZE
|
|
60
|
+
|
|
61
|
+
{ hmac: bytes.byteslice(0, HMAC_SIZE) }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -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
|